')[0];\n\n var __filter_div_textContent = __filter_div.textContent !== undefined; // Update the filtering data for each row if needed (by invalidation or first run)\n\n\n function _fnFilterData(settings) {\n var columns = settings.aoColumns;\n var column;\n var i, j, ien, jen, filterData, cellData, row;\n var fomatters = DataTable.ext.type.search;\n var wasInvalidated = false;\n\n for (i = 0, ien = settings.aoData.length; i < ien; i++) {\n row = settings.aoData[i];\n\n if (!row._aFilterData) {\n filterData = [];\n\n for (j = 0, jen = columns.length; j < jen; j++) {\n column = columns[j];\n\n if (column.bSearchable) {\n cellData = _fnGetCellData(settings, i, j, 'filter');\n\n if (fomatters[column.sType]) {\n cellData = fomatters[column.sType](cellData);\n } // Search in DataTables 1.10 is string based. In 1.11 this\n // should be altered to also allow strict type checking.\n\n\n if (cellData === null) {\n cellData = '';\n }\n\n if (typeof cellData !== 'string' && cellData.toString) {\n cellData = cellData.toString();\n }\n } else {\n cellData = '';\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 http://jsperf.com/html-decode\n\n\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\n if (cellData.replace) {\n cellData = cellData.replace(/[\\r\\n]/g, '');\n }\n\n filterData.push(cellData);\n }\n\n row._aFilterData = filterData;\n row._sFilterRow = filterData.join(' ');\n wasInvalidated = true;\n }\n }\n\n return wasInvalidated;\n }\n /**\n * Convert from the internal Hungarian notation to camelCase for external\n * interaction\n * @param {object} obj Object to convert\n * @returns {object} Inverted object\n * @memberof DataTable#oApi\n */\n\n\n function _fnSearchToCamel(obj) {\n return {\n search: obj.sSearch,\n smart: obj.bSmart,\n regex: obj.bRegex,\n caseInsensitive: obj.bCaseInsensitive\n };\n }\n /**\n * Convert from camelCase notation to the internal Hungarian. We could use the\n * Hungarian convert function here, but this is cleaner\n * @param {object} obj Object to convert\n * @returns {object} Inverted object\n * @memberof DataTable#oApi\n */\n\n\n function _fnSearchToHung(obj) {\n return {\n sSearch: obj.search,\n bSmart: obj.smart,\n bRegex: obj.regex,\n bCaseInsensitive: obj.caseInsensitive\n };\n }\n /**\n * Generate the node required for the info display\n * @param {object} oSettings dataTables settings object\n * @returns {node} Information element\n * @memberof DataTable#oApi\n */\n\n\n function _fnFeatureHtmlInfo(settings) {\n var tid = settings.sTableId,\n nodes = settings.aanFeatures.i,\n n = $('
', {\n 'class': settings.oClasses.sInfo,\n 'id': !nodes ? tid + '_info' : null\n });\n\n if (!nodes) {\n // Update display on each draw\n settings.aoDrawCallback.push({\n \"fn\": _fnUpdateInfo,\n \"sName\": \"information\"\n });\n n.attr('role', 'status').attr('aria-live', 'polite'); // Table is described by our info div\n\n $(settings.nTable).attr('aria-describedby', tid + '_info');\n }\n\n return n[0];\n }\n /**\n * Update the information elements in the display\n * @param {object} settings dataTables settings object\n * @memberof DataTable#oApi\n */\n\n\n function _fnUpdateInfo(settings) {\n /* Show information about the table */\n var nodes = settings.aanFeatures.i;\n\n if (nodes.length === 0) {\n return;\n }\n\n var lang = settings.oLanguage,\n start = settings._iDisplayStart + 1,\n end = settings.fnDisplayEnd(),\n max = settings.fnRecordsTotal(),\n total = settings.fnRecordsDisplay(),\n out = total ? lang.sInfo : lang.sInfoEmpty;\n\n if (total !== max) {\n /* Record set after filtering */\n out += ' ' + lang.sInfoFiltered;\n } // Convert the macros\n\n\n out += lang.sInfoPostFix;\n out = _fnInfoMacros(settings, out);\n var callback = lang.fnInfoCallback;\n\n if (callback !== null) {\n out = callback.call(settings.oInstance, settings, start, end, max, total, out);\n }\n\n $(nodes).html(out);\n }\n\n function _fnInfoMacros(settings, str) {\n // When infinite scrolling, we are always starting at 1. _iDisplayStart is used only\n // internally\n var formatter = settings.fnFormatNumber,\n start = settings._iDisplayStart + 1,\n len = settings._iDisplayLength,\n vis = settings.fnRecordsDisplay(),\n all = len === -1;\n return str.replace(/_START_/g, formatter.call(settings, start)).replace(/_END_/g, formatter.call(settings, settings.fnDisplayEnd())).replace(/_MAX_/g, formatter.call(settings, settings.fnRecordsTotal())).replace(/_TOTAL_/g, formatter.call(settings, vis)).replace(/_PAGE_/g, formatter.call(settings, all ? 1 : Math.ceil(start / len))).replace(/_PAGES_/g, formatter.call(settings, all ? 1 : Math.ceil(vis / len)));\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\n\n function _fnInitialise(settings) {\n var i,\n iLen,\n iAjaxStart = settings.iInitDisplayStart;\n var columns = settings.aoColumns,\n column;\n var features = settings.oFeatures;\n var deferLoading = settings.bDeferLoading; // value modified by the draw\n\n /* Ensure that the table data is fully initialised */\n\n if (!settings.bInitialised) {\n setTimeout(function () {\n _fnInitialise(settings);\n }, 200);\n return;\n }\n /* Show the display HTML options */\n\n\n _fnAddOptionsHtml(settings);\n /* Build and draw the header / footer for the table */\n\n\n _fnBuildHead(settings);\n\n _fnDrawHead(settings, settings.aoHeader);\n\n _fnDrawHead(settings, settings.aoFooter);\n /* Okay to show that something is going on now */\n\n\n _fnProcessingDisplay(settings, true);\n /* Calculate sizes for columns */\n\n\n if (features.bAutoWidth) {\n _fnCalculateColumnWidths(settings);\n }\n\n for (i = 0, iLen = columns.length; i < iLen; i++) {\n column = columns[i];\n\n if (column.sWidth) {\n column.nTh.style.width = _fnStringToCss(column.sWidth);\n }\n }\n\n _fnCallbackFire(settings, null, 'preInit', [settings]); // 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\n\n _fnReDraw(settings); // Server-side processing init complete is done by _fnAjaxUpdateDraw\n\n\n var dataSrc = _fnDataSource(settings);\n\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); // Got the data - add it to the table\n\n\n for (i = 0; i < aData.length; i++) {\n _fnAddData(settings, aData[i]);\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\n\n settings.iInitDisplayStart = iAjaxStart;\n\n _fnReDraw(settings);\n\n _fnProcessingDisplay(settings, false);\n\n _fnInitComplete(settings, json);\n }, settings);\n } else {\n _fnProcessingDisplay(settings, false);\n\n _fnInitComplete(settings);\n }\n }\n }\n /**\n * Draw the table for the first time, adding all required features\n * @param {object} oSettings dataTables settings object\n * @param {object} [json] JSON from the server that completed the table, if using Ajax source\n * with client-side processing (optional)\n * @memberof DataTable#oApi\n */\n\n\n function _fnInitComplete(settings, json) {\n settings._bInitComplete = true; // When data was added after the initialisation (data or Ajax) we need to\n // calculate the column sizing\n\n if (json || settings.oInit.aaData) {\n _fnAdjustColumnSizing(settings);\n }\n\n _fnCallbackFire(settings, null, 'plugin-init', [settings, json]);\n\n _fnCallbackFire(settings, 'aoInitComplete', 'init', [settings, json]);\n }\n\n function _fnLengthChange(settings, val) {\n var len = parseInt(val, 10);\n settings._iDisplayLength = len;\n\n _fnLengthOverflow(settings); // Fire length change event\n\n\n _fnCallbackFire(settings, null, 'length', [settings, len]);\n }\n /**\n * Generate the node required for user display length changing\n * @param {object} settings dataTables settings object\n * @returns {node} Display length feature node\n * @memberof DataTable#oApi\n */\n\n\n function _fnFeatureHtmlLength(settings) {\n var classes = settings.oClasses,\n tableId = settings.sTableId,\n menu = settings.aLengthMenu,\n d2 = $.isArray(menu[0]),\n lengths = d2 ? menu[0] : menu,\n language = d2 ? menu[1] : menu;\n var select = $('
', {\n 'name': tableId + '_length',\n 'aria-controls': tableId,\n 'class': classes.sLengthSelect\n });\n\n for (var i = 0, ien = lengths.length; i < ien; i++) {\n select[0][i] = new Option(typeof language[i] === 'number' ? settings.fnFormatNumber(language[i]) : language[i], lengths[i]);\n }\n\n var div = $('
').addClass(classes.sLength);\n\n if (!settings.aanFeatures.l) {\n div[0].id = tableId + '_length';\n }\n\n div.children().append(settings.oLanguage.sLengthMenu.replace('_MENU_', select[0].outerHTML)); // Can't use `select` variable as user might provide their own and the\n // reference is broken by the use of outerHTML\n\n $('select', div).val(settings._iDisplayLength).on('change.DT', function (e) {\n _fnLengthChange(settings, $(this).val());\n\n _fnDraw(settings);\n }); // Update node value whenever anything changes the table's length\n\n $(settings.nTable).on('length.dt.DT', function (e, s, len) {\n if (settings === s) {\n $('select', div).val(len);\n }\n });\n return div[0];\n }\n /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n * Note that most of the paging logic is done in\n * DataTable.ext.pager\n */\n\n /**\n * Generate the node required for default pagination\n * @param {object} oSettings dataTables settings object\n * @returns {node} Pagination feature node\n * @memberof DataTable#oApi\n */\n\n\n function _fnFeatureHtmlPaginate(settings) {\n var type = settings.sPaginationType,\n plugin = DataTable.ext.pager[type],\n modern = typeof plugin === 'function',\n redraw = function redraw(settings) {\n _fnDraw(settings);\n },\n node = $('
').addClass(settings.oClasses.sPaging + type)[0],\n features = settings.aanFeatures;\n\n if (!modern) {\n plugin.fnInit(settings, node, redraw);\n }\n /* Add a draw callback for the pagination on first instance, to update the paging display */\n\n\n if (!features.p) {\n node.id = settings.sTableId + '_paginate';\n settings.aoDrawCallback.push({\n \"fn\": function fn(settings) {\n if (modern) {\n var start = settings._iDisplayStart,\n len = settings._iDisplayLength,\n visRecords = settings.fnRecordsDisplay(),\n all = len === -1,\n page = all ? 0 : Math.ceil(start / len),\n pages = all ? 1 : Math.ceil(visRecords / len),\n buttons = plugin(page, pages),\n i,\n ien;\n\n for (i = 0, ien = features.p.length; i < ien; i++) {\n _fnRenderer(settings, 'pageButton')(settings, features.p[i], i, buttons, page, pages);\n }\n } else {\n plugin.fnUpdate(settings, redraw);\n }\n },\n \"sName\": \"pagination\"\n });\n }\n\n return node;\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\n\n function _fnPageChange(settings, action, redraw) {\n var start = settings._iDisplayStart,\n len = settings._iDisplayLength,\n records = settings.fnRecordsDisplay();\n\n if (records === 0 || len === -1) {\n start = 0;\n } else if (typeof action === \"number\") {\n start = action * len;\n\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\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 {\n _fnLog(settings, 0, \"Unknown paging action: \" + action, 5);\n }\n\n var changed = settings._iDisplayStart !== start;\n settings._iDisplayStart = start;\n\n if (changed) {\n _fnCallbackFire(settings, null, 'page', [settings]);\n\n if (redraw) {\n _fnDraw(settings);\n }\n }\n\n return changed;\n }\n /**\n * Generate the node required for the processing node\n * @param {object} settings dataTables settings object\n * @returns {node} Processing element\n * @memberof DataTable#oApi\n */\n\n\n function _fnFeatureHtmlProcessing(settings) {\n return $('
', {\n 'id': !settings.aanFeatures.r ? settings.sTableId + '_processing' : null,\n 'class': settings.oClasses.sProcessing\n }).html(settings.oLanguage.sProcessing).insertBefore(settings.nTable)[0];\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 * @memberof DataTable#oApi\n */\n\n\n function _fnProcessingDisplay(settings, show) {\n if (settings.oFeatures.bProcessing) {\n $(settings.aanFeatures.r).css('display', show ? 'block' : 'none');\n }\n\n _fnCallbackFire(settings, null, 'processing', [settings, show]);\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\n\n function _fnFeatureHtmlTable(settings) {\n var table = $(settings.nTable); // Add the ARIA grid role to the table\n\n table.attr('role', 'grid'); // Scrolling from here on in\n\n var scroll = settings.oScroll;\n\n if (scroll.sX === '' && scroll.sY === '') {\n return settings.nTable;\n }\n\n var scrollX = scroll.sX;\n var scrollY = scroll.sY;\n var classes = settings.oClasses;\n var caption = table.children('caption');\n var captionSide = caption.length ? caption[0]._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\n var size = function size(s) {\n return !s ? null : _fnStringToCss(s);\n };\n\n if (!footer.length) {\n footer = null;\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\n\n var scroller = $(_div, {\n 'class': classes.sScrollWrapper\n }).append($(_div, {\n 'class': classes.sScrollHead\n }).css({\n overflow: 'hidden',\n position: 'relative',\n border: 0,\n width: scrollX ? size(scrollX) : '100%'\n }).append($(_div, {\n 'class': classes.sScrollHeadInner\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.sScrollBody\n }).css({\n position: 'relative',\n overflow: 'auto',\n width: size(scrollX)\n }).append(table));\n\n if (footer) {\n scroller.append($(_div, {\n 'class': classes.sScrollFoot\n }).css({\n overflow: 'hidden',\n border: 0,\n width: scrollX ? size(scrollX) : '100%'\n }).append($(_div, {\n 'class': classes.sScrollFootInner\n }).append(footerClone.removeAttr('id').css('margin-left', 0).append(captionSide === 'bottom' ? caption : null).append(table.children('tfoot')))));\n }\n\n var children = scroller.children();\n var scrollHead = children[0];\n var scrollBody = children[1];\n var scrollFoot = footer ? children[2] : null; // When the body is scrolled, then we also want to scroll the headers\n\n if (scrollX) {\n $(scrollBody).on('scroll.DT', function (e) {\n var scrollLeft = this.scrollLeft;\n scrollHead.scrollLeft = scrollLeft;\n\n if (footer) {\n scrollFoot.scrollLeft = scrollLeft;\n }\n });\n }\n\n $(scrollBody).css(scrollY && scroll.bCollapse ? 'max-height' : 'height', scrollY);\n settings.nScrollHead = scrollHead;\n settings.nScrollBody = scrollBody;\n settings.nScrollFoot = scrollFoot; // On redraw - align columns\n\n settings.aoDrawCallback.push({\n \"fn\": _fnScrollDraw,\n \"sName\": \"scrolling\"\n });\n return scroller[0];\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. Take live measurements from the DOM\n * 3. Apply the measurements to align the columns\n * 4. Clean up\n *\n * @param {object} settings dataTables settings object\n * @memberof DataTable#oApi\n */\n\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 scrollX = scroll.sX,\n scrollXInner = scroll.sXInner,\n scrollY = scroll.sY,\n barWidth = scroll.iBarWidth,\n divHeader = $(settings.nScrollHead),\n divHeaderStyle = divHeader[0].style,\n divHeaderInner = divHeader.children('div'),\n divHeaderInnerStyle = divHeaderInner[0].style,\n divHeaderTable = divHeaderInner.children('table'),\n divBodyEl = settings.nScrollBody,\n divBody = $(divBodyEl),\n divBodyStyle = divBodyEl.style,\n divFooter = $(settings.nScrollFoot),\n divFooterInner = divFooter.children('div'),\n divFooterTable = divFooterInner.children('table'),\n header = $(settings.nTHead),\n table = $(settings.nTable),\n tableEl = table[0],\n tableStyle = tableEl.style,\n footer = settings.nTFoot ? $(settings.nTFoot) : null,\n browser = settings.oBrowser,\n ie67 = browser.bScrollOversize,\n dtHeaderCells = _pluck(settings.aoColumns, 'nTh'),\n headerTrgEls,\n footerTrgEls,\n headerSrcEls,\n footerSrcEls,\n headerCopy,\n footerCopy,\n headerWidths = [],\n footerWidths = [],\n headerContent = [],\n footerContent = [],\n idx,\n correction,\n sanityWidth,\n zeroOut = function zeroOut(nSizer) {\n var style = nSizer.style;\n style.paddingTop = \"0\";\n style.paddingBottom = \"0\";\n style.borderTopWidth = \"0\";\n style.borderBottomWidth = \"0\";\n style.height = 0;\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\n\n var scrollBarVis = divBodyEl.scrollHeight > divBodyEl.clientHeight;\n\n if (settings.scrollBarVis !== scrollBarVis && settings.scrollBarVis !== undefined) {\n settings.scrollBarVis = scrollBarVis;\n\n _fnAdjustColumnSizing(settings);\n\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 */\n // Remove the old minimised thead and tfoot elements in the inner table\n\n\n table.children('thead, tfoot').remove();\n\n if (footer) {\n footerCopy = footer.clone().prependTo(table);\n footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized\n\n footerSrcEls = footerCopy.find('tr');\n } // Clone the current header and footer elements and then place it into the inner table\n\n\n headerCopy = header.clone().prependTo(table);\n headerTrgEls = header.find('tr'); // original header is in its own table\n\n headerSrcEls = headerCopy.find('tr');\n headerCopy.find('th, td').removeAttr('tabindex');\n /*\n * 2. Take live measurements from the DOM - do not alter the DOM itself!\n */\n // Remove old sizing and apply the calculated column widths\n // Get the unique column headers in the newly created (cloned) header. We want to apply the\n // calculated sizes to this header\n\n if (!scrollX) {\n divBodyStyle.width = '100%';\n divHeader[0].style.width = '100%';\n }\n\n $.each(_fnGetUniqueThs(settings, headerCopy), function (i, el) {\n idx = _fnVisibleToColumnIndex(settings, i);\n el.style.width = settings.aoColumns[idx].sWidth;\n });\n\n if (footer) {\n _fnApplyToChildren(function (n) {\n n.style.width = \"\";\n }, footerSrcEls);\n } // Size the table as a whole\n\n\n sanityWidth = table.outerWidth();\n\n if (scrollX === \"\") {\n // No x scrolling\n tableStyle.width = \"100%\"; // IE7 will make the width of the table when 100% include the scrollbar\n // - which is shouldn't. When there is a scrollbar we need to take this\n // into account.\n\n if (ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight || divBody.css('overflow-y') == \"scroll\")) {\n tableStyle.width = _fnStringToCss(table.outerWidth() - barWidth);\n } // Recalculate the sanity width\n\n\n sanityWidth = table.outerWidth();\n } else if (scrollXInner !== \"\") {\n // legacy x scroll inner has been given - use it\n tableStyle.width = _fnStringToCss(scrollXInner); // Recalculate the sanity width\n\n sanityWidth = table.outerWidth();\n } // Hidden header should have zero height, so remove padding and borders. Then\n // set the width based on the real headers\n // Apply all styles in one pass\n\n\n _fnApplyToChildren(zeroOut, headerSrcEls); // Read all widths in next pass\n\n\n _fnApplyToChildren(function (nSizer) {\n headerContent.push(nSizer.innerHTML);\n headerWidths.push(_fnStringToCss($(nSizer).css('width')));\n }, headerSrcEls); // Apply all widths in final pass\n\n\n _fnApplyToChildren(function (nToSize, i) {\n // Only apply widths to the DataTables detected header cells - this\n // prevents complex headers from having contradictory sizes applied\n if ($.inArray(nToSize, dtHeaderCells) !== -1) {\n nToSize.style.width = headerWidths[i];\n }\n }, headerTrgEls);\n\n $(headerSrcEls).height(0);\n /* Same again with the footer if we have one */\n\n if (footer) {\n _fnApplyToChildren(zeroOut, footerSrcEls);\n\n _fnApplyToChildren(function (nSizer) {\n footerContent.push(nSizer.innerHTML);\n footerWidths.push(_fnStringToCss($(nSizer).css('width')));\n }, footerSrcEls);\n\n _fnApplyToChildren(function (nToSize, i) {\n nToSize.style.width = footerWidths[i];\n }, footerTrgEls);\n\n $(footerSrcEls).height(0);\n }\n /*\n * 3. Apply the measurements\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. We want to also fix their\n // width to what they currently are\n\n\n _fnApplyToChildren(function (nSizer, i) {\n nSizer.innerHTML = '
' + headerContent[i] + '
';\n nSizer.childNodes[0].style.height = \"0\";\n nSizer.childNodes[0].style.overflow = \"hidden\";\n nSizer.style.width = headerWidths[i];\n }, headerSrcEls);\n\n if (footer) {\n _fnApplyToChildren(function (nSizer, i) {\n nSizer.innerHTML = '
' + footerContent[i] + '
';\n nSizer.childNodes[0].style.height = \"0\";\n nSizer.childNodes[0].style.overflow = \"hidden\";\n nSizer.style.width = footerWidths[i];\n }, footerSrcEls);\n } // Sanity check that the table is of a sensible width. If not then we are going to get\n // misalignment - try to prevent this by not allowing the table to shrink below its min width\n\n\n if (table.outerWidth() < sanityWidth) {\n // The min width depends upon if we have a vertical scrollbar visible or not */\n correction = divBodyEl.scrollHeight > divBodyEl.offsetHeight || divBody.css('overflow-y') == \"scroll\" ? sanityWidth + barWidth : sanityWidth; // IE6/7 are a law unto themselves...\n\n if (ie67 && (divBodyEl.scrollHeight > divBodyEl.offsetHeight || divBody.css('overflow-y') == \"scroll\")) {\n tableStyle.width = _fnStringToCss(correction - barWidth);\n } // And give the user a warning that we've stopped the table getting too small\n\n\n if (scrollX === \"\" || scrollXInner !== \"\") {\n _fnLog(settings, 1, 'Possible column misalignment', 6);\n }\n } else {\n correction = '100%';\n } // Apply to the container elements\n\n\n divBodyStyle.width = _fnStringToCss(correction);\n divHeaderStyle.width = _fnStringToCss(correction);\n\n if (footer) {\n settings.nScrollFoot.style.width = _fnStringToCss(correction);\n }\n /*\n * 4. Clean up\n */\n\n\n if (!scrollY) {\n /* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting\n * the scrollbar height from the visible display, rather than adding it on. We need to\n * set the height in order to sort this. Don't want to do it in any other browsers.\n */\n if (ie67) {\n divBodyStyle.height = _fnStringToCss(tableEl.offsetHeight + barWidth);\n }\n }\n /* Finally set the width's of the header and footer tables */\n\n\n var iOuterWidth = table.outerWidth();\n divHeaderTable[0].style.width = _fnStringToCss(iOuterWidth);\n divHeaderInnerStyle.width = _fnStringToCss(iOuterWidth); // Figure out if there are scrollbar present - if so then we need a the header and footer to\n // provide a bit more space to allow \"overflow\" scrolling (i.e. past the scrollbar)\n\n var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == \"scroll\";\n var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right');\n divHeaderInnerStyle[padding] = bScrolling ? barWidth + \"px\" : \"0px\";\n\n if (footer) {\n divFooterTable[0].style.width = _fnStringToCss(iOuterWidth);\n divFooterInner[0].style.width = _fnStringToCss(iOuterWidth);\n divFooterInner[0].style[padding] = bScrolling ? barWidth + \"px\" : \"0px\";\n } // Correct DOM ordering for colgroup - comes before the thead\n\n\n table.children('colgroup').insertBefore(table.children('thead'));\n /* Adjust the position of the header in case we loose the y-scrollbar */\n\n divBody.scroll(); // If sorting or filtering has occurred, jump the scrolling back to the top\n // only if we aren't holding the position\n\n if ((settings.bSorted || settings.bFiltered) && !settings._drawHold) {\n divBodyEl.scrollTop = 0;\n }\n }\n /**\n * Apply a given function to the display child nodes of an element array (typically\n * TD children of TR rows\n * @param {function} fn Method to apply to the objects\n * @param array {nodes} an1 List of elements to look through for display children\n * @param array {nodes} an2 Another list (identical structure to the first) - optional\n * @memberof DataTable#oApi\n */\n\n\n function _fnApplyToChildren(fn, an1, an2) {\n var index = 0,\n i = 0,\n iLen = an1.length;\n var nNode1, nNode2;\n\n while (i < iLen) {\n nNode1 = an1[i].firstChild;\n nNode2 = an2 ? an2[i].firstChild : null;\n\n while (nNode1) {\n if (nNode1.nodeType === 1) {\n if (an2) {\n fn(nNode1, nNode2, index);\n } else {\n fn(nNode1, index);\n }\n\n index++;\n }\n\n nNode1 = nNode1.nextSibling;\n nNode2 = an2 ? nNode2.nextSibling : null;\n }\n\n i++;\n }\n }\n\n var __re_html_remove = /<.*?>/g;\n /**\n * Calculate the width of columns for the table\n * @param {object} oSettings dataTables settings object\n * @memberof DataTable#oApi\n */\n\n function _fnCalculateColumnWidths(oSettings) {\n var table = oSettings.nTable,\n columns = oSettings.aoColumns,\n scroll = oSettings.oScroll,\n scrollY = scroll.sY,\n scrollX = scroll.sX,\n scrollXInner = scroll.sXInner,\n columnCount = columns.length,\n visibleColumns = _fnGetColumns(oSettings, 'bVisible'),\n headerCells = $('th', oSettings.nTHead),\n tableWidthAttr = table.getAttribute('width'),\n // from DOM element\n tableContainer = table.parentNode,\n userInputs = false,\n i,\n column,\n columnIdx,\n width,\n outerWidth,\n browser = oSettings.oBrowser,\n ie67 = browser.bScrollOversize;\n\n var styleWidth = table.style.width;\n\n if (styleWidth && styleWidth.indexOf('%') !== -1) {\n tableWidthAttr = styleWidth;\n }\n /* Convert any user input sizes into pixel sizes */\n\n\n for (i = 0; i < visibleColumns.length; i++) {\n column = columns[visibleColumns[i]];\n\n if (column.sWidth !== null) {\n column.sWidth = _fnConvertToWidth(column.sWidthOrig, tableContainer);\n userInputs = true;\n }\n }\n /* If the number of columns in the DOM equals the number that we have to\n * process in DataTables, then we can use the offsets that are created by\n * the web- browser. No custom sizes can be set in order for this to happen,\n * nor scrolling used\n */\n\n\n if (ie67 || !userInputs && !scrollX && !scrollY && columnCount == _fnVisbleColumns(oSettings) && columnCount == headerCells.length) {\n for (i = 0; i < columnCount; i++) {\n var colIdx = _fnVisibleToColumnIndex(oSettings, i);\n\n if (colIdx !== null) {\n columns[colIdx].sWidth = _fnStringToCss(headerCells.eq(i).width());\n }\n }\n } else {\n // Otherwise construct a single row, worst case, table with the widest\n // node in the data, assign any user defined widths, then insert it into\n // the DOM and allow the browser to do all the hard work of calculating\n // table widths\n var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table\n .css('visibility', 'hidden').removeAttr('id'); // Clean up the table body\n\n tmpTable.find('tbody tr').remove();\n var tr = $('
').appendTo(tmpTable.find('tbody')); // Clone the table header and footer - we can't use the header / footer\n // from the cloned table, since if scrolling is active, the table's\n // real header and footer are contained in different table tags\n\n tmpTable.find('thead, tfoot').remove();\n tmpTable.append($(oSettings.nTHead).clone()).append($(oSettings.nTFoot).clone()); // Remove any assigned widths from the footer (from scrolling)\n\n tmpTable.find('tfoot th, tfoot td').css('width', ''); // Apply custom sizing to the cloned header\n\n headerCells = _fnGetUniqueThs(oSettings, tmpTable.find('thead')[0]);\n\n for (i = 0; i < visibleColumns.length; i++) {\n column = columns[visibleColumns[i]];\n headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ? _fnStringToCss(column.sWidthOrig) : ''; // For scrollX we need to force the column width otherwise the\n // browser will collapse it. If this width is smaller than the\n // width the column requires, then it will have no effect\n\n if (column.sWidthOrig && scrollX) {\n $(headerCells[i]).append($('
').css({\n width: column.sWidthOrig,\n margin: 0,\n padding: 0,\n border: 0,\n height: 1\n }));\n }\n } // Find the widest cell for each column and put it into the table\n\n\n if (oSettings.aoData.length) {\n for (i = 0; i < visibleColumns.length; i++) {\n columnIdx = visibleColumns[i];\n column = columns[columnIdx];\n $(_fnGetWidestNode(oSettings, columnIdx)).clone(false).append(column.sContentPadding).appendTo(tr);\n }\n } // Tidy the temporary table - remove name attributes so there aren't\n // duplicated in the dom (radio elements for example)\n\n\n $('[name]', tmpTable).removeAttr('name'); // Table has been built, attach to the document so we can work with it.\n // A holding element is used, positioned at the top of the container\n // with minimal height, so it has no effect on if the container scrolls\n // or not. Otherwise it might trigger scrolling when it actually isn't\n // needed\n\n var holder = $('
').css(scrollX || scrollY ? {\n position: 'absolute',\n top: 0,\n left: 0,\n height: 1,\n right: 0,\n overflow: 'hidden'\n } : {}).append(tmpTable).appendTo(tableContainer); // When scrolling (X or Y) we want to set the width of the table as \n // appropriate. However, when not scrolling leave the table width as it\n // is. This results in slightly different, but I think correct behaviour\n\n if (scrollX && scrollXInner) {\n tmpTable.width(scrollXInner);\n } else if (scrollX) {\n tmpTable.css('width', 'auto');\n tmpTable.removeAttr('width'); // If there is no width attribute or style, then allow the table to\n // collapse\n\n if (tmpTable.width() < tableContainer.clientWidth && tableWidthAttr) {\n tmpTable.width(tableContainer.clientWidth);\n }\n } else if (scrollY) {\n tmpTable.width(tableContainer.clientWidth);\n } else if (tableWidthAttr) {\n tmpTable.width(tableWidthAttr);\n } // Get the width of each column in the constructed table - we need to\n // know the inner width (so it can be assigned to the other table's\n // cells) and the outer width so we can calculate the full width of the\n // table. This is safe since DataTables requires a unique cell for each\n // column, but if ever a header can span multiple columns, this will\n // need to be modified.\n\n\n var total = 0;\n\n for (i = 0; i < visibleColumns.length; i++) {\n var cell = $(headerCells[i]);\n var border = cell.outerWidth() - cell.width(); // Use getBounding... where possible (not IE8-) because it can give\n // sub-pixel accuracy, which we then want to round up!\n\n var bounding = browser.bBounding ? Math.ceil(headerCells[i].getBoundingClientRect().width) : cell.outerWidth(); // Total is tracked to remove any sub-pixel errors as the outerWidth\n // of the table might not equal the total given here (IE!).\n\n total += bounding; // Width for each column to use\n\n columns[visibleColumns[i]].sWidth = _fnStringToCss(bounding - border);\n }\n\n table.style.width = _fnStringToCss(total); // Finished with the table - ditch it\n\n holder.remove();\n } // If there is a width attr, we want to attach an event listener which\n // allows the table sizing to automatically adjust when the window is\n // resized. Use the width attr rather than CSS, since we can't know if the\n // CSS is a relative value or absolute - DOM read is always px.\n\n\n if (tableWidthAttr) {\n table.style.width = _fnStringToCss(tableWidthAttr);\n }\n\n if ((tableWidthAttr || scrollX) && !oSettings._reszEvt) {\n var bindResize = function bindResize() {\n $(window).on('resize.DT-' + oSettings.sInstance, _fnThrottle(function () {\n _fnAdjustColumnSizing(oSettings);\n }));\n }; // IE6/7 will crash if we bind a resize event handler on page load.\n // To be removed in 1.11 which drops IE6/7 support\n\n\n if (ie67) {\n setTimeout(bindResize, 1000);\n } else {\n bindResize();\n }\n\n oSettings._reszEvt = true;\n }\n }\n /**\n * Throttle the calls to a function. Arguments and context are maintained for\n * the throttled function\n * @param {function} fn Function to be called\n * @param {int} [freq=200] call frequency in mS\n * @returns {function} wrapped function\n * @memberof DataTable#oApi\n */\n\n\n var _fnThrottle = DataTable.util.throttle;\n /**\n * Convert a CSS unit width to pixels (e.g. 2em)\n * @param {string} width width to be converted\n * @param {node} parent parent to get the with for (required for relative widths) - optional\n * @returns {int} width in pixels\n * @memberof DataTable#oApi\n */\n\n function _fnConvertToWidth(width, parent) {\n if (!width) {\n return 0;\n }\n\n var n = $('
').css('width', _fnStringToCss(width)).appendTo(parent || document.body);\n var val = n[0].offsetWidth;\n n.remove();\n return val;\n }\n /**\n * Get the widest node\n * @param {object} settings dataTables settings object\n * @param {int} colIdx column of interest\n * @returns {node} widest table node\n * @memberof DataTable#oApi\n */\n\n\n function _fnGetWidestNode(settings, colIdx) {\n var idx = _fnGetMaxLenString(settings, colIdx);\n\n if (idx < 0) {\n return null;\n }\n\n var data = settings.aoData[idx];\n return !data.nTr ? // Might not have been created when deferred rendering\n $('
').html(_fnGetCellData(settings, idx, colIdx, 'display'))[0] : data.anCells[colIdx];\n }\n /**\n * Get the maximum strlen for each data column\n * @param {object} settings dataTables settings object\n * @param {int} colIdx column of interest\n * @returns {string} max string length for each column\n * @memberof DataTable#oApi\n */\n\n\n function _fnGetMaxLenString(settings, colIdx) {\n var s,\n max = -1,\n maxIdx = -1;\n\n for (var i = 0, ien = settings.aoData.length; i < ien; i++) {\n s = _fnGetCellData(settings, i, colIdx, 'display') + '';\n s = s.replace(__re_html_remove, '');\n s = s.replace(/ /g, ' ');\n\n if (s.length > max) {\n max = s.length;\n maxIdx = i;\n }\n }\n\n return maxIdx;\n }\n /**\n * Append a CSS unit (only if required) to a string\n * @param {string} value to css-ify\n * @returns {string} value with css unit\n * @memberof DataTable#oApi\n */\n\n\n function _fnStringToCss(s) {\n if (s === null) {\n return '0px';\n }\n\n if (typeof s == 'number') {\n return s < 0 ? '0px' : s + 'px';\n } // Check it has a unit character already\n\n\n return s.match(/\\d$/) ? s + 'px' : s;\n }\n\n function _fnSortFlatten(settings) {\n var i,\n iLen,\n k,\n kLen,\n aSort = [],\n aiOrig = [],\n aoColumns = settings.aoColumns,\n aDataSort,\n iCol,\n sType,\n srcCol,\n fixed = settings.aaSortingFixed,\n fixedObj = $.isPlainObject(fixed),\n nestedSort = [],\n add = function add(a) {\n if (a.length && !$.isArray(a[0])) {\n // 1D array\n nestedSort.push(a);\n } else {\n // 2D array\n $.merge(nestedSort, a);\n }\n }; // Build the sort array, with pre-fix and post-fix options if they have been\n // specified\n\n\n if ($.isArray(fixed)) {\n add(fixed);\n }\n\n if (fixedObj && fixed.pre) {\n add(fixed.pre);\n }\n\n add(settings.aaSorting);\n\n if (fixedObj && fixed.post) {\n add(fixed.post);\n }\n\n for (i = 0; i < nestedSort.length; i++) {\n srcCol = nestedSort[i][0];\n aDataSort = aoColumns[srcCol].aDataSort;\n\n for (k = 0, kLen = aDataSort.length; k < kLen; k++) {\n iCol = aDataSort[k];\n sType = aoColumns[iCol].sType || 'string';\n\n if (nestedSort[i]._idx === undefined) {\n nestedSort[i]._idx = $.inArray(nestedSort[i][1], aoColumns[iCol].asSorting);\n }\n\n aSort.push({\n src: srcCol,\n col: iCol,\n dir: nestedSort[i][1],\n index: nestedSort[i]._idx,\n type: sType,\n formatter: DataTable.ext.type.order[sType + \"-pre\"]\n });\n }\n }\n\n return aSort;\n }\n /**\n * Change the order of the table\n * @param {object} oSettings dataTables settings object\n * @memberof DataTable#oApi\n * @todo This really needs split up!\n */\n\n\n function _fnSort(oSettings) {\n var i,\n ien,\n iLen,\n j,\n jLen,\n k,\n kLen,\n sDataType,\n nTh,\n aiOrig = [],\n oExtSort = DataTable.ext.type.order,\n aoData = oSettings.aoData,\n aoColumns = oSettings.aoColumns,\n aDataSort,\n data,\n iCol,\n sType,\n oSort,\n formatters = 0,\n sortCol,\n displayMaster = oSettings.aiDisplayMaster,\n aSort; // Resolve any column types that are unknown due to addition or invalidation\n // @todo Can this be moved into a 'data-ready' handler which is called when\n // data is going to be used in the table?\n\n _fnColumnTypes(oSettings);\n\n aSort = _fnSortFlatten(oSettings);\n\n for (i = 0, ien = aSort.length; i < ien; i++) {\n sortCol = aSort[i]; // Track if we can use the fast sort algorithm\n\n if (sortCol.formatter) {\n formatters++;\n } // Load the data needed for the sort, for each cell\n\n\n _fnSortData(oSettings, sortCol.col);\n }\n /* No sorting required if server-side or no sorting array */\n\n\n if (_fnDataSource(oSettings) != 'ssp' && aSort.length !== 0) {\n // Create a value - key array of the current row positions such that we can use their\n // current position during the sort, if values match, in order to perform stable sorting\n for (i = 0, iLen = displayMaster.length; i < iLen; i++) {\n aiOrig[displayMaster[i]] = i;\n }\n /* Do the sort - here we want multi-column sorting based on a given data source (column)\n * and sorting function (from oSort) in a certain direction. It's reasonably complex to\n * follow on it's own, but this is what we want (example two column sorting):\n * fnLocalSorting = function(a,b){\n * var iTest;\n * iTest = oSort['string-asc']('data11', 'data12');\n * if (iTest !== 0)\n * return iTest;\n * iTest = oSort['numeric-desc']('data21', 'data22');\n * if (iTest !== 0)\n * return iTest;\n * return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );\n * }\n * Basically we have a test for each sorting column, if the data in that column is equal,\n * test the next column. If all columns match, then we use a numeric sort on the row\n * positions in the original data array to provide a stable sort.\n *\n * Note - I know it seems excessive to have two sorting methods, but the first is around\n * 15% faster, so the second is only maintained for backwards compatibility with sorting\n * methods which do not have a pre-sort formatting function.\n */\n\n\n if (formatters === aSort.length) {\n // All sort types have formatting functions\n displayMaster.sort(function (a, b) {\n var x,\n y,\n k,\n test,\n sort,\n len = aSort.length,\n dataA = aoData[a]._aSortData,\n dataB = aoData[b]._aSortData;\n\n for (k = 0; k < len; k++) {\n sort = aSort[k];\n x = dataA[sort.col];\n y = dataB[sort.col];\n test = x < y ? -1 : x > y ? 1 : 0;\n\n if (test !== 0) {\n return sort.dir === 'asc' ? test : -test;\n }\n }\n\n x = aiOrig[a];\n y = aiOrig[b];\n return x < y ? -1 : x > y ? 1 : 0;\n });\n } else {\n // Depreciated - remove in 1.11 (providing a plug-in option)\n // Not all sort types have formatting methods, so we have to call their sorting\n // methods.\n displayMaster.sort(function (a, b) {\n var x,\n y,\n k,\n l,\n test,\n sort,\n fn,\n len = aSort.length,\n dataA = aoData[a]._aSortData,\n dataB = aoData[b]._aSortData;\n\n for (k = 0; k < len; k++) {\n sort = aSort[k];\n x = dataA[sort.col];\n y = dataB[sort.col];\n fn = oExtSort[sort.type + \"-\" + sort.dir] || oExtSort[\"string-\" + sort.dir];\n test = fn(x, y);\n\n if (test !== 0) {\n return test;\n }\n }\n\n x = aiOrig[a];\n y = aiOrig[b];\n return x < y ? -1 : x > y ? 1 : 0;\n });\n }\n }\n /* Tell the draw function that we have sorted the data */\n\n\n oSettings.bSorted = true;\n }\n\n function _fnSortAria(settings) {\n var label;\n var nextSort;\n var columns = settings.aoColumns;\n\n var aSort = _fnSortFlatten(settings);\n\n var oAria = settings.oLanguage.oAria; // ARIA attributes - need to loop all columns, to update all (removing old\n // attributes as needed)\n\n for (var i = 0, iLen = columns.length; i < iLen; i++) {\n var col = columns[i];\n var asSorting = col.asSorting;\n var sTitle = col.sTitle.replace(/<.*?>/g, \"\");\n var th = col.nTh; // IE7 is throwing an error when setting these properties with jQuery's\n // attr() and removeAttr() methods...\n\n th.removeAttribute('aria-sort');\n /* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */\n\n if (col.bSortable) {\n if (aSort.length > 0 && aSort[0].col == i) {\n th.setAttribute('aria-sort', aSort[0].dir == \"asc\" ? \"ascending\" : \"descending\");\n nextSort = asSorting[aSort[0].index + 1] || asSorting[0];\n } else {\n nextSort = asSorting[0];\n }\n\n label = sTitle + (nextSort === \"asc\" ? oAria.sSortAscending : oAria.sSortDescending);\n } else {\n label = sTitle;\n }\n\n th.setAttribute('aria-label', label);\n }\n }\n /**\n * Function to run on user sort request\n * @param {object} settings dataTables settings object\n * @param {node} attachTo node to attach the handler to\n * @param {int} colIdx column sorting index\n * @param {boolean} [append=false] Append the requested sort to the existing\n * sort if true (i.e. multi-column sort)\n * @param {function} [callback] callback function\n * @memberof DataTable#oApi\n */\n\n\n function _fnSortListener(settings, colIdx, append, callback) {\n var col = settings.aoColumns[colIdx];\n var sorting = settings.aaSorting;\n var asSorting = col.asSorting;\n var nextSortIdx;\n\n var next = function next(a, overflow) {\n var idx = a._idx;\n\n if (idx === undefined) {\n idx = $.inArray(a[1], asSorting);\n }\n\n return idx + 1 < asSorting.length ? idx + 1 : overflow ? null : 0;\n }; // Convert to 2D array if needed\n\n\n if (typeof sorting[0] === 'number') {\n sorting = settings.aaSorting = [sorting];\n } // If appending the sort then we are multi-column sorting\n\n\n if (append && settings.oFeatures.bSortMulti) {\n // Are we already doing some kind of sort on this column?\n var sortIdx = $.inArray(colIdx, _pluck(sorting, '0'));\n\n if (sortIdx !== -1) {\n // Yes, modify the sort\n nextSortIdx = next(sorting[sortIdx], true);\n\n if (nextSortIdx === null && sorting.length === 1) {\n nextSortIdx = 0; // can't remove sorting completely\n }\n\n if (nextSortIdx === null) {\n sorting.splice(sortIdx, 1);\n } else {\n sorting[sortIdx][1] = asSorting[nextSortIdx];\n sorting[sortIdx]._idx = nextSortIdx;\n }\n } else {\n // No sort on this column yet\n sorting.push([colIdx, asSorting[0], 0]);\n sorting[sorting.length - 1]._idx = 0;\n }\n } else if (sorting.length && sorting[0][0] == colIdx) {\n // Single column - already sorting on this column, modify the sort\n nextSortIdx = next(sorting[0]);\n sorting.length = 1;\n sorting[0][1] = asSorting[nextSortIdx];\n sorting[0]._idx = nextSortIdx;\n } else {\n // Single column - sort only on this column\n sorting.length = 0;\n sorting.push([colIdx, asSorting[0]]);\n sorting[0]._idx = 0;\n } // Run the sort by calling a full redraw\n\n\n _fnReDraw(settings); // callback used for async user interaction\n\n\n if (typeof callback == 'function') {\n callback(settings);\n }\n }\n /**\n * Attach a sort handler (click) to a node\n * @param {object} settings dataTables settings object\n * @param {node} attachTo node to attach the handler to\n * @param {int} colIdx column sorting index\n * @param {function} [callback] callback function\n * @memberof DataTable#oApi\n */\n\n\n function _fnSortAttachListener(settings, attachTo, colIdx, callback) {\n var col = settings.aoColumns[colIdx];\n\n _fnBindAction(attachTo, {}, function (e) {\n /* If the column is not sortable - don't to anything */\n if (col.bSortable === false) {\n return;\n } // If processing is enabled use a timeout to allow the processing\n // display to be shown - otherwise to it synchronously\n\n\n if (settings.oFeatures.bProcessing) {\n _fnProcessingDisplay(settings, true);\n\n setTimeout(function () {\n _fnSortListener(settings, colIdx, e.shiftKey, callback); // In server-side processing, the draw callback will remove the\n // processing display\n\n\n if (_fnDataSource(settings) !== 'ssp') {\n _fnProcessingDisplay(settings, false);\n }\n }, 0);\n } else {\n _fnSortListener(settings, colIdx, e.shiftKey, callback);\n }\n });\n }\n /**\n * Set the sorting classes on table's body, Note: it is safe to call this function\n * when bSort and bSortClasses are false\n * @param {object} oSettings dataTables settings object\n * @memberof DataTable#oApi\n */\n\n\n function _fnSortingClasses(settings) {\n var oldSort = settings.aLastSort;\n var sortClass = settings.oClasses.sSortColumn;\n\n var sort = _fnSortFlatten(settings);\n\n var features = settings.oFeatures;\n var i, ien, colIdx;\n\n if (features.bSort && features.bSortClasses) {\n // Remove old sorting classes\n for (i = 0, ien = oldSort.length; i < ien; i++) {\n colIdx = oldSort[i].src; // Remove column sorting\n\n $(_pluck(settings.aoData, 'anCells', colIdx)).removeClass(sortClass + (i < 2 ? i + 1 : 3));\n } // Add new column sorting\n\n\n for (i = 0, ien = sort.length; i < ien; i++) {\n colIdx = sort[i].src;\n $(_pluck(settings.aoData, 'anCells', colIdx)).addClass(sortClass + (i < 2 ? i + 1 : 3));\n }\n }\n\n settings.aLastSort = sort;\n } // Get the data to sort a column, be it from cache, fresh (populating the\n // cache), or from a sort formatter\n\n\n function _fnSortData(settings, idx) {\n // Custom sorting function - provided by the sort data type\n var column = settings.aoColumns[idx];\n var customSort = DataTable.ext.order[column.sSortDataType];\n var customData;\n\n if (customSort) {\n customData = customSort.call(settings.oInstance, settings, idx, _fnColumnIndexToVisible(settings, idx));\n } // Use / populate cache\n\n\n var row, cellData;\n var formatter = DataTable.ext.type.order[column.sType + \"-pre\"];\n\n for (var i = 0, ien = settings.aoData.length; i < ien; i++) {\n row = settings.aoData[i];\n\n if (!row._aSortData) {\n row._aSortData = [];\n }\n\n if (!row._aSortData[idx] || customSort) {\n cellData = customSort ? customData[i] : // If there was a custom sort function, use data from there\n _fnGetCellData(settings, i, idx, 'sort');\n row._aSortData[idx] = formatter ? formatter(cellData) : cellData;\n }\n }\n }\n /**\n * Save the state of a table\n * @param {object} oSettings dataTables settings object\n * @memberof DataTable#oApi\n */\n\n\n function _fnSaveState(settings) {\n if (!settings.oFeatures.bStateSave || settings.bDestroying) {\n return;\n }\n /* Store the interesting variables */\n\n\n var state = {\n time: +new Date(),\n start: settings._iDisplayStart,\n length: settings._iDisplayLength,\n order: $.extend(true, [], settings.aaSorting),\n search: _fnSearchToCamel(settings.oPreviousSearch),\n columns: $.map(settings.aoColumns, function (col, i) {\n return {\n visible: col.bVisible,\n search: _fnSearchToCamel(settings.aoPreSearchCols[i])\n };\n })\n };\n\n _fnCallbackFire(settings, \"aoStateSaveParams\", 'stateSaveParams', [settings, state]);\n\n settings.oSavedState = state;\n settings.fnStateSaveCallback.call(settings.oInstance, settings, state);\n }\n /**\n * Attempt to load a saved table state\n * @param {object} oSettings dataTables settings object\n * @param {object} oInit DataTables init object so we can override settings\n * @param {function} callback Callback to execute when the state has been loaded\n * @memberof DataTable#oApi\n */\n\n\n function _fnLoadState(settings, oInit, callback) {\n var i, ien;\n var columns = settings.aoColumns;\n\n var loaded = function loaded(s) {\n if (!s || !s.time) {\n callback();\n return;\n } // Allow custom and plug-in manipulation functions to alter the saved data set and\n // cancelling of loading by returning false\n\n\n var abStateLoad = _fnCallbackFire(settings, 'aoStateLoadParams', 'stateLoadParams', [settings, s]);\n\n if ($.inArray(false, abStateLoad) !== -1) {\n callback();\n return;\n } // Reject old data\n\n\n var duration = settings.iStateDuration;\n\n if (duration > 0 && s.time < +new Date() - duration * 1000) {\n callback();\n return;\n } // Number of columns have changed - all bets are off, no restore of settings\n\n\n if (s.columns && columns.length !== s.columns.length) {\n callback();\n return;\n } // Store the saved state so it might be accessed at any time\n\n\n settings.oLoadedState = $.extend(true, {}, s); // Restore key features - todo - for 1.11 this needs to be done by\n // subscribed events\n\n if (s.start !== undefined) {\n settings._iDisplayStart = s.start;\n settings.iInitDisplayStart = s.start;\n }\n\n if (s.length !== undefined) {\n settings._iDisplayLength = s.length;\n } // Order\n\n\n if (s.order !== undefined) {\n settings.aaSorting = [];\n $.each(s.order, function (i, col) {\n settings.aaSorting.push(col[0] >= columns.length ? [0, col[1]] : col);\n });\n } // Search\n\n\n if (s.search !== undefined) {\n $.extend(settings.oPreviousSearch, _fnSearchToHung(s.search));\n } // Columns\n //\n\n\n if (s.columns) {\n for (i = 0, ien = s.columns.length; i < ien; i++) {\n var col = s.columns[i]; // Visibility\n\n if (col.visible !== undefined) {\n columns[i].bVisible = col.visible;\n } // Search\n\n\n if (col.search !== undefined) {\n $.extend(settings.aoPreSearchCols[i], _fnSearchToHung(col.search));\n }\n }\n }\n\n _fnCallbackFire(settings, 'aoStateLoaded', 'stateLoaded', [settings, s]);\n\n callback();\n };\n\n if (!settings.oFeatures.bStateSave) {\n callback();\n return;\n }\n\n var state = settings.fnStateLoadCallback.call(settings.oInstance, settings, loaded);\n\n if (state !== undefined) {\n loaded(state);\n } // otherwise, wait for the loaded callback to be executed\n\n }\n /**\n * Return the settings object for a particular table\n * @param {node} table table we are using as a dataTable\n * @returns {object} Settings object - or null if not found\n * @memberof DataTable#oApi\n */\n\n\n function _fnSettingsFromNode(table) {\n var settings = DataTable.settings;\n var idx = $.inArray(table, _pluck(settings, 'nTable'));\n return idx !== -1 ? settings[idx] : null;\n }\n /**\n * Log an error message\n * @param {object} settings dataTables settings object\n * @param {int} level log error messages, or display them to the user\n * @param {string} msg error message\n * @param {int} tn Technical note id to get more information about the error.\n * @memberof DataTable#oApi\n */\n\n\n function _fnLog(settings, level, msg, tn) {\n msg = 'DataTables warning: ' + (settings ? 'table id=' + settings.sTableId + ' - ' : '') + msg;\n\n if (tn) {\n msg += '. For more information about this error, please see ' + 'http://datatables.net/tn/' + tn;\n }\n\n if (!level) {\n // Backwards compatibility pre 1.10\n var ext = DataTable.ext;\n var type = ext.sErrMode || ext.errMode;\n\n if (settings) {\n _fnCallbackFire(settings, null, 'error', [settings, tn, msg]);\n }\n\n if (type == 'alert') {\n alert(msg);\n } else if (type == 'throw') {\n throw new Error(msg);\n } else if (typeof type == 'function') {\n type(settings, tn, msg);\n }\n } else if (window.console && console.log) {\n console.log(msg);\n }\n }\n /**\n * See if a property is defined on one object, if so assign it to the other object\n * @param {object} ret target object\n * @param {object} src source object\n * @param {string} name property\n * @param {string} [mappedName] name to map too - optional, name used if not given\n * @memberof DataTable#oApi\n */\n\n\n function _fnMap(ret, src, name, mappedName) {\n if ($.isArray(name)) {\n $.each(name, function (i, val) {\n if ($.isArray(val)) {\n _fnMap(ret, src, val[0], val[1]);\n } else {\n _fnMap(ret, src, val);\n }\n });\n return;\n }\n\n if (mappedName === undefined) {\n mappedName = name;\n }\n\n if (src[name] !== undefined) {\n ret[mappedName] = src[name];\n }\n }\n /**\n * Extend objects - very similar to jQuery.extend, but deep copy objects, and\n * shallow copy arrays. The reason we need to do this, is that we don't want to\n * deep copy array init values (such as aaSorting) since the dev wouldn't be\n * able to override them, but we do want to deep copy arrays.\n * @param {object} out Object to extend\n * @param {object} extender Object from which the properties will be applied to\n * out\n * @param {boolean} breakRefs If true, then arrays will be sliced to take an\n * independent copy with the exception of the `data` or `aaData` parameters\n * if they are present. This is so you can pass in a collection to\n * DataTables and have that used as your data source without breaking the\n * references\n * @returns {object} out Reference, just for convenience - out === the return.\n * @memberof DataTable#oApi\n * @todo This doesn't take account of arrays inside the deep copied objects.\n */\n\n\n function _fnExtend(out, extender, breakRefs) {\n var val;\n\n for (var prop in extender) {\n if (extender.hasOwnProperty(prop)) {\n val = extender[prop];\n\n if ($.isPlainObject(val)) {\n if (!$.isPlainObject(out[prop])) {\n out[prop] = {};\n }\n\n $.extend(true, out[prop], val);\n } else if (breakRefs && prop !== 'data' && prop !== 'aaData' && $.isArray(val)) {\n out[prop] = val.slice();\n } else {\n out[prop] = val;\n }\n }\n }\n\n return out;\n }\n /**\n * Bind an event handers to allow a click or return key to activate the callback.\n * This is good for accessibility since a return on the keyboard will have the\n * same effect as a click, if the element has focus.\n * @param {element} n Element to bind the action to\n * @param {object} oData Data object to pass to the triggered function\n * @param {function} fn Callback function for when the event is triggered\n * @memberof DataTable#oApi\n */\n\n\n function _fnBindAction(n, oData, fn) {\n $(n).on('click.DT', oData, function (e) {\n $(n).blur(); // Remove focus outline for mouse users\n\n fn(e);\n }).on('keypress.DT', oData, function (e) {\n if (e.which === 13) {\n e.preventDefault();\n fn(e);\n }\n }).on('selectstart.DT', function () {\n /* Take the brutal approach to cancelling text selection */\n return false;\n });\n }\n /**\n * Register a callback function. Easily allows a callback function to be added to\n * an array store of callback functions that can then all be called together.\n * @param {object} oSettings dataTables settings object\n * @param {string} sStore Name of the array storage for the callbacks in oSettings\n * @param {function} fn Function to be called back\n * @param {string} sName Identifying name for the callback (i.e. a label)\n * @memberof DataTable#oApi\n */\n\n\n function _fnCallbackReg(oSettings, sStore, fn, sName) {\n if (fn) {\n oSettings[sStore].push({\n \"fn\": fn,\n \"sName\": sName\n });\n }\n }\n /**\n * Fire callback functions and trigger events. Note that the loop over the\n * callback array store is done backwards! Further note that you do not want to\n * fire off triggers in time sensitive applications (for example cell creation)\n * as its slow.\n * @param {object} settings dataTables settings object\n * @param {string} callbackArr Name of the array storage for the callbacks in\n * oSettings\n * @param {string} eventName Name of the jQuery custom event to trigger. If\n * null no trigger is fired\n * @param {array} args Array of arguments to pass to the callback function /\n * trigger\n * @memberof DataTable#oApi\n */\n\n\n function _fnCallbackFire(settings, callbackArr, eventName, args) {\n var ret = [];\n\n if (callbackArr) {\n ret = $.map(settings[callbackArr].slice().reverse(), function (val, i) {\n return val.fn.apply(settings.oInstance, args);\n });\n }\n\n if (eventName !== null) {\n var e = $.Event(eventName + '.dt');\n $(settings.nTable).trigger(e, args);\n ret.push(e.result);\n }\n\n return ret;\n }\n\n function _fnLengthOverflow(settings) {\n var start = settings._iDisplayStart,\n end = settings.fnDisplayEnd(),\n len = settings._iDisplayLength;\n /* If we have space to show extra rows (backing up from the end point - then do so */\n\n if (start >= end) {\n start = end - len;\n } // Keep the start record on the current page\n\n\n start -= start % len;\n\n if (len === -1 || start < 0) {\n start = 0;\n }\n\n settings._iDisplayStart = start;\n }\n\n function _fnRenderer(settings, type) {\n var renderer = settings.renderer;\n var host = DataTable.ext.renderer[type];\n\n if ($.isPlainObject(renderer) && renderer[type]) {\n // Specific renderer for this type. If available use it, otherwise use\n // the default.\n return host[renderer[type]] || host._;\n } else if (typeof renderer === 'string') {\n // Common renderer - if there is one available for this type use it,\n // otherwise use the default\n return host[renderer] || host._;\n } // Use the default\n\n\n return host._;\n }\n /**\n * Detect the data source being used for the table. Used to simplify the code\n * a little (ajax) and to make it compress a little smaller.\n *\n * @param {object} settings dataTables settings object\n * @returns {string} Data source\n * @memberof DataTable#oApi\n */\n\n\n function _fnDataSource(settings) {\n if (settings.oFeatures.bServerSide) {\n return 'ssp';\n } else if (settings.ajax || settings.sAjaxSource) {\n return 'ajax';\n }\n\n return 'dom';\n }\n /**\n * Computed structure of the DataTables API, defined by the options passed to\n * `DataTable.Api.register()` when building the API.\n *\n * The structure is built in order to speed creation and extension of the Api\n * objects since the extensions are effectively pre-parsed.\n *\n * The array is an array of objects with the following structure, where this\n * base array represents the Api prototype base:\n *\n * [\n * {\n * name: 'data' -- string - Property name\n * val: function () {}, -- function - Api method (or undefined if just an object\n * methodExt: [ ... ], -- array - Array of Api object definitions to extend the method result\n * propExt: [ ... ] -- array - Array of Api object definitions to extend the property\n * },\n * {\n * name: 'row'\n * val: {},\n * methodExt: [ ... ],\n * propExt: [\n * {\n * name: 'data'\n * val: function () {},\n * methodExt: [ ... ],\n * propExt: [ ... ]\n * },\n * ...\n * ]\n * }\n * ]\n *\n * @type {Array}\n * @ignore\n */\n\n\n var __apiStruct = [];\n /**\n * `Array.prototype` reference.\n *\n * @type object\n * @ignore\n */\n\n var __arrayProto = Array.prototype;\n /**\n * Abstraction for `context` parameter of the `Api` constructor to allow it to\n * take several different forms for ease of use.\n *\n * Each of the input parameter types will be converted to a DataTables settings\n * object where possible.\n *\n * @param {string|node|jQuery|object} mixed DataTable identifier. Can be one\n * of:\n *\n * * `string` - jQuery selector. Any DataTables' matching the given selector\n * with be found and used.\n * * `node` - `TABLE` node which has already been formed into a DataTable.\n * * `jQuery` - A jQuery object of `TABLE` nodes.\n * * `object` - DataTables settings object\n * * `DataTables.Api` - API instance\n * @return {array|null} Matching DataTables settings objects. `null` or\n * `undefined` is returned if no matching DataTable is found.\n * @ignore\n */\n\n var _toSettings = function _toSettings(mixed) {\n var idx, jq;\n var settings = DataTable.settings;\n var tables = $.map(settings, function (el, i) {\n return el.nTable;\n });\n\n if (!mixed) {\n return [];\n } else if (mixed.nTable && mixed.oApi) {\n // DataTables settings object\n return [mixed];\n } else if (mixed.nodeName && mixed.nodeName.toLowerCase() === 'table') {\n // Table node\n idx = $.inArray(mixed, tables);\n return idx !== -1 ? [settings[idx]] : null;\n } else if (mixed && typeof mixed.settings === 'function') {\n return mixed.settings().toArray();\n } else if (typeof mixed === 'string') {\n // jQuery selector\n jq = $(mixed);\n } else if (mixed instanceof $) {\n // jQuery object (also DataTables instance)\n jq = mixed;\n }\n\n if (jq) {\n return jq.map(function (i) {\n idx = $.inArray(this, tables);\n return idx !== -1 ? settings[idx] : null;\n }).toArray();\n }\n };\n /**\n * DataTables API class - used to control and interface with one or more\n * DataTables enhanced tables.\n *\n * The API class is heavily based on jQuery, presenting a chainable interface\n * that you can use to interact with tables. Each instance of the API class has\n * a \"context\" - i.e. the tables that it will operate on. This could be a single\n * table, all tables on a page or a sub-set thereof.\n *\n * Additionally the API is designed to allow you to easily work with the data in\n * the tables, retrieving and manipulating it as required. This is done by\n * presenting the API class as an array like interface. The contents of the\n * array depend upon the actions requested by each method (for example\n * `rows().nodes()` will return an array of nodes, while `rows().data()` will\n * return an array of objects or arrays depending upon your table's\n * configuration). The API object has a number of array like methods (`push`,\n * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`,\n * `unique` etc) to assist your working with the data held in a table.\n *\n * Most methods (those which return an Api instance) are chainable, which means\n * the return from a method call also has all of the methods available that the\n * top level object had. For example, these two calls are equivalent:\n *\n * // Not chained\n * api.row.add( {...} );\n * api.draw();\n *\n * // Chained\n * api.row.add( {...} ).draw();\n *\n * @class DataTable.Api\n * @param {array|object|string|jQuery} context DataTable identifier. This is\n * used to define which DataTables enhanced tables this API will operate on.\n * Can be one of:\n *\n * * `string` - jQuery selector. Any DataTables' matching the given selector\n * with be found and used.\n * * `node` - `TABLE` node which has already been formed into a DataTable.\n * * `jQuery` - A jQuery object of `TABLE` nodes.\n * * `object` - DataTables settings object\n * @param {array} [data] Data to initialise the Api instance with.\n *\n * @example\n * // Direct initialisation during DataTables construction\n * var api = $('#example').DataTable();\n *\n * @example\n * // Initialisation using a DataTables jQuery object\n * var api = $('#example').dataTable().api();\n *\n * @example\n * // Initialisation as a constructor\n * var api = new $.fn.DataTable.Api( 'table.dataTable' );\n */\n\n\n _Api2 = function _Api(context, data) {\n if (!(this instanceof _Api2)) {\n return new _Api2(context, data);\n }\n\n var settings = [];\n\n var ctxSettings = function ctxSettings(o) {\n var a = _toSettings(o);\n\n if (a) {\n settings = settings.concat(a);\n }\n };\n\n if ($.isArray(context)) {\n for (var i = 0, ien = context.length; i < ien; i++) {\n ctxSettings(context[i]);\n }\n } else {\n ctxSettings(context);\n } // Remove duplicates\n\n\n this.context = _unique(settings); // Initial data\n\n if (data) {\n $.merge(this, data);\n } // selector\n\n\n this.selector = {\n rows: null,\n cols: null,\n opts: null\n };\n\n _Api2.extend(this, this, __apiStruct);\n };\n\n DataTable.Api = _Api2; // Don't destroy the existing prototype, just extend it. Required for jQuery 2's\n // isPlainObject.\n\n $.extend(_Api2.prototype, {\n any: function any() {\n return this.count() !== 0;\n },\n concat: __arrayProto.concat,\n context: [],\n // array of table settings objects\n count: function count() {\n return this.flatten().length;\n },\n each: function each(fn) {\n for (var i = 0, ien = this.length; i < ien; i++) {\n fn.call(this, this[i], i, this);\n }\n\n return this;\n },\n eq: function eq(idx) {\n var ctx = this.context;\n return ctx.length > idx ? new _Api2(ctx[idx], this[idx]) : null;\n },\n filter: function filter(fn) {\n var a = [];\n\n if (__arrayProto.filter) {\n a = __arrayProto.filter.call(this, fn, this);\n } else {\n // Compatibility for browsers without EMCA-252-5 (JS 1.6)\n for (var i = 0, ien = this.length; i < ien; i++) {\n if (fn.call(this, this[i], i, this)) {\n a.push(this[i]);\n }\n }\n }\n\n return new _Api2(this.context, a);\n },\n flatten: function flatten() {\n var a = [];\n return new _Api2(this.context, a.concat.apply(a, this.toArray()));\n },\n join: __arrayProto.join,\n indexOf: __arrayProto.indexOf || function (obj, start) {\n for (var i = start || 0, ien = this.length; i < ien; i++) {\n if (this[i] === obj) {\n return i;\n }\n }\n\n return -1;\n },\n iterator: function iterator(flatten, type, fn, alwaysNew) {\n var a = [],\n ret,\n i,\n ien,\n j,\n jen,\n context = this.context,\n rows,\n items,\n item,\n selector = this.selector; // Argument shifting\n\n if (typeof flatten === 'string') {\n alwaysNew = fn;\n fn = type;\n type = flatten;\n flatten = false;\n }\n\n for (i = 0, ien = context.length; i < ien; i++) {\n var apiInst = new _Api2(context[i]);\n\n if (type === 'table') {\n ret = fn.call(apiInst, context[i], i);\n\n if (ret !== undefined) {\n a.push(ret);\n }\n } else if (type === 'columns' || type === 'rows') {\n // this has same length as context - one entry for each table\n ret = fn.call(apiInst, context[i], this[i], i);\n\n if (ret !== undefined) {\n a.push(ret);\n }\n } else if (type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell') {\n // columns and rows share the same structure.\n // 'this' is an array of column indexes for each context\n items = this[i];\n\n if (type === 'column-rows') {\n rows = _selector_row_indexes(context[i], selector.opts);\n }\n\n for (j = 0, jen = items.length; j < jen; j++) {\n item = items[j];\n\n if (type === 'cell') {\n ret = fn.call(apiInst, context[i], item.row, item.column, i, j);\n } else {\n ret = fn.call(apiInst, context[i], item, i, j, rows);\n }\n\n if (ret !== undefined) {\n a.push(ret);\n }\n }\n }\n }\n\n if (a.length || alwaysNew) {\n var api = new _Api2(context, flatten ? a.concat.apply([], a) : a);\n var apiSelector = api.selector;\n apiSelector.rows = selector.rows;\n apiSelector.cols = selector.cols;\n apiSelector.opts = selector.opts;\n return api;\n }\n\n return this;\n },\n lastIndexOf: __arrayProto.lastIndexOf || function (obj, start) {\n // Bit cheeky...\n return this.indexOf.apply(this.toArray.reverse(), arguments);\n },\n length: 0,\n map: function map(fn) {\n var a = [];\n\n if (__arrayProto.map) {\n a = __arrayProto.map.call(this, fn, this);\n } else {\n // Compatibility for browsers without EMCA-252-5 (JS 1.6)\n for (var i = 0, ien = this.length; i < ien; i++) {\n a.push(fn.call(this, this[i], i));\n }\n }\n\n return new _Api2(this.context, a);\n },\n pluck: function pluck(prop) {\n return this.map(function (el) {\n return el[prop];\n });\n },\n pop: __arrayProto.pop,\n push: __arrayProto.push,\n // Does not return an API instance\n reduce: __arrayProto.reduce || function (fn, init) {\n return _fnReduce(this, fn, init, 0, this.length, 1);\n },\n reduceRight: __arrayProto.reduceRight || function (fn, init) {\n return _fnReduce(this, fn, init, this.length - 1, -1, -1);\n },\n reverse: __arrayProto.reverse,\n // Object with rows, columns and opts\n selector: null,\n shift: __arrayProto.shift,\n slice: function slice() {\n return new _Api2(this.context, this);\n },\n sort: __arrayProto.sort,\n // ? name - order?\n splice: __arrayProto.splice,\n toArray: function toArray() {\n return __arrayProto.slice.call(this);\n },\n to$: function to$() {\n return $(this);\n },\n toJQuery: function toJQuery() {\n return $(this);\n },\n unique: function unique() {\n return new _Api2(this.context, _unique(this));\n },\n unshift: __arrayProto.unshift\n });\n\n _Api2.extend = function (scope, obj, ext) {\n // Only extend API instances and static properties of the API\n if (!ext.length || !obj || !(obj instanceof _Api2) && !obj.__dt_wrapper) {\n return;\n }\n\n var i,\n ien,\n j,\n jen,\n struct,\n inner,\n methodScoping = function methodScoping(scope, fn, struc) {\n return function () {\n var ret = fn.apply(scope, arguments); // Method extension\n\n _Api2.extend(ret, ret, struc.methodExt);\n\n return ret;\n };\n };\n\n for (i = 0, ien = ext.length; i < ien; i++) {\n struct = ext[i]; // Value\n\n obj[struct.name] = typeof struct.val === 'function' ? methodScoping(scope, struct.val, struct) : $.isPlainObject(struct.val) ? {} : struct.val;\n obj[struct.name].__dt_wrapper = true; // Property extension\n\n _Api2.extend(scope, obj[struct.name], struct.propExt);\n }\n }; // @todo - Is there need for an augment function?\n // _Api.augment = function ( inst, name )\n // {\n // \t// Find src object in the structure from the name\n // \tvar parts = name.split('.');\n // \t_Api.extend( inst, obj );\n // };\n // [\n // {\n // name: 'data' -- string - Property name\n // val: function () {}, -- function - Api method (or undefined if just an object\n // methodExt: [ ... ], -- array - Array of Api object definitions to extend the method result\n // propExt: [ ... ] -- array - Array of Api object definitions to extend the property\n // },\n // {\n // name: 'row'\n // val: {},\n // methodExt: [ ... ],\n // propExt: [\n // {\n // name: 'data'\n // val: function () {},\n // methodExt: [ ... ],\n // propExt: [ ... ]\n // },\n // ...\n // ]\n // }\n // ]\n\n\n _Api2.register = _api_register = function _api_register(name, val) {\n if ($.isArray(name)) {\n for (var j = 0, jen = name.length; j < jen; j++) {\n _Api2.register(name[j], val);\n }\n\n return;\n }\n\n var i,\n ien,\n heir = name.split('.'),\n struct = __apiStruct,\n key,\n method;\n\n var find = function find(src, name) {\n for (var i = 0, ien = src.length; i < ien; i++) {\n if (src[i].name === name) {\n return src[i];\n }\n }\n\n return null;\n };\n\n for (i = 0, ien = heir.length; i < ien; i++) {\n method = heir[i].indexOf('()') !== -1;\n key = method ? heir[i].replace('()', '') : heir[i];\n var src = find(struct, key);\n\n if (!src) {\n src = {\n name: key,\n val: {},\n methodExt: [],\n propExt: []\n };\n struct.push(src);\n }\n\n if (i === ien - 1) {\n src.val = val;\n } else {\n struct = method ? src.methodExt : src.propExt;\n }\n }\n };\n\n _Api2.registerPlural = _api_registerPlural = function _api_registerPlural(pluralName, singularName, val) {\n _Api2.register(pluralName, val);\n\n _Api2.register(singularName, function () {\n var ret = val.apply(this, arguments);\n\n if (ret === this) {\n // Returned item is the API instance that was passed in, return it\n return this;\n } else if (ret instanceof _Api2) {\n // New API instance returned, want the value from the first item\n // in the returned array for the singular result.\n return ret.length ? $.isArray(ret[0]) ? new _Api2(ret.context, ret[0]) : // Array results are 'enhanced'\n ret[0] : undefined;\n } // Non-API return - just fire it back\n\n\n return ret;\n });\n };\n /**\n * Selector for HTML tables. Apply the given selector to the give array of\n * DataTables settings objects.\n *\n * @param {string|integer} [selector] jQuery selector string or integer\n * @param {array} Array of DataTables settings objects to be filtered\n * @return {array}\n * @ignore\n */\n\n\n var __table_selector = function __table_selector(selector, a) {\n // Integer is used to pick out a table by index\n if (typeof selector === 'number') {\n return [a[selector]];\n } // Perform a jQuery selector on the table nodes\n\n\n var nodes = $.map(a, function (el, i) {\n return el.nTable;\n });\n return $(nodes).filter(selector).map(function (i) {\n // Need to translate back from the table node to the settings\n var idx = $.inArray(this, nodes);\n return a[idx];\n }).toArray();\n };\n /**\n * Context selector for the API's context (i.e. the tables the API instance\n * refers to.\n *\n * @name DataTable.Api#tables\n * @param {string|integer} [selector] Selector to pick which tables the iterator\n * should operate on. If not given, all tables in the current context are\n * used. This can be given as a jQuery selector (for example `':gt(0)'`) to\n * select multiple tables or as an integer to select a single table.\n * @returns {DataTable.Api} Returns a new API instance if a selector is given.\n */\n\n\n _api_register('tables()', function (selector) {\n // A new instance is created if there was a selector specified\n return selector ? new _Api2(__table_selector(selector, this.context)) : this;\n });\n\n _api_register('table()', function (selector) {\n var tables = this.tables(selector);\n var ctx = tables.context; // Truncate to the first matched table\n\n return ctx.length ? new _Api2(ctx[0]) : tables;\n });\n\n _api_registerPlural('tables().nodes()', 'table().node()', function () {\n return this.iterator('table', function (ctx) {\n return ctx.nTable;\n }, 1);\n });\n\n _api_registerPlural('tables().body()', 'table().body()', function () {\n return this.iterator('table', function (ctx) {\n return ctx.nTBody;\n }, 1);\n });\n\n _api_registerPlural('tables().header()', 'table().header()', function () {\n return this.iterator('table', function (ctx) {\n return ctx.nTHead;\n }, 1);\n });\n\n _api_registerPlural('tables().footer()', 'table().footer()', function () {\n return this.iterator('table', function (ctx) {\n return ctx.nTFoot;\n }, 1);\n });\n\n _api_registerPlural('tables().containers()', 'table().container()', function () {\n return this.iterator('table', function (ctx) {\n return ctx.nTableWrapper;\n }, 1);\n });\n /**\n * Redraw the tables in the current context.\n */\n\n\n _api_register('draw()', function (paging) {\n return this.iterator('table', function (settings) {\n if (paging === 'page') {\n _fnDraw(settings);\n } else {\n if (typeof paging === 'string') {\n paging = paging === 'full-hold' ? false : true;\n }\n\n _fnReDraw(settings, paging === false);\n }\n });\n });\n /**\n * Get the current page index.\n *\n * @return {integer} Current page index (zero based)\n */\n\n /**\n * Set the current page.\n *\n * Note that if you attempt to show a page which does not exist, DataTables will\n * not throw an error, but rather reset the paging.\n *\n * @param {integer|string} action The paging action to take. This can be one of:\n * * `integer` - The page index to jump to\n * * `string` - An action to take:\n * * `first` - Jump to first page.\n * * `next` - Jump to the next page\n * * `previous` - Jump to previous page\n * * `last` - Jump to the last page.\n * @returns {DataTables.Api} this\n */\n\n\n _api_register('page()', function (action) {\n if (action === undefined) {\n return this.page.info().page; // not an expensive call\n } // else, have an action to take on all tables\n\n\n return this.iterator('table', function (settings) {\n _fnPageChange(settings, action);\n });\n });\n /**\n * Paging information for the first table in the current context.\n *\n * If you require paging information for another table, use the `table()` method\n * with a suitable selector.\n *\n * @return {object} Object with the following properties set:\n * * `page` - Current page index (zero based - i.e. the first page is `0`)\n * * `pages` - Total number of pages\n * * `start` - Display index for the first record shown on the current page\n * * `end` - Display index for the last record shown on the current page\n * * `length` - Display length (number of records). Note that generally `start\n * + length = end`, but this is not always true, for example if there are\n * only 2 records to show on the final page, with a length of 10.\n * * `recordsTotal` - Full data set length\n * * `recordsDisplay` - Data set length once the current filtering criterion\n * are applied.\n */\n\n\n _api_register('page.info()', function (action) {\n if (this.context.length === 0) {\n return undefined;\n }\n\n var settings = this.context[0],\n start = settings._iDisplayStart,\n len = settings.oFeatures.bPaginate ? settings._iDisplayLength : -1,\n visRecords = settings.fnRecordsDisplay(),\n all = len === -1;\n return {\n \"page\": all ? 0 : Math.floor(start / len),\n \"pages\": all ? 1 : Math.ceil(visRecords / len),\n \"start\": start,\n \"end\": settings.fnDisplayEnd(),\n \"length\": len,\n \"recordsTotal\": settings.fnRecordsTotal(),\n \"recordsDisplay\": visRecords,\n \"serverSide\": _fnDataSource(settings) === 'ssp'\n };\n });\n /**\n * Get the current page length.\n *\n * @return {integer} Current page length. Note `-1` indicates that all records\n * are to be shown.\n */\n\n /**\n * Set the current page length.\n *\n * @param {integer} Page length to set. Use `-1` to show all records.\n * @returns {DataTables.Api} this\n */\n\n\n _api_register('page.len()', function (len) {\n // Note that we can't call this function 'length()' because `length`\n // is a Javascript property of functions which defines how many arguments\n // the function expects.\n if (len === undefined) {\n return this.context.length !== 0 ? this.context[0]._iDisplayLength : undefined;\n } // else, set the page length\n\n\n return this.iterator('table', function (settings) {\n _fnLengthChange(settings, len);\n });\n });\n\n var __reload = function __reload(settings, holdPosition, callback) {\n // Use the draw event to trigger a callback\n if (callback) {\n var api = new _Api2(settings);\n api.one('draw', function () {\n callback(api.ajax.json());\n });\n }\n\n if (_fnDataSource(settings) == 'ssp') {\n _fnReDraw(settings, holdPosition);\n } else {\n _fnProcessingDisplay(settings, true); // Cancel an existing request\n\n\n var xhr = settings.jqXHR;\n\n if (xhr && xhr.readyState !== 4) {\n xhr.abort();\n } // Trigger xhr\n\n\n _fnBuildAjax(settings, [], function (json) {\n _fnClearTable(settings);\n\n var data = _fnAjaxDataSrc(settings, json);\n\n for (var i = 0, ien = data.length; i < ien; i++) {\n _fnAddData(settings, data[i]);\n }\n\n _fnReDraw(settings, holdPosition);\n\n _fnProcessingDisplay(settings, false);\n });\n }\n };\n /**\n * Get the JSON response from the last Ajax request that DataTables made to the\n * server. Note that this returns the JSON from the first table in the current\n * context.\n *\n * @return {object} JSON received from the server.\n */\n\n\n _api_register('ajax.json()', function () {\n var ctx = this.context;\n\n if (ctx.length > 0) {\n return ctx[0].json;\n } // else return undefined;\n\n });\n /**\n * Get the data submitted in the last Ajax request\n */\n\n\n _api_register('ajax.params()', function () {\n var ctx = this.context;\n\n if (ctx.length > 0) {\n return ctx[0].oAjaxData;\n } // else return undefined;\n\n });\n /**\n * Reload tables from the Ajax data source. Note that this function will\n * automatically re-draw the table when the remote data has been loaded.\n *\n * @param {boolean} [reset=true] Reset (default) or hold the current paging\n * position. A full re-sort and re-filter is performed when this method is\n * called, which is why the pagination reset is the default action.\n * @returns {DataTables.Api} this\n */\n\n\n _api_register('ajax.reload()', function (callback, resetPaging) {\n return this.iterator('table', function (settings) {\n __reload(settings, resetPaging === false, callback);\n });\n });\n /**\n * Get the current Ajax URL. Note that this returns the URL from the first\n * table in the current context.\n *\n * @return {string} Current Ajax source URL\n */\n\n /**\n * Set the Ajax URL. Note that this will set the URL for all tables in the\n * current context.\n *\n * @param {string} url URL to set.\n * @returns {DataTables.Api} this\n */\n\n\n _api_register('ajax.url()', function (url) {\n var ctx = this.context;\n\n if (url === undefined) {\n // get\n if (ctx.length === 0) {\n return undefined;\n }\n\n ctx = ctx[0];\n return ctx.ajax ? $.isPlainObject(ctx.ajax) ? ctx.ajax.url : ctx.ajax : ctx.sAjaxSource;\n } // set\n\n\n return this.iterator('table', function (settings) {\n if ($.isPlainObject(settings.ajax)) {\n settings.ajax.url = url;\n } else {\n settings.ajax = url;\n } // No need to consider sAjaxSource here since DataTables gives priority\n // to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any\n // value of `sAjaxSource` redundant.\n\n });\n });\n /**\n * Load data from the newly set Ajax URL. Note that this method is only\n * available when `ajax.url()` is used to set a URL. Additionally, this method\n * has the same effect as calling `ajax.reload()` but is provided for\n * convenience when setting a new URL. Like `ajax.reload()` it will\n * automatically redraw the table once the remote data has been loaded.\n *\n * @returns {DataTables.Api} this\n */\n\n\n _api_register('ajax.url().load()', function (callback, resetPaging) {\n // Same as a reload, but makes sense to present it for easy access after a\n // url change\n return this.iterator('table', function (ctx) {\n __reload(ctx, resetPaging === false, callback);\n });\n });\n\n var _selector_run = function _selector_run(type, selector, selectFn, settings, opts) {\n var out = [],\n res,\n a,\n i,\n ien,\n j,\n jen,\n selectorType = _typeof(selector); // Can't just check for isArray here, as an API or jQuery instance might be\n // given with their array like look\n\n\n if (!selector || selectorType === 'string' || selectorType === 'function' || selector.length === undefined) {\n selector = [selector];\n }\n\n for (i = 0, ien = selector.length; i < ien; i++) {\n // Only split on simple strings - complex expressions will be jQuery selectors\n a = selector[i] && selector[i].split && !selector[i].match(/[\\[\\(:]/) ? selector[i].split(',') : [selector[i]];\n\n for (j = 0, jen = a.length; j < jen; j++) {\n res = selectFn(typeof a[j] === 'string' ? $.trim(a[j]) : a[j]);\n\n if (res && res.length) {\n out = out.concat(res);\n }\n }\n } // selector extensions\n\n\n var ext = _ext.selector[type];\n\n if (ext.length) {\n for (i = 0, ien = ext.length; i < ien; i++) {\n out = ext[i](settings, opts, out);\n }\n }\n\n return _unique(out);\n };\n\n var _selector_opts = function _selector_opts(opts) {\n if (!opts) {\n opts = {};\n } // Backwards compatibility for 1.9- which used the terminology filter rather\n // than search\n\n\n if (opts.filter && opts.search === undefined) {\n opts.search = opts.filter;\n }\n\n return $.extend({\n search: 'none',\n order: 'current',\n page: 'all'\n }, opts);\n };\n\n var _selector_first = function _selector_first(inst) {\n // Reduce the API instance to the first item found\n for (var i = 0, ien = inst.length; i < ien; i++) {\n if (inst[i].length > 0) {\n // Assign the first element to the first item in the instance\n // and truncate the instance and context\n inst[0] = inst[i];\n inst[0].length = 1;\n inst.length = 1;\n inst.context = [inst.context[i]];\n return inst;\n }\n } // Not found - return an empty instance\n\n\n inst.length = 0;\n return inst;\n };\n\n var _selector_row_indexes = function _selector_row_indexes(settings, opts) {\n var i,\n ien,\n tmp,\n a = [],\n displayFiltered = settings.aiDisplay,\n displayMaster = settings.aiDisplayMaster;\n var search = opts.search,\n // none, applied, removed\n order = opts.order,\n // applied, current, index (original - compatibility with 1.9)\n page = opts.page; // all, current\n\n if (_fnDataSource(settings) == 'ssp') {\n // In server-side processing mode, most options are irrelevant since\n // rows not shown don't exist and the index order is the applied order\n // Removed is a special case - for consistency just return an empty\n // array\n return search === 'removed' ? [] : _range(0, displayMaster.length);\n } else if (page == 'current') {\n // Current page implies that order=current and fitler=applied, since it is\n // fairly senseless otherwise, regardless of what order and search actually\n // are\n for (i = settings._iDisplayStart, ien = settings.fnDisplayEnd(); i < ien; i++) {\n a.push(displayFiltered[i]);\n }\n } else if (order == 'current' || order == 'applied') {\n if (search == 'none') {\n a = displayMaster.slice();\n } else if (search == 'applied') {\n a = displayFiltered.slice();\n } else if (search == 'removed') {\n // O(n+m) solution by creating a hash map\n var displayFilteredMap = {};\n\n for (var i = 0, ien = displayFiltered.length; i < ien; i++) {\n displayFilteredMap[displayFiltered[i]] = null;\n }\n\n a = $.map(displayMaster, function (el) {\n return !displayFilteredMap.hasOwnProperty(el) ? el : null;\n });\n }\n } else if (order == 'index' || order == 'original') {\n for (i = 0, ien = settings.aoData.length; i < ien; i++) {\n if (search == 'none') {\n a.push(i);\n } else {\n // applied | removed\n tmp = $.inArray(i, displayFiltered);\n\n if (tmp === -1 && search == 'removed' || tmp >= 0 && search == 'applied') {\n a.push(i);\n }\n }\n }\n }\n\n return a;\n };\n /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n * Rows\n *\n * {} - no selector - use all available rows\n * {integer} - row aoData index\n * {node} - TR node\n * {string} - jQuery selector to apply to the TR elements\n * {array} - jQuery array of nodes, or simply an array of TR nodes\n *\n */\n\n\n var __row_selector = function __row_selector(settings, selector, opts) {\n var rows;\n\n var run = function run(sel) {\n var selInt = _intVal(sel);\n\n var i, ien;\n var aoData = settings.aoData; // Short cut - selector is a number and no options provided (default is\n // all records, so no need to check if the index is in there, since it\n // must be - dev error if the index doesn't exist).\n\n if (selInt !== null && !opts) {\n return [selInt];\n }\n\n if (!rows) {\n rows = _selector_row_indexes(settings, opts);\n }\n\n if (selInt !== null && $.inArray(selInt, rows) !== -1) {\n // Selector - integer\n return [selInt];\n } else if (sel === null || sel === undefined || sel === '') {\n // Selector - none\n return rows;\n } // Selector - function\n\n\n if (typeof sel === 'function') {\n return $.map(rows, function (idx) {\n var row = aoData[idx];\n return sel(idx, row._aData, row.nTr) ? idx : null;\n });\n } // Selector - node\n\n\n if (sel.nodeName) {\n var rowIdx = sel._DT_RowIndex; // Property added by DT for fast lookup\n\n var cellIdx = sel._DT_CellIndex;\n\n if (rowIdx !== undefined) {\n // Make sure that the row is actually still present in the table\n return aoData[rowIdx] && aoData[rowIdx].nTr === sel ? [rowIdx] : [];\n } else if (cellIdx) {\n return aoData[cellIdx.row] && aoData[cellIdx.row].nTr === sel ? [cellIdx.row] : [];\n } else {\n var host = $(sel).closest('*[data-dt-row]');\n return host.length ? [host.data('dt-row')] : [];\n }\n } // ID selector. Want to always be able to select rows by id, regardless\n // of if the tr element has been created or not, so can't rely upon\n // jQuery here - hence a custom implementation. This does not match\n // Sizzle's fast selector or HTML4 - in HTML5 the ID can be anything,\n // but to select it using a CSS selector engine (like Sizzle or\n // querySelect) it would need to need to be escaped for some characters.\n // DataTables simplifies this for row selectors since you can select\n // only a row. A # indicates an id any anything that follows is the id -\n // unescaped.\n\n\n if (typeof sel === 'string' && sel.charAt(0) === '#') {\n // get row index from id\n var rowObj = settings.aIds[sel.replace(/^#/, '')];\n\n if (rowObj !== undefined) {\n return [rowObj.idx];\n } // need to fall through to jQuery in case there is DOM id that\n // matches\n\n } // Get nodes in the order from the `rows` array with null values removed\n\n\n var nodes = _removeEmpty(_pluck_order(settings.aoData, rows, 'nTr')); // Selector - jQuery selector string, array of nodes or jQuery object/\n // As jQuery's .filter() allows jQuery objects to be passed in filter,\n // it also allows arrays, so this will cope with all three options\n\n\n return $(nodes).filter(sel).map(function () {\n return this._DT_RowIndex;\n }).toArray();\n };\n\n return _selector_run('row', selector, run, settings, opts);\n };\n\n _api_register('rows()', function (selector, opts) {\n // argument shifting\n if (selector === undefined) {\n selector = '';\n } else if ($.isPlainObject(selector)) {\n opts = selector;\n selector = '';\n }\n\n opts = _selector_opts(opts);\n var inst = this.iterator('table', function (settings) {\n return __row_selector(settings, selector, opts);\n }, 1); // Want argument shifting here and in __row_selector?\n\n inst.selector.rows = selector;\n inst.selector.opts = opts;\n return inst;\n });\n\n _api_register('rows().nodes()', function () {\n return this.iterator('row', function (settings, row) {\n return settings.aoData[row].nTr || undefined;\n }, 1);\n });\n\n _api_register('rows().data()', function () {\n return this.iterator(true, 'rows', function (settings, rows) {\n return _pluck_order(settings.aoData, rows, '_aData');\n }, 1);\n });\n\n _api_registerPlural('rows().cache()', 'row().cache()', function (type) {\n return this.iterator('row', function (settings, row) {\n var r = settings.aoData[row];\n return type === 'search' ? r._aFilterData : r._aSortData;\n }, 1);\n });\n\n _api_registerPlural('rows().invalidate()', 'row().invalidate()', function (src) {\n return this.iterator('row', function (settings, row) {\n _fnInvalidate(settings, row, src);\n });\n });\n\n _api_registerPlural('rows().indexes()', 'row().index()', function () {\n return this.iterator('row', function (settings, row) {\n return row;\n }, 1);\n });\n\n _api_registerPlural('rows().ids()', 'row().id()', function (hash) {\n var a = [];\n var context = this.context; // `iterator` will drop undefined values, but in this case we want them\n\n for (var i = 0, ien = context.length; i < ien; i++) {\n for (var j = 0, jen = this[i].length; j < jen; j++) {\n var id = context[i].rowIdFn(context[i].aoData[this[i][j]]._aData);\n a.push((hash === true ? '#' : '') + id);\n }\n }\n\n return new _Api2(context, a);\n });\n\n _api_registerPlural('rows().remove()', 'row().remove()', function () {\n var that = this;\n this.iterator('row', function (settings, row, thatIdx) {\n var data = settings.aoData;\n var rowData = data[row];\n var i, ien, j, jen;\n var loopRow, loopCells;\n data.splice(row, 1); // Update the cached indexes\n\n for (i = 0, ien = data.length; i < ien; i++) {\n loopRow = data[i];\n loopCells = loopRow.anCells; // Rows\n\n if (loopRow.nTr !== null) {\n loopRow.nTr._DT_RowIndex = i;\n } // Cells\n\n\n if (loopCells !== null) {\n for (j = 0, jen = loopCells.length; j < jen; j++) {\n loopCells[j]._DT_CellIndex.row = i;\n }\n }\n } // Delete from the display arrays\n\n\n _fnDeleteIndex(settings.aiDisplayMaster, row);\n\n _fnDeleteIndex(settings.aiDisplay, row);\n\n _fnDeleteIndex(that[thatIdx], row, false); // maintain local indexes\n // For server-side processing tables - subtract the deleted row from the count\n\n\n if (settings._iRecordsDisplay > 0) {\n settings._iRecordsDisplay--;\n } // Check for an 'overflow' they case for displaying the table\n\n\n _fnLengthOverflow(settings); // Remove the row's ID reference if there is one\n\n\n var id = settings.rowIdFn(rowData._aData);\n\n if (id !== undefined) {\n delete settings.aIds[id];\n }\n });\n this.iterator('table', function (settings) {\n for (var i = 0, ien = settings.aoData.length; i < ien; i++) {\n settings.aoData[i].idx = i;\n }\n });\n return this;\n });\n\n _api_register('rows.add()', function (rows) {\n var newRows = this.iterator('table', function (settings) {\n var row, i, ien;\n var out = [];\n\n for (i = 0, ien = rows.length; i < ien; i++) {\n row = rows[i];\n\n if (row.nodeName && row.nodeName.toUpperCase() === 'TR') {\n out.push(_fnAddTr(settings, row)[0]);\n } else {\n out.push(_fnAddData(settings, row));\n }\n }\n\n return out;\n }, 1); // Return an Api.rows() extended instance, so rows().nodes() etc can be used\n\n var modRows = this.rows(-1);\n modRows.pop();\n $.merge(modRows, newRows);\n return modRows;\n });\n /**\n *\n */\n\n\n _api_register('row()', function (selector, opts) {\n return _selector_first(this.rows(selector, opts));\n });\n\n _api_register('row().data()', function (data) {\n var ctx = this.context;\n\n if (data === undefined) {\n // Get\n return ctx.length && this.length ? ctx[0].aoData[this[0]]._aData : undefined;\n } // Set\n\n\n var row = ctx[0].aoData[this[0]];\n row._aData = data; // If the DOM has an id, and the data source is an array\n\n if ($.isArray(data) && row.nTr.id) {\n _fnSetObjectDataFn(ctx[0].rowId)(data, row.nTr.id);\n } // Automatically invalidate\n\n\n _fnInvalidate(ctx[0], this[0], 'data');\n\n return this;\n });\n\n _api_register('row().node()', function () {\n var ctx = this.context;\n return ctx.length && this.length ? ctx[0].aoData[this[0]].nTr || null : null;\n });\n\n _api_register('row.add()', function (row) {\n // Allow a jQuery object to be passed in - only a single row is added from\n // it though - the first element in the set\n if (row instanceof $ && row.length) {\n row = row[0];\n }\n\n var rows = this.iterator('table', function (settings) {\n if (row.nodeName && row.nodeName.toUpperCase() === 'TR') {\n return _fnAddTr(settings, row)[0];\n }\n\n return _fnAddData(settings, row);\n }); // Return an Api.rows() extended instance, with the newly added row selected\n\n return this.row(rows[0]);\n });\n\n var __details_add = function __details_add(ctx, row, data, klass) {\n // Convert to array of TR elements\n var rows = [];\n\n var addRow = function addRow(r, k) {\n // Recursion to allow for arrays of jQuery objects\n if ($.isArray(r) || r instanceof $) {\n for (var i = 0, ien = r.length; i < ien; i++) {\n addRow(r[i], k);\n }\n\n return;\n } // If we get a TR element, then just add it directly - up to the dev\n // to add the correct number of columns etc\n\n\n if (r.nodeName && r.nodeName.toLowerCase() === 'tr') {\n rows.push(r);\n } else {\n // Otherwise create a row with a wrapper\n var created = $('
').addClass(k);\n $('td', created).addClass(k).html(r)[0].colSpan = _fnVisbleColumns(ctx);\n rows.push(created[0]);\n }\n };\n\n addRow(data, klass);\n\n if (row._details) {\n row._details.detach();\n }\n\n row._details = $(rows); // If the children were already shown, that state should be retained\n\n if (row._detailsShow) {\n row._details.insertAfter(row.nTr);\n }\n };\n\n var __details_remove = function __details_remove(api, idx) {\n var ctx = api.context;\n\n if (ctx.length) {\n var row = ctx[0].aoData[idx !== undefined ? idx : api[0]];\n\n if (row && row._details) {\n row._details.remove();\n\n row._detailsShow = undefined;\n row._details = undefined;\n }\n }\n };\n\n var __details_display = function __details_display(api, show) {\n var ctx = api.context;\n\n if (ctx.length && api.length) {\n var row = ctx[0].aoData[api[0]];\n\n if (row._details) {\n row._detailsShow = show;\n\n if (show) {\n row._details.insertAfter(row.nTr);\n } else {\n row._details.detach();\n }\n\n __details_events(ctx[0]);\n }\n }\n };\n\n var __details_events = function __details_events(settings) {\n var api = new _Api2(settings);\n var namespace = '.dt.DT_details';\n var drawEvent = 'draw' + namespace;\n var colvisEvent = 'column-visibility' + namespace;\n var destroyEvent = 'destroy' + namespace;\n var data = settings.aoData;\n api.off(drawEvent + ' ' + colvisEvent + ' ' + destroyEvent);\n\n if (_pluck(data, '_details').length > 0) {\n // On each draw, insert the required elements into the document\n api.on(drawEvent, function (e, ctx) {\n if (settings !== ctx) {\n return;\n }\n\n api.rows({\n page: 'current'\n }).eq(0).each(function (idx) {\n // Internal data grab\n var row = data[idx];\n\n if (row._detailsShow) {\n row._details.insertAfter(row.nTr);\n }\n });\n }); // Column visibility change - update the colspan\n\n api.on(colvisEvent, function (e, ctx, idx, vis) {\n if (settings !== ctx) {\n return;\n } // Update the colspan for the details rows (note, only if it already has\n // a colspan)\n\n\n var row,\n visible = _fnVisbleColumns(ctx);\n\n for (var i = 0, ien = data.length; i < ien; i++) {\n row = data[i];\n\n if (row._details) {\n row._details.children('td[colspan]').attr('colspan', visible);\n }\n }\n }); // Table destroyed - nuke any child rows\n\n api.on(destroyEvent, function (e, ctx) {\n if (settings !== ctx) {\n return;\n }\n\n for (var i = 0, ien = data.length; i < ien; i++) {\n if (data[i]._details) {\n __details_remove(api, i);\n }\n }\n });\n }\n }; // Strings for the method names to help minification\n\n\n var _emp = '';\n\n var _child_obj = _emp + 'row().child';\n\n var _child_mth = _child_obj + '()'; // data can be:\n // tr\n // string\n // jQuery or array of any of the above\n\n\n _api_register(_child_mth, function (data, klass) {\n var ctx = this.context;\n\n if (data === undefined) {\n // get\n return ctx.length && this.length ? ctx[0].aoData[this[0]]._details : undefined;\n } else if (data === true) {\n // show\n this.child.show();\n } else if (data === false) {\n // remove\n __details_remove(this);\n } else if (ctx.length && this.length) {\n // set\n __details_add(ctx[0], ctx[0].aoData[this[0]], data, klass);\n }\n\n return this;\n });\n\n _api_register([_child_obj + '.show()', _child_mth + '.show()' // only when `child()` was called with parameters (without\n ], function (show) {\n // it returns an object and this method is not executed)\n __details_display(this, true);\n\n return this;\n });\n\n _api_register([_child_obj + '.hide()', _child_mth + '.hide()' // only when `child()` was called with parameters (without\n ], function () {\n // it returns an object and this method is not executed)\n __details_display(this, false);\n\n return this;\n });\n\n _api_register([_child_obj + '.remove()', _child_mth + '.remove()' // only when `child()` was called with parameters (without\n ], function () {\n // it returns an object and this method is not executed)\n __details_remove(this);\n\n return this;\n });\n\n _api_register(_child_obj + '.isShown()', function () {\n var ctx = this.context;\n\n if (ctx.length && this.length) {\n // _detailsShown as false or undefined will fall through to return false\n return ctx[0].aoData[this[0]]._detailsShow || false;\n }\n\n return false;\n });\n /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n * Columns\n *\n * {integer} - column index (>=0 count from left, <0 count from right)\n * \"{integer}:visIdx\" - visible column index (i.e. translate to column index) (>=0 count from left, <0 count from right)\n * \"{integer}:visible\" - alias for {integer}:visIdx (>=0 count from left, <0 count from right)\n * \"{string}:name\" - column name\n * \"{string}\" - jQuery selector on column header nodes\n *\n */\n // can be an array of these items, comma separated list, or an array of comma\n // separated lists\n\n\n var __re_column_selector = /^([^:]+):(name|visIdx|visible)$/; // r1 and r2 are redundant - but it means that the parameters match for the\n // iterator callback in columns().data()\n\n var __columnData = function __columnData(settings, column, r1, r2, rows) {\n var a = [];\n\n for (var row = 0, ien = rows.length; row < ien; row++) {\n a.push(_fnGetCellData(settings, rows[row], column));\n }\n\n return a;\n };\n\n var __column_selector = function __column_selector(settings, selector, opts) {\n var columns = settings.aoColumns,\n names = _pluck(columns, 'sName'),\n nodes = _pluck(columns, 'nTh');\n\n var run = function run(s) {\n var selInt = _intVal(s); // Selector - all\n\n\n if (s === '') {\n return _range(columns.length);\n } // Selector - index\n\n\n if (selInt !== null) {\n return [selInt >= 0 ? selInt : // Count from left\n columns.length + selInt // Count from right (+ because its a negative value)\n ];\n } // Selector = function\n\n\n if (typeof s === 'function') {\n var rows = _selector_row_indexes(settings, opts);\n\n return $.map(columns, function (col, idx) {\n return s(idx, __columnData(settings, idx, 0, 0, rows), nodes[idx]) ? idx : null;\n });\n } // jQuery or string selector\n\n\n var match = typeof s === 'string' ? s.match(__re_column_selector) : '';\n\n if (match) {\n switch (match[2]) {\n case 'visIdx':\n case 'visible':\n var idx = parseInt(match[1], 10); // Visible index given, convert to column index\n\n if (idx < 0) {\n // Counting from the right\n var visColumns = $.map(columns, function (col, i) {\n return col.bVisible ? i : null;\n });\n return [visColumns[visColumns.length + idx]];\n } // Counting from the left\n\n\n return [_fnVisibleToColumnIndex(settings, idx)];\n\n case 'name':\n // match by name. `names` is column index complete and in order\n return $.map(names, function (name, i) {\n return name === match[1] ? i : null;\n });\n\n default:\n return [];\n }\n } // Cell in the table body\n\n\n if (s.nodeName && s._DT_CellIndex) {\n return [s._DT_CellIndex.column];\n } // jQuery selector on the TH elements for the columns\n\n\n var jqResult = $(nodes).filter(s).map(function () {\n return $.inArray(this, nodes); // `nodes` is column index complete and in order\n }).toArray();\n\n if (jqResult.length || !s.nodeName) {\n return jqResult;\n } // Otherwise a node which might have a `dt-column` data attribute, or be\n // a child or such an element\n\n\n var host = $(s).closest('*[data-dt-column]');\n return host.length ? [host.data('dt-column')] : [];\n };\n\n return _selector_run('column', selector, run, settings, opts);\n };\n\n var __setColumnVis = function __setColumnVis(settings, column, vis) {\n var cols = settings.aoColumns,\n col = cols[column],\n data = settings.aoData,\n row,\n cells,\n i,\n ien,\n tr; // Get\n\n if (vis === undefined) {\n return col.bVisible;\n } // Set\n // No change\n\n\n if (col.bVisible === vis) {\n return;\n }\n\n if (vis) {\n // Insert column\n // Need to decide if we should use appendChild or insertBefore\n var insertBefore = $.inArray(true, _pluck(cols, 'bVisible'), column + 1);\n\n for (i = 0, ien = data.length; i < ien; i++) {\n tr = data[i].nTr;\n cells = data[i].anCells;\n\n if (tr) {\n // insertBefore can act like appendChild if 2nd arg is null\n tr.insertBefore(cells[column], cells[insertBefore] || null);\n }\n }\n } else {\n // Remove column\n $(_pluck(settings.aoData, 'anCells', column)).detach();\n } // Common actions\n\n\n col.bVisible = vis;\n\n _fnDrawHead(settings, settings.aoHeader);\n\n _fnDrawHead(settings, settings.aoFooter); // Update colspan for no records display. Child rows and extensions will use their own\n // listeners to do this - only need to update the empty table item here\n\n\n if (!settings.aiDisplay.length) {\n $(settings.nTBody).find('td[colspan]').attr('colspan', _fnVisbleColumns(settings));\n }\n\n _fnSaveState(settings);\n };\n\n _api_register('columns()', function (selector, opts) {\n // argument shifting\n if (selector === undefined) {\n selector = '';\n } else if ($.isPlainObject(selector)) {\n opts = selector;\n selector = '';\n }\n\n opts = _selector_opts(opts);\n var inst = this.iterator('table', function (settings) {\n return __column_selector(settings, selector, opts);\n }, 1); // Want argument shifting here and in _row_selector?\n\n inst.selector.cols = selector;\n inst.selector.opts = opts;\n return inst;\n });\n\n _api_registerPlural('columns().header()', 'column().header()', function (selector, opts) {\n return this.iterator('column', function (settings, column) {\n return settings.aoColumns[column].nTh;\n }, 1);\n });\n\n _api_registerPlural('columns().footer()', 'column().footer()', function (selector, opts) {\n return this.iterator('column', function (settings, column) {\n return settings.aoColumns[column].nTf;\n }, 1);\n });\n\n _api_registerPlural('columns().data()', 'column().data()', function () {\n return this.iterator('column-rows', __columnData, 1);\n });\n\n _api_registerPlural('columns().dataSrc()', 'column().dataSrc()', function () {\n return this.iterator('column', function (settings, column) {\n return settings.aoColumns[column].mData;\n }, 1);\n });\n\n _api_registerPlural('columns().cache()', 'column().cache()', function (type) {\n return this.iterator('column-rows', function (settings, column, i, j, rows) {\n return _pluck_order(settings.aoData, rows, type === 'search' ? '_aFilterData' : '_aSortData', column);\n }, 1);\n });\n\n _api_registerPlural('columns().nodes()', 'column().nodes()', function () {\n return this.iterator('column-rows', function (settings, column, i, j, rows) {\n return _pluck_order(settings.aoData, rows, 'anCells', column);\n }, 1);\n });\n\n _api_registerPlural('columns().visible()', 'column().visible()', function (vis, calc) {\n var ret = this.iterator('column', function (settings, column) {\n if (vis === undefined) {\n return settings.aoColumns[column].bVisible;\n } // else\n\n\n __setColumnVis(settings, column, vis);\n }); // Group the column visibility changes\n\n if (vis !== undefined) {\n // Second loop once the first is done for events\n this.iterator('column', function (settings, column) {\n _fnCallbackFire(settings, null, 'column-visibility', [settings, column, vis, calc]);\n });\n\n if (calc === undefined || calc) {\n this.columns.adjust();\n }\n }\n\n return ret;\n });\n\n _api_registerPlural('columns().indexes()', 'column().index()', function (type) {\n return this.iterator('column', function (settings, column) {\n return type === 'visible' ? _fnColumnIndexToVisible(settings, column) : column;\n }, 1);\n });\n\n _api_register('columns.adjust()', function () {\n return this.iterator('table', function (settings) {\n _fnAdjustColumnSizing(settings);\n }, 1);\n });\n\n _api_register('column.index()', function (type, idx) {\n if (this.context.length !== 0) {\n var ctx = this.context[0];\n\n if (type === 'fromVisible' || type === 'toData') {\n return _fnVisibleToColumnIndex(ctx, idx);\n } else if (type === 'fromData' || type === 'toVisible') {\n return _fnColumnIndexToVisible(ctx, idx);\n }\n }\n });\n\n _api_register('column()', function (selector, opts) {\n return _selector_first(this.columns(selector, opts));\n });\n\n var __cell_selector = function __cell_selector(settings, selector, opts) {\n var data = settings.aoData;\n\n var rows = _selector_row_indexes(settings, opts);\n\n var cells = _removeEmpty(_pluck_order(data, rows, 'anCells'));\n\n var allCells = $([].concat.apply([], cells));\n var row;\n var columns = settings.aoColumns.length;\n var a, i, ien, j, o, host;\n\n var run = function run(s) {\n var fnSelector = typeof s === 'function';\n\n if (s === null || s === undefined || fnSelector) {\n // All cells and function selectors\n a = [];\n\n for (i = 0, ien = rows.length; i < ien; i++) {\n row = rows[i];\n\n for (j = 0; j < columns; j++) {\n o = {\n row: row,\n column: j\n };\n\n if (fnSelector) {\n // Selector - function\n host = data[row];\n\n if (s(o, _fnGetCellData(settings, row, j), host.anCells ? host.anCells[j] : null)) {\n a.push(o);\n }\n } else {\n // Selector - all\n a.push(o);\n }\n }\n }\n\n return a;\n } // Selector - index\n\n\n if ($.isPlainObject(s)) {\n // Valid cell index and its in the array of selectable rows\n return s.column !== undefined && s.row !== undefined && $.inArray(s.row, rows) !== -1 ? [s] : [];\n } // Selector - jQuery filtered cells\n\n\n var jqResult = allCells.filter(s).map(function (i, el) {\n return {\n // use a new object, in case someone changes the values\n row: el._DT_CellIndex.row,\n column: el._DT_CellIndex.column\n };\n }).toArray();\n\n if (jqResult.length || !s.nodeName) {\n return jqResult;\n } // Otherwise the selector is a node, and there is one last option - the\n // element might be a child of an element which has dt-row and dt-column\n // data attributes\n\n\n host = $(s).closest('*[data-dt-row]');\n return host.length ? [{\n row: host.data('dt-row'),\n column: host.data('dt-column')\n }] : [];\n };\n\n return _selector_run('cell', selector, run, settings, opts);\n };\n\n _api_register('cells()', function (rowSelector, columnSelector, opts) {\n // Argument shifting\n if ($.isPlainObject(rowSelector)) {\n // Indexes\n if (rowSelector.row === undefined) {\n // Selector options in first parameter\n opts = rowSelector;\n rowSelector = null;\n } else {\n // Cell index objects in first parameter\n opts = columnSelector;\n columnSelector = null;\n }\n }\n\n if ($.isPlainObject(columnSelector)) {\n opts = columnSelector;\n columnSelector = null;\n } // Cell selector\n\n\n if (columnSelector === null || columnSelector === undefined) {\n return this.iterator('table', function (settings) {\n return __cell_selector(settings, rowSelector, _selector_opts(opts));\n });\n } // Row + column selector\n\n\n var columns = this.columns(columnSelector);\n var rows = this.rows(rowSelector);\n var a, i, ien, j, jen;\n this.iterator('table', function (settings, idx) {\n a = [];\n\n for (i = 0, ien = rows[idx].length; i < ien; i++) {\n for (j = 0, jen = columns[idx].length; j < jen; j++) {\n a.push({\n row: rows[idx][i],\n column: columns[idx][j]\n });\n }\n }\n }, 1); // Now pass through the cell selector for options\n\n var cells = this.cells(a, opts);\n $.extend(cells.selector, {\n cols: columnSelector,\n rows: rowSelector,\n opts: opts\n });\n return cells;\n });\n\n _api_registerPlural('cells().nodes()', 'cell().node()', function () {\n return this.iterator('cell', function (settings, row, column) {\n var data = settings.aoData[row];\n return data && data.anCells ? data.anCells[column] : undefined;\n }, 1);\n });\n\n _api_register('cells().data()', function () {\n return this.iterator('cell', function (settings, row, column) {\n return _fnGetCellData(settings, row, column);\n }, 1);\n });\n\n _api_registerPlural('cells().cache()', 'cell().cache()', function (type) {\n type = type === 'search' ? '_aFilterData' : '_aSortData';\n return this.iterator('cell', function (settings, row, column) {\n return settings.aoData[row][type][column];\n }, 1);\n });\n\n _api_registerPlural('cells().render()', 'cell().render()', function (type) {\n return this.iterator('cell', function (settings, row, column) {\n return _fnGetCellData(settings, row, column, type);\n }, 1);\n });\n\n _api_registerPlural('cells().indexes()', 'cell().index()', function () {\n return this.iterator('cell', function (settings, row, column) {\n return {\n row: row,\n column: column,\n columnVisible: _fnColumnIndexToVisible(settings, column)\n };\n }, 1);\n });\n\n _api_registerPlural('cells().invalidate()', 'cell().invalidate()', function (src) {\n return this.iterator('cell', function (settings, row, column) {\n _fnInvalidate(settings, row, src, column);\n });\n });\n\n _api_register('cell()', function (rowSelector, columnSelector, opts) {\n return _selector_first(this.cells(rowSelector, columnSelector, opts));\n });\n\n _api_register('cell().data()', function (data) {\n var ctx = this.context;\n var cell = this[0];\n\n if (data === undefined) {\n // Get\n return ctx.length && cell.length ? _fnGetCellData(ctx[0], cell[0].row, cell[0].column) : undefined;\n } // Set\n\n\n _fnSetCellData(ctx[0], cell[0].row, cell[0].column, data);\n\n _fnInvalidate(ctx[0], cell[0].row, 'data', cell[0].column);\n\n return this;\n });\n /**\n * Get current ordering (sorting) that has been applied to the table.\n *\n * @returns {array} 2D array containing the sorting information for the first\n * table in the current context. Each element in the parent array represents\n * a column being sorted upon (i.e. multi-sorting with two columns would have\n * 2 inner arrays). The inner arrays may have 2 or 3 elements. The first is\n * the column index that the sorting condition applies to, the second is the\n * direction of the sort (`desc` or `asc`) and, optionally, the third is the\n * index of the sorting order from the `column.sorting` initialisation array.\n */\n\n /**\n * Set the ordering for the table.\n *\n * @param {integer} order Column index to sort upon.\n * @param {string} direction Direction of the sort to be applied (`asc` or `desc`)\n * @returns {DataTables.Api} this\n */\n\n /**\n * Set the ordering for the table.\n *\n * @param {array} order 1D array of sorting information to be applied.\n * @param {array} [...] Optional additional sorting conditions\n * @returns {DataTables.Api} this\n */\n\n /**\n * Set the ordering for the table.\n *\n * @param {array} order 2D array of sorting information to be applied.\n * @returns {DataTables.Api} this\n */\n\n\n _api_register('order()', function (order, dir) {\n var ctx = this.context;\n\n if (order === undefined) {\n // get\n return ctx.length !== 0 ? ctx[0].aaSorting : undefined;\n } // set\n\n\n if (typeof order === 'number') {\n // Simple column / direction passed in\n order = [[order, dir]];\n } else if (order.length && !$.isArray(order[0])) {\n // Arguments passed in (list of 1D arrays)\n order = Array.prototype.slice.call(arguments);\n } // otherwise a 2D array was passed in\n\n\n return this.iterator('table', function (settings) {\n settings.aaSorting = order.slice();\n });\n });\n /**\n * Attach a sort listener to an element for a given column\n *\n * @param {node|jQuery|string} node Identifier for the element(s) to attach the\n * listener to. This can take the form of a single DOM node, a jQuery\n * collection of nodes or a jQuery selector which will identify the node(s).\n * @param {integer} column the column that a click on this node will sort on\n * @param {function} [callback] callback function when sort is run\n * @returns {DataTables.Api} this\n */\n\n\n _api_register('order.listener()', function (node, column, callback) {\n return this.iterator('table', function (settings) {\n _fnSortAttachListener(settings, node, column, callback);\n });\n });\n\n _api_register('order.fixed()', function (set) {\n if (!set) {\n var ctx = this.context;\n var fixed = ctx.length ? ctx[0].aaSortingFixed : undefined;\n return $.isArray(fixed) ? {\n pre: fixed\n } : fixed;\n }\n\n return this.iterator('table', function (settings) {\n settings.aaSortingFixed = $.extend(true, {}, set);\n });\n }); // Order by the selected column(s)\n\n\n _api_register(['columns().order()', 'column().order()'], function (dir) {\n var that = this;\n return this.iterator('table', function (settings, i) {\n var sort = [];\n $.each(that[i], function (j, col) {\n sort.push([col, dir]);\n });\n settings.aaSorting = sort;\n });\n });\n\n _api_register('search()', function (input, regex, smart, caseInsen) {\n var ctx = this.context;\n\n if (input === undefined) {\n // get\n return ctx.length !== 0 ? ctx[0].oPreviousSearch.sSearch : undefined;\n } // set\n\n\n return this.iterator('table', function (settings) {\n if (!settings.oFeatures.bFilter) {\n return;\n }\n\n _fnFilterComplete(settings, $.extend({}, settings.oPreviousSearch, {\n \"sSearch\": input + \"\",\n \"bRegex\": regex === null ? false : regex,\n \"bSmart\": smart === null ? true : smart,\n \"bCaseInsensitive\": caseInsen === null ? true : caseInsen\n }), 1);\n });\n });\n\n _api_registerPlural('columns().search()', 'column().search()', function (input, regex, smart, caseInsen) {\n return this.iterator('column', function (settings, column) {\n var preSearch = settings.aoPreSearchCols;\n\n if (input === undefined) {\n // get\n return preSearch[column].sSearch;\n } // set\n\n\n if (!settings.oFeatures.bFilter) {\n return;\n }\n\n $.extend(preSearch[column], {\n \"sSearch\": input + \"\",\n \"bRegex\": regex === null ? false : regex,\n \"bSmart\": smart === null ? true : smart,\n \"bCaseInsensitive\": caseInsen === null ? true : caseInsen\n });\n\n _fnFilterComplete(settings, settings.oPreviousSearch, 1);\n });\n });\n /*\n * State API methods\n */\n\n\n _api_register('state()', function () {\n return this.context.length ? this.context[0].oSavedState : null;\n });\n\n _api_register('state.clear()', function () {\n return this.iterator('table', function (settings) {\n // Save an empty object\n settings.fnStateSaveCallback.call(settings.oInstance, settings, {});\n });\n });\n\n _api_register('state.loaded()', function () {\n return this.context.length ? this.context[0].oLoadedState : null;\n });\n\n _api_register('state.save()', function () {\n return this.iterator('table', function (settings) {\n _fnSaveState(settings);\n });\n });\n /**\n * Provide a common method for plug-ins to check the version of DataTables being\n * used, in order to ensure compatibility.\n *\n * @param {string} version Version string to check for, in the format \"X.Y.Z\".\n * Note that the formats \"X\" and \"X.Y\" are also acceptable.\n * @returns {boolean} true if this version of DataTables is greater or equal to\n * the required version, or false if this version of DataTales is not\n * suitable\n * @static\n * @dtopt API-Static\n *\n * @example\n * alert( $.fn.dataTable.versionCheck( '1.9.0' ) );\n */\n\n\n DataTable.versionCheck = DataTable.fnVersionCheck = function (version) {\n var aThis = DataTable.version.split('.');\n var aThat = version.split('.');\n var iThis, iThat;\n\n for (var i = 0, iLen = aThat.length; i < iLen; i++) {\n iThis = parseInt(aThis[i], 10) || 0;\n iThat = parseInt(aThat[i], 10) || 0; // Parts are the same, keep comparing\n\n if (iThis === iThat) {\n continue;\n } // Parts are different, return immediately\n\n\n return iThis > iThat;\n }\n\n return true;\n };\n /**\n * Check if a `
` node is a DataTable table already or not.\n *\n * @param {node|jquery|string} table Table node, jQuery object or jQuery\n * selector for the table to test. Note that if more than more than one\n * table is passed on, only the first will be checked\n * @returns {boolean} true the table given is a DataTable, or false otherwise\n * @static\n * @dtopt API-Static\n *\n * @example\n * if ( ! $.fn.DataTable.isDataTable( '#example' ) ) {\n * $('#example').dataTable();\n * }\n */\n\n\n DataTable.isDataTable = DataTable.fnIsDataTable = function (table) {\n var t = $(table).get(0);\n var is = false;\n\n if (table instanceof DataTable.Api) {\n return true;\n }\n\n $.each(DataTable.settings, function (i, o) {\n var head = o.nScrollHead ? $('table', o.nScrollHead)[0] : null;\n var foot = o.nScrollFoot ? $('table', o.nScrollFoot)[0] : null;\n\n if (o.nTable === t || head === t || foot === t) {\n is = true;\n }\n });\n return is;\n };\n /**\n * Get all DataTable tables that have been initialised - optionally you can\n * select to get only currently visible tables.\n *\n * @param {boolean} [visible=false] Flag to indicate if you want all (default)\n * or visible tables only.\n * @returns {array} Array of `table` nodes (not DataTable instances) which are\n * DataTables\n * @static\n * @dtopt API-Static\n *\n * @example\n * $.each( $.fn.dataTable.tables(true), function () {\n * $(table).DataTable().columns.adjust();\n * } );\n */\n\n\n DataTable.tables = DataTable.fnTables = function (visible) {\n var api = false;\n\n if ($.isPlainObject(visible)) {\n api = visible.api;\n visible = visible.visible;\n }\n\n var a = $.map(DataTable.settings, function (o) {\n if (!visible || visible && $(o.nTable).is(':visible')) {\n return o.nTable;\n }\n });\n return api ? new _Api2(a) : a;\n };\n /**\n * Convert from camel case parameters to Hungarian notation. This is made public\n * for the extensions to provide the same ability as DataTables core to accept\n * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase\n * parameters.\n *\n * @param {object} src The model object which holds all parameters that can be\n * mapped.\n * @param {object} user The object to convert from camel case to Hungarian.\n * @param {boolean} force When set to `true`, properties which already have a\n * Hungarian value in the `user` object will be overwritten. Otherwise they\n * won't be.\n */\n\n\n DataTable.camelToHungarian = _fnCamelToHungarian;\n /**\n *\n */\n\n _api_register('$()', function (selector, opts) {\n var rows = this.rows(opts).nodes(),\n // Get all rows\n jqRows = $(rows);\n return $([].concat(jqRows.filter(selector).toArray(), jqRows.find(selector).toArray()));\n }); // jQuery functions to operate on the tables\n\n\n $.each(['on', 'one', 'off'], function (i, key) {\n _api_register(key + '()', function\n /* event, handler */\n () {\n var args = Array.prototype.slice.call(arguments); // Add the `dt` namespace automatically if it isn't already present\n\n args[0] = $.map(args[0].split(/\\s/), function (e) {\n return !e.match(/\\.dt\\b/) ? e + '.dt' : e;\n }).join(' ');\n var inst = $(this.tables().nodes());\n inst[key].apply(inst, args);\n return this;\n });\n });\n\n _api_register('clear()', function () {\n return this.iterator('table', function (settings) {\n _fnClearTable(settings);\n });\n });\n\n _api_register('settings()', function () {\n return new _Api2(this.context, this.context);\n });\n\n _api_register('init()', function () {\n var ctx = this.context;\n return ctx.length ? ctx[0].oInit : null;\n });\n\n _api_register('data()', function () {\n return this.iterator('table', function (settings) {\n return _pluck(settings.aoData, '_aData');\n }).flatten();\n });\n\n _api_register('destroy()', function (remove) {\n remove = remove || false;\n return this.iterator('table', function (settings) {\n var orig = settings.nTableWrapper.parentNode;\n var classes = settings.oClasses;\n var table = settings.nTable;\n var tbody = settings.nTBody;\n var thead = settings.nTHead;\n var tfoot = settings.nTFoot;\n var jqTable = $(table);\n var jqTbody = $(tbody);\n var jqWrapper = $(settings.nTableWrapper);\n var rows = $.map(settings.aoData, function (r) {\n return r.nTr;\n });\n var i, ien; // Flag to note that the table is currently being destroyed - no action\n // should be taken\n\n settings.bDestroying = true; // Fire off the destroy callbacks for plug-ins etc\n\n _fnCallbackFire(settings, \"aoDestroyCallback\", \"destroy\", [settings]); // If not being removed from the document, make all columns visible\n\n\n if (!remove) {\n new _Api2(settings).columns().visible(true);\n } // Blitz all `DT` namespaced events (these are internal events, the\n // lowercase, `dt` events are user subscribed and they are responsible\n // for removing them\n\n\n jqWrapper.off('.DT').find(':not(tbody *)').off('.DT');\n $(window).off('.DT-' + settings.sInstance); // When scrolling we had to break the table up - restore it\n\n if (table != thead.parentNode) {\n jqTable.children('thead').detach();\n jqTable.append(thead);\n }\n\n if (tfoot && table != tfoot.parentNode) {\n jqTable.children('tfoot').detach();\n jqTable.append(tfoot);\n }\n\n settings.aaSorting = [];\n settings.aaSortingFixed = [];\n\n _fnSortingClasses(settings);\n\n $(rows).removeClass(settings.asStripeClasses.join(' '));\n $('th, td', thead).removeClass(classes.sSortable + ' ' + classes.sSortableAsc + ' ' + classes.sSortableDesc + ' ' + classes.sSortableNone); // Add the TR elements back into the table in their original order\n\n jqTbody.children().detach();\n jqTbody.append(rows); // Remove the DataTables generated nodes, events and classes\n\n var removedMethod = remove ? 'remove' : 'detach';\n jqTable[removedMethod]();\n jqWrapper[removedMethod](); // If we need to reattach the table to the document\n\n if (!remove && orig) {\n // insertBefore acts like appendChild if !arg[1]\n orig.insertBefore(table, settings.nTableReinsertBefore); // Restore the width of the original table - was read from the style property,\n // so we can restore directly to that\n\n jqTable.css('width', settings.sDestroyWidth).removeClass(classes.sTable); // If the were originally stripe classes - then we add them back here.\n // Note this is not fool proof (for example if not all rows had stripe\n // classes - but it's a good effort without getting carried away\n\n ien = settings.asDestroyStripes.length;\n\n if (ien) {\n jqTbody.children().each(function (i) {\n $(this).addClass(settings.asDestroyStripes[i % ien]);\n });\n }\n }\n /* Remove the settings object from the settings array */\n\n\n var idx = $.inArray(settings, DataTable.settings);\n\n if (idx !== -1) {\n DataTable.settings.splice(idx, 1);\n }\n });\n }); // Add the `every()` method for rows, columns and cells in a compact form\n\n\n $.each(['column', 'row', 'cell'], function (i, type) {\n _api_register(type + 's().every()', function (fn) {\n var opts = this.selector.opts;\n var api = this;\n return this.iterator(type, function (settings, arg1, arg2, arg3, arg4) {\n // Rows and columns:\n // arg1 - index\n // arg2 - table counter\n // arg3 - loop counter\n // arg4 - undefined\n // Cells:\n // arg1 - row index\n // arg2 - column index\n // arg3 - table counter\n // arg4 - loop counter\n fn.call(api[type](arg1, type === 'cell' ? arg2 : opts, type === 'cell' ? opts : undefined), arg1, arg2, arg3, arg4);\n });\n });\n }); // i18n method for extensions to be able to use the language object from the\n // DataTable\n\n _api_register('i18n()', function (token, def, plural) {\n var ctx = this.context[0];\n\n var resolved = _fnGetObjectDataFn(token)(ctx.oLanguage);\n\n if (resolved === undefined) {\n resolved = def;\n }\n\n if (plural !== undefined && $.isPlainObject(resolved)) {\n resolved = resolved[plural] !== undefined ? resolved[plural] : resolved._;\n }\n\n return resolved.replace('%d', plural); // nb: plural might be undefined,\n });\n /**\n * Version string for plug-ins to check compatibility. Allowed format is\n * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used\n * only for non-release builds. See http://semver.org/ for more information.\n * @member\n * @type string\n * @default Version number\n */\n\n\n DataTable.version = \"1.10.18\";\n /**\n * Private data store, containing all of the settings objects that are\n * created for the tables on a given page.\n *\n * Note that the `DataTable.settings` object is aliased to\n * `jQuery.fn.dataTableExt` through which it may be accessed and\n * manipulated, or `jQuery.fn.dataTable.settings`.\n * @member\n * @type array\n * @default []\n * @private\n */\n\n DataTable.settings = [];\n /**\n * Object models container, for the various models that DataTables has\n * available to it. These models define the objects that are used to hold\n * the active state and configuration of the table.\n * @namespace\n */\n\n DataTable.models = {};\n /**\n * Template object for the way in which DataTables holds information about\n * search information for the global filter and individual column filters.\n * @namespace\n */\n\n DataTable.models.oSearch = {\n /**\n * Flag to indicate if the filtering should be case insensitive or not\n * @type boolean\n * @default true\n */\n \"bCaseInsensitive\": true,\n\n /**\n * Applied search term\n * @type string\n * @default Empty string \n */\n \"sSearch\": \"\",\n\n /**\n * Flag to indicate if the search term should be interpreted as a\n * regular expression (true) or not (false) and therefore and special\n * regex characters escaped.\n * @type boolean\n * @default false\n */\n \"bRegex\": false,\n\n /**\n * Flag to indicate if DataTables is to use its smart filtering or not.\n * @type boolean\n * @default true\n */\n \"bSmart\": true\n };\n /**\n * Template object for the way in which DataTables holds information about\n * each individual row. This is the object format used for the settings\n * aoData array.\n * @namespace\n */\n\n DataTable.models.oRow = {\n /**\n * TR element for the row\n * @type node\n * @default null\n */\n \"nTr\": null,\n\n /**\n * Array of TD elements for each row. This is null until the row has been\n * created.\n * @type array nodes\n * @default []\n */\n \"anCells\": null,\n\n /**\n * Data object from the original data source for the row. This is either\n * an array if using the traditional form of DataTables, or an object if\n * using mData options. The exact type will depend on the passed in\n * data from the data source, or will be an array if using DOM a data\n * source.\n * @type array|object\n * @default []\n */\n \"_aData\": [],\n\n /**\n * Sorting data cache - this array is ostensibly the same length as the\n * number of columns (although each index is generated only as it is\n * needed), and holds the data that is used for sorting each column in the\n * row. We do this cache generation at the start of the sort in order that\n * the formatting of the sort data need be done only once for each cell\n * per sort. This array should not be read from or written to by anything\n * other than the master sorting methods.\n * @type array\n * @default null\n * @private\n */\n \"_aSortData\": null,\n\n /**\n * Per cell filtering data cache. As per the sort data cache, used to\n * increase the performance of the filtering in DataTables\n * @type array\n * @default null\n * @private\n */\n \"_aFilterData\": null,\n\n /**\n * Filtering data cache. This is the same as the cell filtering cache, but\n * in this case a string rather than an array. This is easily computed with\n * a join on `_aFilterData`, but is provided as a cache so the join isn't\n * needed on every search (memory traded for performance)\n * @type array\n * @default null\n * @private\n */\n \"_sFilterRow\": null,\n\n /**\n * Cache of the class name that DataTables has applied to the row, so we\n * can quickly look at this variable rather than needing to do a DOM check\n * on className for the nTr property.\n * @type string\n * @default Empty string \n * @private\n */\n \"_sRowStripe\": \"\",\n\n /**\n * Denote if the original data source was from the DOM, or the data source\n * object. This is used for invalidating data, so DataTables can\n * automatically read data from the original source, unless uninstructed\n * otherwise.\n * @type string\n * @default null\n * @private\n */\n \"src\": null,\n\n /**\n * Index in the aoData array. This saves an indexOf lookup when we have the\n * object, but want to know the index\n * @type integer\n * @default -1\n * @private\n */\n \"idx\": -1\n };\n /**\n * Template object for the column information object in DataTables. This object\n * is held in the settings aoColumns array and contains all the information that\n * DataTables needs about each individual column.\n *\n * Note that this object is related to {@link DataTable.defaults.column}\n * but this one is the internal data store for DataTables's cache of columns.\n * It should NOT be manipulated outside of DataTables. Any configuration should\n * be done through the initialisation options.\n * @namespace\n */\n\n DataTable.models.oColumn = {\n /**\n * Column index. This could be worked out on-the-fly with $.inArray, but it\n * is faster to just hold it as a variable\n * @type integer\n * @default null\n */\n \"idx\": null,\n\n /**\n * A list of the columns that sorting should occur on when this column\n * is sorted. That this property is an array allows multi-column sorting\n * to be defined for a column (for example first name / last name columns\n * would benefit from this). The values are integers pointing to the\n * columns to be sorted on (typically it will be a single integer pointing\n * at itself, but that doesn't need to be the case).\n * @type array\n */\n \"aDataSort\": null,\n\n /**\n * Define the sorting directions that are applied to the column, in sequence\n * as the column is repeatedly sorted upon - i.e. the first value is used\n * as the sorting direction when the column if first sorted (clicked on).\n * Sort it again (click again) and it will move on to the next index.\n * Repeat until loop.\n * @type array\n */\n \"asSorting\": null,\n\n /**\n * Flag to indicate if the column is searchable, and thus should be included\n * in the filtering or not.\n * @type boolean\n */\n \"bSearchable\": null,\n\n /**\n * Flag to indicate if the column is sortable or not.\n * @type boolean\n */\n \"bSortable\": null,\n\n /**\n * Flag to indicate if the column is currently visible in the table or not\n * @type boolean\n */\n \"bVisible\": null,\n\n /**\n * Store for manual type assignment using the `column.type` option. This\n * is held in store so we can manipulate the column's `sType` property.\n * @type string\n * @default null\n * @private\n */\n \"_sManualType\": null,\n\n /**\n * Flag to indicate if HTML5 data attributes should be used as the data\n * source for filtering or sorting. True is either are.\n * @type boolean\n * @default false\n * @private\n */\n \"_bAttrSrc\": false,\n\n /**\n * Developer definable function that is called whenever a cell is created (Ajax source,\n * etc) or processed for input (DOM source). This can be used as a compliment to mRender\n * allowing you to modify the DOM element (add background colour for example) when the\n * element is available.\n * @type function\n * @param {element} nTd The TD node that has been created\n * @param {*} sData The Data for the cell\n * @param {array|object} oData The data for the whole row\n * @param {int} iRow The row index for the aoData data store\n * @default null\n */\n \"fnCreatedCell\": null,\n\n /**\n * Function to get data from a cell in a column. You should never \n * access data directly through _aData internally in DataTables - always use\n * the method attached to this property. It allows mData to function as\n * required. This function is automatically assigned by the column\n * initialisation method\n * @type function\n * @param {array|object} oData The data array/object for the array\n * (i.e. aoData[]._aData)\n * @param {string} sSpecific The specific data type you want to get -\n * 'display', 'type' 'filter' 'sort'\n * @returns {*} The data for the cell from the given row's data\n * @default null\n */\n \"fnGetData\": null,\n\n /**\n * Function to set data for a cell in the column. You should never \n * set the data directly to _aData internally in DataTables - always use\n * this method. It allows mData to function as required. This function\n * is automatically assigned by the column initialisation method\n * @type function\n * @param {array|object} oData The data array/object for the array\n * (i.e. aoData[]._aData)\n * @param {*} sValue Value to set\n * @default null\n */\n \"fnSetData\": null,\n\n /**\n * Property to read the value for the cells in the column from the data\n * source array / object. If null, then the default content is used, if a\n * function is given then the return from the function is used.\n * @type function|int|string|null\n * @default null\n */\n \"mData\": null,\n\n /**\n * Partner property to mData which is used (only when defined) to get\n * the data - i.e. it is basically the same as mData, but without the\n * 'set' option, and also the data fed to it is the result from mData.\n * This is the rendering method to match the data method of mData.\n * @type function|int|string|null\n * @default null\n */\n \"mRender\": null,\n\n /**\n * Unique header TH/TD element for this column - this is what the sorting\n * listener is attached to (if sorting is enabled.)\n * @type node\n * @default null\n */\n \"nTh\": null,\n\n /**\n * Unique footer TH/TD element for this column (if there is one). Not used\n * in DataTables as such, but can be used for plug-ins to reference the\n * footer for each column.\n * @type node\n * @default null\n */\n \"nTf\": null,\n\n /**\n * The class to apply to all TD elements in the table's TBODY for the column\n * @type string\n * @default null\n */\n \"sClass\": null,\n\n /**\n * When DataTables calculates the column widths to assign to each column,\n * it finds the longest string in each column and then constructs a\n * temporary table and reads the widths from that. The problem with this\n * is that \"mmm\" is much wider then \"iiii\", but the latter is a longer\n * string - thus the calculation can go wrong (doing it properly and putting\n * it into an DOM object and measuring that is horribly(!) slow). Thus as\n * a \"work around\" we provide this option. It will append its value to the\n * text that is found to be the longest string for the column - i.e. padding.\n * @type string\n */\n \"sContentPadding\": null,\n\n /**\n * Allows a default value to be given for a column's data, and will be used\n * whenever a null data source is encountered (this can be because mData\n * is set to null, or because the data source itself is null).\n * @type string\n * @default null\n */\n \"sDefaultContent\": null,\n\n /**\n * Name for the column, allowing reference to the column by name as well as\n * by index (needs a lookup to work by name).\n * @type string\n */\n \"sName\": null,\n\n /**\n * Custom sorting data type - defines which of the available plug-ins in\n * afnSortData the custom sorting will use - if any is defined.\n * @type string\n * @default std\n */\n \"sSortDataType\": 'std',\n\n /**\n * Class to be applied to the header element when sorting on this column\n * @type string\n * @default null\n */\n \"sSortingClass\": null,\n\n /**\n * Class to be applied to the header element when sorting on this column -\n * when jQuery UI theming is used.\n * @type string\n * @default null\n */\n \"sSortingClassJUI\": null,\n\n /**\n * Title of the column - what is seen in the TH element (nTh).\n * @type string\n */\n \"sTitle\": null,\n\n /**\n * Column sorting and filtering type\n * @type string\n * @default null\n */\n \"sType\": null,\n\n /**\n * Width of the column\n * @type string\n * @default null\n */\n \"sWidth\": null,\n\n /**\n * Width of the column when it was first \"encountered\"\n * @type string\n * @default null\n */\n \"sWidthOrig\": null\n };\n /*\n * Developer note: The properties of the object below are given in Hungarian\n * notation, that was used as the interface for DataTables prior to v1.10, however\n * from v1.10 onwards the primary interface is camel case. In order to avoid\n * breaking backwards compatibility utterly with this change, the Hungarian\n * version is still, internally the primary interface, but is is not documented\n * - hence the @name tags in each doc comment. This allows a Javascript function\n * to create a map from Hungarian notation to camel case (going the other direction\n * would require each property to be listed, which would at around 3K to the size\n * of DataTables, while this method is about a 0.5K hit.\n *\n * Ultimately this does pave the way for Hungarian notation to be dropped\n * completely, but that is a massive amount of work and will break current\n * installs (therefore is on-hold until v2).\n */\n\n /**\n * Initialisation options that can be given to DataTables at initialisation\n * time.\n * @namespace\n */\n\n DataTable.defaults = {\n /**\n * An array of data to use for the table, passed in at initialisation which\n * will be used in preference to any data which is already in the DOM. This is\n * particularly useful for constructing tables purely in Javascript, for\n * example with a custom Ajax call.\n * @type array\n * @default null\n *\n * @dtopt Option\n * @name DataTable.defaults.data\n *\n * @example\n * // Using a 2D array data source\n * $(document).ready( function () {\n * $('#example').dataTable( {\n * \"data\": [\n * ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],\n * ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],\n * ],\n * \"columns\": [\n * { \"title\": \"Engine\" },\n * { \"title\": \"Browser\" },\n * { \"title\": \"Platform\" },\n * { \"title\": \"Version\" },\n * { \"title\": \"Grade\" }\n * ]\n * } );\n * } );\n *\n * @example\n * // Using an array of objects as a data source (`data`)\n * $(document).ready( function () {\n * $('#example').dataTable( {\n * \"data\": [\n * {\n * \"engine\": \"Trident\",\n * \"browser\": \"Internet Explorer 4.0\",\n * \"platform\": \"Win 95+\",\n * \"version\": 4,\n * \"grade\": \"X\"\n * },\n * {\n * \"engine\": \"Trident\",\n * \"browser\": \"Internet Explorer 5.0\",\n * \"platform\": \"Win 95+\",\n * \"version\": 5,\n * \"grade\": \"C\"\n * }\n * ],\n * \"columns\": [\n * { \"title\": \"Engine\", \"data\": \"engine\" },\n * { \"title\": \"Browser\", \"data\": \"browser\" },\n * { \"title\": \"Platform\", \"data\": \"platform\" },\n * { \"title\": \"Version\", \"data\": \"version\" },\n * { \"title\": \"Grade\", \"data\": \"grade\" }\n * ]\n * } );\n * } );\n */\n \"aaData\": null,\n\n /**\n * If ordering is enabled, then DataTables will perform a first pass sort on\n * initialisation. You can define which column(s) the sort is performed\n * upon, and the sorting direction, with this variable. The `sorting` array\n * should contain an array for each column to be sorted initially containing\n * the column's index and a direction string ('asc' or 'desc').\n * @type array\n * @default [[0,'asc']]\n *\n * @dtopt Option\n * @name DataTable.defaults.order\n *\n * @example\n * // Sort by 3rd column first, and then 4th column\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"order\": [[2,'asc'], [3,'desc']]\n * } );\n * } );\n *\n * // No initial sorting\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"order\": []\n * } );\n * } );\n */\n \"aaSorting\": [[0, 'asc']],\n\n /**\n * This parameter is basically identical to the `sorting` parameter, but\n * cannot be overridden by user interaction with the table. What this means\n * is that you could have a column (visible or hidden) which the sorting\n * will always be forced on first - any sorting after that (from the user)\n * will then be performed as required. This can be useful for grouping rows\n * together.\n * @type array\n * @default null\n *\n * @dtopt Option\n * @name DataTable.defaults.orderFixed\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"orderFixed\": [[0,'asc']]\n * } );\n * } )\n */\n \"aaSortingFixed\": [],\n\n /**\n * DataTables can be instructed to load data to display in the table from a\n * Ajax source. This option defines how that Ajax call is made and where to.\n *\n * The `ajax` property has three different modes of operation, depending on\n * how it is defined. These are:\n *\n * * `string` - Set the URL from where the data should be loaded from.\n * * `object` - Define properties for `jQuery.ajax`.\n * * `function` - Custom data get function\n *\n * `string`\n * --------\n *\n * As a string, the `ajax` property simply defines the URL from which\n * DataTables will load data.\n *\n * `object`\n * --------\n *\n * As an object, the parameters in the object are passed to\n * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control\n * of the Ajax request. DataTables has a number of default parameters which\n * you can override using this option. Please refer to the jQuery\n * documentation for a full description of the options available, although\n * the following parameters provide additional options in DataTables or\n * require special consideration:\n *\n * * `data` - As with jQuery, `data` can be provided as an object, but it\n * can also be used as a function to manipulate the data DataTables sends\n * to the server. The function takes a single parameter, an object of\n * parameters with the values that DataTables has readied for sending. An\n * object may be returned which will be merged into the DataTables\n * defaults, or you can add the items to the object that was passed in and\n * not return anything from the function. This supersedes `fnServerParams`\n * from DataTables 1.9-.\n *\n * * `dataSrc` - By default DataTables will look for the property `data` (or\n * `aaData` for compatibility with DataTables 1.9-) when obtaining data\n * from an Ajax source or for server-side processing - this parameter\n * allows that property to be changed. You can use Javascript dotted\n * object notation to get a data source for multiple levels of nesting, or\n * it my be used as a function. As a function it takes a single parameter,\n * the JSON returned from the server, which can be manipulated as\n * required, with the returned value being that used by DataTables as the\n * data source for the table. This supersedes `sAjaxDataProp` from\n * DataTables 1.9-.\n *\n * * `success` - Should not be overridden it is used internally in\n * DataTables. To manipulate / transform the data returned by the server\n * use `ajax.dataSrc`, or use `ajax` as a function (see below).\n *\n * `function`\n * ----------\n *\n * As a function, making the Ajax call is left up to yourself allowing\n * complete control of the Ajax request. Indeed, if desired, a method other\n * than Ajax could be used to obtain the required data, such as Web storage\n * or an AIR database.\n *\n * The function is given four parameters and no return is required. The\n * parameters are:\n *\n * 1. _object_ - Data to send to the server\n * 2. _function_ - Callback function that must be executed when the required\n * data has been obtained. That data should be passed into the callback\n * as the only parameter\n * 3. _object_ - DataTables settings object for the table\n *\n * Note that this supersedes `fnServerData` from DataTables 1.9-.\n *\n * @type string|object|function\n * @default null\n *\n * @dtopt Option\n * @name DataTable.defaults.ajax\n * @since 1.10.0\n *\n * @example\n * // Get JSON data from a file via Ajax.\n * // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default).\n * $('#example').dataTable( {\n * \"ajax\": \"data.json\"\n * } );\n *\n * @example\n * // Get JSON data from a file via Ajax, using `dataSrc` to change\n * // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`)\n * $('#example').dataTable( {\n * \"ajax\": {\n * \"url\": \"data.json\",\n * \"dataSrc\": \"tableData\"\n * }\n * } );\n *\n * @example\n * // Get JSON data from a file via Ajax, using `dataSrc` to read data\n * // from a plain array rather than an array in an object\n * $('#example').dataTable( {\n * \"ajax\": {\n * \"url\": \"data.json\",\n * \"dataSrc\": \"\"\n * }\n * } );\n *\n * @example\n * // Manipulate the data returned from the server - add a link to data\n * // (note this can, should, be done using `render` for the column - this\n * // is just a simple example of how the data can be manipulated).\n * $('#example').dataTable( {\n * \"ajax\": {\n * \"url\": \"data.json\",\n * \"dataSrc\": function ( json ) {\n * for ( var i=0, ien=json.length ; iView message';\n * }\n * return json;\n * }\n * }\n * } );\n *\n * @example\n * // Add data to the request\n * $('#example').dataTable( {\n * \"ajax\": {\n * \"url\": \"data.json\",\n * \"data\": function ( d ) {\n * return {\n * \"extra_search\": $('#extra').val()\n * };\n * }\n * }\n * } );\n *\n * @example\n * // Send request as POST\n * $('#example').dataTable( {\n * \"ajax\": {\n * \"url\": \"data.json\",\n * \"type\": \"POST\"\n * }\n * } );\n *\n * @example\n * // Get the data from localStorage (could interface with a form for\n * // adding, editing and removing rows).\n * $('#example').dataTable( {\n * \"ajax\": function (data, callback, settings) {\n * callback(\n * JSON.parse( localStorage.getItem('dataTablesData') )\n * );\n * }\n * } );\n */\n \"ajax\": null,\n\n /**\n * This parameter allows you to readily specify the entries in the length drop\n * down menu that DataTables shows when pagination is enabled. It can be\n * either a 1D array of options which will be used for both the displayed\n * option and the value, or a 2D array which will use the array in the first\n * position as the value, and the array in the second position as the\n * displayed options (useful for language strings such as 'All').\n *\n * Note that the `pageLength` property will be automatically set to the\n * first value given in this array, unless `pageLength` is also provided.\n * @type array\n * @default [ 10, 25, 50, 100 ]\n *\n * @dtopt Option\n * @name DataTable.defaults.lengthMenu\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"lengthMenu\": [[10, 25, 50, -1], [10, 25, 50, \"All\"]]\n * } );\n * } );\n */\n \"aLengthMenu\": [10, 25, 50, 100],\n\n /**\n * The `columns` option in the initialisation parameter allows you to define\n * details about the way individual columns behave. For a full list of\n * column options that can be set, please see\n * {@link DataTable.defaults.column}. Note that if you use `columns` to\n * define your columns, you must have an entry in the array for every single\n * column that you have in your table (these can be null if you don't which\n * to specify any options).\n * @member\n *\n * @name DataTable.defaults.column\n */\n \"aoColumns\": null,\n\n /**\n * Very similar to `columns`, `columnDefs` allows you to target a specific\n * column, multiple columns, or all columns, using the `targets` property of\n * each object in the array. This allows great flexibility when creating\n * tables, as the `columnDefs` arrays can be of any length, targeting the\n * columns you specifically want. `columnDefs` may use any of the column\n * options available: {@link DataTable.defaults.column}, but it _must_\n * have `targets` defined in each object in the array. Values in the `targets`\n * array may be:\n * \n * a string - class name will be matched on the TH for the column \n * 0 or a positive integer - column index counting from the left \n * a negative integer - column index counting from the right \n * the string \"_all\" - all columns (i.e. assign a default) \n * \n * @member\n *\n * @name DataTable.defaults.columnDefs\n */\n \"aoColumnDefs\": null,\n\n /**\n * Basically the same as `search`, this parameter defines the individual column\n * filtering state at initialisation time. The array must be of the same size\n * as the number of columns, and each element be an object with the parameters\n * `search` and `escapeRegex` (the latter is optional). 'null' is also\n * accepted and the default will be used.\n * @type array\n * @default []\n *\n * @dtopt Option\n * @name DataTable.defaults.searchCols\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"searchCols\": [\n * null,\n * { \"search\": \"My filter\" },\n * null,\n * { \"search\": \"^[0-9]\", \"escapeRegex\": false }\n * ]\n * } );\n * } )\n */\n \"aoSearchCols\": [],\n\n /**\n * An array of CSS classes that should be applied to displayed rows. This\n * array may be of any length, and DataTables will apply each class\n * sequentially, looping when required.\n * @type array\n * @default null Will take the values determined by the `oClasses.stripe*`\n * options \n *\n * @dtopt Option\n * @name DataTable.defaults.stripeClasses\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"stripeClasses\": [ 'strip1', 'strip2', 'strip3' ]\n * } );\n * } )\n */\n \"asStripeClasses\": null,\n\n /**\n * Enable or disable automatic column width calculation. This can be disabled\n * as an optimisation (it takes some time to calculate the widths) if the\n * tables widths are passed in using `columns`.\n * @type boolean\n * @default true\n *\n * @dtopt Features\n * @name DataTable.defaults.autoWidth\n *\n * @example\n * $(document).ready( function () {\n * $('#example').dataTable( {\n * \"autoWidth\": false\n * } );\n * } );\n */\n \"bAutoWidth\": true,\n\n /**\n * Deferred rendering can provide DataTables with a huge speed boost when you\n * are using an Ajax or JS data source for the table. This option, when set to\n * true, will cause DataTables to defer the creation of the table elements for\n * each row until they are needed for a draw - saving a significant amount of\n * time.\n * @type boolean\n * @default false\n *\n * @dtopt Features\n * @name DataTable.defaults.deferRender\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"ajax\": \"sources/arrays.txt\",\n * \"deferRender\": true\n * } );\n * } );\n */\n \"bDeferRender\": false,\n\n /**\n * Replace a DataTable which matches the given selector and replace it with\n * one which has the properties of the new initialisation object passed. If no\n * table matches the selector, then the new DataTable will be constructed as\n * per normal.\n * @type boolean\n * @default false\n *\n * @dtopt Options\n * @name DataTable.defaults.destroy\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"srollY\": \"200px\",\n * \"paginate\": false\n * } );\n *\n * // Some time later....\n * $('#example').dataTable( {\n * \"filter\": false,\n * \"destroy\": true\n * } );\n * } );\n */\n \"bDestroy\": false,\n\n /**\n * Enable or disable filtering of data. Filtering in DataTables is \"smart\" in\n * that it allows the end user to input multiple words (space separated) and\n * will match a row containing those words, even if not in the order that was\n * specified (this allow matching across multiple columns). Note that if you\n * wish to use filtering in DataTables this must remain 'true' - to remove the\n * default filtering input box and retain filtering abilities, please use\n * {@link DataTable.defaults.dom}.\n * @type boolean\n * @default true\n *\n * @dtopt Features\n * @name DataTable.defaults.searching\n *\n * @example\n * $(document).ready( function () {\n * $('#example').dataTable( {\n * \"searching\": false\n * } );\n * } );\n */\n \"bFilter\": true,\n\n /**\n * Enable or disable the table information display. This shows information\n * about the data that is currently visible on the page, including information\n * about filtered data if that action is being performed.\n * @type boolean\n * @default true\n *\n * @dtopt Features\n * @name DataTable.defaults.info\n *\n * @example\n * $(document).ready( function () {\n * $('#example').dataTable( {\n * \"info\": false\n * } );\n * } );\n */\n \"bInfo\": true,\n\n /**\n * Allows the end user to select the size of a formatted page from a select\n * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`).\n * @type boolean\n * @default true\n *\n * @dtopt Features\n * @name DataTable.defaults.lengthChange\n *\n * @example\n * $(document).ready( function () {\n * $('#example').dataTable( {\n * \"lengthChange\": false\n * } );\n * } );\n */\n \"bLengthChange\": true,\n\n /**\n * Enable or disable pagination.\n * @type boolean\n * @default true\n *\n * @dtopt Features\n * @name DataTable.defaults.paging\n *\n * @example\n * $(document).ready( function () {\n * $('#example').dataTable( {\n * \"paging\": false\n * } );\n * } );\n */\n \"bPaginate\": true,\n\n /**\n * Enable or disable the display of a 'processing' indicator when the table is\n * being processed (e.g. a sort). This is particularly useful for tables with\n * large amounts of data where it can take a noticeable amount of time to sort\n * the entries.\n * @type boolean\n * @default false\n *\n * @dtopt Features\n * @name DataTable.defaults.processing\n *\n * @example\n * $(document).ready( function () {\n * $('#example').dataTable( {\n * \"processing\": true\n * } );\n * } );\n */\n \"bProcessing\": false,\n\n /**\n * Retrieve the DataTables object for the given selector. Note that if the\n * table has already been initialised, this parameter will cause DataTables\n * to simply return the object that has already been set up - it will not take\n * account of any changes you might have made to the initialisation object\n * passed to DataTables (setting this parameter to true is an acknowledgement\n * that you understand this). `destroy` can be used to reinitialise a table if\n * you need.\n * @type boolean\n * @default false\n *\n * @dtopt Options\n * @name DataTable.defaults.retrieve\n *\n * @example\n * $(document).ready( function() {\n * initTable();\n * tableActions();\n * } );\n *\n * function initTable ()\n * {\n * return $('#example').dataTable( {\n * \"scrollY\": \"200px\",\n * \"paginate\": false,\n * \"retrieve\": true\n * } );\n * }\n *\n * function tableActions ()\n * {\n * var table = initTable();\n * // perform API operations with oTable\n * }\n */\n \"bRetrieve\": false,\n\n /**\n * When vertical (y) scrolling is enabled, DataTables will force the height of\n * the table's viewport to the given height at all times (useful for layout).\n * However, this can look odd when filtering data down to a small data set,\n * and the footer is left \"floating\" further down. This parameter (when\n * enabled) will cause DataTables to collapse the table's viewport down when\n * the result set will fit within the given Y height.\n * @type boolean\n * @default false\n *\n * @dtopt Options\n * @name DataTable.defaults.scrollCollapse\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"scrollY\": \"200\",\n * \"scrollCollapse\": true\n * } );\n * } );\n */\n \"bScrollCollapse\": false,\n\n /**\n * Configure DataTables to use server-side processing. Note that the\n * `ajax` parameter must also be given in order to give DataTables a\n * source to obtain the required data for each draw.\n * @type boolean\n * @default false\n *\n * @dtopt Features\n * @dtopt Server-side\n * @name DataTable.defaults.serverSide\n *\n * @example\n * $(document).ready( function () {\n * $('#example').dataTable( {\n * \"serverSide\": true,\n * \"ajax\": \"xhr.php\"\n * } );\n * } );\n */\n \"bServerSide\": false,\n\n /**\n * Enable or disable sorting of columns. Sorting of individual columns can be\n * disabled by the `sortable` option for each column.\n * @type boolean\n * @default true\n *\n * @dtopt Features\n * @name DataTable.defaults.ordering\n *\n * @example\n * $(document).ready( function () {\n * $('#example').dataTable( {\n * \"ordering\": false\n * } );\n * } );\n */\n \"bSort\": true,\n\n /**\n * Enable or display DataTables' ability to sort multiple columns at the\n * same time (activated by shift-click by the user).\n * @type boolean\n * @default true\n *\n * @dtopt Options\n * @name DataTable.defaults.orderMulti\n *\n * @example\n * // Disable multiple column sorting ability\n * $(document).ready( function () {\n * $('#example').dataTable( {\n * \"orderMulti\": false\n * } );\n * } );\n */\n \"bSortMulti\": true,\n\n /**\n * Allows control over whether DataTables should use the top (true) unique\n * cell that is found for a single column, or the bottom (false - default).\n * This is useful when using complex headers.\n * @type boolean\n * @default false\n *\n * @dtopt Options\n * @name DataTable.defaults.orderCellsTop\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"orderCellsTop\": true\n * } );\n * } );\n */\n \"bSortCellsTop\": false,\n\n /**\n * Enable or disable the addition of the classes `sorting\\_1`, `sorting\\_2` and\n * `sorting\\_3` to the columns which are currently being sorted on. This is\n * presented as a feature switch as it can increase processing time (while\n * classes are removed and added) so for large data sets you might want to\n * turn this off.\n * @type boolean\n * @default true\n *\n * @dtopt Features\n * @name DataTable.defaults.orderClasses\n *\n * @example\n * $(document).ready( function () {\n * $('#example').dataTable( {\n * \"orderClasses\": false\n * } );\n * } );\n */\n \"bSortClasses\": true,\n\n /**\n * Enable or disable state saving. When enabled HTML5 `localStorage` will be\n * used to save table display information such as pagination information,\n * display length, filtering and sorting. As such when the end user reloads\n * the page the display display will match what thy had previously set up.\n *\n * Due to the use of `localStorage` the default state saving is not supported\n * in IE6 or 7. If state saving is required in those browsers, use\n * `stateSaveCallback` to provide a storage solution such as cookies.\n * @type boolean\n * @default false\n *\n * @dtopt Features\n * @name DataTable.defaults.stateSave\n *\n * @example\n * $(document).ready( function () {\n * $('#example').dataTable( {\n * \"stateSave\": true\n * } );\n * } );\n */\n \"bStateSave\": false,\n\n /**\n * This function is called when a TR element is created (and all TD child\n * elements have been inserted), or registered if using a DOM source, allowing\n * manipulation of the TR element (adding classes etc).\n * @type function\n * @param {node} row \"TR\" element for the current row\n * @param {array} data Raw data array for this row\n * @param {int} dataIndex The index of this row in the internal aoData array\n *\n * @dtopt Callbacks\n * @name DataTable.defaults.createdRow\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"createdRow\": function( row, data, dataIndex ) {\n * // Bold the grade for all 'A' grade browsers\n * if ( data[4] == \"A\" )\n * {\n * $('td:eq(4)', row).html( 'A ' );\n * }\n * }\n * } );\n * } );\n */\n \"fnCreatedRow\": null,\n\n /**\n * This function is called on every 'draw' event, and allows you to\n * dynamically modify any aspect you want about the created DOM.\n * @type function\n * @param {object} settings DataTables settings object\n *\n * @dtopt Callbacks\n * @name DataTable.defaults.drawCallback\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"drawCallback\": function( settings ) {\n * alert( 'DataTables has redrawn the table' );\n * }\n * } );\n * } );\n */\n \"fnDrawCallback\": null,\n\n /**\n * Identical to fnHeaderCallback() but for the table footer this function\n * allows you to modify the table footer on every 'draw' event.\n * @type function\n * @param {node} foot \"TR\" element for the footer\n * @param {array} data Full table data (as derived from the original HTML)\n * @param {int} start Index for the current display starting point in the\n * display array\n * @param {int} end Index for the current display ending point in the\n * display array\n * @param {array int} display Index array to translate the visual position\n * to the full data array\n *\n * @dtopt Callbacks\n * @name DataTable.defaults.footerCallback\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"footerCallback\": function( tfoot, data, start, end, display ) {\n * tfoot.getElementsByTagName('th')[0].innerHTML = \"Starting index is \"+start;\n * }\n * } );\n * } )\n */\n \"fnFooterCallback\": null,\n\n /**\n * When rendering large numbers in the information element for the table\n * (i.e. \"Showing 1 to 10 of 57 entries\") DataTables will render large numbers\n * to have a comma separator for the 'thousands' units (e.g. 1 million is\n * rendered as \"1,000,000\") to help readability for the end user. This\n * function will override the default method DataTables uses.\n * @type function\n * @member\n * @param {int} toFormat number to be formatted\n * @returns {string} formatted string for DataTables to show the number\n *\n * @dtopt Callbacks\n * @name DataTable.defaults.formatNumber\n *\n * @example\n * // Format a number using a single quote for the separator (note that\n * // this can also be done with the language.thousands option)\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"formatNumber\": function ( toFormat ) {\n * return toFormat.toString().replace(\n * /\\B(?=(\\d{3})+(?!\\d))/g, \"'\"\n * );\n * };\n * } );\n * } );\n */\n \"fnFormatNumber\": function fnFormatNumber(toFormat) {\n return toFormat.toString().replace(/\\B(?=(\\d{3})+(?!\\d))/g, this.oLanguage.sThousands);\n },\n\n /**\n * This function is called on every 'draw' event, and allows you to\n * dynamically modify the header row. This can be used to calculate and\n * display useful information about the table.\n * @type function\n * @param {node} head \"TR\" element for the header\n * @param {array} data Full table data (as derived from the original HTML)\n * @param {int} start Index for the current display starting point in the\n * display array\n * @param {int} end Index for the current display ending point in the\n * display array\n * @param {array int} display Index array to translate the visual position\n * to the full data array\n *\n * @dtopt Callbacks\n * @name DataTable.defaults.headerCallback\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"fheaderCallback\": function( head, data, start, end, display ) {\n * head.getElementsByTagName('th')[0].innerHTML = \"Displaying \"+(end-start)+\" records\";\n * }\n * } );\n * } )\n */\n \"fnHeaderCallback\": null,\n\n /**\n * The information element can be used to convey information about the current\n * state of the table. Although the internationalisation options presented by\n * DataTables are quite capable of dealing with most customisations, there may\n * be times where you wish to customise the string further. This callback\n * allows you to do exactly that.\n * @type function\n * @param {object} oSettings DataTables settings object\n * @param {int} start Starting position in data for the draw\n * @param {int} end End position in data for the draw\n * @param {int} max Total number of rows in the table (regardless of\n * filtering)\n * @param {int} total Total number of rows in the data set, after filtering\n * @param {string} pre The string that DataTables has formatted using it's\n * own rules\n * @returns {string} The string to be displayed in the information element.\n *\n * @dtopt Callbacks\n * @name DataTable.defaults.infoCallback\n *\n * @example\n * $('#example').dataTable( {\n * \"infoCallback\": function( settings, start, end, max, total, pre ) {\n * return start +\" to \"+ end;\n * }\n * } );\n */\n \"fnInfoCallback\": null,\n\n /**\n * Called when the table has been initialised. Normally DataTables will\n * initialise sequentially and there will be no need for this function,\n * however, this does not hold true when using external language information\n * since that is obtained using an async XHR call.\n * @type function\n * @param {object} settings DataTables settings object\n * @param {object} json The JSON object request from the server - only\n * present if client-side Ajax sourced data is used\n *\n * @dtopt Callbacks\n * @name DataTable.defaults.initComplete\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"initComplete\": function(settings, json) {\n * alert( 'DataTables has finished its initialisation.' );\n * }\n * } );\n * } )\n */\n \"fnInitComplete\": null,\n\n /**\n * Called at the very start of each table draw and can be used to cancel the\n * draw by returning false, any other return (including undefined) results in\n * the full draw occurring).\n * @type function\n * @param {object} settings DataTables settings object\n * @returns {boolean} False will cancel the draw, anything else (including no\n * return) will allow it to complete.\n *\n * @dtopt Callbacks\n * @name DataTable.defaults.preDrawCallback\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"preDrawCallback\": function( settings ) {\n * if ( $('#test').val() == 1 ) {\n * return false;\n * }\n * }\n * } );\n * } );\n */\n \"fnPreDrawCallback\": null,\n\n /**\n * This function allows you to 'post process' each row after it have been\n * generated for each table draw, but before it is rendered on screen. This\n * function might be used for setting the row class name etc.\n * @type function\n * @param {node} row \"TR\" element for the current row\n * @param {array} data Raw data array for this row\n * @param {int} displayIndex The display index for the current table draw\n * @param {int} displayIndexFull The index of the data in the full list of\n * rows (after filtering)\n *\n * @dtopt Callbacks\n * @name DataTable.defaults.rowCallback\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"rowCallback\": function( row, data, displayIndex, displayIndexFull ) {\n * // Bold the grade for all 'A' grade browsers\n * if ( data[4] == \"A\" ) {\n * $('td:eq(4)', row).html( 'A ' );\n * }\n * }\n * } );\n * } );\n */\n \"fnRowCallback\": null,\n\n /**\n * __Deprecated__ The functionality provided by this parameter has now been\n * superseded by that provided through `ajax`, which should be used instead.\n *\n * This parameter allows you to override the default function which obtains\n * the data from the server so something more suitable for your application.\n * For example you could use POST data, or pull information from a Gears or\n * AIR database.\n * @type function\n * @member\n * @param {string} source HTTP source to obtain the data from (`ajax`)\n * @param {array} data A key/value pair object containing the data to send\n * to the server\n * @param {function} callback to be called on completion of the data get\n * process that will draw the data on the page.\n * @param {object} settings DataTables settings object\n *\n * @dtopt Callbacks\n * @dtopt Server-side\n * @name DataTable.defaults.serverData\n *\n * @deprecated 1.10. Please use `ajax` for this functionality now.\n */\n \"fnServerData\": null,\n\n /**\n * __Deprecated__ The functionality provided by this parameter has now been\n * superseded by that provided through `ajax`, which should be used instead.\n *\n * It is often useful to send extra data to the server when making an Ajax\n * request - for example custom filtering information, and this callback\n * function makes it trivial to send extra information to the server. The\n * passed in parameter is the data set that has been constructed by\n * DataTables, and you can add to this or modify it as you require.\n * @type function\n * @param {array} data Data array (array of objects which are name/value\n * pairs) that has been constructed by DataTables and will be sent to the\n * server. In the case of Ajax sourced data with server-side processing\n * this will be an empty array, for server-side processing there will be a\n * significant number of parameters!\n * @returns {undefined} Ensure that you modify the data array passed in,\n * as this is passed by reference.\n *\n * @dtopt Callbacks\n * @dtopt Server-side\n * @name DataTable.defaults.serverParams\n *\n * @deprecated 1.10. Please use `ajax` for this functionality now.\n */\n \"fnServerParams\": null,\n\n /**\n * Load the table state. With this function you can define from where, and how, the\n * state of a table is loaded. By default DataTables will load from `localStorage`\n * but you might wish to use a server-side database or cookies.\n * @type function\n * @member\n * @param {object} settings DataTables settings object\n * @param {object} callback Callback that can be executed when done. It\n * should be passed the loaded state object.\n * @return {object} The DataTables state object to be loaded\n *\n * @dtopt Callbacks\n * @name DataTable.defaults.stateLoadCallback\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"stateSave\": true,\n * \"stateLoadCallback\": function (settings, callback) {\n * $.ajax( {\n * \"url\": \"/state_load\",\n * \"dataType\": \"json\",\n * \"success\": function (json) {\n * callback( json );\n * }\n * } );\n * }\n * } );\n * } );\n */\n \"fnStateLoadCallback\": function fnStateLoadCallback(settings) {\n try {\n return JSON.parse((settings.iStateDuration === -1 ? sessionStorage : localStorage).getItem('DataTables_' + settings.sInstance + '_' + location.pathname));\n } catch (e) {}\n },\n\n /**\n * Callback which allows modification of the saved state prior to loading that state.\n * This callback is called when the table is loading state from the stored data, but\n * prior to the settings object being modified by the saved state. Note that for\n * plug-in authors, you should use the `stateLoadParams` event to load parameters for\n * a plug-in.\n * @type function\n * @param {object} settings DataTables settings object\n * @param {object} data The state object that is to be loaded\n *\n * @dtopt Callbacks\n * @name DataTable.defaults.stateLoadParams\n *\n * @example\n * // Remove a saved filter, so filtering is never loaded\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"stateSave\": true,\n * \"stateLoadParams\": function (settings, data) {\n * data.oSearch.sSearch = \"\";\n * }\n * } );\n * } );\n *\n * @example\n * // Disallow state loading by returning false\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"stateSave\": true,\n * \"stateLoadParams\": function (settings, data) {\n * return false;\n * }\n * } );\n * } );\n */\n \"fnStateLoadParams\": null,\n\n /**\n * Callback that is called when the state has been loaded from the state saving method\n * and the DataTables settings object has been modified as a result of the loaded state.\n * @type function\n * @param {object} settings DataTables settings object\n * @param {object} data The state object that was loaded\n *\n * @dtopt Callbacks\n * @name DataTable.defaults.stateLoaded\n *\n * @example\n * // Show an alert with the filtering value that was saved\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"stateSave\": true,\n * \"stateLoaded\": function (settings, data) {\n * alert( 'Saved filter was: '+data.oSearch.sSearch );\n * }\n * } );\n * } );\n */\n \"fnStateLoaded\": null,\n\n /**\n * Save the table state. This function allows you to define where and how the state\n * information for the table is stored By default DataTables will use `localStorage`\n * but you might wish to use a server-side database or cookies.\n * @type function\n * @member\n * @param {object} settings DataTables settings object\n * @param {object} data The state object to be saved\n *\n * @dtopt Callbacks\n * @name DataTable.defaults.stateSaveCallback\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"stateSave\": true,\n * \"stateSaveCallback\": function (settings, data) {\n * // Send an Ajax request to the server with the state object\n * $.ajax( {\n * \"url\": \"/state_save\",\n * \"data\": data,\n * \"dataType\": \"json\",\n * \"method\": \"POST\"\n * \"success\": function () {}\n * } );\n * }\n * } );\n * } );\n */\n \"fnStateSaveCallback\": function fnStateSaveCallback(settings, data) {\n try {\n (settings.iStateDuration === -1 ? sessionStorage : localStorage).setItem('DataTables_' + settings.sInstance + '_' + location.pathname, JSON.stringify(data));\n } catch (e) {}\n },\n\n /**\n * Callback which allows modification of the state to be saved. Called when the table\n * has changed state a new state save is required. This method allows modification of\n * the state saving object prior to actually doing the save, including addition or\n * other state properties or modification. Note that for plug-in authors, you should\n * use the `stateSaveParams` event to save parameters for a plug-in.\n * @type function\n * @param {object} settings DataTables settings object\n * @param {object} data The state object to be saved\n *\n * @dtopt Callbacks\n * @name DataTable.defaults.stateSaveParams\n *\n * @example\n * // Remove a saved filter, so filtering is never saved\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"stateSave\": true,\n * \"stateSaveParams\": function (settings, data) {\n * data.oSearch.sSearch = \"\";\n * }\n * } );\n * } );\n */\n \"fnStateSaveParams\": null,\n\n /**\n * Duration for which the saved state information is considered valid. After this period\n * has elapsed the state will be returned to the default.\n * Value is given in seconds.\n * @type int\n * @default 7200 (2 hours) \n *\n * @dtopt Options\n * @name DataTable.defaults.stateDuration\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"stateDuration\": 60*60*24; // 1 day\n * } );\n * } )\n */\n \"iStateDuration\": 7200,\n\n /**\n * When enabled DataTables will not make a request to the server for the first\n * page draw - rather it will use the data already on the page (no sorting etc\n * will be applied to it), thus saving on an XHR at load time. `deferLoading`\n * is used to indicate that deferred loading is required, but it is also used\n * to tell DataTables how many records there are in the full table (allowing\n * the information element and pagination to be displayed correctly). In the case\n * where a filtering is applied to the table on initial load, this can be\n * indicated by giving the parameter as an array, where the first element is\n * the number of records available after filtering and the second element is the\n * number of records without filtering (allowing the table information element\n * to be shown correctly).\n * @type int | array\n * @default null\n *\n * @dtopt Options\n * @name DataTable.defaults.deferLoading\n *\n * @example\n * // 57 records available in the table, no filtering applied\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"serverSide\": true,\n * \"ajax\": \"scripts/server_processing.php\",\n * \"deferLoading\": 57\n * } );\n * } );\n *\n * @example\n * // 57 records after filtering, 100 without filtering (an initial filter applied)\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"serverSide\": true,\n * \"ajax\": \"scripts/server_processing.php\",\n * \"deferLoading\": [ 57, 100 ],\n * \"search\": {\n * \"search\": \"my_filter\"\n * }\n * } );\n * } );\n */\n \"iDeferLoading\": null,\n\n /**\n * Number of rows to display on a single page when using pagination. If\n * feature enabled (`lengthChange`) then the end user will be able to override\n * this to a custom setting using a pop-up menu.\n * @type int\n * @default 10\n *\n * @dtopt Options\n * @name DataTable.defaults.pageLength\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"pageLength\": 50\n * } );\n * } )\n */\n \"iDisplayLength\": 10,\n\n /**\n * Define the starting point for data display when using DataTables with\n * pagination. Note that this parameter is the number of records, rather than\n * the page number, so if you have 10 records per page and want to start on\n * the third page, it should be \"20\".\n * @type int\n * @default 0\n *\n * @dtopt Options\n * @name DataTable.defaults.displayStart\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"displayStart\": 20\n * } );\n * } )\n */\n \"iDisplayStart\": 0,\n\n /**\n * By default DataTables allows keyboard navigation of the table (sorting, paging,\n * and filtering) by adding a `tabindex` attribute to the required elements. This\n * allows you to tab through the controls and press the enter key to activate them.\n * The tabindex is default 0, meaning that the tab follows the flow of the document.\n * You can overrule this using this parameter if you wish. Use a value of -1 to\n * disable built-in keyboard navigation.\n * @type int\n * @default 0\n *\n * @dtopt Options\n * @name DataTable.defaults.tabIndex\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"tabIndex\": 1\n * } );\n * } );\n */\n \"iTabIndex\": 0,\n\n /**\n * Classes that DataTables assigns to the various components and features\n * that it adds to the HTML table. This allows classes to be configured\n * during initialisation in addition to through the static\n * {@link DataTable.ext.oStdClasses} object).\n * @namespace\n * @name DataTable.defaults.classes\n */\n \"oClasses\": {},\n\n /**\n * All strings that DataTables uses in the user interface that it creates\n * are defined in this object, allowing you to modified them individually or\n * completely replace them all as required.\n * @namespace\n * @name DataTable.defaults.language\n */\n \"oLanguage\": {\n /**\n * Strings that are used for WAI-ARIA labels and controls only (these are not\n * actually visible on the page, but will be read by screenreaders, and thus\n * must be internationalised as well).\n * @namespace\n * @name DataTable.defaults.language.aria\n */\n \"oAria\": {\n /**\n * ARIA label that is added to the table headers when the column may be\n * sorted ascending by activing the column (click or return when focused).\n * Note that the column header is prefixed to this string.\n * @type string\n * @default : activate to sort column ascending\n *\n * @dtopt Language\n * @name DataTable.defaults.language.aria.sortAscending\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"language\": {\n * \"aria\": {\n * \"sortAscending\": \" - click/return to sort ascending\"\n * }\n * }\n * } );\n * } );\n */\n \"sSortAscending\": \": activate to sort column ascending\",\n\n /**\n * ARIA label that is added to the table headers when the column may be\n * sorted descending by activing the column (click or return when focused).\n * Note that the column header is prefixed to this string.\n * @type string\n * @default : activate to sort column ascending\n *\n * @dtopt Language\n * @name DataTable.defaults.language.aria.sortDescending\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"language\": {\n * \"aria\": {\n * \"sortDescending\": \" - click/return to sort descending\"\n * }\n * }\n * } );\n * } );\n */\n \"sSortDescending\": \": activate to sort column descending\"\n },\n\n /**\n * Pagination string used by DataTables for the built-in pagination\n * control types.\n * @namespace\n * @name DataTable.defaults.language.paginate\n */\n \"oPaginate\": {\n /**\n * Text to use when using the 'full_numbers' type of pagination for the\n * button to take the user to the first page.\n * @type string\n * @default First\n *\n * @dtopt Language\n * @name DataTable.defaults.language.paginate.first\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"language\": {\n * \"paginate\": {\n * \"first\": \"First page\"\n * }\n * }\n * } );\n * } );\n */\n \"sFirst\": \"First\",\n\n /**\n * Text to use when using the 'full_numbers' type of pagination for the\n * button to take the user to the last page.\n * @type string\n * @default Last\n *\n * @dtopt Language\n * @name DataTable.defaults.language.paginate.last\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"language\": {\n * \"paginate\": {\n * \"last\": \"Last page\"\n * }\n * }\n * } );\n * } );\n */\n \"sLast\": \"Last\",\n\n /**\n * Text to use for the 'next' pagination button (to take the user to the\n * next page).\n * @type string\n * @default Next\n *\n * @dtopt Language\n * @name DataTable.defaults.language.paginate.next\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"language\": {\n * \"paginate\": {\n * \"next\": \"Next page\"\n * }\n * }\n * } );\n * } );\n */\n \"sNext\": \"Next\",\n\n /**\n * Text to use for the 'previous' pagination button (to take the user to\n * the previous page).\n * @type string\n * @default Previous\n *\n * @dtopt Language\n * @name DataTable.defaults.language.paginate.previous\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"language\": {\n * \"paginate\": {\n * \"previous\": \"Previous page\"\n * }\n * }\n * } );\n * } );\n */\n \"sPrevious\": \"Previous\"\n },\n\n /**\n * This string is shown in preference to `zeroRecords` when the table is\n * empty of data (regardless of filtering). Note that this is an optional\n * parameter - if it is not given, the value of `zeroRecords` will be used\n * instead (either the default or given value).\n * @type string\n * @default No data available in table\n *\n * @dtopt Language\n * @name DataTable.defaults.language.emptyTable\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"language\": {\n * \"emptyTable\": \"No data available in table\"\n * }\n * } );\n * } );\n */\n \"sEmptyTable\": \"No data available in table\",\n\n /**\n * This string gives information to the end user about the information\n * that is current on display on the page. The following tokens can be\n * used in the string and will be dynamically replaced as the table\n * display updates. This tokens can be placed anywhere in the string, or\n * removed as needed by the language requires:\n *\n * * `\\_START\\_` - Display index of the first record on the current page\n * * `\\_END\\_` - Display index of the last record on the current page\n * * `\\_TOTAL\\_` - Number of records in the table after filtering\n * * `\\_MAX\\_` - Number of records in the table without filtering\n * * `\\_PAGE\\_` - Current page number\n * * `\\_PAGES\\_` - Total number of pages of data in the table\n *\n * @type string\n * @default Showing _START_ to _END_ of _TOTAL_ entries\n *\n * @dtopt Language\n * @name DataTable.defaults.language.info\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"language\": {\n * \"info\": \"Showing page _PAGE_ of _PAGES_\"\n * }\n * } );\n * } );\n */\n \"sInfo\": \"Showing _START_ to _END_ of _TOTAL_ entries\",\n\n /**\n * Display information string for when the table is empty. Typically the\n * format of this string should match `info`.\n * @type string\n * @default Showing 0 to 0 of 0 entries\n *\n * @dtopt Language\n * @name DataTable.defaults.language.infoEmpty\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"language\": {\n * \"infoEmpty\": \"No entries to show\"\n * }\n * } );\n * } );\n */\n \"sInfoEmpty\": \"Showing 0 to 0 of 0 entries\",\n\n /**\n * When a user filters the information in a table, this string is appended\n * to the information (`info`) to give an idea of how strong the filtering\n * is. The variable _MAX_ is dynamically updated.\n * @type string\n * @default (filtered from _MAX_ total entries)\n *\n * @dtopt Language\n * @name DataTable.defaults.language.infoFiltered\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"language\": {\n * \"infoFiltered\": \" - filtering from _MAX_ records\"\n * }\n * } );\n * } );\n */\n \"sInfoFiltered\": \"(filtered from _MAX_ total entries)\",\n\n /**\n * If can be useful to append extra information to the info string at times,\n * and this variable does exactly that. This information will be appended to\n * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are\n * being used) at all times.\n * @type string\n * @default Empty string \n *\n * @dtopt Language\n * @name DataTable.defaults.language.infoPostFix\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"language\": {\n * \"infoPostFix\": \"All records shown are derived from real information.\"\n * }\n * } );\n * } );\n */\n \"sInfoPostFix\": \"\",\n\n /**\n * This decimal place operator is a little different from the other\n * language options since DataTables doesn't output floating point\n * numbers, so it won't ever use this for display of a number. Rather,\n * what this parameter does is modify the sort methods of the table so\n * that numbers which are in a format which has a character other than\n * a period (`.`) as a decimal place will be sorted numerically.\n *\n * Note that numbers with different decimal places cannot be shown in\n * the same table and still be sortable, the table must be consistent.\n * However, multiple different tables on the page can use different\n * decimal place characters.\n * @type string\n * @default \n *\n * @dtopt Language\n * @name DataTable.defaults.language.decimal\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"language\": {\n * \"decimal\": \",\"\n * \"thousands\": \".\"\n * }\n * } );\n * } );\n */\n \"sDecimal\": \"\",\n\n /**\n * DataTables has a build in number formatter (`formatNumber`) which is\n * used to format large numbers that are used in the table information.\n * By default a comma is used, but this can be trivially changed to any\n * character you wish with this parameter.\n * @type string\n * @default ,\n *\n * @dtopt Language\n * @name DataTable.defaults.language.thousands\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"language\": {\n * \"thousands\": \"'\"\n * }\n * } );\n * } );\n */\n \"sThousands\": \",\",\n\n /**\n * Detail the action that will be taken when the drop down menu for the\n * pagination length option is changed. The '_MENU_' variable is replaced\n * with a default select list of 10, 25, 50 and 100, and can be replaced\n * with a custom select box if required.\n * @type string\n * @default Show _MENU_ entries\n *\n * @dtopt Language\n * @name DataTable.defaults.language.lengthMenu\n *\n * @example\n * // Language change only\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"language\": {\n * \"lengthMenu\": \"Display _MENU_ records\"\n * }\n * } );\n * } );\n *\n * @example\n * // Language and options change\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"language\": {\n * \"lengthMenu\": 'Display '+\n * '10 '+\n * '20 '+\n * '30 '+\n * '40 '+\n * '50 '+\n * 'All '+\n * ' records'\n * }\n * } );\n * } );\n */\n \"sLengthMenu\": \"Show _MENU_ entries\",\n\n /**\n * When using Ajax sourced data and during the first draw when DataTables is\n * gathering the data, this message is shown in an empty row in the table to\n * indicate to the end user the the data is being loaded. Note that this\n * parameter is not used when loading data by server-side processing, just\n * Ajax sourced data with client-side processing.\n * @type string\n * @default Loading...\n *\n * @dtopt Language\n * @name DataTable.defaults.language.loadingRecords\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"language\": {\n * \"loadingRecords\": \"Please wait - loading...\"\n * }\n * } );\n * } );\n */\n \"sLoadingRecords\": \"Loading...\",\n\n /**\n * Text which is displayed when the table is processing a user action\n * (usually a sort command or similar).\n * @type string\n * @default Processing...\n *\n * @dtopt Language\n * @name DataTable.defaults.language.processing\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"language\": {\n * \"processing\": \"DataTables is currently busy\"\n * }\n * } );\n * } );\n */\n \"sProcessing\": \"Processing...\",\n\n /**\n * Details the actions that will be taken when the user types into the\n * filtering input text box. The variable \"_INPUT_\", if used in the string,\n * is replaced with the HTML text box for the filtering input allowing\n * control over where it appears in the string. If \"_INPUT_\" is not given\n * then the input box is appended to the string automatically.\n * @type string\n * @default Search:\n *\n * @dtopt Language\n * @name DataTable.defaults.language.search\n *\n * @example\n * // Input text box will be appended at the end automatically\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"language\": {\n * \"search\": \"Filter records:\"\n * }\n * } );\n * } );\n *\n * @example\n * // Specify where the filter should appear\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"language\": {\n * \"search\": \"Apply filter _INPUT_ to table\"\n * }\n * } );\n * } );\n */\n \"sSearch\": \"Search:\",\n\n /**\n * Assign a `placeholder` attribute to the search `input` element\n * @type string\n * @default \n *\n * @dtopt Language\n * @name DataTable.defaults.language.searchPlaceholder\n */\n \"sSearchPlaceholder\": \"\",\n\n /**\n * All of the language information can be stored in a file on the\n * server-side, which DataTables will look up if this parameter is passed.\n * It must store the URL of the language file, which is in a JSON format,\n * and the object has the same properties as the oLanguage object in the\n * initialiser object (i.e. the above parameters). Please refer to one of\n * the example language files to see how this works in action.\n * @type string\n * @default Empty string - i.e. disabled \n *\n * @dtopt Language\n * @name DataTable.defaults.language.url\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"language\": {\n * \"url\": \"http://www.sprymedia.co.uk/dataTables/lang.txt\"\n * }\n * } );\n * } );\n */\n \"sUrl\": \"\",\n\n /**\n * Text shown inside the table records when the is no information to be\n * displayed after filtering. `emptyTable` is shown when there is simply no\n * information in the table at all (regardless of filtering).\n * @type string\n * @default No matching records found\n *\n * @dtopt Language\n * @name DataTable.defaults.language.zeroRecords\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"language\": {\n * \"zeroRecords\": \"No records to display\"\n * }\n * } );\n * } );\n */\n \"sZeroRecords\": \"No matching records found\"\n },\n\n /**\n * This parameter allows you to have define the global filtering state at\n * initialisation time. As an object the `search` parameter must be\n * defined, but all other parameters are optional. When `regex` is true,\n * the search string will be treated as a regular expression, when false\n * (default) it will be treated as a straight string. When `smart`\n * DataTables will use it's smart filtering methods (to word match at\n * any point in the data), when false this will not be done.\n * @namespace\n * @extends DataTable.models.oSearch\n *\n * @dtopt Options\n * @name DataTable.defaults.search\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"search\": {\"search\": \"Initial search\"}\n * } );\n * } )\n */\n \"oSearch\": $.extend({}, DataTable.models.oSearch),\n\n /**\n * __Deprecated__ The functionality provided by this parameter has now been\n * superseded by that provided through `ajax`, which should be used instead.\n *\n * By default DataTables will look for the property `data` (or `aaData` for\n * compatibility with DataTables 1.9-) when obtaining data from an Ajax\n * source or for server-side processing - this parameter allows that\n * property to be changed. You can use Javascript dotted object notation to\n * get a data source for multiple levels of nesting.\n * @type string\n * @default data\n *\n * @dtopt Options\n * @dtopt Server-side\n * @name DataTable.defaults.ajaxDataProp\n *\n * @deprecated 1.10. Please use `ajax` for this functionality now.\n */\n \"sAjaxDataProp\": \"data\",\n\n /**\n * __Deprecated__ The functionality provided by this parameter has now been\n * superseded by that provided through `ajax`, which should be used instead.\n *\n * You can instruct DataTables to load data from an external\n * source using this parameter (use aData if you want to pass data in you\n * already have). Simply provide a url a JSON object can be obtained from.\n * @type string\n * @default null\n *\n * @dtopt Options\n * @dtopt Server-side\n * @name DataTable.defaults.ajaxSource\n *\n * @deprecated 1.10. Please use `ajax` for this functionality now.\n */\n \"sAjaxSource\": null,\n\n /**\n * This initialisation variable allows you to specify exactly where in the\n * DOM you want DataTables to inject the various controls it adds to the page\n * (for example you might want the pagination controls at the top of the\n * table). DIV elements (with or without a custom class) can also be added to\n * aid styling. The follow syntax is used:\n * \n * The following options are allowed:\n * \n * 'l' - Length changing \n * 'f' - Filtering input \n * 't' - The table! \n * 'i' - Information \n * 'p' - Pagination \n * 'r' - pRocessing \n * \n * \n * The following constants are allowed:\n * \n * 'H' - jQueryUI theme \"header\" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix') \n * 'F' - jQueryUI theme \"footer\" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix') \n * \n * \n * The following syntax is expected:\n * \n * '<' and '>' - div elements \n * '<\"class\" and '>' - div with a class \n * '<\"#id\" and '>' - div with an ID \n * \n * \n * Examples:\n * \n * '<\"wrapper\"flipt>' \n * '<lf<t>ip>' \n * \n * \n * \n * @type string\n * @default lfrtip (when `jQueryUI` is false) or \n * <\"H\"lfr>t<\"F\"ip> (when `jQueryUI` is true) \n *\n * @dtopt Options\n * @name DataTable.defaults.dom\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"dom\": '<\"top\"i>rt<\"bottom\"flp><\"clear\">'\n * } );\n * } );\n */\n \"sDom\": \"lfrtip\",\n\n /**\n * Search delay option. This will throttle full table searches that use the\n * DataTables provided search input element (it does not effect calls to\n * `dt-api search()`, providing a delay before the search is made.\n * @type integer\n * @default 0\n *\n * @dtopt Options\n * @name DataTable.defaults.searchDelay\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"searchDelay\": 200\n * } );\n * } )\n */\n \"searchDelay\": null,\n\n /**\n * DataTables features six different built-in options for the buttons to\n * display for pagination control:\n *\n * * `numbers` - Page number buttons only\n * * `simple` - 'Previous' and 'Next' buttons only\n * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers\n * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons\n * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus page numbers\n * * `first_last_numbers` - 'First' and 'Last' buttons, plus page numbers\n * \n * Further methods can be added using {@link DataTable.ext.oPagination}.\n * @type string\n * @default simple_numbers\n *\n * @dtopt Options\n * @name DataTable.defaults.pagingType\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"pagingType\": \"full_numbers\"\n * } );\n * } )\n */\n \"sPaginationType\": \"simple_numbers\",\n\n /**\n * Enable horizontal scrolling. When a table is too wide to fit into a\n * certain layout, or you have a large number of columns in the table, you\n * can enable x-scrolling to show the table in a viewport, which can be\n * scrolled. This property can be `true` which will allow the table to\n * scroll horizontally when needed, or any CSS unit, or a number (in which\n * case it will be treated as a pixel measurement). Setting as simply `true`\n * is recommended.\n * @type boolean|string\n * @default blank string - i.e. disabled \n *\n * @dtopt Features\n * @name DataTable.defaults.scrollX\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"scrollX\": true,\n * \"scrollCollapse\": true\n * } );\n * } );\n */\n \"sScrollX\": \"\",\n\n /**\n * This property can be used to force a DataTable to use more width than it\n * might otherwise do when x-scrolling is enabled. For example if you have a\n * table which requires to be well spaced, this parameter is useful for\n * \"over-sizing\" the table, and thus forcing scrolling. This property can by\n * any CSS unit, or a number (in which case it will be treated as a pixel\n * measurement).\n * @type string\n * @default blank string - i.e. disabled \n *\n * @dtopt Options\n * @name DataTable.defaults.scrollXInner\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"scrollX\": \"100%\",\n * \"scrollXInner\": \"110%\"\n * } );\n * } );\n */\n \"sScrollXInner\": \"\",\n\n /**\n * Enable vertical scrolling. Vertical scrolling will constrain the DataTable\n * to the given height, and enable scrolling for any data which overflows the\n * current viewport. This can be used as an alternative to paging to display\n * a lot of data in a small area (although paging and scrolling can both be\n * enabled at the same time). This property can be any CSS unit, or a number\n * (in which case it will be treated as a pixel measurement).\n * @type string\n * @default blank string - i.e. disabled \n *\n * @dtopt Features\n * @name DataTable.defaults.scrollY\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"scrollY\": \"200px\",\n * \"paginate\": false\n * } );\n * } );\n */\n \"sScrollY\": \"\",\n\n /**\n * __Deprecated__ The functionality provided by this parameter has now been\n * superseded by that provided through `ajax`, which should be used instead.\n *\n * Set the HTTP method that is used to make the Ajax call for server-side\n * processing or Ajax sourced data.\n * @type string\n * @default GET\n *\n * @dtopt Options\n * @dtopt Server-side\n * @name DataTable.defaults.serverMethod\n *\n * @deprecated 1.10. Please use `ajax` for this functionality now.\n */\n \"sServerMethod\": \"GET\",\n\n /**\n * DataTables makes use of renderers when displaying HTML elements for\n * a table. These renderers can be added or modified by plug-ins to\n * generate suitable mark-up for a site. For example the Bootstrap\n * integration plug-in for DataTables uses a paging button renderer to\n * display pagination buttons in the mark-up required by Bootstrap.\n *\n * For further information about the renderers available see\n * DataTable.ext.renderer\n * @type string|object\n * @default null\n *\n * @name DataTable.defaults.renderer\n *\n */\n \"renderer\": null,\n\n /**\n * Set the data property name that DataTables should use to get a row's id\n * to set as the `id` property in the node.\n * @type string\n * @default DT_RowId\n *\n * @name DataTable.defaults.rowId\n */\n \"rowId\": \"DT_RowId\"\n };\n\n _fnHungarianMap(DataTable.defaults);\n /*\n * Developer note - See note in model.defaults.js about the use of Hungarian\n * notation and camel case.\n */\n\n /**\n * Column options that can be given to DataTables at initialisation time.\n * @namespace\n */\n\n\n DataTable.defaults.column = {\n /**\n * Define which column(s) an order will occur on for this column. This\n * allows a column's ordering to take multiple columns into account when\n * doing a sort or use the data from a different column. For example first\n * name / last name columns make sense to do a multi-column sort over the\n * two columns.\n * @type array|int\n * @default null Takes the value of the column index automatically \n *\n * @name DataTable.defaults.column.orderData\n * @dtopt Columns\n *\n * @example\n * // Using `columnDefs`\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"columnDefs\": [\n * { \"orderData\": [ 0, 1 ], \"targets\": [ 0 ] },\n * { \"orderData\": [ 1, 0 ], \"targets\": [ 1 ] },\n * { \"orderData\": 2, \"targets\": [ 2 ] }\n * ]\n * } );\n * } );\n *\n * @example\n * // Using `columns`\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"columns\": [\n * { \"orderData\": [ 0, 1 ] },\n * { \"orderData\": [ 1, 0 ] },\n * { \"orderData\": 2 },\n * null,\n * null\n * ]\n * } );\n * } );\n */\n \"aDataSort\": null,\n \"iDataSort\": -1,\n\n /**\n * You can control the default ordering direction, and even alter the\n * behaviour of the sort handler (i.e. only allow ascending ordering etc)\n * using this parameter.\n * @type array\n * @default [ 'asc', 'desc' ]\n *\n * @name DataTable.defaults.column.orderSequence\n * @dtopt Columns\n *\n * @example\n * // Using `columnDefs`\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"columnDefs\": [\n * { \"orderSequence\": [ \"asc\" ], \"targets\": [ 1 ] },\n * { \"orderSequence\": [ \"desc\", \"asc\", \"asc\" ], \"targets\": [ 2 ] },\n * { \"orderSequence\": [ \"desc\" ], \"targets\": [ 3 ] }\n * ]\n * } );\n * } );\n *\n * @example\n * // Using `columns`\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"columns\": [\n * null,\n * { \"orderSequence\": [ \"asc\" ] },\n * { \"orderSequence\": [ \"desc\", \"asc\", \"asc\" ] },\n * { \"orderSequence\": [ \"desc\" ] },\n * null\n * ]\n * } );\n * } );\n */\n \"asSorting\": ['asc', 'desc'],\n\n /**\n * Enable or disable filtering on the data in this column.\n * @type boolean\n * @default true\n *\n * @name DataTable.defaults.column.searchable\n * @dtopt Columns\n *\n * @example\n * // Using `columnDefs`\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"columnDefs\": [\n * { \"searchable\": false, \"targets\": [ 0 ] }\n * ] } );\n * } );\n *\n * @example\n * // Using `columns`\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"columns\": [\n * { \"searchable\": false },\n * null,\n * null,\n * null,\n * null\n * ] } );\n * } );\n */\n \"bSearchable\": true,\n\n /**\n * Enable or disable ordering on this column.\n * @type boolean\n * @default true\n *\n * @name DataTable.defaults.column.orderable\n * @dtopt Columns\n *\n * @example\n * // Using `columnDefs`\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"columnDefs\": [\n * { \"orderable\": false, \"targets\": [ 0 ] }\n * ] } );\n * } );\n *\n * @example\n * // Using `columns`\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"columns\": [\n * { \"orderable\": false },\n * null,\n * null,\n * null,\n * null\n * ] } );\n * } );\n */\n \"bSortable\": true,\n\n /**\n * Enable or disable the display of this column.\n * @type boolean\n * @default true\n *\n * @name DataTable.defaults.column.visible\n * @dtopt Columns\n *\n * @example\n * // Using `columnDefs`\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"columnDefs\": [\n * { \"visible\": false, \"targets\": [ 0 ] }\n * ] } );\n * } );\n *\n * @example\n * // Using `columns`\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"columns\": [\n * { \"visible\": false },\n * null,\n * null,\n * null,\n * null\n * ] } );\n * } );\n */\n \"bVisible\": true,\n\n /**\n * Developer definable function that is called whenever a cell is created (Ajax source,\n * etc) or processed for input (DOM source). This can be used as a compliment to mRender\n * allowing you to modify the DOM element (add background colour for example) when the\n * element is available.\n * @type function\n * @param {element} td The TD node that has been created\n * @param {*} cellData The Data for the cell\n * @param {array|object} rowData The data for the whole row\n * @param {int} row The row index for the aoData data store\n * @param {int} col The column index for aoColumns\n *\n * @name DataTable.defaults.column.createdCell\n * @dtopt Columns\n *\n * @example\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"columnDefs\": [ {\n * \"targets\": [3],\n * \"createdCell\": function (td, cellData, rowData, row, col) {\n * if ( cellData == \"1.7\" ) {\n * $(td).css('color', 'blue')\n * }\n * }\n * } ]\n * });\n * } );\n */\n \"fnCreatedCell\": null,\n\n /**\n * This parameter has been replaced by `data` in DataTables to ensure naming\n * consistency. `dataProp` can still be used, as there is backwards\n * compatibility in DataTables for this option, but it is strongly\n * recommended that you use `data` in preference to `dataProp`.\n * @name DataTable.defaults.column.dataProp\n */\n\n /**\n * This property can be used to read data from any data source property,\n * including deeply nested objects / properties. `data` can be given in a\n * number of different ways which effect its behaviour:\n *\n * * `integer` - treated as an array index for the data source. This is the\n * default that DataTables uses (incrementally increased for each column).\n * * `string` - read an object property from the data source. There are\n * three 'special' options that can be used in the string to alter how\n * DataTables reads the data from the source object:\n * * `.` - Dotted Javascript notation. Just as you use a `.` in\n * Javascript to read from nested objects, so to can the options\n * specified in `data`. For example: `browser.version` or\n * `browser.name`. If your object parameter name contains a period, use\n * `\\\\` to escape it - i.e. `first\\\\.name`.\n * * `[]` - Array notation. DataTables can automatically combine data\n * from and array source, joining the data with the characters provided\n * between the two brackets. For example: `name[, ]` would provide a\n * comma-space separated list from the source array. If no characters\n * are provided between the brackets, the original array source is\n * returned.\n * * `()` - Function notation. Adding `()` to the end of a parameter will\n * execute a function of the name given. For example: `browser()` for a\n * simple function on the data source, `browser.version()` for a\n * function in a nested property or even `browser().version` to get an\n * object property if the function called returns an object. Note that\n * function notation is recommended for use in `render` rather than\n * `data` as it is much simpler to use as a renderer.\n * * `null` - use the original data source for the row rather than plucking\n * data directly from it. This action has effects on two other\n * initialisation options:\n * * `defaultContent` - When null is given as the `data` option and\n * `defaultContent` is specified for the column, the value defined by\n * `defaultContent` will be used for the cell.\n * * `render` - When null is used for the `data` option and the `render`\n * option is specified for the column, the whole data source for the\n * row is used for the renderer.\n * * `function` - the function given will be executed whenever DataTables\n * needs to set or get the data for a cell in the column. The function\n * takes three parameters:\n * * Parameters:\n * * `{array|object}` The data source for the row\n * * `{string}` The type call data requested - this will be 'set' when\n * setting data or 'filter', 'display', 'type', 'sort' or undefined\n * when gathering data. Note that when `undefined` is given for the\n * type DataTables expects to get the raw data for the object back<\n * * `{*}` Data to set when the second parameter is 'set'.\n * * Return:\n * * The return value from the function is not required when 'set' is\n * the type of call, but otherwise the return is what will be used\n * for the data requested.\n *\n * Note that `data` is a getter and setter option. If you just require\n * formatting of data for output, you will likely want to use `render` which\n * is simply a getter and thus simpler to use.\n *\n * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The\n * name change reflects the flexibility of this property and is consistent\n * with the naming of mRender. If 'mDataProp' is given, then it will still\n * be used by DataTables, as it automatically maps the old name to the new\n * if required.\n *\n * @type string|int|function|null\n * @default null Use automatically calculated column index \n *\n * @name DataTable.defaults.column.data\n * @dtopt Columns\n *\n * @example\n * // Read table data from objects\n * // JSON structure for each row:\n * // {\n * // \"engine\": {value},\n * // \"browser\": {value},\n * // \"platform\": {value},\n * // \"version\": {value},\n * // \"grade\": {value}\n * // }\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"ajaxSource\": \"sources/objects.txt\",\n * \"columns\": [\n * { \"data\": \"engine\" },\n * { \"data\": \"browser\" },\n * { \"data\": \"platform\" },\n * { \"data\": \"version\" },\n * { \"data\": \"grade\" }\n * ]\n * } );\n * } );\n *\n * @example\n * // Read information from deeply nested objects\n * // JSON structure for each row:\n * // {\n * // \"engine\": {value},\n * // \"browser\": {value},\n * // \"platform\": {\n * // \"inner\": {value}\n * // },\n * // \"details\": [\n * // {value}, {value}\n * // ]\n * // }\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"ajaxSource\": \"sources/deep.txt\",\n * \"columns\": [\n * { \"data\": \"engine\" },\n * { \"data\": \"browser\" },\n * { \"data\": \"platform.inner\" },\n * { \"data\": \"details.0\" },\n * { \"data\": \"details.1\" }\n * ]\n * } );\n * } );\n *\n * @example\n * // Using `data` as a function to provide different information for\n * // sorting, filtering and display. In this case, currency (price)\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"columnDefs\": [ {\n * \"targets\": [ 0 ],\n * \"data\": function ( source, type, val ) {\n * if (type === 'set') {\n * source.price = val;\n * // Store the computed dislay and filter values for efficiency\n * source.price_display = val==\"\" ? \"\" : \"$\"+numberFormat(val);\n * source.price_filter = val==\"\" ? \"\" : \"$\"+numberFormat(val)+\" \"+val;\n * return;\n * }\n * else if (type === 'display') {\n * return source.price_display;\n * }\n * else if (type === 'filter') {\n * return source.price_filter;\n * }\n * // 'sort', 'type' and undefined all just use the integer\n * return source.price;\n * }\n * } ]\n * } );\n * } );\n *\n * @example\n * // Using default content\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"columnDefs\": [ {\n * \"targets\": [ 0 ],\n * \"data\": null,\n * \"defaultContent\": \"Click to edit\"\n * } ]\n * } );\n * } );\n *\n * @example\n * // Using array notation - outputting a list from an array\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"columnDefs\": [ {\n * \"targets\": [ 0 ],\n * \"data\": \"name[, ]\"\n * } ]\n * } );\n * } );\n *\n */\n \"mData\": null,\n\n /**\n * This property is the rendering partner to `data` and it is suggested that\n * when you want to manipulate data for display (including filtering,\n * sorting etc) without altering the underlying data for the table, use this\n * property. `render` can be considered to be the the read only companion to\n * `data` which is read / write (then as such more complex). Like `data`\n * this option can be given in a number of different ways to effect its\n * behaviour:\n *\n * * `integer` - treated as an array index for the data source. This is the\n * default that DataTables uses (incrementally increased for each column).\n * * `string` - read an object property from the data source. There are\n * three 'special' options that can be used in the string to alter how\n * DataTables reads the data from the source object:\n * * `.` - Dotted Javascript notation. Just as you use a `.` in\n * Javascript to read from nested objects, so to can the options\n * specified in `data`. For example: `browser.version` or\n * `browser.name`. If your object parameter name contains a period, use\n * `\\\\` to escape it - i.e. `first\\\\.name`.\n * * `[]` - Array notation. DataTables can automatically combine data\n * from and array source, joining the data with the characters provided\n * between the two brackets. For example: `name[, ]` would provide a\n * comma-space separated list from the source array. If no characters\n * are provided between the brackets, the original array source is\n * returned.\n * * `()` - Function notation. Adding `()` to the end of a parameter will\n * execute a function of the name given. For example: `browser()` for a\n * simple function on the data source, `browser.version()` for a\n * function in a nested property or even `browser().version` to get an\n * object property if the function called returns an object.\n * * `object` - use different data for the different data types requested by\n * DataTables ('filter', 'display', 'type' or 'sort'). The property names\n * of the object is the data type the property refers to and the value can\n * defined using an integer, string or function using the same rules as\n * `render` normally does. Note that an `_` option _must_ be specified.\n * This is the default value to use if you haven't specified a value for\n * the data type requested by DataTables.\n * * `function` - the function given will be executed whenever DataTables\n * needs to set or get the data for a cell in the column. The function\n * takes three parameters:\n * * Parameters:\n * * {array|object} The data source for the row (based on `data`)\n * * {string} The type call data requested - this will be 'filter',\n * 'display', 'type' or 'sort'.\n * * {array|object} The full data source for the row (not based on\n * `data`)\n * * Return:\n * * The return value from the function is what will be used for the\n * data requested.\n *\n * @type string|int|function|object|null\n * @default null Use the data source value.\n *\n * @name DataTable.defaults.column.render\n * @dtopt Columns\n *\n * @example\n * // Create a comma separated list from an array of objects\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"ajaxSource\": \"sources/deep.txt\",\n * \"columns\": [\n * { \"data\": \"engine\" },\n * { \"data\": \"browser\" },\n * {\n * \"data\": \"platform\",\n * \"render\": \"[, ].name\"\n * }\n * ]\n * } );\n * } );\n *\n * @example\n * // Execute a function to obtain data\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"columnDefs\": [ {\n * \"targets\": [ 0 ],\n * \"data\": null, // Use the full data source object for the renderer's source\n * \"render\": \"browserName()\"\n * } ]\n * } );\n * } );\n *\n * @example\n * // As an object, extracting different data for the different types\n * // This would be used with a data source such as:\n * // { \"phone\": 5552368, \"phone_filter\": \"5552368 555-2368\", \"phone_display\": \"555-2368\" }\n * // Here the `phone` integer is used for sorting and type detection, while `phone_filter`\n * // (which has both forms) is used for filtering for if a user inputs either format, while\n * // the formatted phone number is the one that is shown in the table.\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"columnDefs\": [ {\n * \"targets\": [ 0 ],\n * \"data\": null, // Use the full data source object for the renderer's source\n * \"render\": {\n * \"_\": \"phone\",\n * \"filter\": \"phone_filter\",\n * \"display\": \"phone_display\"\n * }\n * } ]\n * } );\n * } );\n *\n * @example\n * // Use as a function to create a link from the data source\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"columnDefs\": [ {\n * \"targets\": [ 0 ],\n * \"data\": \"download_link\",\n * \"render\": function ( data, type, full ) {\n * return 'Download ';\n * }\n * } ]\n * } );\n * } );\n */\n \"mRender\": null,\n\n /**\n * Change the cell type created for the column - either TD cells or TH cells. This\n * can be useful as TH cells have semantic meaning in the table body, allowing them\n * to act as a header for a row (you may wish to add scope='row' to the TH elements).\n * @type string\n * @default td\n *\n * @name DataTable.defaults.column.cellType\n * @dtopt Columns\n *\n * @example\n * // Make the first column use TH cells\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"columnDefs\": [ {\n * \"targets\": [ 0 ],\n * \"cellType\": \"th\"\n * } ]\n * } );\n * } );\n */\n \"sCellType\": \"td\",\n\n /**\n * Class to give to each cell in this column.\n * @type string\n * @default Empty string \n *\n * @name DataTable.defaults.column.class\n * @dtopt Columns\n *\n * @example\n * // Using `columnDefs`\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"columnDefs\": [\n * { \"class\": \"my_class\", \"targets\": [ 0 ] }\n * ]\n * } );\n * } );\n *\n * @example\n * // Using `columns`\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"columns\": [\n * { \"class\": \"my_class\" },\n * null,\n * null,\n * null,\n * null\n * ]\n * } );\n * } );\n */\n \"sClass\": \"\",\n\n /**\n * When DataTables calculates the column widths to assign to each column,\n * it finds the longest string in each column and then constructs a\n * temporary table and reads the widths from that. The problem with this\n * is that \"mmm\" is much wider then \"iiii\", but the latter is a longer\n * string - thus the calculation can go wrong (doing it properly and putting\n * it into an DOM object and measuring that is horribly(!) slow). Thus as\n * a \"work around\" we provide this option. It will append its value to the\n * text that is found to be the longest string for the column - i.e. padding.\n * Generally you shouldn't need this!\n * @type string\n * @default Empty string\n *\n * @name DataTable.defaults.column.contentPadding\n * @dtopt Columns\n *\n * @example\n * // Using `columns`\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"columns\": [\n * null,\n * null,\n * null,\n * {\n * \"contentPadding\": \"mmm\"\n * }\n * ]\n * } );\n * } );\n */\n \"sContentPadding\": \"\",\n\n /**\n * Allows a default value to be given for a column's data, and will be used\n * whenever a null data source is encountered (this can be because `data`\n * is set to null, or because the data source itself is null).\n * @type string\n * @default null\n *\n * @name DataTable.defaults.column.defaultContent\n * @dtopt Columns\n *\n * @example\n * // Using `columnDefs`\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"columnDefs\": [\n * {\n * \"data\": null,\n * \"defaultContent\": \"Edit\",\n * \"targets\": [ -1 ]\n * }\n * ]\n * } );\n * } );\n *\n * @example\n * // Using `columns`\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"columns\": [\n * null,\n * null,\n * null,\n * {\n * \"data\": null,\n * \"defaultContent\": \"Edit\"\n * }\n * ]\n * } );\n * } );\n */\n \"sDefaultContent\": null,\n\n /**\n * This parameter is only used in DataTables' server-side processing. It can\n * be exceptionally useful to know what columns are being displayed on the\n * client side, and to map these to database fields. When defined, the names\n * also allow DataTables to reorder information from the server if it comes\n * back in an unexpected order (i.e. if you switch your columns around on the\n * client-side, your server-side code does not also need updating).\n * @type string\n * @default Empty string \n *\n * @name DataTable.defaults.column.name\n * @dtopt Columns\n *\n * @example\n * // Using `columnDefs`\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"columnDefs\": [\n * { \"name\": \"engine\", \"targets\": [ 0 ] },\n * { \"name\": \"browser\", \"targets\": [ 1 ] },\n * { \"name\": \"platform\", \"targets\": [ 2 ] },\n * { \"name\": \"version\", \"targets\": [ 3 ] },\n * { \"name\": \"grade\", \"targets\": [ 4 ] }\n * ]\n * } );\n * } );\n *\n * @example\n * // Using `columns`\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"columns\": [\n * { \"name\": \"engine\" },\n * { \"name\": \"browser\" },\n * { \"name\": \"platform\" },\n * { \"name\": \"version\" },\n * { \"name\": \"grade\" }\n * ]\n * } );\n * } );\n */\n \"sName\": \"\",\n\n /**\n * Defines a data source type for the ordering which can be used to read\n * real-time information from the table (updating the internally cached\n * version) prior to ordering. This allows ordering to occur on user\n * editable elements such as form inputs.\n * @type string\n * @default std\n *\n * @name DataTable.defaults.column.orderDataType\n * @dtopt Columns\n *\n * @example\n * // Using `columnDefs`\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"columnDefs\": [\n * { \"orderDataType\": \"dom-text\", \"targets\": [ 2, 3 ] },\n * { \"type\": \"numeric\", \"targets\": [ 3 ] },\n * { \"orderDataType\": \"dom-select\", \"targets\": [ 4 ] },\n * { \"orderDataType\": \"dom-checkbox\", \"targets\": [ 5 ] }\n * ]\n * } );\n * } );\n *\n * @example\n * // Using `columns`\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"columns\": [\n * null,\n * null,\n * { \"orderDataType\": \"dom-text\" },\n * { \"orderDataType\": \"dom-text\", \"type\": \"numeric\" },\n * { \"orderDataType\": \"dom-select\" },\n * { \"orderDataType\": \"dom-checkbox\" }\n * ]\n * } );\n * } );\n */\n \"sSortDataType\": \"std\",\n\n /**\n * The title of this column.\n * @type string\n * @default null Derived from the 'TH' value for this column in the\n * original HTML table. \n *\n * @name DataTable.defaults.column.title\n * @dtopt Columns\n *\n * @example\n * // Using `columnDefs`\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"columnDefs\": [\n * { \"title\": \"My column title\", \"targets\": [ 0 ] }\n * ]\n * } );\n * } );\n *\n * @example\n * // Using `columns`\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"columns\": [\n * { \"title\": \"My column title\" },\n * null,\n * null,\n * null,\n * null\n * ]\n * } );\n * } );\n */\n \"sTitle\": null,\n\n /**\n * The type allows you to specify how the data for this column will be\n * ordered. Four types (string, numeric, date and html (which will strip\n * HTML tags before ordering)) are currently available. Note that only date\n * formats understood by Javascript's Date() object will be accepted as type\n * date. For example: \"Mar 26, 2008 5:03 PM\". May take the values: 'string',\n * 'numeric', 'date' or 'html' (by default). Further types can be adding\n * through plug-ins.\n * @type string\n * @default null Auto-detected from raw data \n *\n * @name DataTable.defaults.column.type\n * @dtopt Columns\n *\n * @example\n * // Using `columnDefs`\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"columnDefs\": [\n * { \"type\": \"html\", \"targets\": [ 0 ] }\n * ]\n * } );\n * } );\n *\n * @example\n * // Using `columns`\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"columns\": [\n * { \"type\": \"html\" },\n * null,\n * null,\n * null,\n * null\n * ]\n * } );\n * } );\n */\n \"sType\": null,\n\n /**\n * Defining the width of the column, this parameter may take any CSS value\n * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not\n * been given a specific width through this interface ensuring that the table\n * remains readable.\n * @type string\n * @default null Automatic \n *\n * @name DataTable.defaults.column.width\n * @dtopt Columns\n *\n * @example\n * // Using `columnDefs`\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"columnDefs\": [\n * { \"width\": \"20%\", \"targets\": [ 0 ] }\n * ]\n * } );\n * } );\n *\n * @example\n * // Using `columns`\n * $(document).ready( function() {\n * $('#example').dataTable( {\n * \"columns\": [\n * { \"width\": \"20%\" },\n * null,\n * null,\n * null,\n * null\n * ]\n * } );\n * } );\n */\n \"sWidth\": null\n };\n\n _fnHungarianMap(DataTable.defaults.column);\n /**\n * DataTables settings object - this holds all the information needed for a\n * given table, including configuration, data and current application of the\n * table options. DataTables does not have a single instance for each DataTable\n * with the settings attached to that instance, but rather instances of the\n * DataTable \"class\" are created on-the-fly as needed (typically by a\n * $().dataTable() call) and the settings object is then applied to that\n * instance.\n *\n * Note that this object is related to {@link DataTable.defaults} but this\n * one is the internal data store for DataTables's cache of columns. It should\n * NOT be manipulated outside of DataTables. Any configuration should be done\n * through the initialisation options.\n * @namespace\n * @todo Really should attach the settings object to individual instances so we\n * don't need to create new instances on each $().dataTable() call (if the\n * table already exists). It would also save passing oSettings around and\n * into every single function. However, this is a very significant\n * architecture change for DataTables and will almost certainly break\n * backwards compatibility with older installations. This is something that\n * will be done in 2.0.\n */\n\n\n DataTable.models.oSettings = {\n /**\n * Primary features of DataTables and their enablement state.\n * @namespace\n */\n \"oFeatures\": {\n /**\n * Flag to say if DataTables should automatically try to calculate the\n * optimum table and columns widths (true) or not (false).\n * Note that this parameter will be set by the initialisation routine. To\n * set a default use {@link DataTable.defaults}.\n * @type boolean\n */\n \"bAutoWidth\": null,\n\n /**\n * Delay the creation of TR and TD elements until they are actually\n * needed by a driven page draw. This can give a significant speed\n * increase for Ajax source and Javascript source data, but makes no\n * difference at all fro DOM and server-side processing tables.\n * Note that this parameter will be set by the initialisation routine. To\n * set a default use {@link DataTable.defaults}.\n * @type boolean\n */\n \"bDeferRender\": null,\n\n /**\n * Enable filtering on the table or not. Note that if this is disabled\n * then there is no filtering at all on the table, including fnFilter.\n * To just remove the filtering input use sDom and remove the 'f' option.\n * Note that this parameter will be set by the initialisation routine. To\n * set a default use {@link DataTable.defaults}.\n * @type boolean\n */\n \"bFilter\": null,\n\n /**\n * Table information element (the 'Showing x of y records' div) enable\n * flag.\n * Note that this parameter will be set by the initialisation routine. To\n * set a default use {@link DataTable.defaults}.\n * @type boolean\n */\n \"bInfo\": null,\n\n /**\n * Present a user control allowing the end user to change the page size\n * when pagination is enabled.\n * Note that this parameter will be set by the initialisation routine. To\n * set a default use {@link DataTable.defaults}.\n * @type boolean\n */\n \"bLengthChange\": null,\n\n /**\n * Pagination enabled or not. Note that if this is disabled then length\n * changing must also be disabled.\n * Note that this parameter will be set by the initialisation routine. To\n * set a default use {@link DataTable.defaults}.\n * @type boolean\n */\n \"bPaginate\": null,\n\n /**\n * Processing indicator enable flag whenever DataTables is enacting a\n * user request - typically an Ajax request for server-side processing.\n * Note that this parameter will be set by the initialisation routine. To\n * set a default use {@link DataTable.defaults}.\n * @type boolean\n */\n \"bProcessing\": null,\n\n /**\n * Server-side processing enabled flag - when enabled DataTables will\n * get all data from the server for every draw - there is no filtering,\n * sorting or paging done on the client-side.\n * Note that this parameter will be set by the initialisation routine. To\n * set a default use {@link DataTable.defaults}.\n * @type boolean\n */\n \"bServerSide\": null,\n\n /**\n * Sorting enablement flag.\n * Note that this parameter will be set by the initialisation routine. To\n * set a default use {@link DataTable.defaults}.\n * @type boolean\n */\n \"bSort\": null,\n\n /**\n * Multi-column sorting\n * Note that this parameter will be set by the initialisation routine. To\n * set a default use {@link DataTable.defaults}.\n * @type boolean\n */\n \"bSortMulti\": null,\n\n /**\n * Apply a class to the columns which are being sorted to provide a\n * visual highlight or not. This can slow things down when enabled since\n * there is a lot of DOM interaction.\n * Note that this parameter will be set by the initialisation routine. To\n * set a default use {@link DataTable.defaults}.\n * @type boolean\n */\n \"bSortClasses\": null,\n\n /**\n * State saving enablement flag.\n * Note that this parameter will be set by the initialisation routine. To\n * set a default use {@link DataTable.defaults}.\n * @type boolean\n */\n \"bStateSave\": null\n },\n\n /**\n * Scrolling settings for a table.\n * @namespace\n */\n \"oScroll\": {\n /**\n * When the table is shorter in height than sScrollY, collapse the\n * table container down to the height of the table (when true).\n * Note that this parameter will be set by the initialisation routine. To\n * set a default use {@link DataTable.defaults}.\n * @type boolean\n */\n \"bCollapse\": null,\n\n /**\n * Width of the scrollbar for the web-browser's platform. Calculated\n * during table initialisation.\n * @type int\n * @default 0\n */\n \"iBarWidth\": 0,\n\n /**\n * Viewport width for horizontal scrolling. Horizontal scrolling is\n * disabled if an empty string.\n * Note that this parameter will be set by the initialisation routine. To\n * set a default use {@link DataTable.defaults}.\n * @type string\n */\n \"sX\": null,\n\n /**\n * Width to expand the table to when using x-scrolling. Typically you\n * should not need to use this.\n * Note that this parameter will be set by the initialisation routine. To\n * set a default use {@link DataTable.defaults}.\n * @type string\n * @deprecated\n */\n \"sXInner\": null,\n\n /**\n * Viewport height for vertical scrolling. Vertical scrolling is disabled\n * if an empty string.\n * Note that this parameter will be set by the initialisation routine. To\n * set a default use {@link DataTable.defaults}.\n * @type string\n */\n \"sY\": null\n },\n\n /**\n * Language information for the table.\n * @namespace\n * @extends DataTable.defaults.oLanguage\n */\n \"oLanguage\": {\n /**\n * Information callback function. See\n * {@link DataTable.defaults.fnInfoCallback}\n * @type function\n * @default null\n */\n \"fnInfoCallback\": null\n },\n\n /**\n * Browser support parameters\n * @namespace\n */\n \"oBrowser\": {\n /**\n * Indicate if the browser incorrectly calculates width:100% inside a\n * scrolling element (IE6/7)\n * @type boolean\n * @default false\n */\n \"bScrollOversize\": false,\n\n /**\n * Determine if the vertical scrollbar is on the right or left of the\n * scrolling container - needed for rtl language layout, although not\n * all browsers move the scrollbar (Safari).\n * @type boolean\n * @default false\n */\n \"bScrollbarLeft\": false,\n\n /**\n * Flag for if `getBoundingClientRect` is fully supported or not\n * @type boolean\n * @default false\n */\n \"bBounding\": false,\n\n /**\n * Browser scrollbar width\n * @type integer\n * @default 0\n */\n \"barWidth\": 0\n },\n \"ajax\": null,\n\n /**\n * Array referencing the nodes which are used for the features. The\n * parameters of this object match what is allowed by sDom - i.e.\n * \n * 'l' - Length changing \n * 'f' - Filtering input \n * 't' - The table! \n * 'i' - Information \n * 'p' - Pagination \n * 'r' - pRocessing \n * \n * @type array\n * @default []\n */\n \"aanFeatures\": [],\n\n /**\n * Store data information - see {@link DataTable.models.oRow} for detailed\n * information.\n * @type array\n * @default []\n */\n \"aoData\": [],\n\n /**\n * Array of indexes which are in the current display (after filtering etc)\n * @type array\n * @default []\n */\n \"aiDisplay\": [],\n\n /**\n * Array of indexes for display - no filtering\n * @type array\n * @default []\n */\n \"aiDisplayMaster\": [],\n\n /**\n * Map of row ids to data indexes\n * @type object\n * @default {}\n */\n \"aIds\": {},\n\n /**\n * Store information about each column that is in use\n * @type array\n * @default []\n */\n \"aoColumns\": [],\n\n /**\n * Store information about the table's header\n * @type array\n * @default []\n */\n \"aoHeader\": [],\n\n /**\n * Store information about the table's footer\n * @type array\n * @default []\n */\n \"aoFooter\": [],\n\n /**\n * Store the applied global search information in case we want to force a\n * research or compare the old search to a new one.\n * Note that this parameter will be set by the initialisation routine. To\n * set a default use {@link DataTable.defaults}.\n * @namespace\n * @extends DataTable.models.oSearch\n */\n \"oPreviousSearch\": {},\n\n /**\n * Store the applied search for each column - see\n * {@link DataTable.models.oSearch} for the format that is used for the\n * filtering information for each column.\n * @type array\n * @default []\n */\n \"aoPreSearchCols\": [],\n\n /**\n * Sorting that is applied to the table. Note that the inner arrays are\n * used in the following manner:\n * \n * Index 0 - column number \n * Index 1 - current sorting direction \n * \n * Note that this parameter will be set by the initialisation routine. To\n * set a default use {@link DataTable.defaults}.\n * @type array\n * @todo These inner arrays should really be objects\n */\n \"aaSorting\": null,\n\n /**\n * Sorting that is always applied to the table (i.e. prefixed in front of\n * aaSorting).\n * Note that this parameter will be set by the initialisation routine. To\n * set a default use {@link DataTable.defaults}.\n * @type array\n * @default []\n */\n \"aaSortingFixed\": [],\n\n /**\n * Classes to use for the striping of a table.\n * Note that this parameter will be set by the initialisation routine. To\n * set a default use {@link DataTable.defaults}.\n * @type array\n * @default []\n */\n \"asStripeClasses\": null,\n\n /**\n * If restoring a table - we should restore its striping classes as well\n * @type array\n * @default []\n */\n \"asDestroyStripes\": [],\n\n /**\n * If restoring a table - we should restore its width\n * @type int\n * @default 0\n */\n \"sDestroyWidth\": 0,\n\n /**\n * Callback functions array for every time a row is inserted (i.e. on a draw).\n * @type array\n * @default []\n */\n \"aoRowCallback\": [],\n\n /**\n * Callback functions for the header on each draw.\n * @type array\n * @default []\n */\n \"aoHeaderCallback\": [],\n\n /**\n * Callback function for the footer on each draw.\n * @type array\n * @default []\n */\n \"aoFooterCallback\": [],\n\n /**\n * Array of callback functions for draw callback functions\n * @type array\n * @default []\n */\n \"aoDrawCallback\": [],\n\n /**\n * Array of callback functions for row created function\n * @type array\n * @default []\n */\n \"aoRowCreatedCallback\": [],\n\n /**\n * Callback functions for just before the table is redrawn. A return of\n * false will be used to cancel the draw.\n * @type array\n * @default []\n */\n \"aoPreDrawCallback\": [],\n\n /**\n * Callback functions for when the table has been initialised.\n * @type array\n * @default []\n */\n \"aoInitComplete\": [],\n\n /**\n * Callbacks for modifying the settings to be stored for state saving, prior to\n * saving state.\n * @type array\n * @default []\n */\n \"aoStateSaveParams\": [],\n\n /**\n * Callbacks for modifying the settings that have been stored for state saving\n * prior to using the stored values to restore the state.\n * @type array\n * @default []\n */\n \"aoStateLoadParams\": [],\n\n /**\n * Callbacks for operating on the settings object once the saved state has been\n * loaded\n * @type array\n * @default []\n */\n \"aoStateLoaded\": [],\n\n /**\n * Cache the table ID for quick access\n * @type string\n * @default Empty string \n */\n \"sTableId\": \"\",\n\n /**\n * The TABLE node for the main table\n * @type node\n * @default null\n */\n \"nTable\": null,\n\n /**\n * Permanent ref to the thead element\n * @type node\n * @default null\n */\n \"nTHead\": null,\n\n /**\n * Permanent ref to the tfoot element - if it exists\n * @type node\n * @default null\n */\n \"nTFoot\": null,\n\n /**\n * Permanent ref to the tbody element\n * @type node\n * @default null\n */\n \"nTBody\": null,\n\n /**\n * Cache the wrapper node (contains all DataTables controlled elements)\n * @type node\n * @default null\n */\n \"nTableWrapper\": null,\n\n /**\n * Indicate if when using server-side processing the loading of data\n * should be deferred until the second draw.\n * Note that this parameter will be set by the initialisation routine. To\n * set a default use {@link DataTable.defaults}.\n * @type boolean\n * @default false\n */\n \"bDeferLoading\": false,\n\n /**\n * Indicate if all required information has been read in\n * @type boolean\n * @default false\n */\n \"bInitialised\": false,\n\n /**\n * Information about open rows. Each object in the array has the parameters\n * 'nTr' and 'nParent'\n * @type array\n * @default []\n */\n \"aoOpenRows\": [],\n\n /**\n * Dictate the positioning of DataTables' control elements - see\n * {@link DataTable.model.oInit.sDom}.\n * Note that this parameter will be set by the initialisation routine. To\n * set a default use {@link DataTable.defaults}.\n * @type string\n * @default null\n */\n \"sDom\": null,\n\n /**\n * Search delay (in mS)\n * @type integer\n * @default null\n */\n \"searchDelay\": null,\n\n /**\n * Which type of pagination should be used.\n * Note that this parameter will be set by the initialisation routine. To\n * set a default use {@link DataTable.defaults}.\n * @type string\n * @default two_button\n */\n \"sPaginationType\": \"two_button\",\n\n /**\n * The state duration (for `stateSave`) in seconds.\n * Note that this parameter will be set by the initialisation routine. To\n * set a default use {@link DataTable.defaults}.\n * @type int\n * @default 0\n */\n \"iStateDuration\": 0,\n\n /**\n * Array of callback functions for state saving. Each array element is an\n * object with the following parameters:\n * \n * function:fn - function to call. Takes two parameters, oSettings\n * and the JSON string to save that has been thus far created. Returns\n * a JSON string to be inserted into a json object\n * (i.e. '\"param\": [ 0, 1, 2]') \n * string:sName - name of callback \n * \n * @type array\n * @default []\n */\n \"aoStateSave\": [],\n\n /**\n * Array of callback functions for state loading. Each array element is an\n * object with the following parameters:\n * \n * function:fn - function to call. Takes two parameters, oSettings\n * and the object stored. May return false to cancel state loading \n * string:sName - name of callback \n * \n * @type array\n * @default []\n */\n \"aoStateLoad\": [],\n\n /**\n * State that was saved. Useful for back reference\n * @type object\n * @default null\n */\n \"oSavedState\": null,\n\n /**\n * State that was loaded. Useful for back reference\n * @type object\n * @default null\n */\n \"oLoadedState\": null,\n\n /**\n * Source url for AJAX data for the table.\n * Note that this parameter will be set by the initialisation routine. To\n * set a default use {@link DataTable.defaults}.\n * @type string\n * @default null\n */\n \"sAjaxSource\": null,\n\n /**\n * Property from a given object from which to read the table data from. This\n * can be an empty string (when not server-side processing), in which case\n * it is assumed an an array is given directly.\n * Note that this parameter will be set by the initialisation routine. To\n * set a default use {@link DataTable.defaults}.\n * @type string\n */\n \"sAjaxDataProp\": null,\n\n /**\n * Note if draw should be blocked while getting data\n * @type boolean\n * @default true\n */\n \"bAjaxDataGet\": true,\n\n /**\n * The last jQuery XHR object that was used for server-side data gathering.\n * This can be used for working with the XHR information in one of the\n * callbacks\n * @type object\n * @default null\n */\n \"jqXHR\": null,\n\n /**\n * JSON returned from the server in the last Ajax request\n * @type object\n * @default undefined\n */\n \"json\": undefined,\n\n /**\n * Data submitted as part of the last Ajax request\n * @type object\n * @default undefined\n */\n \"oAjaxData\": undefined,\n\n /**\n * Function to get the server-side data.\n * Note that this parameter will be set by the initialisation routine. To\n * set a default use {@link DataTable.defaults}.\n * @type function\n */\n \"fnServerData\": null,\n\n /**\n * Functions which are called prior to sending an Ajax request so extra\n * parameters can easily be sent to the server\n * @type array\n * @default []\n */\n \"aoServerParams\": [],\n\n /**\n * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if\n * required).\n * Note that this parameter will be set by the initialisation routine. To\n * set a default use {@link DataTable.defaults}.\n * @type string\n */\n \"sServerMethod\": null,\n\n /**\n * Format numbers for display.\n * Note that this parameter will be set by the initialisation routine. To\n * set a default use {@link DataTable.defaults}.\n * @type function\n */\n \"fnFormatNumber\": null,\n\n /**\n * List of options that can be used for the user selectable length menu.\n * Note that this parameter will be set by the initialisation routine. To\n * set a default use {@link DataTable.defaults}.\n * @type array\n * @default []\n */\n \"aLengthMenu\": null,\n\n /**\n * Counter for the draws that the table does. Also used as a tracker for\n * server-side processing\n * @type int\n * @default 0\n */\n \"iDraw\": 0,\n\n /**\n * Indicate if a redraw is being done - useful for Ajax\n * @type boolean\n * @default false\n */\n \"bDrawing\": false,\n\n /**\n * Draw index (iDraw) of the last error when parsing the returned data\n * @type int\n * @default -1\n */\n \"iDrawError\": -1,\n\n /**\n * Paging display length\n * @type int\n * @default 10\n */\n \"_iDisplayLength\": 10,\n\n /**\n * Paging start point - aiDisplay index\n * @type int\n * @default 0\n */\n \"_iDisplayStart\": 0,\n\n /**\n * Server-side processing - number of records in the result set\n * (i.e. before filtering), Use fnRecordsTotal rather than\n * this property to get the value of the number of records, regardless of\n * the server-side processing setting.\n * @type int\n * @default 0\n * @private\n */\n \"_iRecordsTotal\": 0,\n\n /**\n * Server-side processing - number of records in the current display set\n * (i.e. after filtering). Use fnRecordsDisplay rather than\n * this property to get the value of the number of records, regardless of\n * the server-side processing setting.\n * @type boolean\n * @default 0\n * @private\n */\n \"_iRecordsDisplay\": 0,\n\n /**\n * The classes to use for the table\n * @type object\n * @default {}\n */\n \"oClasses\": {},\n\n /**\n * Flag attached to the settings object so you can check in the draw\n * callback if filtering has been done in the draw. Deprecated in favour of\n * events.\n * @type boolean\n * @default false\n * @deprecated\n */\n \"bFiltered\": false,\n\n /**\n * Flag attached to the settings object so you can check in the draw\n * callback if sorting has been done in the draw. Deprecated in favour of\n * events.\n * @type boolean\n * @default false\n * @deprecated\n */\n \"bSorted\": false,\n\n /**\n * Indicate that if multiple rows are in the header and there is more than\n * one unique cell per column, if the top one (true) or bottom one (false)\n * should be used for sorting / title by DataTables.\n * Note that this parameter will be set by the initialisation routine. To\n * set a default use {@link DataTable.defaults}.\n * @type boolean\n */\n \"bSortCellsTop\": null,\n\n /**\n * Initialisation object that is used for the table\n * @type object\n * @default null\n */\n \"oInit\": null,\n\n /**\n * Destroy callback functions - for plug-ins to attach themselves to the\n * destroy so they can clean up markup and events.\n * @type array\n * @default []\n */\n \"aoDestroyCallback\": [],\n\n /**\n * Get the number of records in the current record set, before filtering\n * @type function\n */\n \"fnRecordsTotal\": function fnRecordsTotal() {\n return _fnDataSource(this) == 'ssp' ? this._iRecordsTotal * 1 : this.aiDisplayMaster.length;\n },\n\n /**\n * Get the number of records in the current record set, after filtering\n * @type function\n */\n \"fnRecordsDisplay\": function fnRecordsDisplay() {\n return _fnDataSource(this) == 'ssp' ? this._iRecordsDisplay * 1 : this.aiDisplay.length;\n },\n\n /**\n * Get the display end point - aiDisplay index\n * @type function\n */\n \"fnDisplayEnd\": function fnDisplayEnd() {\n var len = this._iDisplayLength,\n start = this._iDisplayStart,\n calc = start + len,\n records = this.aiDisplay.length,\n features = this.oFeatures,\n paginate = features.bPaginate;\n\n if (features.bServerSide) {\n return paginate === false || len === -1 ? start + records : Math.min(start + len, this._iRecordsDisplay);\n } else {\n return !paginate || calc > records || len === -1 ? records : calc;\n }\n },\n\n /**\n * The DataTables object for this table\n * @type object\n * @default null\n */\n \"oInstance\": null,\n\n /**\n * Unique identifier for each instance of the DataTables object. If there\n * is an ID on the table node, then it takes that value, otherwise an\n * incrementing internal counter is used.\n * @type string\n * @default null\n */\n \"sInstance\": null,\n\n /**\n * tabindex attribute value that is added to DataTables control elements, allowing\n * keyboard navigation of the table and its controls.\n */\n \"iTabIndex\": 0,\n\n /**\n * DIV container for the footer scrolling table if scrolling\n */\n \"nScrollHead\": null,\n\n /**\n * DIV container for the footer scrolling table if scrolling\n */\n \"nScrollFoot\": null,\n\n /**\n * Last applied sort\n * @type array\n * @default []\n */\n \"aLastSort\": [],\n\n /**\n * Stored plug-in instances\n * @type object\n * @default {}\n */\n \"oPlugins\": {},\n\n /**\n * Function used to get a row's id from the row's data\n * @type function\n * @default null\n */\n \"rowIdFn\": null,\n\n /**\n * Data location where to store a row's id\n * @type string\n * @default null\n */\n \"rowId\": null\n };\n /**\n * Extension object for DataTables that is used to provide all extension\n * options.\n *\n * Note that the `DataTable.ext` object is available through\n * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is\n * also aliased to `jQuery.fn.dataTableExt` for historic reasons.\n * @namespace\n * @extends DataTable.models.ext\n */\n\n /**\n * DataTables extensions\n * \n * This namespace acts as a collection area for plug-ins that can be used to\n * extend DataTables capabilities. Indeed many of the build in methods\n * use this method to provide their own capabilities (sorting methods for\n * example).\n *\n * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy\n * reasons\n *\n * @namespace\n */\n\n DataTable.ext = _ext = {\n /**\n * Buttons. For use with the Buttons extension for DataTables. This is\n * defined here so other extensions can define buttons regardless of load\n * order. It is _not_ used by DataTables core.\n *\n * @type object\n * @default {}\n */\n buttons: {},\n\n /**\n * Element class names\n *\n * @type object\n * @default {}\n */\n classes: {},\n\n /**\n * DataTables build type (expanded by the download builder)\n *\n * @type string\n */\n builder: \"-source-\",\n\n /**\n * Error reporting.\n * \n * How should DataTables report an error. Can take the value 'alert',\n * 'throw', 'none' or a function.\n *\n * @type string|function\n * @default alert\n */\n errMode: \"alert\",\n\n /**\n * Feature plug-ins.\n * \n * This is an array of objects which describe the feature plug-ins that are\n * available to DataTables. These feature plug-ins are then available for\n * use through the `dom` initialisation option.\n * \n * Each feature plug-in is described by an object which must have the\n * following properties:\n * \n * * `fnInit` - function that is used to initialise the plug-in,\n * * `cFeature` - a character so the feature can be enabled by the `dom`\n * instillation option. This is case sensitive.\n *\n * The `fnInit` function has the following input parameters:\n *\n * 1. `{object}` DataTables settings object: see\n * {@link DataTable.models.oSettings}\n *\n * And the following return is expected:\n * \n * * {node|null} The element which contains your feature. Note that the\n * return may also be void if your plug-in does not require to inject any\n * DOM elements into DataTables control (`dom`) - for example this might\n * be useful when developing a plug-in which allows table control via\n * keyboard entry\n *\n * @type array\n *\n * @example\n * $.fn.dataTable.ext.features.push( {\n * \"fnInit\": function( oSettings ) {\n * return new TableTools( { \"oDTSettings\": oSettings } );\n * },\n * \"cFeature\": \"T\"\n * } );\n */\n feature: [],\n\n /**\n * Row searching.\n * \n * This method of searching is complimentary to the default type based\n * searching, and a lot more comprehensive as it allows you complete control\n * over the searching logic. Each element in this array is a function\n * (parameters described below) that is called for every row in the table,\n * and your logic decides if it should be included in the searching data set\n * or not.\n *\n * Searching functions have the following input parameters:\n *\n * 1. `{object}` DataTables settings object: see\n * {@link DataTable.models.oSettings}\n * 2. `{array|object}` Data for the row to be processed (same as the\n * original format that was passed in as the data source, or an array\n * from a DOM data source\n * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which\n * can be useful to retrieve the `TR` element if you need DOM interaction.\n *\n * And the following return is expected:\n *\n * * {boolean} Include the row in the searched result set (true) or not\n * (false)\n *\n * Note that as with the main search ability in DataTables, technically this\n * is \"filtering\", since it is subtractive. However, for consistency in\n * naming we call it searching here.\n *\n * @type array\n * @default []\n *\n * @example\n * // The following example shows custom search being applied to the\n * // fourth column (i.e. the data[3] index) based on two input values\n * // from the end-user, matching the data in a certain range.\n * $.fn.dataTable.ext.search.push(\n * function( settings, data, dataIndex ) {\n * var min = document.getElementById('min').value * 1;\n * var max = document.getElementById('max').value * 1;\n * var version = data[3] == \"-\" ? 0 : data[3]*1;\n *\n * if ( min == \"\" && max == \"\" ) {\n * return true;\n * }\n * else if ( min == \"\" && version < max ) {\n * return true;\n * }\n * else if ( min < version && \"\" == max ) {\n * return true;\n * }\n * else if ( min < version && version < max ) {\n * return true;\n * }\n * return false;\n * }\n * );\n */\n search: [],\n\n /**\n * Selector extensions\n *\n * The `selector` option can be used to extend the options available for the\n * selector modifier options (`selector-modifier` object data type) that\n * each of the three built in selector types offer (row, column and cell +\n * their plural counterparts). For example the Select extension uses this\n * mechanism to provide an option to select only rows, columns and cells\n * that have been marked as selected by the end user (`{selected: true}`),\n * which can be used in conjunction with the existing built in selector\n * options.\n *\n * Each property is an array to which functions can be pushed. The functions\n * take three attributes:\n *\n * * Settings object for the host table\n * * Options object (`selector-modifier` object type)\n * * Array of selected item indexes\n *\n * The return is an array of the resulting item indexes after the custom\n * selector has been applied.\n *\n * @type object\n */\n selector: {\n cell: [],\n column: [],\n row: []\n },\n\n /**\n * Internal functions, exposed for used in plug-ins.\n * \n * Please note that you should not need to use the internal methods for\n * anything other than a plug-in (and even then, try to avoid if possible).\n * The internal function may change between releases.\n *\n * @type object\n * @default {}\n */\n internal: {},\n\n /**\n * Legacy configuration options. Enable and disable legacy options that\n * are available in DataTables.\n *\n * @type object\n */\n legacy: {\n /**\n * Enable / disable DataTables 1.9 compatible server-side processing\n * requests\n *\n * @type boolean\n * @default null\n */\n ajax: null\n },\n\n /**\n * Pagination plug-in methods.\n * \n * Each entry in this object is a function and defines which buttons should\n * be shown by the pagination rendering method that is used for the table:\n * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the\n * buttons are displayed in the document, while the functions here tell it\n * what buttons to display. This is done by returning an array of button\n * descriptions (what each button will do).\n *\n * Pagination types (the four built in options and any additional plug-in\n * options defined here) can be used through the `paginationType`\n * initialisation parameter.\n *\n * The functions defined take two parameters:\n *\n * 1. `{int} page` The current page index\n * 2. `{int} pages` The number of pages in the table\n *\n * Each function is expected to return an array where each element of the\n * array can be one of:\n *\n * * `first` - Jump to first page when activated\n * * `last` - Jump to last page when activated\n * * `previous` - Show previous page when activated\n * * `next` - Show next page when activated\n * * `{int}` - Show page of the index given\n * * `{array}` - A nested array containing the above elements to add a\n * containing 'DIV' element (might be useful for styling).\n *\n * Note that DataTables v1.9- used this object slightly differently whereby\n * an object with two functions would be defined for each plug-in. That\n * ability is still supported by DataTables 1.10+ to provide backwards\n * compatibility, but this option of use is now decremented and no longer\n * documented in DataTables 1.10+.\n *\n * @type object\n * @default {}\n *\n * @example\n * // Show previous, next and current page buttons only\n * $.fn.dataTableExt.oPagination.current = function ( page, pages ) {\n * return [ 'previous', page, 'next' ];\n * };\n */\n pager: {},\n renderer: {\n pageButton: {},\n header: {}\n },\n\n /**\n * Ordering plug-ins - custom data source\n * \n * The extension options for ordering of data available here is complimentary\n * to the default type based ordering that DataTables typically uses. It\n * allows much greater control over the the data that is being used to\n * order a column, but is necessarily therefore more complex.\n * \n * This type of ordering is useful if you want to do ordering based on data\n * live from the DOM (for example the contents of an 'input' element) rather\n * than just the static string that DataTables knows of.\n * \n * The way these plug-ins work is that you create an array of the values you\n * wish to be ordering for the column in question and then return that\n * array. The data in the array much be in the index order of the rows in\n * the table (not the currently ordering order!). Which order data gathering\n * function is run here depends on the `dt-init columns.orderDataType`\n * parameter that is used for the column (if any).\n *\n * The functions defined take two parameters:\n *\n * 1. `{object}` DataTables settings object: see\n * {@link DataTable.models.oSettings}\n * 2. `{int}` Target column index\n *\n * Each function is expected to return an array:\n *\n * * `{array}` Data for the column to be ordering upon\n *\n * @type array\n *\n * @example\n * // Ordering using `input` node values\n * $.fn.dataTable.ext.order['dom-text'] = function ( settings, col )\n * {\n * return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {\n * return $('input', td).val();\n * } );\n * }\n */\n order: {},\n\n /**\n * Type based plug-ins.\n *\n * Each column in DataTables has a type assigned to it, either by automatic\n * detection or by direct assignment using the `type` option for the column.\n * The type of a column will effect how it is ordering and search (plug-ins\n * can also make use of the column type if required).\n *\n * @namespace\n */\n type: {\n /**\n * Type detection functions.\n *\n * The functions defined in this object are used to automatically detect\n * a column's type, making initialisation of DataTables super easy, even\n * when complex data is in the table.\n *\n * The functions defined take two parameters:\n *\n * 1. `{*}` Data from the column cell to be analysed\n * 2. `{settings}` DataTables settings object. This can be used to\n * perform context specific type detection - for example detection\n * based on language settings such as using a comma for a decimal\n * place. Generally speaking the options from the settings will not\n * be required\n *\n * Each function is expected to return:\n *\n * * `{string|null}` Data type detected, or null if unknown (and thus\n * pass it on to the other type detection functions.\n *\n * @type array\n *\n * @example\n * // Currency type detection plug-in:\n * $.fn.dataTable.ext.type.detect.push(\n * function ( data, settings ) {\n * // Check the numeric part\n * if ( ! data.substring(1).match(/[0-9]/) ) {\n * return null;\n * }\n *\n * // Check prefixed by currency\n * if ( data.charAt(0) == '$' || data.charAt(0) == '£' ) {\n * return 'currency';\n * }\n * return null;\n * }\n * );\n */\n detect: [],\n\n /**\n * Type based search formatting.\n *\n * The type based searching functions can be used to pre-format the\n * data to be search on. For example, it can be used to strip HTML\n * tags or to de-format telephone numbers for numeric only searching.\n *\n * Note that is a search is not defined for a column of a given type,\n * no search formatting will be performed.\n * \n * Pre-processing of searching data plug-ins - When you assign the sType\n * for a column (or have it automatically detected for you by DataTables\n * or a type detection plug-in), you will typically be using this for\n * custom sorting, but it can also be used to provide custom searching\n * by allowing you to pre-processing the data and returning the data in\n * the format that should be searched upon. This is done by adding\n * functions this object with a parameter name which matches the sType\n * for that target column. This is the corollary of afnSortData \n * for searching data.\n *\n * The functions defined take a single parameter:\n *\n * 1. `{*}` Data from the column cell to be prepared for searching\n *\n * Each function is expected to return:\n *\n * * `{string|null}` Formatted string that will be used for the searching.\n *\n * @type object\n * @default {}\n *\n * @example\n * $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) {\n * return d.replace(/\\n/g,\" \").replace( /<.*?>/g, \"\" );\n * }\n */\n search: {},\n\n /**\n * Type based ordering.\n *\n * The column type tells DataTables what ordering to apply to the table\n * when a column is sorted upon. The order for each type that is defined,\n * is defined by the functions available in this object.\n *\n * Each ordering option can be described by three properties added to\n * this object:\n *\n * * `{type}-pre` - Pre-formatting function\n * * `{type}-asc` - Ascending order function\n * * `{type}-desc` - Descending order function\n *\n * All three can be used together, only `{type}-pre` or only\n * `{type}-asc` and `{type}-desc` together. It is generally recommended\n * that only `{type}-pre` is used, as this provides the optimal\n * implementation in terms of speed, although the others are provided\n * for compatibility with existing Javascript sort functions.\n *\n * `{type}-pre`: Functions defined take a single parameter:\n *\n * 1. `{*}` Data from the column cell to be prepared for ordering\n *\n * And return:\n *\n * * `{*}` Data to be sorted upon\n *\n * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort\n * functions, taking two parameters:\n *\n * 1. `{*}` Data to compare to the second parameter\n * 2. `{*}` Data to compare to the first parameter\n *\n * And returning:\n *\n * * `{*}` Ordering match: <0 if first parameter should be sorted lower\n * than the second parameter, ===0 if the two parameters are equal and\n * >0 if the first parameter should be sorted height than the second\n * parameter.\n * \n * @type object\n * @default {}\n *\n * @example\n * // Numeric ordering of formatted numbers with a pre-formatter\n * $.extend( $.fn.dataTable.ext.type.order, {\n * \"string-pre\": function(x) {\n * a = (a === \"-\" || a === \"\") ? 0 : a.replace( /[^\\d\\-\\.]/g, \"\" );\n * return parseFloat( a );\n * }\n * } );\n *\n * @example\n * // Case-sensitive string ordering, with no pre-formatting method\n * $.extend( $.fn.dataTable.ext.order, {\n * \"string-case-asc\": function(x,y) {\n * return ((x < y) ? -1 : ((x > y) ? 1 : 0));\n * },\n * \"string-case-desc\": function(x,y) {\n * return ((x < y) ? 1 : ((x > y) ? -1 : 0));\n * }\n * } );\n */\n order: {}\n },\n\n /**\n * Unique DataTables instance counter\n *\n * @type int\n * @private\n */\n _unique: 0,\n //\n // Depreciated\n // The following properties are retained for backwards compatiblity only.\n // The should not be used in new projects and will be removed in a future\n // version\n //\n\n /**\n * Version check function.\n * @type function\n * @depreciated Since 1.10\n */\n fnVersionCheck: DataTable.fnVersionCheck,\n\n /**\n * Index for what 'this' index API functions should use\n * @type int\n * @deprecated Since v1.10\n */\n iApiIndex: 0,\n\n /**\n * jQuery UI class container\n * @type object\n * @deprecated Since v1.10\n */\n oJUIClasses: {},\n\n /**\n * Software version\n * @type string\n * @deprecated Since v1.10\n */\n sVersion: DataTable.version\n }; //\n // Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts\n //\n\n $.extend(_ext, {\n afnFiltering: _ext.search,\n aTypes: _ext.type.detect,\n ofnSearch: _ext.type.search,\n oSort: _ext.type.order,\n afnSortData: _ext.order,\n aoFeatures: _ext.feature,\n oApi: _ext.internal,\n oStdClasses: _ext.classes,\n oPagination: _ext.pager\n });\n $.extend(DataTable.ext.classes, {\n \"sTable\": \"dataTable\",\n \"sNoFooter\": \"no-footer\",\n\n /* Paging buttons */\n \"sPageButton\": \"paginate_button\",\n \"sPageButtonActive\": \"current\",\n \"sPageButtonDisabled\": \"disabled\",\n\n /* Striping classes */\n \"sStripeOdd\": \"odd\",\n \"sStripeEven\": \"even\",\n\n /* Empty row */\n \"sRowEmpty\": \"dataTables_empty\",\n\n /* Features */\n \"sWrapper\": \"dataTables_wrapper\",\n \"sFilter\": \"dataTables_filter\",\n \"sInfo\": \"dataTables_info\",\n \"sPaging\": \"dataTables_paginate paging_\",\n\n /* Note that the type is postfixed */\n \"sLength\": \"dataTables_length\",\n \"sProcessing\": \"dataTables_processing\",\n\n /* Sorting */\n \"sSortAsc\": \"sorting_asc\",\n \"sSortDesc\": \"sorting_desc\",\n \"sSortable\": \"sorting\",\n\n /* Sortable in both directions */\n \"sSortableAsc\": \"sorting_asc_disabled\",\n \"sSortableDesc\": \"sorting_desc_disabled\",\n \"sSortableNone\": \"sorting_disabled\",\n \"sSortColumn\": \"sorting_\",\n\n /* Note that an int is postfixed for the sorting order */\n\n /* Filtering */\n \"sFilterInput\": \"\",\n\n /* Page length */\n \"sLengthSelect\": \"\",\n\n /* Scrolling */\n \"sScrollWrapper\": \"dataTables_scroll\",\n \"sScrollHead\": \"dataTables_scrollHead\",\n \"sScrollHeadInner\": \"dataTables_scrollHeadInner\",\n \"sScrollBody\": \"dataTables_scrollBody\",\n \"sScrollFoot\": \"dataTables_scrollFoot\",\n \"sScrollFootInner\": \"dataTables_scrollFootInner\",\n\n /* Misc */\n \"sHeaderTH\": \"\",\n \"sFooterTH\": \"\",\n // Deprecated\n \"sSortJUIAsc\": \"\",\n \"sSortJUIDesc\": \"\",\n \"sSortJUI\": \"\",\n \"sSortJUIAscAllowed\": \"\",\n \"sSortJUIDescAllowed\": \"\",\n \"sSortJUIWrapper\": \"\",\n \"sSortIcon\": \"\",\n \"sJUIHeader\": \"\",\n \"sJUIFooter\": \"\"\n });\n var extPagination = DataTable.ext.pager;\n\n function _numbers(page, pages) {\n var numbers = [],\n buttons = extPagination.numbers_length,\n half = Math.floor(buttons / 2),\n i = 1;\n\n if (pages <= buttons) {\n numbers = _range(0, pages);\n } else if (page <= half) {\n numbers = _range(0, buttons - 2);\n numbers.push('ellipsis');\n numbers.push(pages - 1);\n } else if (page >= pages - 1 - half) {\n numbers = _range(pages - (buttons - 2), pages);\n numbers.splice(0, 0, 'ellipsis'); // no unshift in ie6\n\n numbers.splice(0, 0, 0);\n } else {\n numbers = _range(page - half + 2, page + half - 1);\n numbers.push('ellipsis');\n numbers.push(pages - 1);\n numbers.splice(0, 0, 'ellipsis');\n numbers.splice(0, 0, 0);\n }\n\n numbers.DT_el = 'span';\n return numbers;\n }\n\n $.extend(extPagination, {\n simple: function simple(page, pages) {\n return ['previous', 'next'];\n },\n full: function full(page, pages) {\n return ['first', 'previous', 'next', 'last'];\n },\n numbers: function numbers(page, pages) {\n return [_numbers(page, pages)];\n },\n simple_numbers: function simple_numbers(page, pages) {\n return ['previous', _numbers(page, pages), 'next'];\n },\n full_numbers: function full_numbers(page, pages) {\n return ['first', 'previous', _numbers(page, pages), 'next', 'last'];\n },\n first_last_numbers: function first_last_numbers(page, pages) {\n return ['first', _numbers(page, pages), 'last'];\n },\n // For testing and plug-ins to use\n _numbers: _numbers,\n // Number of number buttons (including ellipsis) to show. _Must be odd!_\n numbers_length: 7\n });\n $.extend(true, DataTable.ext.renderer, {\n pageButton: {\n _: function _(settings, host, idx, buttons, page, pages) {\n var classes = settings.oClasses;\n var lang = settings.oLanguage.oPaginate;\n var aria = settings.oLanguage.oAria.paginate || {};\n var btnDisplay,\n btnClass,\n counter = 0;\n\n var attach = function attach(container, buttons) {\n var i, ien, node, button;\n\n var clickHandler = function clickHandler(e) {\n _fnPageChange(settings, e.data.action, true);\n };\n\n for (i = 0, ien = buttons.length; i < ien; i++) {\n button = buttons[i];\n\n if ($.isArray(button)) {\n var inner = $('<' + (button.DT_el || 'div') + '/>').appendTo(container);\n attach(inner, button);\n } else {\n btnDisplay = null;\n btnClass = '';\n\n switch (button) {\n case 'ellipsis':\n container.append('… ');\n break;\n\n case 'first':\n btnDisplay = lang.sFirst;\n btnClass = button + (page > 0 ? '' : ' ' + classes.sPageButtonDisabled);\n break;\n\n case 'previous':\n btnDisplay = lang.sPrevious;\n btnClass = button + (page > 0 ? '' : ' ' + classes.sPageButtonDisabled);\n break;\n\n case 'next':\n btnDisplay = lang.sNext;\n btnClass = button + (page < pages - 1 ? '' : ' ' + classes.sPageButtonDisabled);\n break;\n\n case 'last':\n btnDisplay = lang.sLast;\n btnClass = button + (page < pages - 1 ? '' : ' ' + classes.sPageButtonDisabled);\n break;\n\n default:\n btnDisplay = button + 1;\n btnClass = page === button ? classes.sPageButtonActive : '';\n break;\n }\n\n if (btnDisplay !== null) {\n node = $('', {\n 'class': classes.sPageButton + ' ' + btnClass,\n 'aria-controls': settings.sTableId,\n 'aria-label': aria[button],\n 'data-dt-idx': counter,\n 'tabindex': settings.iTabIndex,\n 'id': idx === 0 && typeof button === 'string' ? settings.sTableId + '_' + button : null\n }).html(btnDisplay).appendTo(container);\n\n _fnBindAction(node, {\n action: button\n }, clickHandler);\n\n counter++;\n }\n }\n }\n }; // IE9 throws an 'unknown error' if document.activeElement is used\n // inside an iframe or frame. Try / catch the error. Not good for\n // accessibility, but neither are frames.\n\n\n var activeEl;\n\n try {\n // Because this approach is destroying and recreating the paging\n // elements, focus is lost on the select button which is bad for\n // accessibility. So we want to restore focus once the draw has\n // completed\n activeEl = $(host).find(document.activeElement).data('dt-idx');\n } catch (e) {}\n\n attach($(host).empty(), buttons);\n\n if (activeEl !== undefined) {\n $(host).find('[data-dt-idx=' + activeEl + ']').focus();\n }\n }\n }\n }); // Built in type detection. See model.ext.aTypes for information about\n // what is required from this methods.\n\n $.extend(DataTable.ext.type.detect, [// Plain numbers - first since V8 detects some plain numbers as dates\n // e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...).\n function (d, settings) {\n var decimal = settings.oLanguage.sDecimal;\n return _isNumber(d, decimal) ? 'num' + decimal : null;\n }, // Dates (only those recognised by the browser's Date.parse)\n function (d, settings) {\n // V8 tries _very_ hard to make a string passed into `Date.parse()`\n // valid, so we need to use a regex to restrict date formats. Use a\n // plug-in for anything other than ISO8601 style strings\n if (d && !(d instanceof Date) && !_re_date.test(d)) {\n return null;\n }\n\n var parsed = Date.parse(d);\n return parsed !== null && !isNaN(parsed) || _empty(d) ? 'date' : null;\n }, // Formatted numbers\n function (d, settings) {\n var decimal = settings.oLanguage.sDecimal;\n return _isNumber(d, decimal, true) ? 'num-fmt' + decimal : null;\n }, // HTML numeric\n function (d, settings) {\n var decimal = settings.oLanguage.sDecimal;\n return _htmlNumeric(d, decimal) ? 'html-num' + decimal : null;\n }, // HTML numeric, formatted\n function (d, settings) {\n var decimal = settings.oLanguage.sDecimal;\n return _htmlNumeric(d, decimal, true) ? 'html-num-fmt' + decimal : null;\n }, // HTML (this is strict checking - there must be html)\n function (d, settings) {\n return _empty(d) || typeof d === 'string' && d.indexOf('<') !== -1 ? 'html' : null;\n }]); // Filter formatting functions. See model.ext.ofnSearch for information about\n // what is required from these methods.\n // \n // Note that additional search methods are added for the html numbers and\n // html formatted numbers by `_addNumericSort()` when we know what the decimal\n // place is\n\n $.extend(DataTable.ext.type.search, {\n html: function html(data) {\n return _empty(data) ? data : typeof data === 'string' ? data.replace(_re_new_lines, \" \").replace(_re_html, \"\") : '';\n },\n string: function string(data) {\n return _empty(data) ? data : typeof data === 'string' ? data.replace(_re_new_lines, \" \") : data;\n }\n });\n\n var __numericReplace = function __numericReplace(d, decimalPlace, re1, re2) {\n if (d !== 0 && (!d || d === '-')) {\n return -Infinity;\n } // If a decimal place other than `.` is used, it needs to be given to the\n // function so we can detect it and replace with a `.` which is the only\n // decimal place Javascript recognises - it is not locale aware.\n\n\n if (decimalPlace) {\n d = _numToDecimal(d, decimalPlace);\n }\n\n if (d.replace) {\n if (re1) {\n d = d.replace(re1, '');\n }\n\n if (re2) {\n d = d.replace(re2, '');\n }\n }\n\n return d * 1;\n }; // Add the numeric 'deformatting' functions for sorting and search. This is done\n // in a function to provide an easy ability for the language options to add\n // additional methods if a non-period decimal place is used.\n\n\n function _addNumericSort(decimalPlace) {\n $.each({\n // Plain numbers\n \"num\": function num(d) {\n return __numericReplace(d, decimalPlace);\n },\n // Formatted numbers\n \"num-fmt\": function numFmt(d) {\n return __numericReplace(d, decimalPlace, _re_formatted_numeric);\n },\n // HTML numeric\n \"html-num\": function htmlNum(d) {\n return __numericReplace(d, decimalPlace, _re_html);\n },\n // HTML numeric, formatted\n \"html-num-fmt\": function htmlNumFmt(d) {\n return __numericReplace(d, decimalPlace, _re_html, _re_formatted_numeric);\n }\n }, function (key, fn) {\n // Add the ordering method\n _ext.type.order[key + decimalPlace + '-pre'] = fn; // For HTML types add a search formatter that will strip the HTML\n\n if (key.match(/^html\\-/)) {\n _ext.type.search[key + decimalPlace] = _ext.type.search.html;\n }\n });\n } // Default sort methods\n\n\n $.extend(_ext.type.order, {\n // Dates\n \"date-pre\": function datePre(d) {\n var ts = Date.parse(d);\n return isNaN(ts) ? -Infinity : ts;\n },\n // html\n \"html-pre\": function htmlPre(a) {\n return _empty(a) ? '' : a.replace ? a.replace(/<.*?>/g, \"\").toLowerCase() : a + '';\n },\n // string\n \"string-pre\": function stringPre(a) {\n // This is a little complex, but faster than always calling toString,\n // http://jsperf.com/tostring-v-check\n return _empty(a) ? '' : typeof a === 'string' ? a.toLowerCase() : !a.toString ? '' : a.toString();\n },\n // string-asc and -desc are retained only for compatibility with the old\n // sort methods\n \"string-asc\": function stringAsc(x, y) {\n return x < y ? -1 : x > y ? 1 : 0;\n },\n \"string-desc\": function stringDesc(x, y) {\n return x < y ? 1 : x > y ? -1 : 0;\n }\n }); // Numeric sorting types - order doesn't matter here\n\n _addNumericSort('');\n\n $.extend(true, DataTable.ext.renderer, {\n header: {\n _: function _(settings, cell, column, classes) {\n // No additional mark-up required\n // Attach a sort listener to update on sort - note that using the\n // `DT` namespace will allow the event to be removed automatically\n // on destroy, while the `dt` namespaced event is the one we are\n // listening for\n $(settings.nTable).on('order.dt.DT', function (e, ctx, sorting, columns) {\n if (settings !== ctx) {\n // need to check this this is the host\n return; // table, not a nested one\n }\n\n var colIdx = column.idx;\n cell.removeClass(column.sSortingClass + ' ' + classes.sSortAsc + ' ' + classes.sSortDesc).addClass(columns[colIdx] == 'asc' ? classes.sSortAsc : columns[colIdx] == 'desc' ? classes.sSortDesc : column.sSortingClass);\n });\n },\n jqueryui: function jqueryui(settings, cell, column, classes) {\n $('
').addClass(classes.sSortJUIWrapper).append(cell.contents()).append($(' ').addClass(classes.sSortIcon + ' ' + column.sSortingClassJUI)).appendTo(cell); // Attach a sort listener to update on sort\n\n $(settings.nTable).on('order.dt.DT', function (e, ctx, sorting, columns) {\n if (settings !== ctx) {\n return;\n }\n\n var colIdx = column.idx;\n cell.removeClass(classes.sSortAsc + \" \" + classes.sSortDesc).addClass(columns[colIdx] == 'asc' ? classes.sSortAsc : columns[colIdx] == 'desc' ? classes.sSortDesc : column.sSortingClass);\n cell.find('span.' + classes.sSortIcon).removeClass(classes.sSortJUIAsc + \" \" + classes.sSortJUIDesc + \" \" + classes.sSortJUI + \" \" + classes.sSortJUIAscAllowed + \" \" + classes.sSortJUIDescAllowed).addClass(columns[colIdx] == 'asc' ? classes.sSortJUIAsc : columns[colIdx] == 'desc' ? classes.sSortJUIDesc : column.sSortingClassJUI);\n });\n }\n }\n });\n /*\n * Public helper functions. These aren't used internally by DataTables, or\n * called by any of the options passed into DataTables, but they can be used\n * externally by developers working with DataTables. They are helper functions\n * to make working with DataTables a little bit easier.\n */\n\n var __htmlEscapeEntities = function __htmlEscapeEntities(d) {\n return typeof d === 'string' ? d.replace(//g, '>').replace(/\"/g, '"') : d;\n };\n /**\n * Helpers for `columns.render`.\n *\n * The options defined here can be used with the `columns.render` initialisation\n * option to provide a display renderer. The following functions are defined:\n *\n * * `number` - Will format numeric data (defined by `columns.data`) for\n * display, retaining the original unformatted data for sorting and filtering.\n * It takes 5 parameters:\n * * `string` - Thousands grouping separator\n * * `string` - Decimal point indicator\n * * `integer` - Number of decimal points to show\n * * `string` (optional) - Prefix.\n * * `string` (optional) - Postfix (/suffix).\n * * `text` - Escape HTML to help prevent XSS attacks. It has no optional\n * parameters.\n *\n * @example\n * // Column definition using the number renderer\n * {\n * data: \"salary\",\n * render: $.fn.dataTable.render.number( '\\'', '.', 0, '$' )\n * }\n *\n * @namespace\n */\n\n\n DataTable.render = {\n number: function number(thousands, decimal, precision, prefix, postfix) {\n return {\n display: function display(d) {\n if (typeof d !== 'number' && typeof d !== 'string') {\n return d;\n }\n\n var negative = d < 0 ? '-' : '';\n var flo = parseFloat(d); // If NaN then there isn't much formatting that we can do - just\n // return immediately, escaping any HTML (this was supposed to\n // be a number after all)\n\n if (isNaN(flo)) {\n return __htmlEscapeEntities(d);\n }\n\n flo = flo.toFixed(precision);\n d = Math.abs(flo);\n var intPart = parseInt(d, 10);\n var floatPart = precision ? decimal + (d - intPart).toFixed(precision).substring(2) : '';\n return negative + (prefix || '') + intPart.toString().replace(/\\B(?=(\\d{3})+(?!\\d))/g, thousands) + floatPart + (postfix || '');\n }\n };\n },\n text: function text() {\n return {\n display: __htmlEscapeEntities\n };\n }\n };\n /*\n * This is really a good bit rubbish this method of exposing the internal methods\n * publicly... - To be fixed in 2.0 using methods on the prototype\n */\n\n /**\n * Create a wrapper function for exporting an internal functions to an external API.\n * @param {string} fn API function name\n * @returns {function} wrapped function\n * @memberof DataTable#internal\n */\n\n function _fnExternApiFunc(fn) {\n return function () {\n var args = [_fnSettingsFromNode(this[DataTable.ext.iApiIndex])].concat(Array.prototype.slice.call(arguments));\n return DataTable.ext.internal[fn].apply(this, args);\n };\n }\n /**\n * Reference to internal functions for use by plug-in developers. Note that\n * these methods are references to internal functions and are considered to be\n * private. If you use these methods, be aware that they are liable to change\n * between versions.\n * @namespace\n */\n\n\n $.extend(DataTable.ext.internal, {\n _fnExternApiFunc: _fnExternApiFunc,\n _fnBuildAjax: _fnBuildAjax,\n _fnAjaxUpdate: _fnAjaxUpdate,\n _fnAjaxParameters: _fnAjaxParameters,\n _fnAjaxUpdateDraw: _fnAjaxUpdateDraw,\n _fnAjaxDataSrc: _fnAjaxDataSrc,\n _fnAddColumn: _fnAddColumn,\n _fnColumnOptions: _fnColumnOptions,\n _fnAdjustColumnSizing: _fnAdjustColumnSizing,\n _fnVisibleToColumnIndex: _fnVisibleToColumnIndex,\n _fnColumnIndexToVisible: _fnColumnIndexToVisible,\n _fnVisbleColumns: _fnVisbleColumns,\n _fnGetColumns: _fnGetColumns,\n _fnColumnTypes: _fnColumnTypes,\n _fnApplyColumnDefs: _fnApplyColumnDefs,\n _fnHungarianMap: _fnHungarianMap,\n _fnCamelToHungarian: _fnCamelToHungarian,\n _fnLanguageCompat: _fnLanguageCompat,\n _fnBrowserDetect: _fnBrowserDetect,\n _fnAddData: _fnAddData,\n _fnAddTr: _fnAddTr,\n _fnNodeToDataIndex: _fnNodeToDataIndex,\n _fnNodeToColumnIndex: _fnNodeToColumnIndex,\n _fnGetCellData: _fnGetCellData,\n _fnSetCellData: _fnSetCellData,\n _fnSplitObjNotation: _fnSplitObjNotation,\n _fnGetObjectDataFn: _fnGetObjectDataFn,\n _fnSetObjectDataFn: _fnSetObjectDataFn,\n _fnGetDataMaster: _fnGetDataMaster,\n _fnClearTable: _fnClearTable,\n _fnDeleteIndex: _fnDeleteIndex,\n _fnInvalidate: _fnInvalidate,\n _fnGetRowElements: _fnGetRowElements,\n _fnCreateTr: _fnCreateTr,\n _fnBuildHead: _fnBuildHead,\n _fnDrawHead: _fnDrawHead,\n _fnDraw: _fnDraw,\n _fnReDraw: _fnReDraw,\n _fnAddOptionsHtml: _fnAddOptionsHtml,\n _fnDetectHeader: _fnDetectHeader,\n _fnGetUniqueThs: _fnGetUniqueThs,\n _fnFeatureHtmlFilter: _fnFeatureHtmlFilter,\n _fnFilterComplete: _fnFilterComplete,\n _fnFilterCustom: _fnFilterCustom,\n _fnFilterColumn: _fnFilterColumn,\n _fnFilter: _fnFilter,\n _fnFilterCreateSearch: _fnFilterCreateSearch,\n _fnEscapeRegex: _fnEscapeRegex,\n _fnFilterData: _fnFilterData,\n _fnFeatureHtmlInfo: _fnFeatureHtmlInfo,\n _fnUpdateInfo: _fnUpdateInfo,\n _fnInfoMacros: _fnInfoMacros,\n _fnInitialise: _fnInitialise,\n _fnInitComplete: _fnInitComplete,\n _fnLengthChange: _fnLengthChange,\n _fnFeatureHtmlLength: _fnFeatureHtmlLength,\n _fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate,\n _fnPageChange: _fnPageChange,\n _fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing,\n _fnProcessingDisplay: _fnProcessingDisplay,\n _fnFeatureHtmlTable: _fnFeatureHtmlTable,\n _fnScrollDraw: _fnScrollDraw,\n _fnApplyToChildren: _fnApplyToChildren,\n _fnCalculateColumnWidths: _fnCalculateColumnWidths,\n _fnThrottle: _fnThrottle,\n _fnConvertToWidth: _fnConvertToWidth,\n _fnGetWidestNode: _fnGetWidestNode,\n _fnGetMaxLenString: _fnGetMaxLenString,\n _fnStringToCss: _fnStringToCss,\n _fnSortFlatten: _fnSortFlatten,\n _fnSort: _fnSort,\n _fnSortAria: _fnSortAria,\n _fnSortListener: _fnSortListener,\n _fnSortAttachListener: _fnSortAttachListener,\n _fnSortingClasses: _fnSortingClasses,\n _fnSortData: _fnSortData,\n _fnSaveState: _fnSaveState,\n _fnLoadState: _fnLoadState,\n _fnSettingsFromNode: _fnSettingsFromNode,\n _fnLog: _fnLog,\n _fnMap: _fnMap,\n _fnBindAction: _fnBindAction,\n _fnCallbackReg: _fnCallbackReg,\n _fnCallbackFire: _fnCallbackFire,\n _fnLengthOverflow: _fnLengthOverflow,\n _fnRenderer: _fnRenderer,\n _fnDataSource: _fnDataSource,\n _fnRowAttributes: _fnRowAttributes,\n _fnExtend: _fnExtend,\n _fnCalculateEnd: function _fnCalculateEnd() {} // Used by a lot of plug-ins, but redundant\n // in 1.10, so this dead-end function is\n // added to prevent errors\n\n }); // jQuery access\n\n $.fn.dataTable = DataTable; // Provide access to the host jQuery object (circular reference)\n\n DataTable.$ = $; // Legacy aliases\n\n $.fn.dataTableSettings = DataTable.settings;\n $.fn.dataTableExt = DataTable.ext; // With a capital `D` we return a DataTables API instance rather than a\n // jQuery object\n\n $.fn.DataTable = function (opts) {\n return $(this).dataTable(opts).api();\n }; // All properties that are available to $.fn.dataTable should also be\n // available on $.fn.DataTable\n\n\n $.each(DataTable, function (prop, val) {\n $.fn.DataTable[prop] = val;\n }); // Information about events fired by DataTables - for documentation.\n\n /**\n * Draw event, fired whenever the table is redrawn on the page, at the same\n * point as fnDrawCallback. This may be useful for binding events or\n * performing calculations when the table is altered at all.\n * @name DataTable#draw.dt\n * @event\n * @param {event} e jQuery event object\n * @param {object} o DataTables settings object {@link DataTable.models.oSettings}\n */\n\n /**\n * Search event, fired when the searching applied to the table (using the\n * built-in global search, or column filters) is altered.\n * @name DataTable#search.dt\n * @event\n * @param {event} e jQuery event object\n * @param {object} o DataTables settings object {@link DataTable.models.oSettings}\n */\n\n /**\n * Page change event, fired when the paging of the table is altered.\n * @name DataTable#page.dt\n * @event\n * @param {event} e jQuery event object\n * @param {object} o DataTables settings object {@link DataTable.models.oSettings}\n */\n\n /**\n * Order event, fired when the ordering applied to the table is altered.\n * @name DataTable#order.dt\n * @event\n * @param {event} e jQuery event object\n * @param {object} o DataTables settings object {@link DataTable.models.oSettings}\n */\n\n /**\n * DataTables initialisation complete event, fired when the table is fully\n * drawn, including Ajax data loaded, if Ajax data is required.\n * @name DataTable#init.dt\n * @event\n * @param {event} e jQuery event object\n * @param {object} oSettings DataTables settings object\n * @param {object} json The JSON object request from the server - only\n * present if client-side Ajax sourced data is used\n */\n\n /**\n * State save event, fired when the table has changed state a new state save\n * is required. This event allows modification of the state saving object\n * prior to actually doing the save, including addition or other state\n * properties (for plug-ins) or modification of a DataTables core property.\n * @name DataTable#stateSaveParams.dt\n * @event\n * @param {event} e jQuery event object\n * @param {object} oSettings DataTables settings object\n * @param {object} json The state information to be saved\n */\n\n /**\n * State load event, fired when the table is loading state from the stored\n * data, but prior to the settings object being modified by the saved state\n * - allowing modification of the saved state is required or loading of\n * state for a plug-in.\n * @name DataTable#stateLoadParams.dt\n * @event\n * @param {event} e jQuery event object\n * @param {object} oSettings DataTables settings object\n * @param {object} json The saved state information\n */\n\n /**\n * State loaded event, fired when state has been loaded from stored data and\n * the settings object has been modified by the loaded data.\n * @name DataTable#stateLoaded.dt\n * @event\n * @param {event} e jQuery event object\n * @param {object} oSettings DataTables settings object\n * @param {object} json The saved state information\n */\n\n /**\n * Processing event, fired when DataTables is doing some kind of processing\n * (be it, order, searcg or anything else). It can be used to indicate to\n * the end user that there is something happening, or that something has\n * finished.\n * @name DataTable#processing.dt\n * @event\n * @param {event} e jQuery event object\n * @param {object} oSettings DataTables settings object\n * @param {boolean} bShow Flag for if DataTables is doing processing or not\n */\n\n /**\n * Ajax (XHR) event, fired whenever an Ajax request is completed from a\n * request to made to the server for new data. This event is called before\n * DataTables processed the returned data, so it can also be used to pre-\n * process the data returned from the server, if needed.\n *\n * Note that this trigger is called in `fnServerData`, if you override\n * `fnServerData` and which to use this event, you need to trigger it in you\n * success function.\n * @name DataTable#xhr.dt\n * @event\n * @param {event} e jQuery event object\n * @param {object} o DataTables settings object {@link DataTable.models.oSettings}\n * @param {object} json JSON returned from the server\n *\n * @example\n * // Use a custom property returned from the server in another DOM element\n * $('#table').dataTable().on('xhr.dt', function (e, settings, json) {\n * $('#status').html( json.status );\n * } );\n *\n * @example\n * // Pre-process the data returned from the server\n * $('#table').dataTable().on('xhr.dt', function (e, settings, json) {\n * for ( var i=0, ien=json.aaData.length ; i elements\n // (i.e., `typeof document.createElement( \"object\" ) === \"function\"`).\n // We don't want to classify *any* DOM node as a function.\n // Support: QtWeb <=3.8.5, WebKit <=534.34, wkhtmltopdf tool <=0.12.5\n // Plus for old WebKit, typeof returns \"function\" for HTML collections\n // (e.g., `typeof document.getElementsByTagName(\"div\") === \"function\"`). (gh-4756)\n return typeof obj === \"function\" && typeof obj.nodeType !== \"number\" && typeof obj.item !== \"function\";\n };\n\n var isWindow = function isWindow(obj) {\n return obj != null && obj === obj.window;\n };\n\n var document = window.document;\n var preservedScriptAttributes = {\n type: true,\n src: true,\n nonce: true,\n noModule: true\n };\n\n function DOMEval(code, node, doc) {\n doc = doc || document;\n var i,\n val,\n script = doc.createElement(\"script\");\n script.text = code;\n\n if (node) {\n for (i in preservedScriptAttributes) {\n // Support: Firefox 64+, Edge 18+\n // Some browsers don't support the \"nonce\" property on scripts.\n // On the other hand, just using `getAttribute` is not enough as\n // the `nonce` attribute is reset to an empty string whenever it\n // becomes browsing-context connected.\n // See https://github.com/whatwg/html/issues/2369\n // See https://html.spec.whatwg.org/#nonce-attributes\n // The `node.getAttribute` check was added for the sake of\n // `jQuery.globalEval` so that it can fake a nonce-containing node\n // via an object.\n val = node[i] || node.getAttribute && node.getAttribute(i);\n\n if (val) {\n script.setAttribute(i, val);\n }\n }\n }\n\n doc.head.appendChild(script).parentNode.removeChild(script);\n }\n\n function toType(obj) {\n if (obj == null) {\n return obj + \"\";\n } // Support: Android <=2.3 only (functionish RegExp)\n\n\n return _typeof(obj) === \"object\" || typeof obj === \"function\" ? class2type[toString.call(obj)] || \"object\" : _typeof(obj);\n }\n /* global Symbol */\n // Defining this global in .eslintrc.json would create a danger of using the global\n // unguarded in another place, it seems safer to define global only for this module\n\n\n var version = \"3.6.0\",\n // Define a local copy of jQuery\n jQuery = function jQuery(selector, context) {\n // The jQuery object is actually just the init constructor 'enhanced'\n // Need init if jQuery is called (just allow error to be thrown if not included)\n return new jQuery.fn.init(selector, context);\n };\n\n jQuery.fn = jQuery.prototype = {\n // The current version of jQuery being used\n jquery: version,\n constructor: jQuery,\n // The default length of a jQuery object is 0\n length: 0,\n toArray: function toArray() {\n return _slice.call(this);\n },\n // Get the Nth element in the matched element set OR\n // Get the whole matched element set as a clean array\n get: function get(num) {\n // Return all the elements in a clean array\n if (num == null) {\n return _slice.call(this);\n } // Return just the one element from the set\n\n\n return num < 0 ? this[num + this.length] : this[num];\n },\n // Take an array of elements and push it onto the stack\n // (returning the new matched element set)\n pushStack: function pushStack(elems) {\n // Build a new jQuery matched element set\n var ret = jQuery.merge(this.constructor(), elems); // Add the old object onto the stack (as a reference)\n\n ret.prevObject = this; // Return the newly-formed element set\n\n return ret;\n },\n // Execute a callback for every element in the matched set.\n each: function each(callback) {\n return jQuery.each(this, callback);\n },\n map: function map(callback) {\n return this.pushStack(jQuery.map(this, function (elem, i) {\n return callback.call(elem, i, elem);\n }));\n },\n slice: function slice() {\n return this.pushStack(_slice.apply(this, arguments));\n },\n first: function first() {\n return this.eq(0);\n },\n last: function last() {\n return this.eq(-1);\n },\n even: function even() {\n return this.pushStack(jQuery.grep(this, function (_elem, i) {\n return (i + 1) % 2;\n }));\n },\n odd: function odd() {\n return this.pushStack(jQuery.grep(this, function (_elem, i) {\n return i % 2;\n }));\n },\n eq: function eq(i) {\n var len = this.length,\n j = +i + (i < 0 ? len : 0);\n return this.pushStack(j >= 0 && j < len ? [this[j]] : []);\n },\n end: function end() {\n return this.prevObject || this.constructor();\n },\n // For internal use only.\n // Behaves like an Array's method, not like a jQuery method.\n push: push,\n sort: arr.sort,\n splice: arr.splice\n };\n\n jQuery.extend = jQuery.fn.extend = function () {\n var options,\n name,\n src,\n copy,\n copyIsArray,\n clone,\n target = arguments[0] || {},\n i = 1,\n length = arguments.length,\n deep = false; // Handle a deep copy situation\n\n if (typeof target === \"boolean\") {\n deep = target; // Skip the boolean and the target\n\n target = arguments[i] || {};\n i++;\n } // Handle case when target is a string or something (possible in deep copy)\n\n\n if (_typeof(target) !== \"object\" && !isFunction(target)) {\n target = {};\n } // Extend jQuery itself if only one argument is passed\n\n\n if (i === length) {\n target = this;\n i--;\n }\n\n for (; i < length; i++) {\n // Only deal with non-null/undefined values\n if ((options = arguments[i]) != null) {\n // Extend the base object\n for (name in options) {\n copy = options[name]; // Prevent Object.prototype pollution\n // Prevent never-ending loop\n\n if (name === \"__proto__\" || target === copy) {\n continue;\n } // Recurse if we're merging plain objects or arrays\n\n\n if (deep && copy && (jQuery.isPlainObject(copy) || (copyIsArray = Array.isArray(copy)))) {\n src = target[name]; // Ensure proper type for the source value\n\n if (copyIsArray && !Array.isArray(src)) {\n clone = [];\n } else if (!copyIsArray && !jQuery.isPlainObject(src)) {\n clone = {};\n } else {\n clone = src;\n }\n\n copyIsArray = false; // Never move original objects, clone them\n\n target[name] = jQuery.extend(deep, clone, copy); // Don't bring in undefined values\n } else if (copy !== undefined) {\n target[name] = copy;\n }\n }\n }\n } // Return the modified object\n\n\n return target;\n };\n\n jQuery.extend({\n // Unique for each copy of jQuery on the page\n expando: \"jQuery\" + (version + Math.random()).replace(/\\D/g, \"\"),\n // Assume jQuery is ready without the ready module\n isReady: true,\n error: function error(msg) {\n throw new Error(msg);\n },\n noop: function noop() {},\n isPlainObject: function isPlainObject(obj) {\n var proto, Ctor; // Detect obvious negatives\n // Use toString instead of jQuery.type to catch host objects\n\n if (!obj || toString.call(obj) !== \"[object Object]\") {\n return false;\n }\n\n proto = getProto(obj); // Objects with no prototype (e.g., `Object.create( null )`) are plain\n\n if (!proto) {\n return true;\n } // Objects with prototype are plain iff they were constructed by a global Object function\n\n\n Ctor = hasOwn.call(proto, \"constructor\") && proto.constructor;\n return typeof Ctor === \"function\" && fnToString.call(Ctor) === ObjectFunctionString;\n },\n isEmptyObject: function isEmptyObject(obj) {\n var name;\n\n for (name in obj) {\n return false;\n }\n\n return true;\n },\n // Evaluates a script in a provided context; falls back to the global one\n // if not specified.\n globalEval: function globalEval(code, options, doc) {\n DOMEval(code, {\n nonce: options && options.nonce\n }, doc);\n },\n each: function each(obj, callback) {\n var length,\n i = 0;\n\n if (isArrayLike(obj)) {\n length = obj.length;\n\n for (; i < length; i++) {\n if (callback.call(obj[i], i, obj[i]) === false) {\n break;\n }\n }\n } else {\n for (i in obj) {\n if (callback.call(obj[i], i, obj[i]) === false) {\n break;\n }\n }\n }\n\n return obj;\n },\n // results is for internal usage only\n makeArray: function makeArray(arr, results) {\n var ret = results || [];\n\n if (arr != null) {\n if (isArrayLike(Object(arr))) {\n jQuery.merge(ret, typeof arr === \"string\" ? [arr] : arr);\n } else {\n push.call(ret, arr);\n }\n }\n\n return ret;\n },\n inArray: function inArray(elem, arr, i) {\n return arr == null ? -1 : indexOf.call(arr, elem, i);\n },\n // Support: Android <=4.0 only, PhantomJS 1 only\n // push.apply(_, arraylike) throws on ancient WebKit\n merge: function merge(first, second) {\n var len = +second.length,\n j = 0,\n i = first.length;\n\n for (; j < len; j++) {\n first[i++] = second[j];\n }\n\n first.length = i;\n return first;\n },\n grep: function grep(elems, callback, invert) {\n var callbackInverse,\n matches = [],\n i = 0,\n length = elems.length,\n callbackExpect = !invert; // Go through the array, only saving the items\n // that pass the validator function\n\n for (; i < length; i++) {\n callbackInverse = !callback(elems[i], i);\n\n if (callbackInverse !== callbackExpect) {\n matches.push(elems[i]);\n }\n }\n\n return matches;\n },\n // arg is for internal usage only\n map: function map(elems, callback, arg) {\n var length,\n value,\n i = 0,\n ret = []; // Go through the array, translating each of the items to their new values\n\n if (isArrayLike(elems)) {\n length = elems.length;\n\n for (; i < length; i++) {\n value = callback(elems[i], i, arg);\n\n if (value != null) {\n ret.push(value);\n }\n } // Go through every key on the object,\n\n } else {\n for (i in elems) {\n value = callback(elems[i], i, arg);\n\n if (value != null) {\n ret.push(value);\n }\n }\n } // Flatten any nested arrays\n\n\n return flat(ret);\n },\n // A global GUID counter for objects\n guid: 1,\n // jQuery.support is not used in Core but other projects attach their\n // properties to it so it needs to exist.\n support: support\n });\n\n if (typeof Symbol === \"function\") {\n jQuery.fn[Symbol.iterator] = arr[Symbol.iterator];\n } // Populate the class2type map\n\n\n jQuery.each(\"Boolean Number String Function Array Date RegExp Object Error Symbol\".split(\" \"), function (_i, name) {\n class2type[\"[object \" + name + \"]\"] = name.toLowerCase();\n });\n\n function isArrayLike(obj) {\n // Support: real iOS 8.2 only (not reproducible in simulator)\n // `in` check used to prevent JIT error (gh-2145)\n // hasOwn isn't used here due to false negatives\n // regarding Nodelist length in IE\n var length = !!obj && \"length\" in obj && obj.length,\n type = toType(obj);\n\n if (isFunction(obj) || isWindow(obj)) {\n return false;\n }\n\n return type === \"array\" || length === 0 || typeof length === \"number\" && length > 0 && length - 1 in obj;\n }\n\n var Sizzle =\n /*!\n * Sizzle CSS Selector Engine v2.3.6\n * https://sizzlejs.com/\n *\n * Copyright JS Foundation and other contributors\n * Released under the MIT license\n * https://js.foundation/\n *\n * Date: 2021-02-16\n */\n function (window) {\n var i,\n support,\n Expr,\n getText,\n isXML,\n tokenize,\n compile,\n select,\n outermostContext,\n sortInput,\n hasDuplicate,\n // Local document vars\n setDocument,\n document,\n docElem,\n documentIsHTML,\n rbuggyQSA,\n rbuggyMatches,\n matches,\n contains,\n // Instance-specific data\n expando = \"sizzle\" + 1 * new Date(),\n preferredDoc = window.document,\n dirruns = 0,\n done = 0,\n classCache = createCache(),\n tokenCache = createCache(),\n compilerCache = createCache(),\n nonnativeSelectorCache = createCache(),\n sortOrder = function sortOrder(a, b) {\n if (a === b) {\n hasDuplicate = true;\n }\n\n return 0;\n },\n // Instance methods\n hasOwn = {}.hasOwnProperty,\n arr = [],\n pop = arr.pop,\n pushNative = arr.push,\n push = arr.push,\n slice = arr.slice,\n // Use a stripped-down indexOf as it's faster than native\n // https://jsperf.com/thor-indexof-vs-for/5\n indexOf = function indexOf(list, elem) {\n var i = 0,\n len = list.length;\n\n for (; i < len; i++) {\n if (list[i] === elem) {\n return i;\n }\n }\n\n return -1;\n },\n booleans = \"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|\" + \"ismap|loop|multiple|open|readonly|required|scoped\",\n // Regular expressions\n // http://www.w3.org/TR/css3-selectors/#whitespace\n whitespace = \"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",\n // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram\n identifier = \"(?:\\\\\\\\[\\\\da-fA-F]{1,6}\" + whitespace + \"?|\\\\\\\\[^\\\\r\\\\n\\\\f]|[\\\\w-]|[^\\0-\\\\x7f])+\",\n // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors\n attributes = \"\\\\[\" + whitespace + \"*(\" + identifier + \")(?:\" + whitespace + // Operator (capture 2)\n \"*([*^$|!~]?=)\" + whitespace + // \"Attribute values must be CSS identifiers [capture 5]\n // or strings [capture 3 or capture 4]\"\n \"*(?:'((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\"|(\" + identifier + \"))|)\" + whitespace + \"*\\\\]\",\n pseudos = \":(\" + identifier + \")(?:\\\\((\" + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:\n // 1. quoted (capture 3; capture 4 or capture 5)\n \"('((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\")|\" + // 2. simple (capture 6)\n \"((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\" + attributes + \")*)|\" + // 3. anything else (capture 2)\n \".*\" + \")\\\\)|)\",\n // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter\n rwhitespace = new RegExp(whitespace + \"+\", \"g\"),\n rtrim = new RegExp(\"^\" + whitespace + \"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\" + whitespace + \"+$\", \"g\"),\n rcomma = new RegExp(\"^\" + whitespace + \"*,\" + whitespace + \"*\"),\n rcombinators = new RegExp(\"^\" + whitespace + \"*([>+~]|\" + whitespace + \")\" + whitespace + \"*\"),\n rdescend = new RegExp(whitespace + \"|>\"),\n rpseudo = new RegExp(pseudos),\n ridentifier = new RegExp(\"^\" + identifier + \"$\"),\n matchExpr = {\n \"ID\": new RegExp(\"^#(\" + identifier + \")\"),\n \"CLASS\": new RegExp(\"^\\\\.(\" + identifier + \")\"),\n \"TAG\": new RegExp(\"^(\" + identifier + \"|[*])\"),\n \"ATTR\": new RegExp(\"^\" + attributes),\n \"PSEUDO\": new RegExp(\"^\" + pseudos),\n \"CHILD\": new RegExp(\"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\" + whitespace + \"*(even|odd|(([+-]|)(\\\\d*)n|)\" + whitespace + \"*(?:([+-]|)\" + whitespace + \"*(\\\\d+)|))\" + whitespace + \"*\\\\)|)\", \"i\"),\n \"bool\": new RegExp(\"^(?:\" + booleans + \")$\", \"i\"),\n // For use in libraries implementing .is()\n // We use this for POS matching in `select`\n \"needsContext\": new RegExp(\"^\" + whitespace + \"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\" + whitespace + \"*((?:-\\\\d)?\\\\d*)\" + whitespace + \"*\\\\)|)(?=[^-]|$)\", \"i\")\n },\n rhtml = /HTML$/i,\n rinputs = /^(?:input|select|textarea|button)$/i,\n rheader = /^h\\d$/i,\n rnative = /^[^{]+\\{\\s*\\[native \\w/,\n // Easily-parseable/retrievable ID or TAG or CLASS selectors\n rquickExpr = /^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,\n rsibling = /[+~]/,\n // CSS escapes\n // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters\n runescape = new RegExp(\"\\\\\\\\[\\\\da-fA-F]{1,6}\" + whitespace + \"?|\\\\\\\\([^\\\\r\\\\n\\\\f])\", \"g\"),\n funescape = function funescape(escape, nonHex) {\n var high = \"0x\" + escape.slice(1) - 0x10000;\n return nonHex ? // Strip the backslash prefix from a non-hex escape sequence\n nonHex : // Replace a hexadecimal escape sequence with the encoded Unicode code point\n // Support: IE <=11+\n // For values outside the Basic Multilingual Plane (BMP), manually construct a\n // surrogate pair\n high < 0 ? String.fromCharCode(high + 0x10000) : String.fromCharCode(high >> 10 | 0xD800, high & 0x3FF | 0xDC00);\n },\n // CSS string/identifier serialization\n // https://drafts.csswg.org/cssom/#common-serializing-idioms\n rcssescape = /([\\0-\\x1f\\x7f]|^-?\\d)|^-$|[^\\0-\\x1f\\x7f-\\uFFFF\\w-]/g,\n fcssescape = function fcssescape(ch, asCodePoint) {\n if (asCodePoint) {\n // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER\n if (ch === \"\\0\") {\n return \"\\uFFFD\";\n } // Control characters and (dependent upon position) numbers get escaped as code points\n\n\n return ch.slice(0, -1) + \"\\\\\" + ch.charCodeAt(ch.length - 1).toString(16) + \" \";\n } // Other potentially-special ASCII characters get backslash-escaped\n\n\n return \"\\\\\" + ch;\n },\n // Used for iframes\n // See setDocument()\n // Removing the function wrapper causes a \"Permission Denied\"\n // error in IE\n unloadHandler = function unloadHandler() {\n setDocument();\n },\n inDisabledFieldset = addCombinator(function (elem) {\n return elem.disabled === true && elem.nodeName.toLowerCase() === \"fieldset\";\n }, {\n dir: \"parentNode\",\n next: \"legend\"\n }); // Optimize for push.apply( _, NodeList )\n\n\n try {\n push.apply(arr = slice.call(preferredDoc.childNodes), preferredDoc.childNodes); // Support: Android<4.0\n // Detect silently failing push.apply\n // eslint-disable-next-line no-unused-expressions\n\n arr[preferredDoc.childNodes.length].nodeType;\n } catch (e) {\n push = {\n apply: arr.length ? // Leverage slice if possible\n function (target, els) {\n pushNative.apply(target, slice.call(els));\n } : // Support: IE<9\n // Otherwise append directly\n function (target, els) {\n var j = target.length,\n i = 0; // Can't trust NodeList.length\n\n while (target[j++] = els[i++]) {}\n\n target.length = j - 1;\n }\n };\n }\n\n function Sizzle(selector, context, results, seed) {\n var m,\n i,\n elem,\n nid,\n match,\n groups,\n newSelector,\n newContext = context && context.ownerDocument,\n // nodeType defaults to 9, since context defaults to document\n nodeType = context ? context.nodeType : 9;\n results = results || []; // Return early from calls with invalid selector or context\n\n if (typeof selector !== \"string\" || !selector || nodeType !== 1 && nodeType !== 9 && nodeType !== 11) {\n return results;\n } // Try to shortcut find operations (as opposed to filters) in HTML documents\n\n\n if (!seed) {\n setDocument(context);\n context = context || document;\n\n if (documentIsHTML) {\n // If the selector is sufficiently simple, try using a \"get*By*\" DOM method\n // (excepting DocumentFragment context, where the methods don't exist)\n if (nodeType !== 11 && (match = rquickExpr.exec(selector))) {\n // ID selector\n if (m = match[1]) {\n // Document context\n if (nodeType === 9) {\n if (elem = context.getElementById(m)) {\n // Support: IE, Opera, Webkit\n // TODO: identify versions\n // getElementById can match elements by name instead of ID\n if (elem.id === m) {\n results.push(elem);\n return results;\n }\n } else {\n return results;\n } // Element context\n\n } else {\n // Support: IE, Opera, Webkit\n // TODO: identify versions\n // getElementById can match elements by name instead of ID\n if (newContext && (elem = newContext.getElementById(m)) && contains(context, elem) && elem.id === m) {\n results.push(elem);\n return results;\n }\n } // Type selector\n\n } else if (match[2]) {\n push.apply(results, context.getElementsByTagName(selector));\n return results; // Class selector\n } else if ((m = match[3]) && support.getElementsByClassName && context.getElementsByClassName) {\n push.apply(results, context.getElementsByClassName(m));\n return results;\n }\n } // Take advantage of querySelectorAll\n\n\n if (support.qsa && !nonnativeSelectorCache[selector + \" \"] && (!rbuggyQSA || !rbuggyQSA.test(selector)) && ( // Support: IE 8 only\n // Exclude object elements\n nodeType !== 1 || context.nodeName.toLowerCase() !== \"object\")) {\n newSelector = selector;\n newContext = context; // qSA considers elements outside a scoping root when evaluating child or\n // descendant combinators, which is not what we want.\n // In such cases, we work around the behavior by prefixing every selector in the\n // list with an ID selector referencing the scope context.\n // The technique has to be used as well when a leading combinator is used\n // as such selectors are not recognized by querySelectorAll.\n // Thanks to Andrew Dupont for this technique.\n\n if (nodeType === 1 && (rdescend.test(selector) || rcombinators.test(selector))) {\n // Expand context for sibling selectors\n newContext = rsibling.test(selector) && testContext(context.parentNode) || context; // We can use :scope instead of the ID hack if the browser\n // supports it & if we're not changing the context.\n\n if (newContext !== context || !support.scope) {\n // Capture the context ID, setting it first if necessary\n if (nid = context.getAttribute(\"id\")) {\n nid = nid.replace(rcssescape, fcssescape);\n } else {\n context.setAttribute(\"id\", nid = expando);\n }\n } // Prefix every selector in the list\n\n\n groups = tokenize(selector);\n i = groups.length;\n\n while (i--) {\n groups[i] = (nid ? \"#\" + nid : \":scope\") + \" \" + toSelector(groups[i]);\n }\n\n newSelector = groups.join(\",\");\n }\n\n try {\n push.apply(results, newContext.querySelectorAll(newSelector));\n return results;\n } catch (qsaError) {\n nonnativeSelectorCache(selector, true);\n } finally {\n if (nid === expando) {\n context.removeAttribute(\"id\");\n }\n }\n }\n }\n } // All others\n\n\n return select(selector.replace(rtrim, \"$1\"), context, results, seed);\n }\n /**\n * Create key-value caches of limited size\n * @returns {function(string, object)} Returns the Object data after storing it on itself with\n *\tproperty name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)\n *\tdeleting the oldest entry\n */\n\n\n function createCache() {\n var keys = [];\n\n function cache(key, value) {\n // Use (key + \" \") to avoid collision with native prototype properties (see Issue #157)\n if (keys.push(key + \" \") > Expr.cacheLength) {\n // Only keep the most recent entries\n delete cache[keys.shift()];\n }\n\n return cache[key + \" \"] = value;\n }\n\n return cache;\n }\n /**\n * Mark a function for special use by Sizzle\n * @param {Function} fn The function to mark\n */\n\n\n function markFunction(fn) {\n fn[expando] = true;\n return fn;\n }\n /**\n * Support testing using an element\n * @param {Function} fn Passed the created element and returns a boolean result\n */\n\n\n function assert(fn) {\n var el = document.createElement(\"fieldset\");\n\n try {\n return !!fn(el);\n } catch (e) {\n return false;\n } finally {\n // Remove from its parent by default\n if (el.parentNode) {\n el.parentNode.removeChild(el);\n } // release memory in IE\n\n\n el = null;\n }\n }\n /**\n * Adds the same handler for all of the specified attrs\n * @param {String} attrs Pipe-separated list of attributes\n * @param {Function} handler The method that will be applied\n */\n\n\n function addHandle(attrs, handler) {\n var arr = attrs.split(\"|\"),\n i = arr.length;\n\n while (i--) {\n Expr.attrHandle[arr[i]] = handler;\n }\n }\n /**\n * Checks document order of two siblings\n * @param {Element} a\n * @param {Element} b\n * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b\n */\n\n\n function siblingCheck(a, b) {\n var cur = b && a,\n diff = cur && a.nodeType === 1 && b.nodeType === 1 && a.sourceIndex - b.sourceIndex; // Use IE sourceIndex if available on both nodes\n\n if (diff) {\n return diff;\n } // Check if b follows a\n\n\n if (cur) {\n while (cur = cur.nextSibling) {\n if (cur === b) {\n return -1;\n }\n }\n }\n\n return a ? 1 : -1;\n }\n /**\n * Returns a function to use in pseudos for input types\n * @param {String} type\n */\n\n\n function createInputPseudo(type) {\n return function (elem) {\n var name = elem.nodeName.toLowerCase();\n return name === \"input\" && elem.type === type;\n };\n }\n /**\n * Returns a function to use in pseudos for buttons\n * @param {String} type\n */\n\n\n function createButtonPseudo(type) {\n return function (elem) {\n var name = elem.nodeName.toLowerCase();\n return (name === \"input\" || name === \"button\") && elem.type === type;\n };\n }\n /**\n * Returns a function to use in pseudos for :enabled/:disabled\n * @param {Boolean} disabled true for :disabled; false for :enabled\n */\n\n\n function createDisabledPseudo(disabled) {\n // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable\n return function (elem) {\n // Only certain elements can match :enabled or :disabled\n // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled\n // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled\n if (\"form\" in elem) {\n // Check for inherited disabledness on relevant non-disabled elements:\n // * listed form-associated elements in a disabled fieldset\n // https://html.spec.whatwg.org/multipage/forms.html#category-listed\n // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled\n // * option elements in a disabled optgroup\n // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled\n // All such elements have a \"form\" property.\n if (elem.parentNode && elem.disabled === false) {\n // Option elements defer to a parent optgroup if present\n if (\"label\" in elem) {\n if (\"label\" in elem.parentNode) {\n return elem.parentNode.disabled === disabled;\n } else {\n return elem.disabled === disabled;\n }\n } // Support: IE 6 - 11\n // Use the isDisabled shortcut property to check for disabled fieldset ancestors\n\n\n return elem.isDisabled === disabled || // Where there is no isDisabled, check manually\n\n /* jshint -W018 */\n elem.isDisabled !== !disabled && inDisabledFieldset(elem) === disabled;\n }\n\n return elem.disabled === disabled; // Try to winnow out elements that can't be disabled before trusting the disabled property.\n // Some victims get caught in our net (label, legend, menu, track), but it shouldn't\n // even exist on them, let alone have a boolean value.\n } else if (\"label\" in elem) {\n return elem.disabled === disabled;\n } // Remaining elements are neither :enabled nor :disabled\n\n\n return false;\n };\n }\n /**\n * Returns a function to use in pseudos for positionals\n * @param {Function} fn\n */\n\n\n function createPositionalPseudo(fn) {\n return markFunction(function (argument) {\n argument = +argument;\n return markFunction(function (seed, matches) {\n var j,\n matchIndexes = fn([], seed.length, argument),\n i = matchIndexes.length; // Match elements found at the specified indexes\n\n while (i--) {\n if (seed[j = matchIndexes[i]]) {\n seed[j] = !(matches[j] = seed[j]);\n }\n }\n });\n });\n }\n /**\n * Checks a node for validity as a Sizzle context\n * @param {Element|Object=} context\n * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value\n */\n\n\n function testContext(context) {\n return context && typeof context.getElementsByTagName !== \"undefined\" && context;\n } // Expose support vars for convenience\n\n\n support = Sizzle.support = {};\n /**\n * Detects XML nodes\n * @param {Element|Object} elem An element or a document\n * @returns {Boolean} True iff elem is a non-HTML XML node\n */\n\n isXML = Sizzle.isXML = function (elem) {\n var namespace = elem && elem.namespaceURI,\n docElem = elem && (elem.ownerDocument || elem).documentElement; // Support: IE <=8\n // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes\n // https://bugs.jquery.com/ticket/4833\n\n return !rhtml.test(namespace || docElem && docElem.nodeName || \"HTML\");\n };\n /**\n * Sets document-related variables once based on the current document\n * @param {Element|Object} [doc] An element or document object to use to set the document\n * @returns {Object} Returns the current document\n */\n\n\n setDocument = Sizzle.setDocument = function (node) {\n var hasCompare,\n subWindow,\n doc = node ? node.ownerDocument || node : preferredDoc; // Return early if doc is invalid or already selected\n // Support: IE 11+, Edge 17 - 18+\n // IE/Edge sometimes throw a \"Permission denied\" error when strict-comparing\n // two documents; shallow comparisons work.\n // eslint-disable-next-line eqeqeq\n\n if (doc == document || doc.nodeType !== 9 || !doc.documentElement) {\n return document;\n } // Update global variables\n\n\n document = doc;\n docElem = document.documentElement;\n documentIsHTML = !isXML(document); // Support: IE 9 - 11+, Edge 12 - 18+\n // Accessing iframe documents after unload throws \"permission denied\" errors (jQuery #13936)\n // Support: IE 11+, Edge 17 - 18+\n // IE/Edge sometimes throw a \"Permission denied\" error when strict-comparing\n // two documents; shallow comparisons work.\n // eslint-disable-next-line eqeqeq\n\n if (preferredDoc != document && (subWindow = document.defaultView) && subWindow.top !== subWindow) {\n // Support: IE 11, Edge\n if (subWindow.addEventListener) {\n subWindow.addEventListener(\"unload\", unloadHandler, false); // Support: IE 9 - 10 only\n } else if (subWindow.attachEvent) {\n subWindow.attachEvent(\"onunload\", unloadHandler);\n }\n } // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only,\n // Safari 4 - 5 only, Opera <=11.6 - 12.x only\n // IE/Edge & older browsers don't support the :scope pseudo-class.\n // Support: Safari 6.0 only\n // Safari 6.0 supports :scope but it's an alias of :root there.\n\n\n support.scope = assert(function (el) {\n docElem.appendChild(el).appendChild(document.createElement(\"div\"));\n return typeof el.querySelectorAll !== \"undefined\" && !el.querySelectorAll(\":scope fieldset div\").length;\n });\n /* Attributes\n ---------------------------------------------------------------------- */\n // Support: IE<8\n // Verify that getAttribute really returns attributes and not properties\n // (excepting IE8 booleans)\n\n support.attributes = assert(function (el) {\n el.className = \"i\";\n return !el.getAttribute(\"className\");\n });\n /* getElement(s)By*\n ---------------------------------------------------------------------- */\n // Check if getElementsByTagName(\"*\") returns only elements\n\n support.getElementsByTagName = assert(function (el) {\n el.appendChild(document.createComment(\"\"));\n return !el.getElementsByTagName(\"*\").length;\n }); // Support: IE<9\n\n support.getElementsByClassName = rnative.test(document.getElementsByClassName); // Support: IE<10\n // Check if getElementById returns elements by name\n // The broken getElementById methods don't pick up programmatically-set names,\n // so use a roundabout getElementsByName test\n\n support.getById = assert(function (el) {\n docElem.appendChild(el).id = expando;\n return !document.getElementsByName || !document.getElementsByName(expando).length;\n }); // ID filter and find\n\n if (support.getById) {\n Expr.filter[\"ID\"] = function (id) {\n var attrId = id.replace(runescape, funescape);\n return function (elem) {\n return elem.getAttribute(\"id\") === attrId;\n };\n };\n\n Expr.find[\"ID\"] = function (id, context) {\n if (typeof context.getElementById !== \"undefined\" && documentIsHTML) {\n var elem = context.getElementById(id);\n return elem ? [elem] : [];\n }\n };\n } else {\n Expr.filter[\"ID\"] = function (id) {\n var attrId = id.replace(runescape, funescape);\n return function (elem) {\n var node = typeof elem.getAttributeNode !== \"undefined\" && elem.getAttributeNode(\"id\");\n return node && node.value === attrId;\n };\n }; // Support: IE 6 - 7 only\n // getElementById is not reliable as a find shortcut\n\n\n Expr.find[\"ID\"] = function (id, context) {\n if (typeof context.getElementById !== \"undefined\" && documentIsHTML) {\n var node,\n i,\n elems,\n elem = context.getElementById(id);\n\n if (elem) {\n // Verify the id attribute\n node = elem.getAttributeNode(\"id\");\n\n if (node && node.value === id) {\n return [elem];\n } // Fall back on getElementsByName\n\n\n elems = context.getElementsByName(id);\n i = 0;\n\n while (elem = elems[i++]) {\n node = elem.getAttributeNode(\"id\");\n\n if (node && node.value === id) {\n return [elem];\n }\n }\n }\n\n return [];\n }\n };\n } // Tag\n\n\n Expr.find[\"TAG\"] = support.getElementsByTagName ? function (tag, context) {\n if (typeof context.getElementsByTagName !== \"undefined\") {\n return context.getElementsByTagName(tag); // DocumentFragment nodes don't have gEBTN\n } else if (support.qsa) {\n return context.querySelectorAll(tag);\n }\n } : function (tag, context) {\n var elem,\n tmp = [],\n i = 0,\n // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too\n results = context.getElementsByTagName(tag); // Filter out possible comments\n\n if (tag === \"*\") {\n while (elem = results[i++]) {\n if (elem.nodeType === 1) {\n tmp.push(elem);\n }\n }\n\n return tmp;\n }\n\n return results;\n }; // Class\n\n Expr.find[\"CLASS\"] = support.getElementsByClassName && function (className, context) {\n if (typeof context.getElementsByClassName !== \"undefined\" && documentIsHTML) {\n return context.getElementsByClassName(className);\n }\n };\n /* QSA/matchesSelector\n ---------------------------------------------------------------------- */\n // QSA and matchesSelector support\n // matchesSelector(:active) reports false when true (IE9/Opera 11.5)\n\n\n rbuggyMatches = []; // qSa(:focus) reports false when true (Chrome 21)\n // We allow this because of a bug in IE8/9 that throws an error\n // whenever `document.activeElement` is accessed on an iframe\n // So, we allow :focus to pass through QSA all the time to avoid the IE error\n // See https://bugs.jquery.com/ticket/13378\n\n rbuggyQSA = [];\n\n if (support.qsa = rnative.test(document.querySelectorAll)) {\n // Build QSA regex\n // Regex strategy adopted from Diego Perini\n assert(function (el) {\n var input; // Select is set to empty string on purpose\n // This is to test IE's treatment of not explicitly\n // setting a boolean content attribute,\n // since its presence should be enough\n // https://bugs.jquery.com/ticket/12359\n\n docElem.appendChild(el).innerHTML = \" \" + \"\" + \" \"; // Support: IE8, Opera 11-12.16\n // Nothing should be selected when empty strings follow ^= or $= or *=\n // The test attribute must be unknown in Opera but \"safe\" for WinRT\n // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section\n\n if (el.querySelectorAll(\"[msallowcapture^='']\").length) {\n rbuggyQSA.push(\"[*^$]=\" + whitespace + \"*(?:''|\\\"\\\")\");\n } // Support: IE8\n // Boolean attributes and \"value\" are not treated correctly\n\n\n if (!el.querySelectorAll(\"[selected]\").length) {\n rbuggyQSA.push(\"\\\\[\" + whitespace + \"*(?:value|\" + booleans + \")\");\n } // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+\n\n\n if (!el.querySelectorAll(\"[id~=\" + expando + \"-]\").length) {\n rbuggyQSA.push(\"~=\");\n } // Support: IE 11+, Edge 15 - 18+\n // IE 11/Edge don't find elements on a `[name='']` query in some cases.\n // Adding a temporary attribute to the document before the selection works\n // around the issue.\n // Interestingly, IE 10 & older don't seem to have the issue.\n\n\n input = document.createElement(\"input\");\n input.setAttribute(\"name\", \"\");\n el.appendChild(input);\n\n if (!el.querySelectorAll(\"[name='']\").length) {\n rbuggyQSA.push(\"\\\\[\" + whitespace + \"*name\" + whitespace + \"*=\" + whitespace + \"*(?:''|\\\"\\\")\");\n } // Webkit/Opera - :checked should return selected option elements\n // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n // IE8 throws error here and will not see later tests\n\n\n if (!el.querySelectorAll(\":checked\").length) {\n rbuggyQSA.push(\":checked\");\n } // Support: Safari 8+, iOS 8+\n // https://bugs.webkit.org/show_bug.cgi?id=136851\n // In-page `selector#id sibling-combinator selector` fails\n\n\n if (!el.querySelectorAll(\"a#\" + expando + \"+*\").length) {\n rbuggyQSA.push(\".#.+[+~]\");\n } // Support: Firefox <=3.6 - 5 only\n // Old Firefox doesn't throw on a badly-escaped identifier.\n\n\n el.querySelectorAll(\"\\\\\\f\");\n rbuggyQSA.push(\"[\\\\r\\\\n\\\\f]\");\n });\n assert(function (el) {\n el.innerHTML = \" \" + \" \"; // Support: Windows 8 Native Apps\n // The type and name attributes are restricted during .innerHTML assignment\n\n var input = document.createElement(\"input\");\n input.setAttribute(\"type\", \"hidden\");\n el.appendChild(input).setAttribute(\"name\", \"D\"); // Support: IE8\n // Enforce case-sensitivity of name attribute\n\n if (el.querySelectorAll(\"[name=d]\").length) {\n rbuggyQSA.push(\"name\" + whitespace + \"*[*^$|!~]?=\");\n } // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)\n // IE8 throws error here and will not see later tests\n\n\n if (el.querySelectorAll(\":enabled\").length !== 2) {\n rbuggyQSA.push(\":enabled\", \":disabled\");\n } // Support: IE9-11+\n // IE's :disabled selector does not pick up the children of disabled fieldsets\n\n\n docElem.appendChild(el).disabled = true;\n\n if (el.querySelectorAll(\":disabled\").length !== 2) {\n rbuggyQSA.push(\":enabled\", \":disabled\");\n } // Support: Opera 10 - 11 only\n // Opera 10-11 does not throw on post-comma invalid pseudos\n\n\n el.querySelectorAll(\"*,:x\");\n rbuggyQSA.push(\",.*:\");\n });\n }\n\n if (support.matchesSelector = rnative.test(matches = docElem.matches || docElem.webkitMatchesSelector || docElem.mozMatchesSelector || docElem.oMatchesSelector || docElem.msMatchesSelector)) {\n assert(function (el) {\n // Check to see if it's possible to do matchesSelector\n // on a disconnected node (IE 9)\n support.disconnectedMatch = matches.call(el, \"*\"); // This should fail with an exception\n // Gecko does not error, returns false instead\n\n matches.call(el, \"[s!='']:x\");\n rbuggyMatches.push(\"!=\", pseudos);\n });\n }\n\n rbuggyQSA = rbuggyQSA.length && new RegExp(rbuggyQSA.join(\"|\"));\n rbuggyMatches = rbuggyMatches.length && new RegExp(rbuggyMatches.join(\"|\"));\n /* Contains\n ---------------------------------------------------------------------- */\n\n hasCompare = rnative.test(docElem.compareDocumentPosition); // Element contains another\n // Purposefully self-exclusive\n // As in, an element does not contain itself\n\n contains = hasCompare || rnative.test(docElem.contains) ? function (a, b) {\n var adown = a.nodeType === 9 ? a.documentElement : a,\n bup = b && b.parentNode;\n return a === bup || !!(bup && bup.nodeType === 1 && (adown.contains ? adown.contains(bup) : a.compareDocumentPosition && a.compareDocumentPosition(bup) & 16));\n } : function (a, b) {\n if (b) {\n while (b = b.parentNode) {\n if (b === a) {\n return true;\n }\n }\n }\n\n return false;\n };\n /* Sorting\n ---------------------------------------------------------------------- */\n // Document order sorting\n\n sortOrder = hasCompare ? function (a, b) {\n // Flag for duplicate removal\n if (a === b) {\n hasDuplicate = true;\n return 0;\n } // Sort on method existence if only one input has compareDocumentPosition\n\n\n var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;\n\n if (compare) {\n return compare;\n } // Calculate position if both inputs belong to the same document\n // Support: IE 11+, Edge 17 - 18+\n // IE/Edge sometimes throw a \"Permission denied\" error when strict-comparing\n // two documents; shallow comparisons work.\n // eslint-disable-next-line eqeqeq\n\n\n compare = (a.ownerDocument || a) == (b.ownerDocument || b) ? a.compareDocumentPosition(b) : // Otherwise we know they are disconnected\n 1; // Disconnected nodes\n\n if (compare & 1 || !support.sortDetached && b.compareDocumentPosition(a) === compare) {\n // Choose the first element that is related to our preferred document\n // Support: IE 11+, Edge 17 - 18+\n // IE/Edge sometimes throw a \"Permission denied\" error when strict-comparing\n // two documents; shallow comparisons work.\n // eslint-disable-next-line eqeqeq\n if (a == document || a.ownerDocument == preferredDoc && contains(preferredDoc, a)) {\n return -1;\n } // Support: IE 11+, Edge 17 - 18+\n // IE/Edge sometimes throw a \"Permission denied\" error when strict-comparing\n // two documents; shallow comparisons work.\n // eslint-disable-next-line eqeqeq\n\n\n if (b == document || b.ownerDocument == preferredDoc && contains(preferredDoc, b)) {\n return 1;\n } // Maintain original order\n\n\n return sortInput ? indexOf(sortInput, a) - indexOf(sortInput, b) : 0;\n }\n\n return compare & 4 ? -1 : 1;\n } : function (a, b) {\n // Exit early if the nodes are identical\n if (a === b) {\n hasDuplicate = true;\n return 0;\n }\n\n var cur,\n i = 0,\n aup = a.parentNode,\n bup = b.parentNode,\n ap = [a],\n bp = [b]; // Parentless nodes are either documents or disconnected\n\n if (!aup || !bup) {\n // Support: IE 11+, Edge 17 - 18+\n // IE/Edge sometimes throw a \"Permission denied\" error when strict-comparing\n // two documents; shallow comparisons work.\n\n /* eslint-disable eqeqeq */\n return a == document ? -1 : b == document ? 1 :\n /* eslint-enable eqeqeq */\n aup ? -1 : bup ? 1 : sortInput ? indexOf(sortInput, a) - indexOf(sortInput, b) : 0; // If the nodes are siblings, we can do a quick check\n } else if (aup === bup) {\n return siblingCheck(a, b);\n } // Otherwise we need full lists of their ancestors for comparison\n\n\n cur = a;\n\n while (cur = cur.parentNode) {\n ap.unshift(cur);\n }\n\n cur = b;\n\n while (cur = cur.parentNode) {\n bp.unshift(cur);\n } // Walk down the tree looking for a discrepancy\n\n\n while (ap[i] === bp[i]) {\n i++;\n }\n\n return i ? // Do a sibling check if the nodes have a common ancestor\n siblingCheck(ap[i], bp[i]) : // Otherwise nodes in our document sort first\n // Support: IE 11+, Edge 17 - 18+\n // IE/Edge sometimes throw a \"Permission denied\" error when strict-comparing\n // two documents; shallow comparisons work.\n\n /* eslint-disable eqeqeq */\n ap[i] == preferredDoc ? -1 : bp[i] == preferredDoc ? 1 :\n /* eslint-enable eqeqeq */\n 0;\n };\n return document;\n };\n\n Sizzle.matches = function (expr, elements) {\n return Sizzle(expr, null, null, elements);\n };\n\n Sizzle.matchesSelector = function (elem, expr) {\n setDocument(elem);\n\n if (support.matchesSelector && documentIsHTML && !nonnativeSelectorCache[expr + \" \"] && (!rbuggyMatches || !rbuggyMatches.test(expr)) && (!rbuggyQSA || !rbuggyQSA.test(expr))) {\n try {\n var ret = matches.call(elem, expr); // IE 9's matchesSelector returns false on disconnected nodes\n\n if (ret || support.disconnectedMatch || // As well, disconnected nodes are said to be in a document\n // fragment in IE 9\n elem.document && elem.document.nodeType !== 11) {\n return ret;\n }\n } catch (e) {\n nonnativeSelectorCache(expr, true);\n }\n }\n\n return Sizzle(expr, document, null, [elem]).length > 0;\n };\n\n Sizzle.contains = function (context, elem) {\n // Set document vars if needed\n // Support: IE 11+, Edge 17 - 18+\n // IE/Edge sometimes throw a \"Permission denied\" error when strict-comparing\n // two documents; shallow comparisons work.\n // eslint-disable-next-line eqeqeq\n if ((context.ownerDocument || context) != document) {\n setDocument(context);\n }\n\n return contains(context, elem);\n };\n\n Sizzle.attr = function (elem, name) {\n // Set document vars if needed\n // Support: IE 11+, Edge 17 - 18+\n // IE/Edge sometimes throw a \"Permission denied\" error when strict-comparing\n // two documents; shallow comparisons work.\n // eslint-disable-next-line eqeqeq\n if ((elem.ownerDocument || elem) != document) {\n setDocument(elem);\n }\n\n var fn = Expr.attrHandle[name.toLowerCase()],\n // Don't get fooled by Object.prototype properties (jQuery #13807)\n val = fn && hasOwn.call(Expr.attrHandle, name.toLowerCase()) ? fn(elem, name, !documentIsHTML) : undefined;\n return val !== undefined ? val : support.attributes || !documentIsHTML ? elem.getAttribute(name) : (val = elem.getAttributeNode(name)) && val.specified ? val.value : null;\n };\n\n Sizzle.escape = function (sel) {\n return (sel + \"\").replace(rcssescape, fcssescape);\n };\n\n Sizzle.error = function (msg) {\n throw new Error(\"Syntax error, unrecognized expression: \" + msg);\n };\n /**\n * Document sorting and removing duplicates\n * @param {ArrayLike} results\n */\n\n\n Sizzle.uniqueSort = function (results) {\n var elem,\n duplicates = [],\n j = 0,\n i = 0; // Unless we *know* we can detect duplicates, assume their presence\n\n hasDuplicate = !support.detectDuplicates;\n sortInput = !support.sortStable && results.slice(0);\n results.sort(sortOrder);\n\n if (hasDuplicate) {\n while (elem = results[i++]) {\n if (elem === results[i]) {\n j = duplicates.push(i);\n }\n }\n\n while (j--) {\n results.splice(duplicates[j], 1);\n }\n } // Clear input after sorting to release objects\n // See https://github.com/jquery/sizzle/pull/225\n\n\n sortInput = null;\n return results;\n };\n /**\n * Utility function for retrieving the text value of an array of DOM nodes\n * @param {Array|Element} elem\n */\n\n\n getText = Sizzle.getText = function (elem) {\n var node,\n ret = \"\",\n i = 0,\n nodeType = elem.nodeType;\n\n if (!nodeType) {\n // If no nodeType, this is expected to be an array\n while (node = elem[i++]) {\n // Do not traverse comment nodes\n ret += getText(node);\n }\n } else if (nodeType === 1 || nodeType === 9 || nodeType === 11) {\n // Use textContent for elements\n // innerText usage removed for consistency of new lines (jQuery #11153)\n if (typeof elem.textContent === \"string\") {\n return elem.textContent;\n } else {\n // Traverse its children\n for (elem = elem.firstChild; elem; elem = elem.nextSibling) {\n ret += getText(elem);\n }\n }\n } else if (nodeType === 3 || nodeType === 4) {\n return elem.nodeValue;\n } // Do not include comment or processing instruction nodes\n\n\n return ret;\n };\n\n Expr = Sizzle.selectors = {\n // Can be adjusted by the user\n cacheLength: 50,\n createPseudo: markFunction,\n match: matchExpr,\n attrHandle: {},\n find: {},\n relative: {\n \">\": {\n dir: \"parentNode\",\n first: true\n },\n \" \": {\n dir: \"parentNode\"\n },\n \"+\": {\n dir: \"previousSibling\",\n first: true\n },\n \"~\": {\n dir: \"previousSibling\"\n }\n },\n preFilter: {\n \"ATTR\": function ATTR(match) {\n match[1] = match[1].replace(runescape, funescape); // Move the given value to match[3] whether quoted or unquoted\n\n match[3] = (match[3] || match[4] || match[5] || \"\").replace(runescape, funescape);\n\n if (match[2] === \"~=\") {\n match[3] = \" \" + match[3] + \" \";\n }\n\n return match.slice(0, 4);\n },\n \"CHILD\": function CHILD(match) {\n /* matches from matchExpr[\"CHILD\"]\n \t1 type (only|nth|...)\n \t2 what (child|of-type)\n \t3 argument (even|odd|\\d*|\\d*n([+-]\\d+)?|...)\n \t4 xn-component of xn+y argument ([+-]?\\d*n|)\n \t5 sign of xn-component\n \t6 x of xn-component\n \t7 sign of y-component\n \t8 y of y-component\n */\n match[1] = match[1].toLowerCase();\n\n if (match[1].slice(0, 3) === \"nth\") {\n // nth-* requires argument\n if (!match[3]) {\n Sizzle.error(match[0]);\n } // numeric x and y parameters for Expr.filter.CHILD\n // remember that false/true cast respectively to 0/1\n\n\n match[4] = +(match[4] ? match[5] + (match[6] || 1) : 2 * (match[3] === \"even\" || match[3] === \"odd\"));\n match[5] = +(match[7] + match[8] || match[3] === \"odd\"); // other types prohibit arguments\n } else if (match[3]) {\n Sizzle.error(match[0]);\n }\n\n return match;\n },\n \"PSEUDO\": function PSEUDO(match) {\n var excess,\n unquoted = !match[6] && match[2];\n\n if (matchExpr[\"CHILD\"].test(match[0])) {\n return null;\n } // Accept quoted arguments as-is\n\n\n if (match[3]) {\n match[2] = match[4] || match[5] || \"\"; // Strip excess characters from unquoted arguments\n } else if (unquoted && rpseudo.test(unquoted) && ( // Get excess from tokenize (recursively)\n excess = tokenize(unquoted, true)) && ( // advance to the next closing parenthesis\n excess = unquoted.indexOf(\")\", unquoted.length - excess) - unquoted.length)) {\n // excess is a negative index\n match[0] = match[0].slice(0, excess);\n match[2] = unquoted.slice(0, excess);\n } // Return only captures needed by the pseudo filter method (type and argument)\n\n\n return match.slice(0, 3);\n }\n },\n filter: {\n \"TAG\": function TAG(nodeNameSelector) {\n var nodeName = nodeNameSelector.replace(runescape, funescape).toLowerCase();\n return nodeNameSelector === \"*\" ? function () {\n return true;\n } : function (elem) {\n return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;\n };\n },\n \"CLASS\": function CLASS(className) {\n var pattern = classCache[className + \" \"];\n return pattern || (pattern = new RegExp(\"(^|\" + whitespace + \")\" + className + \"(\" + whitespace + \"|$)\")) && classCache(className, function (elem) {\n return pattern.test(typeof elem.className === \"string\" && elem.className || typeof elem.getAttribute !== \"undefined\" && elem.getAttribute(\"class\") || \"\");\n });\n },\n \"ATTR\": function ATTR(name, operator, check) {\n return function (elem) {\n var result = Sizzle.attr(elem, name);\n\n if (result == null) {\n return operator === \"!=\";\n }\n\n if (!operator) {\n return true;\n }\n\n result += \"\";\n /* eslint-disable max-len */\n\n return operator === \"=\" ? result === check : operator === \"!=\" ? result !== check : operator === \"^=\" ? check && result.indexOf(check) === 0 : operator === \"*=\" ? check && result.indexOf(check) > -1 : operator === \"$=\" ? check && result.slice(-check.length) === check : operator === \"~=\" ? (\" \" + result.replace(rwhitespace, \" \") + \" \").indexOf(check) > -1 : operator === \"|=\" ? result === check || result.slice(0, check.length + 1) === check + \"-\" : false;\n /* eslint-enable max-len */\n };\n },\n \"CHILD\": function CHILD(type, what, _argument, first, last) {\n var simple = type.slice(0, 3) !== \"nth\",\n forward = type.slice(-4) !== \"last\",\n ofType = what === \"of-type\";\n return first === 1 && last === 0 ? // Shortcut for :nth-*(n)\n function (elem) {\n return !!elem.parentNode;\n } : function (elem, _context, xml) {\n var cache,\n uniqueCache,\n outerCache,\n node,\n nodeIndex,\n start,\n dir = simple !== forward ? \"nextSibling\" : \"previousSibling\",\n parent = elem.parentNode,\n name = ofType && elem.nodeName.toLowerCase(),\n useCache = !xml && !ofType,\n diff = false;\n\n if (parent) {\n // :(first|last|only)-(child|of-type)\n if (simple) {\n while (dir) {\n node = elem;\n\n while (node = node[dir]) {\n if (ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1) {\n return false;\n }\n } // Reverse direction for :only-* (if we haven't yet done so)\n\n\n start = dir = type === \"only\" && !start && \"nextSibling\";\n }\n\n return true;\n }\n\n start = [forward ? parent.firstChild : parent.lastChild]; // non-xml :nth-child(...) stores cache data on `parent`\n\n if (forward && useCache) {\n // Seek `elem` from a previously-cached index\n // ...in a gzip-friendly way\n node = parent;\n outerCache = node[expando] || (node[expando] = {}); // Support: IE <9 only\n // Defend against cloned attroperties (jQuery gh-1709)\n\n uniqueCache = outerCache[node.uniqueID] || (outerCache[node.uniqueID] = {});\n cache = uniqueCache[type] || [];\n nodeIndex = cache[0] === dirruns && cache[1];\n diff = nodeIndex && cache[2];\n node = nodeIndex && parent.childNodes[nodeIndex];\n\n while (node = ++nodeIndex && node && node[dir] || ( // Fallback to seeking `elem` from the start\n diff = nodeIndex = 0) || start.pop()) {\n // When found, cache indexes on `parent` and break\n if (node.nodeType === 1 && ++diff && node === elem) {\n uniqueCache[type] = [dirruns, nodeIndex, diff];\n break;\n }\n }\n } else {\n // Use previously-cached element index if available\n if (useCache) {\n // ...in a gzip-friendly way\n node = elem;\n outerCache = node[expando] || (node[expando] = {}); // Support: IE <9 only\n // Defend against cloned attroperties (jQuery gh-1709)\n\n uniqueCache = outerCache[node.uniqueID] || (outerCache[node.uniqueID] = {});\n cache = uniqueCache[type] || [];\n nodeIndex = cache[0] === dirruns && cache[1];\n diff = nodeIndex;\n } // xml :nth-child(...)\n // or :nth-last-child(...) or :nth(-last)?-of-type(...)\n\n\n if (diff === false) {\n // Use the same loop as above to seek `elem` from the start\n while (node = ++nodeIndex && node && node[dir] || (diff = nodeIndex = 0) || start.pop()) {\n if ((ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1) && ++diff) {\n // Cache the index of each encountered element\n if (useCache) {\n outerCache = node[expando] || (node[expando] = {}); // Support: IE <9 only\n // Defend against cloned attroperties (jQuery gh-1709)\n\n uniqueCache = outerCache[node.uniqueID] || (outerCache[node.uniqueID] = {});\n uniqueCache[type] = [dirruns, diff];\n }\n\n if (node === elem) {\n break;\n }\n }\n }\n }\n } // Incorporate the offset, then check against cycle size\n\n\n diff -= last;\n return diff === first || diff % first === 0 && diff / first >= 0;\n }\n };\n },\n \"PSEUDO\": function PSEUDO(pseudo, argument) {\n // pseudo-class names are case-insensitive\n // http://www.w3.org/TR/selectors/#pseudo-classes\n // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters\n // Remember that setFilters inherits from pseudos\n var args,\n fn = Expr.pseudos[pseudo] || Expr.setFilters[pseudo.toLowerCase()] || Sizzle.error(\"unsupported pseudo: \" + pseudo); // The user may use createPseudo to indicate that\n // arguments are needed to create the filter function\n // just as Sizzle does\n\n if (fn[expando]) {\n return fn(argument);\n } // But maintain support for old signatures\n\n\n if (fn.length > 1) {\n args = [pseudo, pseudo, \"\", argument];\n return Expr.setFilters.hasOwnProperty(pseudo.toLowerCase()) ? markFunction(function (seed, matches) {\n var idx,\n matched = fn(seed, argument),\n i = matched.length;\n\n while (i--) {\n idx = indexOf(seed, matched[i]);\n seed[idx] = !(matches[idx] = matched[i]);\n }\n }) : function (elem) {\n return fn(elem, 0, args);\n };\n }\n\n return fn;\n }\n },\n pseudos: {\n // Potentially complex pseudos\n \"not\": markFunction(function (selector) {\n // Trim the selector passed to compile\n // to avoid treating leading and trailing\n // spaces as combinators\n var input = [],\n results = [],\n matcher = compile(selector.replace(rtrim, \"$1\"));\n return matcher[expando] ? markFunction(function (seed, matches, _context, xml) {\n var elem,\n unmatched = matcher(seed, null, xml, []),\n i = seed.length; // Match elements unmatched by `matcher`\n\n while (i--) {\n if (elem = unmatched[i]) {\n seed[i] = !(matches[i] = elem);\n }\n }\n }) : function (elem, _context, xml) {\n input[0] = elem;\n matcher(input, null, xml, results); // Don't keep the element (issue #299)\n\n input[0] = null;\n return !results.pop();\n };\n }),\n \"has\": markFunction(function (selector) {\n return function (elem) {\n return Sizzle(selector, elem).length > 0;\n };\n }),\n \"contains\": markFunction(function (text) {\n text = text.replace(runescape, funescape);\n return function (elem) {\n return (elem.textContent || getText(elem)).indexOf(text) > -1;\n };\n }),\n // \"Whether an element is represented by a :lang() selector\n // is based solely on the element's language value\n // being equal to the identifier C,\n // or beginning with the identifier C immediately followed by \"-\".\n // The matching of C against the element's language value is performed case-insensitively.\n // The identifier C does not have to be a valid language name.\"\n // http://www.w3.org/TR/selectors/#lang-pseudo\n \"lang\": markFunction(function (lang) {\n // lang value must be a valid identifier\n if (!ridentifier.test(lang || \"\")) {\n Sizzle.error(\"unsupported lang: \" + lang);\n }\n\n lang = lang.replace(runescape, funescape).toLowerCase();\n return function (elem) {\n var elemLang;\n\n do {\n if (elemLang = documentIsHTML ? elem.lang : elem.getAttribute(\"xml:lang\") || elem.getAttribute(\"lang\")) {\n elemLang = elemLang.toLowerCase();\n return elemLang === lang || elemLang.indexOf(lang + \"-\") === 0;\n }\n } while ((elem = elem.parentNode) && elem.nodeType === 1);\n\n return false;\n };\n }),\n // Miscellaneous\n \"target\": function target(elem) {\n var hash = window.location && window.location.hash;\n return hash && hash.slice(1) === elem.id;\n },\n \"root\": function root(elem) {\n return elem === docElem;\n },\n \"focus\": function focus(elem) {\n return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);\n },\n // Boolean properties\n \"enabled\": createDisabledPseudo(false),\n \"disabled\": createDisabledPseudo(true),\n \"checked\": function checked(elem) {\n // In CSS3, :checked should return both checked and selected elements\n // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n var nodeName = elem.nodeName.toLowerCase();\n return nodeName === \"input\" && !!elem.checked || nodeName === \"option\" && !!elem.selected;\n },\n \"selected\": function selected(elem) {\n // Accessing this property makes selected-by-default\n // options in Safari work properly\n if (elem.parentNode) {\n // eslint-disable-next-line no-unused-expressions\n elem.parentNode.selectedIndex;\n }\n\n return elem.selected === true;\n },\n // Contents\n \"empty\": function empty(elem) {\n // http://www.w3.org/TR/selectors/#empty-pseudo\n // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),\n // but not by others (comment: 8; processing instruction: 7; etc.)\n // nodeType < 6 works because attributes (2) do not appear as children\n for (elem = elem.firstChild; elem; elem = elem.nextSibling) {\n if (elem.nodeType < 6) {\n return false;\n }\n }\n\n return true;\n },\n \"parent\": function parent(elem) {\n return !Expr.pseudos[\"empty\"](elem);\n },\n // Element/input types\n \"header\": function header(elem) {\n return rheader.test(elem.nodeName);\n },\n \"input\": function input(elem) {\n return rinputs.test(elem.nodeName);\n },\n \"button\": function button(elem) {\n var name = elem.nodeName.toLowerCase();\n return name === \"input\" && elem.type === \"button\" || name === \"button\";\n },\n \"text\": function text(elem) {\n var attr;\n return elem.nodeName.toLowerCase() === \"input\" && elem.type === \"text\" && ( // Support: IE<8\n // New HTML5 attribute values (e.g., \"search\") appear with elem.type === \"text\"\n (attr = elem.getAttribute(\"type\")) == null || attr.toLowerCase() === \"text\");\n },\n // Position-in-collection\n \"first\": createPositionalPseudo(function () {\n return [0];\n }),\n \"last\": createPositionalPseudo(function (_matchIndexes, length) {\n return [length - 1];\n }),\n \"eq\": createPositionalPseudo(function (_matchIndexes, length, argument) {\n return [argument < 0 ? argument + length : argument];\n }),\n \"even\": createPositionalPseudo(function (matchIndexes, length) {\n var i = 0;\n\n for (; i < length; i += 2) {\n matchIndexes.push(i);\n }\n\n return matchIndexes;\n }),\n \"odd\": createPositionalPseudo(function (matchIndexes, length) {\n var i = 1;\n\n for (; i < length; i += 2) {\n matchIndexes.push(i);\n }\n\n return matchIndexes;\n }),\n \"lt\": createPositionalPseudo(function (matchIndexes, length, argument) {\n var i = argument < 0 ? argument + length : argument > length ? length : argument;\n\n for (; --i >= 0;) {\n matchIndexes.push(i);\n }\n\n return matchIndexes;\n }),\n \"gt\": createPositionalPseudo(function (matchIndexes, length, argument) {\n var i = argument < 0 ? argument + length : argument;\n\n for (; ++i < length;) {\n matchIndexes.push(i);\n }\n\n return matchIndexes;\n })\n }\n };\n Expr.pseudos[\"nth\"] = Expr.pseudos[\"eq\"]; // Add button/input type pseudos\n\n for (i in {\n radio: true,\n checkbox: true,\n file: true,\n password: true,\n image: true\n }) {\n Expr.pseudos[i] = createInputPseudo(i);\n }\n\n for (i in {\n submit: true,\n reset: true\n }) {\n Expr.pseudos[i] = createButtonPseudo(i);\n } // Easy API for creating new setFilters\n\n\n function setFilters() {}\n\n setFilters.prototype = Expr.filters = Expr.pseudos;\n Expr.setFilters = new setFilters();\n\n tokenize = Sizzle.tokenize = function (selector, parseOnly) {\n var matched,\n match,\n tokens,\n type,\n soFar,\n groups,\n preFilters,\n cached = tokenCache[selector + \" \"];\n\n if (cached) {\n return parseOnly ? 0 : cached.slice(0);\n }\n\n soFar = selector;\n groups = [];\n preFilters = Expr.preFilter;\n\n while (soFar) {\n // Comma and first run\n if (!matched || (match = rcomma.exec(soFar))) {\n if (match) {\n // Don't consume trailing commas as valid\n soFar = soFar.slice(match[0].length) || soFar;\n }\n\n groups.push(tokens = []);\n }\n\n matched = false; // Combinators\n\n if (match = rcombinators.exec(soFar)) {\n matched = match.shift();\n tokens.push({\n value: matched,\n // Cast descendant combinators to space\n type: match[0].replace(rtrim, \" \")\n });\n soFar = soFar.slice(matched.length);\n } // Filters\n\n\n for (type in Expr.filter) {\n if ((match = matchExpr[type].exec(soFar)) && (!preFilters[type] || (match = preFilters[type](match)))) {\n matched = match.shift();\n tokens.push({\n value: matched,\n type: type,\n matches: match\n });\n soFar = soFar.slice(matched.length);\n }\n }\n\n if (!matched) {\n break;\n }\n } // Return the length of the invalid excess\n // if we're just parsing\n // Otherwise, throw an error or return tokens\n\n\n return parseOnly ? soFar.length : soFar ? Sizzle.error(selector) : // Cache the tokens\n tokenCache(selector, groups).slice(0);\n };\n\n function toSelector(tokens) {\n var i = 0,\n len = tokens.length,\n selector = \"\";\n\n for (; i < len; i++) {\n selector += tokens[i].value;\n }\n\n return selector;\n }\n\n function addCombinator(matcher, combinator, base) {\n var dir = combinator.dir,\n skip = combinator.next,\n key = skip || dir,\n checkNonElements = base && key === \"parentNode\",\n doneName = done++;\n return combinator.first ? // Check against closest ancestor/preceding element\n function (elem, context, xml) {\n while (elem = elem[dir]) {\n if (elem.nodeType === 1 || checkNonElements) {\n return matcher(elem, context, xml);\n }\n }\n\n return false;\n } : // Check against all ancestor/preceding elements\n function (elem, context, xml) {\n var oldCache,\n uniqueCache,\n outerCache,\n newCache = [dirruns, doneName]; // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching\n\n if (xml) {\n while (elem = elem[dir]) {\n if (elem.nodeType === 1 || checkNonElements) {\n if (matcher(elem, context, xml)) {\n return true;\n }\n }\n }\n } else {\n while (elem = elem[dir]) {\n if (elem.nodeType === 1 || checkNonElements) {\n outerCache = elem[expando] || (elem[expando] = {}); // Support: IE <9 only\n // Defend against cloned attroperties (jQuery gh-1709)\n\n uniqueCache = outerCache[elem.uniqueID] || (outerCache[elem.uniqueID] = {});\n\n if (skip && skip === elem.nodeName.toLowerCase()) {\n elem = elem[dir] || elem;\n } else if ((oldCache = uniqueCache[key]) && oldCache[0] === dirruns && oldCache[1] === doneName) {\n // Assign to newCache so results back-propagate to previous elements\n return newCache[2] = oldCache[2];\n } else {\n // Reuse newcache so results back-propagate to previous elements\n uniqueCache[key] = newCache; // A match means we're done; a fail means we have to keep checking\n\n if (newCache[2] = matcher(elem, context, xml)) {\n return true;\n }\n }\n }\n }\n }\n\n return false;\n };\n }\n\n function elementMatcher(matchers) {\n return matchers.length > 1 ? function (elem, context, xml) {\n var i = matchers.length;\n\n while (i--) {\n if (!matchers[i](elem, context, xml)) {\n return false;\n }\n }\n\n return true;\n } : matchers[0];\n }\n\n function multipleContexts(selector, contexts, results) {\n var i = 0,\n len = contexts.length;\n\n for (; i < len; i++) {\n Sizzle(selector, contexts[i], results);\n }\n\n return results;\n }\n\n function condense(unmatched, map, filter, context, xml) {\n var elem,\n newUnmatched = [],\n i = 0,\n len = unmatched.length,\n mapped = map != null;\n\n for (; i < len; i++) {\n if (elem = unmatched[i]) {\n if (!filter || filter(elem, context, xml)) {\n newUnmatched.push(elem);\n\n if (mapped) {\n map.push(i);\n }\n }\n }\n }\n\n return newUnmatched;\n }\n\n function setMatcher(preFilter, selector, matcher, postFilter, postFinder, postSelector) {\n if (postFilter && !postFilter[expando]) {\n postFilter = setMatcher(postFilter);\n }\n\n if (postFinder && !postFinder[expando]) {\n postFinder = setMatcher(postFinder, postSelector);\n }\n\n return markFunction(function (seed, results, context, xml) {\n var temp,\n i,\n elem,\n preMap = [],\n postMap = [],\n preexisting = results.length,\n // Get initial elements from seed or context\n elems = seed || multipleContexts(selector || \"*\", context.nodeType ? [context] : context, []),\n // Prefilter to get matcher input, preserving a map for seed-results synchronization\n matcherIn = preFilter && (seed || !selector) ? condense(elems, preMap, preFilter, context, xml) : elems,\n matcherOut = matcher ? // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,\n postFinder || (seed ? preFilter : preexisting || postFilter) ? // ...intermediate processing is necessary\n [] : // ...otherwise use results directly\n results : matcherIn; // Find primary matches\n\n if (matcher) {\n matcher(matcherIn, matcherOut, context, xml);\n } // Apply postFilter\n\n\n if (postFilter) {\n temp = condense(matcherOut, postMap);\n postFilter(temp, [], context, xml); // Un-match failing elements by moving them back to matcherIn\n\n i = temp.length;\n\n while (i--) {\n if (elem = temp[i]) {\n matcherOut[postMap[i]] = !(matcherIn[postMap[i]] = elem);\n }\n }\n }\n\n if (seed) {\n if (postFinder || preFilter) {\n if (postFinder) {\n // Get the final matcherOut by condensing this intermediate into postFinder contexts\n temp = [];\n i = matcherOut.length;\n\n while (i--) {\n if (elem = matcherOut[i]) {\n // Restore matcherIn since elem is not yet a final match\n temp.push(matcherIn[i] = elem);\n }\n }\n\n postFinder(null, matcherOut = [], temp, xml);\n } // Move matched elements from seed to results to keep them synchronized\n\n\n i = matcherOut.length;\n\n while (i--) {\n if ((elem = matcherOut[i]) && (temp = postFinder ? indexOf(seed, elem) : preMap[i]) > -1) {\n seed[temp] = !(results[temp] = elem);\n }\n }\n } // Add elements to results, through postFinder if defined\n\n } else {\n matcherOut = condense(matcherOut === results ? matcherOut.splice(preexisting, matcherOut.length) : matcherOut);\n\n if (postFinder) {\n postFinder(null, results, matcherOut, xml);\n } else {\n push.apply(results, matcherOut);\n }\n }\n });\n }\n\n function matcherFromTokens(tokens) {\n var checkContext,\n matcher,\n j,\n len = tokens.length,\n leadingRelative = Expr.relative[tokens[0].type],\n implicitRelative = leadingRelative || Expr.relative[\" \"],\n i = leadingRelative ? 1 : 0,\n // The foundational matcher ensures that elements are reachable from top-level context(s)\n matchContext = addCombinator(function (elem) {\n return elem === checkContext;\n }, implicitRelative, true),\n matchAnyContext = addCombinator(function (elem) {\n return indexOf(checkContext, elem) > -1;\n }, implicitRelative, true),\n matchers = [function (elem, context, xml) {\n var ret = !leadingRelative && (xml || context !== outermostContext) || ((checkContext = context).nodeType ? matchContext(elem, context, xml) : matchAnyContext(elem, context, xml)); // Avoid hanging onto element (issue #299)\n\n checkContext = null;\n return ret;\n }];\n\n for (; i < len; i++) {\n if (matcher = Expr.relative[tokens[i].type]) {\n matchers = [addCombinator(elementMatcher(matchers), matcher)];\n } else {\n matcher = Expr.filter[tokens[i].type].apply(null, tokens[i].matches); // Return special upon seeing a positional matcher\n\n if (matcher[expando]) {\n // Find the next relative operator (if any) for proper handling\n j = ++i;\n\n for (; j < len; j++) {\n if (Expr.relative[tokens[j].type]) {\n break;\n }\n }\n\n return setMatcher(i > 1 && elementMatcher(matchers), i > 1 && toSelector( // If the preceding token was a descendant combinator, insert an implicit any-element `*`\n tokens.slice(0, i - 1).concat({\n value: tokens[i - 2].type === \" \" ? \"*\" : \"\"\n })).replace(rtrim, \"$1\"), matcher, i < j && matcherFromTokens(tokens.slice(i, j)), j < len && matcherFromTokens(tokens = tokens.slice(j)), j < len && toSelector(tokens));\n }\n\n matchers.push(matcher);\n }\n }\n\n return elementMatcher(matchers);\n }\n\n function matcherFromGroupMatchers(elementMatchers, setMatchers) {\n var bySet = setMatchers.length > 0,\n byElement = elementMatchers.length > 0,\n superMatcher = function superMatcher(seed, context, xml, results, outermost) {\n var elem,\n j,\n matcher,\n matchedCount = 0,\n i = \"0\",\n unmatched = seed && [],\n setMatched = [],\n contextBackup = outermostContext,\n // We must always have either seed elements or outermost context\n elems = seed || byElement && Expr.find[\"TAG\"](\"*\", outermost),\n // Use integer dirruns iff this is the outermost matcher\n dirrunsUnique = dirruns += contextBackup == null ? 1 : Math.random() || 0.1,\n len = elems.length;\n\n if (outermost) {\n // Support: IE 11+, Edge 17 - 18+\n // IE/Edge sometimes throw a \"Permission denied\" error when strict-comparing\n // two documents; shallow comparisons work.\n // eslint-disable-next-line eqeqeq\n outermostContext = context == document || context || outermost;\n } // Add elements passing elementMatchers directly to results\n // Support: IE<9, Safari\n // Tolerate NodeList properties (IE: \"length\"; Safari: ) matching elements by id\n\n\n for (; i !== len && (elem = elems[i]) != null; i++) {\n if (byElement && elem) {\n j = 0; // Support: IE 11+, Edge 17 - 18+\n // IE/Edge sometimes throw a \"Permission denied\" error when strict-comparing\n // two documents; shallow comparisons work.\n // eslint-disable-next-line eqeqeq\n\n if (!context && elem.ownerDocument != document) {\n setDocument(elem);\n xml = !documentIsHTML;\n }\n\n while (matcher = elementMatchers[j++]) {\n if (matcher(elem, context || document, xml)) {\n results.push(elem);\n break;\n }\n }\n\n if (outermost) {\n dirruns = dirrunsUnique;\n }\n } // Track unmatched elements for set filters\n\n\n if (bySet) {\n // They will have gone through all possible matchers\n if (elem = !matcher && elem) {\n matchedCount--;\n } // Lengthen the array for every element, matched or not\n\n\n if (seed) {\n unmatched.push(elem);\n }\n }\n } // `i` is now the count of elements visited above, and adding it to `matchedCount`\n // makes the latter nonnegative.\n\n\n matchedCount += i; // Apply set filters to unmatched elements\n // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`\n // equals `i`), unless we didn't visit _any_ elements in the above loop because we have\n // no element matchers and no seed.\n // Incrementing an initially-string \"0\" `i` allows `i` to remain a string only in that\n // case, which will result in a \"00\" `matchedCount` that differs from `i` but is also\n // numerically zero.\n\n if (bySet && i !== matchedCount) {\n j = 0;\n\n while (matcher = setMatchers[j++]) {\n matcher(unmatched, setMatched, context, xml);\n }\n\n if (seed) {\n // Reintegrate element matches to eliminate the need for sorting\n if (matchedCount > 0) {\n while (i--) {\n if (!(unmatched[i] || setMatched[i])) {\n setMatched[i] = pop.call(results);\n }\n }\n } // Discard index placeholder values to get only actual matches\n\n\n setMatched = condense(setMatched);\n } // Add matches to results\n\n\n push.apply(results, setMatched); // Seedless set matches succeeding multiple successful matchers stipulate sorting\n\n if (outermost && !seed && setMatched.length > 0 && matchedCount + setMatchers.length > 1) {\n Sizzle.uniqueSort(results);\n }\n } // Override manipulation of globals by nested matchers\n\n\n if (outermost) {\n dirruns = dirrunsUnique;\n outermostContext = contextBackup;\n }\n\n return unmatched;\n };\n\n return bySet ? markFunction(superMatcher) : superMatcher;\n }\n\n compile = Sizzle.compile = function (selector, match\n /* Internal Use Only */\n ) {\n var i,\n setMatchers = [],\n elementMatchers = [],\n cached = compilerCache[selector + \" \"];\n\n if (!cached) {\n // Generate a function of recursive functions that can be used to check each element\n if (!match) {\n match = tokenize(selector);\n }\n\n i = match.length;\n\n while (i--) {\n cached = matcherFromTokens(match[i]);\n\n if (cached[expando]) {\n setMatchers.push(cached);\n } else {\n elementMatchers.push(cached);\n }\n } // Cache the compiled function\n\n\n cached = compilerCache(selector, matcherFromGroupMatchers(elementMatchers, setMatchers)); // Save selector and tokenization\n\n cached.selector = selector;\n }\n\n return cached;\n };\n /**\n * A low-level selection function that works with Sizzle's compiled\n * selector functions\n * @param {String|Function} selector A selector or a pre-compiled\n * selector function built with Sizzle.compile\n * @param {Element} context\n * @param {Array} [results]\n * @param {Array} [seed] A set of elements to match against\n */\n\n\n select = Sizzle.select = function (selector, context, results, seed) {\n var i,\n tokens,\n token,\n type,\n find,\n compiled = typeof selector === \"function\" && selector,\n match = !seed && tokenize(selector = compiled.selector || selector);\n results = results || []; // Try to minimize operations if there is only one selector in the list and no seed\n // (the latter of which guarantees us context)\n\n if (match.length === 1) {\n // Reduce context if the leading compound selector is an ID\n tokens = match[0] = match[0].slice(0);\n\n if (tokens.length > 2 && (token = tokens[0]).type === \"ID\" && context.nodeType === 9 && documentIsHTML && Expr.relative[tokens[1].type]) {\n context = (Expr.find[\"ID\"](token.matches[0].replace(runescape, funescape), context) || [])[0];\n\n if (!context) {\n return results; // Precompiled matchers will still verify ancestry, so step up a level\n } else if (compiled) {\n context = context.parentNode;\n }\n\n selector = selector.slice(tokens.shift().value.length);\n } // Fetch a seed set for right-to-left matching\n\n\n i = matchExpr[\"needsContext\"].test(selector) ? 0 : tokens.length;\n\n while (i--) {\n token = tokens[i]; // Abort if we hit a combinator\n\n if (Expr.relative[type = token.type]) {\n break;\n }\n\n if (find = Expr.find[type]) {\n // Search, expanding context for leading sibling combinators\n if (seed = find(token.matches[0].replace(runescape, funescape), rsibling.test(tokens[0].type) && testContext(context.parentNode) || context)) {\n // If seed is empty or no tokens remain, we can return early\n tokens.splice(i, 1);\n selector = seed.length && toSelector(tokens);\n\n if (!selector) {\n push.apply(results, seed);\n return results;\n }\n\n break;\n }\n }\n }\n } // Compile and execute a filtering function if one is not provided\n // Provide `match` to avoid retokenization if we modified the selector above\n\n\n (compiled || compile(selector, match))(seed, context, !documentIsHTML, results, !context || rsibling.test(selector) && testContext(context.parentNode) || context);\n return results;\n }; // One-time assignments\n // Sort stability\n\n\n support.sortStable = expando.split(\"\").sort(sortOrder).join(\"\") === expando; // Support: Chrome 14-35+\n // Always assume duplicates if they aren't passed to the comparison function\n\n support.detectDuplicates = !!hasDuplicate; // Initialize against the default document\n\n setDocument(); // Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)\n // Detached nodes confoundingly follow *each other*\n\n support.sortDetached = assert(function (el) {\n // Should return 1, but returns 4 (following)\n return el.compareDocumentPosition(document.createElement(\"fieldset\")) & 1;\n }); // Support: IE<8\n // Prevent attribute/property \"interpolation\"\n // https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx\n\n if (!assert(function (el) {\n el.innerHTML = \" \";\n return el.firstChild.getAttribute(\"href\") === \"#\";\n })) {\n addHandle(\"type|href|height|width\", function (elem, name, isXML) {\n if (!isXML) {\n return elem.getAttribute(name, name.toLowerCase() === \"type\" ? 1 : 2);\n }\n });\n } // Support: IE<9\n // Use defaultValue in place of getAttribute(\"value\")\n\n\n if (!support.attributes || !assert(function (el) {\n el.innerHTML = \" \";\n el.firstChild.setAttribute(\"value\", \"\");\n return el.firstChild.getAttribute(\"value\") === \"\";\n })) {\n addHandle(\"value\", function (elem, _name, isXML) {\n if (!isXML && elem.nodeName.toLowerCase() === \"input\") {\n return elem.defaultValue;\n }\n });\n } // Support: IE<9\n // Use getAttributeNode to fetch booleans when getAttribute lies\n\n\n if (!assert(function (el) {\n return el.getAttribute(\"disabled\") == null;\n })) {\n addHandle(booleans, function (elem, name, isXML) {\n var val;\n\n if (!isXML) {\n return elem[name] === true ? name.toLowerCase() : (val = elem.getAttributeNode(name)) && val.specified ? val.value : null;\n }\n });\n }\n\n return Sizzle;\n }(window);\n\n jQuery.find = Sizzle;\n jQuery.expr = Sizzle.selectors; // Deprecated\n\n jQuery.expr[\":\"] = jQuery.expr.pseudos;\n jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort;\n jQuery.text = Sizzle.getText;\n jQuery.isXMLDoc = Sizzle.isXML;\n jQuery.contains = Sizzle.contains;\n jQuery.escapeSelector = Sizzle.escape;\n\n var dir = function dir(elem, _dir, until) {\n var matched = [],\n truncate = until !== undefined;\n\n while ((elem = elem[_dir]) && elem.nodeType !== 9) {\n if (elem.nodeType === 1) {\n if (truncate && jQuery(elem).is(until)) {\n break;\n }\n\n matched.push(elem);\n }\n }\n\n return matched;\n };\n\n var _siblings = function siblings(n, elem) {\n var matched = [];\n\n for (; n; n = n.nextSibling) {\n if (n.nodeType === 1 && n !== elem) {\n matched.push(n);\n }\n }\n\n return matched;\n };\n\n var rneedsContext = jQuery.expr.match.needsContext;\n\n function nodeName(elem, name) {\n return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();\n }\n\n var rsingleTag = /^<([a-z][^\\/\\0>:\\x20\\t\\r\\n\\f]*)[\\x20\\t\\r\\n\\f]*\\/?>(?:<\\/\\1>|)$/i; // Implement the identical functionality for filter and not\n\n function winnow(elements, qualifier, not) {\n if (isFunction(qualifier)) {\n return jQuery.grep(elements, function (elem, i) {\n return !!qualifier.call(elem, i, elem) !== not;\n });\n } // Single element\n\n\n if (qualifier.nodeType) {\n return jQuery.grep(elements, function (elem) {\n return elem === qualifier !== not;\n });\n } // Arraylike of elements (jQuery, arguments, Array)\n\n\n if (typeof qualifier !== \"string\") {\n return jQuery.grep(elements, function (elem) {\n return indexOf.call(qualifier, elem) > -1 !== not;\n });\n } // Filtered directly for both simple and complex selectors\n\n\n return jQuery.filter(qualifier, elements, not);\n }\n\n jQuery.filter = function (expr, elems, not) {\n var elem = elems[0];\n\n if (not) {\n expr = \":not(\" + expr + \")\";\n }\n\n if (elems.length === 1 && elem.nodeType === 1) {\n return jQuery.find.matchesSelector(elem, expr) ? [elem] : [];\n }\n\n return jQuery.find.matches(expr, jQuery.grep(elems, function (elem) {\n return elem.nodeType === 1;\n }));\n };\n\n jQuery.fn.extend({\n find: function find(selector) {\n var i,\n ret,\n len = this.length,\n self = this;\n\n if (typeof selector !== \"string\") {\n return this.pushStack(jQuery(selector).filter(function () {\n for (i = 0; i < len; i++) {\n if (jQuery.contains(self[i], this)) {\n return true;\n }\n }\n }));\n }\n\n ret = this.pushStack([]);\n\n for (i = 0; i < len; i++) {\n jQuery.find(selector, self[i], ret);\n }\n\n return len > 1 ? jQuery.uniqueSort(ret) : ret;\n },\n filter: function filter(selector) {\n return this.pushStack(winnow(this, selector || [], false));\n },\n not: function not(selector) {\n return this.pushStack(winnow(this, selector || [], true));\n },\n is: function is(selector) {\n return !!winnow(this, // If this is a positional/relative selector, check membership in the returned set\n // so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n typeof selector === \"string\" && rneedsContext.test(selector) ? jQuery(selector) : selector || [], false).length;\n }\n }); // Initialize a jQuery object\n // A central reference to the root jQuery(document)\n\n var rootjQuery,\n // A simple way to check for HTML strings\n // Prioritize #id over to avoid XSS via location.hash (#9521)\n // Strict HTML recognition (#11290: must start with <)\n // Shortcut simple #id case for speed\n rquickExpr = /^(?:\\s*(<[\\w\\W]+>)[^>]*|#([\\w-]+))$/,\n init = jQuery.fn.init = function (selector, context, root) {\n var match, elem; // HANDLE: $(\"\"), $(null), $(undefined), $(false)\n\n if (!selector) {\n return this;\n } // Method init() accepts an alternate rootjQuery\n // so migrate can support jQuery.sub (gh-2101)\n\n\n root = root || rootjQuery; // Handle HTML strings\n\n if (typeof selector === \"string\") {\n if (selector[0] === \"<\" && selector[selector.length - 1] === \">\" && selector.length >= 3) {\n // Assume that strings that start and end with <> are HTML and skip the regex check\n match = [null, selector, null];\n } else {\n match = rquickExpr.exec(selector);\n } // Match html or make sure no context is specified for #id\n\n\n if (match && (match[1] || !context)) {\n // HANDLE: $(html) -> $(array)\n if (match[1]) {\n context = context instanceof jQuery ? context[0] : context; // Option to run scripts is true for back-compat\n // Intentionally let the error be thrown if parseHTML is not present\n\n jQuery.merge(this, jQuery.parseHTML(match[1], context && context.nodeType ? context.ownerDocument || context : document, true)); // HANDLE: $(html, props)\n\n if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) {\n for (match in context) {\n // Properties of context are called as methods if possible\n if (isFunction(this[match])) {\n this[match](context[match]); // ...and otherwise set as attributes\n } else {\n this.attr(match, context[match]);\n }\n }\n }\n\n return this; // HANDLE: $(#id)\n } else {\n elem = document.getElementById(match[2]);\n\n if (elem) {\n // Inject the element directly into the jQuery object\n this[0] = elem;\n this.length = 1;\n }\n\n return this;\n } // HANDLE: $(expr, $(...))\n\n } else if (!context || context.jquery) {\n return (context || root).find(selector); // HANDLE: $(expr, context)\n // (which is just equivalent to: $(context).find(expr)\n } else {\n return this.constructor(context).find(selector);\n } // HANDLE: $(DOMElement)\n\n } else if (selector.nodeType) {\n this[0] = selector;\n this.length = 1;\n return this; // HANDLE: $(function)\n // Shortcut for document ready\n } else if (isFunction(selector)) {\n return root.ready !== undefined ? root.ready(selector) : // Execute immediately if ready is not present\n selector(jQuery);\n }\n\n return jQuery.makeArray(selector, this);\n }; // Give the init function the jQuery prototype for later instantiation\n\n\n init.prototype = jQuery.fn; // Initialize central reference\n\n rootjQuery = jQuery(document);\n var rparentsprev = /^(?:parents|prev(?:Until|All))/,\n // Methods guaranteed to produce a unique set when starting from a unique set\n guaranteedUnique = {\n children: true,\n contents: true,\n next: true,\n prev: true\n };\n jQuery.fn.extend({\n has: function has(target) {\n var targets = jQuery(target, this),\n l = targets.length;\n return this.filter(function () {\n var i = 0;\n\n for (; i < l; i++) {\n if (jQuery.contains(this, targets[i])) {\n return true;\n }\n }\n });\n },\n closest: function closest(selectors, context) {\n var cur,\n i = 0,\n l = this.length,\n matched = [],\n targets = typeof selectors !== \"string\" && jQuery(selectors); // Positional selectors never match, since there's no _selection_ context\n\n if (!rneedsContext.test(selectors)) {\n for (; i < l; i++) {\n for (cur = this[i]; cur && cur !== context; cur = cur.parentNode) {\n // Always skip document fragments\n if (cur.nodeType < 11 && (targets ? targets.index(cur) > -1 : // Don't pass non-elements to Sizzle\n cur.nodeType === 1 && jQuery.find.matchesSelector(cur, selectors))) {\n matched.push(cur);\n break;\n }\n }\n }\n }\n\n return this.pushStack(matched.length > 1 ? jQuery.uniqueSort(matched) : matched);\n },\n // Determine the position of an element within the set\n index: function index(elem) {\n // No argument, return index in parent\n if (!elem) {\n return this[0] && this[0].parentNode ? this.first().prevAll().length : -1;\n } // Index in selector\n\n\n if (typeof elem === \"string\") {\n return indexOf.call(jQuery(elem), this[0]);\n } // Locate the position of the desired element\n\n\n return indexOf.call(this, // If it receives a jQuery object, the first element is used\n elem.jquery ? elem[0] : elem);\n },\n add: function add(selector, context) {\n return this.pushStack(jQuery.uniqueSort(jQuery.merge(this.get(), jQuery(selector, context))));\n },\n addBack: function addBack(selector) {\n return this.add(selector == null ? this.prevObject : this.prevObject.filter(selector));\n }\n });\n\n function sibling(cur, dir) {\n while ((cur = cur[dir]) && cur.nodeType !== 1) {}\n\n return cur;\n }\n\n jQuery.each({\n parent: function parent(elem) {\n var parent = elem.parentNode;\n return parent && parent.nodeType !== 11 ? parent : null;\n },\n parents: function parents(elem) {\n return dir(elem, \"parentNode\");\n },\n parentsUntil: function parentsUntil(elem, _i, until) {\n return dir(elem, \"parentNode\", until);\n },\n next: function next(elem) {\n return sibling(elem, \"nextSibling\");\n },\n prev: function prev(elem) {\n return sibling(elem, \"previousSibling\");\n },\n nextAll: function nextAll(elem) {\n return dir(elem, \"nextSibling\");\n },\n prevAll: function prevAll(elem) {\n return dir(elem, \"previousSibling\");\n },\n nextUntil: function nextUntil(elem, _i, until) {\n return dir(elem, \"nextSibling\", until);\n },\n prevUntil: function prevUntil(elem, _i, until) {\n return dir(elem, \"previousSibling\", until);\n },\n siblings: function siblings(elem) {\n return _siblings((elem.parentNode || {}).firstChild, elem);\n },\n children: function children(elem) {\n return _siblings(elem.firstChild);\n },\n contents: function contents(elem) {\n if (elem.contentDocument != null && // Support: IE 11+\n // elements with no `data` attribute has an object\n // `contentDocument` with a `null` prototype.\n getProto(elem.contentDocument)) {\n return elem.contentDocument;\n } // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only\n // Treat the template element as a regular one in browsers that\n // don't support it.\n\n\n if (nodeName(elem, \"template\")) {\n elem = elem.content || elem;\n }\n\n return jQuery.merge([], elem.childNodes);\n }\n }, function (name, fn) {\n jQuery.fn[name] = function (until, selector) {\n var matched = jQuery.map(this, fn, until);\n\n if (name.slice(-5) !== \"Until\") {\n selector = until;\n }\n\n if (selector && typeof selector === \"string\") {\n matched = jQuery.filter(selector, matched);\n }\n\n if (this.length > 1) {\n // Remove duplicates\n if (!guaranteedUnique[name]) {\n jQuery.uniqueSort(matched);\n } // Reverse order for parents* and prev-derivatives\n\n\n if (rparentsprev.test(name)) {\n matched.reverse();\n }\n }\n\n return this.pushStack(matched);\n };\n });\n var rnothtmlwhite = /[^\\x20\\t\\r\\n\\f]+/g; // Convert String-formatted options into Object-formatted ones\n\n function createOptions(options) {\n var object = {};\n jQuery.each(options.match(rnothtmlwhite) || [], function (_, flag) {\n object[flag] = true;\n });\n return object;\n }\n /*\n * Create a callback list using the following parameters:\n *\n *\toptions: an optional list of space-separated options that will change how\n *\t\t\tthe callback list behaves or a more traditional option object\n *\n * By default a callback list will act like an event callback list and can be\n * \"fired\" multiple times.\n *\n * Possible options:\n *\n *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n *\n *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n *\t\t\t\t\tafter the list has been fired right away with the latest \"memorized\"\n *\t\t\t\t\tvalues (like a Deferred)\n *\n *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n *\n *\tstopOnFalse:\tinterrupt callings when a callback returns false\n *\n */\n\n\n jQuery.Callbacks = function (options) {\n // Convert options from String-formatted to Object-formatted if needed\n // (we check in cache first)\n options = typeof options === \"string\" ? createOptions(options) : jQuery.extend({}, options);\n\n var // Flag to know if list is currently firing\n firing,\n // Last fire value for non-forgettable lists\n memory,\n // Flag to know if list was already fired\n _fired,\n // Flag to prevent firing\n _locked,\n // Actual callback list\n list = [],\n // Queue of execution data for repeatable lists\n queue = [],\n // Index of currently firing callback (modified by add/remove as needed)\n firingIndex = -1,\n // Fire callbacks\n fire = function fire() {\n // Enforce single-firing\n _locked = _locked || options.once; // Execute callbacks for all pending executions,\n // respecting firingIndex overrides and runtime changes\n\n _fired = firing = true;\n\n for (; queue.length; firingIndex = -1) {\n memory = queue.shift();\n\n while (++firingIndex < list.length) {\n // Run callback and check for early termination\n if (list[firingIndex].apply(memory[0], memory[1]) === false && options.stopOnFalse) {\n // Jump to end and forget the data so .add doesn't re-fire\n firingIndex = list.length;\n memory = false;\n }\n }\n } // Forget the data if we're done with it\n\n\n if (!options.memory) {\n memory = false;\n }\n\n firing = false; // Clean up if we're done firing for good\n\n if (_locked) {\n // Keep an empty list if we have data for future add calls\n if (memory) {\n list = []; // Otherwise, this object is spent\n } else {\n list = \"\";\n }\n }\n },\n // Actual Callbacks object\n self = {\n // Add a callback or a collection of callbacks to the list\n add: function add() {\n if (list) {\n // If we have memory from a past run, we should fire after adding\n if (memory && !firing) {\n firingIndex = list.length - 1;\n queue.push(memory);\n }\n\n (function add(args) {\n jQuery.each(args, function (_, arg) {\n if (isFunction(arg)) {\n if (!options.unique || !self.has(arg)) {\n list.push(arg);\n }\n } else if (arg && arg.length && toType(arg) !== \"string\") {\n // Inspect recursively\n add(arg);\n }\n });\n })(arguments);\n\n if (memory && !firing) {\n fire();\n }\n }\n\n return this;\n },\n // Remove a callback from the list\n remove: function remove() {\n jQuery.each(arguments, function (_, arg) {\n var index;\n\n while ((index = jQuery.inArray(arg, list, index)) > -1) {\n list.splice(index, 1); // Handle firing indexes\n\n if (index <= firingIndex) {\n firingIndex--;\n }\n }\n });\n return this;\n },\n // Check if a given callback is in the list.\n // If no argument is given, return whether or not list has callbacks attached.\n has: function has(fn) {\n return fn ? jQuery.inArray(fn, list) > -1 : list.length > 0;\n },\n // Remove all callbacks from the list\n empty: function empty() {\n if (list) {\n list = [];\n }\n\n return this;\n },\n // Disable .fire and .add\n // Abort any current/pending executions\n // Clear all callbacks and values\n disable: function disable() {\n _locked = queue = [];\n list = memory = \"\";\n return this;\n },\n disabled: function disabled() {\n return !list;\n },\n // Disable .fire\n // Also disable .add unless we have memory (since it would have no effect)\n // Abort any pending executions\n lock: function lock() {\n _locked = queue = [];\n\n if (!memory && !firing) {\n list = memory = \"\";\n }\n\n return this;\n },\n locked: function locked() {\n return !!_locked;\n },\n // Call all callbacks with the given context and arguments\n fireWith: function fireWith(context, args) {\n if (!_locked) {\n args = args || [];\n args = [context, args.slice ? args.slice() : args];\n queue.push(args);\n\n if (!firing) {\n fire();\n }\n }\n\n return this;\n },\n // Call all the callbacks with the given arguments\n fire: function fire() {\n self.fireWith(this, arguments);\n return this;\n },\n // To know if the callbacks have already been called at least once\n fired: function fired() {\n return !!_fired;\n }\n };\n\n return self;\n };\n\n function Identity(v) {\n return v;\n }\n\n function Thrower(ex) {\n throw ex;\n }\n\n function adoptValue(value, resolve, reject, noValue) {\n var method;\n\n try {\n // Check for promise aspect first to privilege synchronous behavior\n if (value && isFunction(method = value.promise)) {\n method.call(value).done(resolve).fail(reject); // Other thenables\n } else if (value && isFunction(method = value.then)) {\n method.call(value, resolve, reject); // Other non-thenables\n } else {\n // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer:\n // * false: [ value ].slice( 0 ) => resolve( value )\n // * true: [ value ].slice( 1 ) => resolve()\n resolve.apply(undefined, [value].slice(noValue));\n } // For Promises/A+, convert exceptions into rejections\n // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in\n // Deferred#then to conditionally suppress rejection.\n\n } catch (value) {\n // Support: Android 4.0 only\n // Strict mode functions invoked without .call/.apply get global-object context\n reject.apply(undefined, [value]);\n }\n }\n\n jQuery.extend({\n Deferred: function Deferred(func) {\n var tuples = [// action, add listener, callbacks,\n // ... .then handlers, argument index, [final state]\n [\"notify\", \"progress\", jQuery.Callbacks(\"memory\"), jQuery.Callbacks(\"memory\"), 2], [\"resolve\", \"done\", jQuery.Callbacks(\"once memory\"), jQuery.Callbacks(\"once memory\"), 0, \"resolved\"], [\"reject\", \"fail\", jQuery.Callbacks(\"once memory\"), jQuery.Callbacks(\"once memory\"), 1, \"rejected\"]],\n _state = \"pending\",\n _promise = {\n state: function state() {\n return _state;\n },\n always: function always() {\n deferred.done(arguments).fail(arguments);\n return this;\n },\n \"catch\": function _catch(fn) {\n return _promise.then(null, fn);\n },\n // Keep pipe for back-compat\n pipe: function\n /* fnDone, fnFail, fnProgress */\n pipe() {\n var fns = arguments;\n return jQuery.Deferred(function (newDefer) {\n jQuery.each(tuples, function (_i, tuple) {\n // Map tuples (progress, done, fail) to arguments (done, fail, progress)\n var fn = isFunction(fns[tuple[4]]) && fns[tuple[4]]; // deferred.progress(function() { bind to newDefer or newDefer.notify })\n // deferred.done(function() { bind to newDefer or newDefer.resolve })\n // deferred.fail(function() { bind to newDefer or newDefer.reject })\n\n deferred[tuple[1]](function () {\n var returned = fn && fn.apply(this, arguments);\n\n if (returned && isFunction(returned.promise)) {\n returned.promise().progress(newDefer.notify).done(newDefer.resolve).fail(newDefer.reject);\n } else {\n newDefer[tuple[0] + \"With\"](this, fn ? [returned] : arguments);\n }\n });\n });\n fns = null;\n }).promise();\n },\n then: function then(onFulfilled, onRejected, onProgress) {\n var maxDepth = 0;\n\n function resolve(depth, deferred, handler, special) {\n return function () {\n var that = this,\n args = arguments,\n mightThrow = function mightThrow() {\n var returned, then; // Support: Promises/A+ section 2.3.3.3.3\n // https://promisesaplus.com/#point-59\n // Ignore double-resolution attempts\n\n if (depth < maxDepth) {\n return;\n }\n\n returned = handler.apply(that, args); // Support: Promises/A+ section 2.3.1\n // https://promisesaplus.com/#point-48\n\n if (returned === deferred.promise()) {\n throw new TypeError(\"Thenable self-resolution\");\n } // Support: Promises/A+ sections 2.3.3.1, 3.5\n // https://promisesaplus.com/#point-54\n // https://promisesaplus.com/#point-75\n // Retrieve `then` only once\n\n\n then = returned && ( // Support: Promises/A+ section 2.3.4\n // https://promisesaplus.com/#point-64\n // Only check objects and functions for thenability\n _typeof(returned) === \"object\" || typeof returned === \"function\") && returned.then; // Handle a returned thenable\n\n if (isFunction(then)) {\n // Special processors (notify) just wait for resolution\n if (special) {\n then.call(returned, resolve(maxDepth, deferred, Identity, special), resolve(maxDepth, deferred, Thrower, special)); // Normal processors (resolve) also hook into progress\n } else {\n // ...and disregard older resolution values\n maxDepth++;\n then.call(returned, resolve(maxDepth, deferred, Identity, special), resolve(maxDepth, deferred, Thrower, special), resolve(maxDepth, deferred, Identity, deferred.notifyWith));\n } // Handle all other returned values\n\n } else {\n // Only substitute handlers pass on context\n // and multiple values (non-spec behavior)\n if (handler !== Identity) {\n that = undefined;\n args = [returned];\n } // Process the value(s)\n // Default process is resolve\n\n\n (special || deferred.resolveWith)(that, args);\n }\n },\n // Only normal processors (resolve) catch and reject exceptions\n process = special ? mightThrow : function () {\n try {\n mightThrow();\n } catch (e) {\n if (jQuery.Deferred.exceptionHook) {\n jQuery.Deferred.exceptionHook(e, process.stackTrace);\n } // Support: Promises/A+ section 2.3.3.3.4.1\n // https://promisesaplus.com/#point-61\n // Ignore post-resolution exceptions\n\n\n if (depth + 1 >= maxDepth) {\n // Only substitute handlers pass on context\n // and multiple values (non-spec behavior)\n if (handler !== Thrower) {\n that = undefined;\n args = [e];\n }\n\n deferred.rejectWith(that, args);\n }\n }\n }; // Support: Promises/A+ section 2.3.3.3.1\n // https://promisesaplus.com/#point-57\n // Re-resolve promises immediately to dodge false rejection from\n // subsequent errors\n\n\n if (depth) {\n process();\n } else {\n // Call an optional hook to record the stack, in case of exception\n // since it's otherwise lost when execution goes async\n if (jQuery.Deferred.getStackHook) {\n process.stackTrace = jQuery.Deferred.getStackHook();\n }\n\n window.setTimeout(process);\n }\n };\n }\n\n return jQuery.Deferred(function (newDefer) {\n // progress_handlers.add( ... )\n tuples[0][3].add(resolve(0, newDefer, isFunction(onProgress) ? onProgress : Identity, newDefer.notifyWith)); // fulfilled_handlers.add( ... )\n\n tuples[1][3].add(resolve(0, newDefer, isFunction(onFulfilled) ? onFulfilled : Identity)); // rejected_handlers.add( ... )\n\n tuples[2][3].add(resolve(0, newDefer, isFunction(onRejected) ? onRejected : Thrower));\n }).promise();\n },\n // Get a promise for this deferred\n // If obj is provided, the promise aspect is added to the object\n promise: function promise(obj) {\n return obj != null ? jQuery.extend(obj, _promise) : _promise;\n }\n },\n deferred = {}; // Add list-specific methods\n\n jQuery.each(tuples, function (i, tuple) {\n var list = tuple[2],\n stateString = tuple[5]; // promise.progress = list.add\n // promise.done = list.add\n // promise.fail = list.add\n\n _promise[tuple[1]] = list.add; // Handle state\n\n if (stateString) {\n list.add(function () {\n // state = \"resolved\" (i.e., fulfilled)\n // state = \"rejected\"\n _state = stateString;\n }, // rejected_callbacks.disable\n // fulfilled_callbacks.disable\n tuples[3 - i][2].disable, // rejected_handlers.disable\n // fulfilled_handlers.disable\n tuples[3 - i][3].disable, // progress_callbacks.lock\n tuples[0][2].lock, // progress_handlers.lock\n tuples[0][3].lock);\n } // progress_handlers.fire\n // fulfilled_handlers.fire\n // rejected_handlers.fire\n\n\n list.add(tuple[3].fire); // deferred.notify = function() { deferred.notifyWith(...) }\n // deferred.resolve = function() { deferred.resolveWith(...) }\n // deferred.reject = function() { deferred.rejectWith(...) }\n\n deferred[tuple[0]] = function () {\n deferred[tuple[0] + \"With\"](this === deferred ? undefined : this, arguments);\n return this;\n }; // deferred.notifyWith = list.fireWith\n // deferred.resolveWith = list.fireWith\n // deferred.rejectWith = list.fireWith\n\n\n deferred[tuple[0] + \"With\"] = list.fireWith;\n }); // Make the deferred a promise\n\n _promise.promise(deferred); // Call given func if any\n\n\n if (func) {\n func.call(deferred, deferred);\n } // All done!\n\n\n return deferred;\n },\n // Deferred helper\n when: function when(singleValue) {\n var // count of uncompleted subordinates\n remaining = arguments.length,\n // count of unprocessed arguments\n i = remaining,\n // subordinate fulfillment data\n resolveContexts = Array(i),\n resolveValues = _slice.call(arguments),\n // the primary Deferred\n primary = jQuery.Deferred(),\n // subordinate callback factory\n updateFunc = function updateFunc(i) {\n return function (value) {\n resolveContexts[i] = this;\n resolveValues[i] = arguments.length > 1 ? _slice.call(arguments) : value;\n\n if (! --remaining) {\n primary.resolveWith(resolveContexts, resolveValues);\n }\n };\n }; // Single- and empty arguments are adopted like Promise.resolve\n\n\n if (remaining <= 1) {\n adoptValue(singleValue, primary.done(updateFunc(i)).resolve, primary.reject, !remaining); // Use .then() to unwrap secondary thenables (cf. gh-3000)\n\n if (primary.state() === \"pending\" || isFunction(resolveValues[i] && resolveValues[i].then)) {\n return primary.then();\n }\n } // Multiple arguments are aggregated like Promise.all array elements\n\n\n while (i--) {\n adoptValue(resolveValues[i], updateFunc(i), primary.reject);\n }\n\n return primary.promise();\n }\n }); // These usually indicate a programmer mistake during development,\n // warn about them ASAP rather than swallowing them by default.\n\n var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;\n\n jQuery.Deferred.exceptionHook = function (error, stack) {\n // Support: IE 8 - 9 only\n // Console exists when dev tools are open, which can happen at any time\n if (window.console && window.console.warn && error && rerrorNames.test(error.name)) {\n window.console.warn(\"jQuery.Deferred exception: \" + error.message, error.stack, stack);\n }\n };\n\n jQuery.readyException = function (error) {\n window.setTimeout(function () {\n throw error;\n });\n }; // The deferred used on DOM ready\n\n\n var readyList = jQuery.Deferred();\n\n jQuery.fn.ready = function (fn) {\n readyList.then(fn) // Wrap jQuery.readyException in a function so that the lookup\n // happens at the time of error handling instead of callback\n // registration.\n .catch(function (error) {\n jQuery.readyException(error);\n });\n return this;\n };\n\n jQuery.extend({\n // Is the DOM ready to be used? Set to true once it occurs.\n isReady: false,\n // A counter to track how many items to wait for before\n // the ready event fires. See #6781\n readyWait: 1,\n // Handle when the DOM is ready\n ready: function ready(wait) {\n // Abort if there are pending holds or we're already ready\n if (wait === true ? --jQuery.readyWait : jQuery.isReady) {\n return;\n } // Remember that the DOM is ready\n\n\n jQuery.isReady = true; // If a normal DOM Ready event fired, decrement, and wait if need be\n\n if (wait !== true && --jQuery.readyWait > 0) {\n return;\n } // If there are functions bound, to execute\n\n\n readyList.resolveWith(document, [jQuery]);\n }\n });\n jQuery.ready.then = readyList.then; // The ready event handler and self cleanup method\n\n function completed() {\n document.removeEventListener(\"DOMContentLoaded\", completed);\n window.removeEventListener(\"load\", completed);\n jQuery.ready();\n } // Catch cases where $(document).ready() is called\n // after the browser event has already occurred.\n // Support: IE <=9 - 10 only\n // Older IE sometimes signals \"interactive\" too soon\n\n\n if (document.readyState === \"complete\" || document.readyState !== \"loading\" && !document.documentElement.doScroll) {\n // Handle it asynchronously to allow scripts the opportunity to delay ready\n window.setTimeout(jQuery.ready);\n } else {\n // Use the handy event callback\n document.addEventListener(\"DOMContentLoaded\", completed); // A fallback to window.onload, that will always work\n\n window.addEventListener(\"load\", completed);\n } // Multifunctional method to get and set values of a collection\n // The value/s can optionally be executed if it's a function\n\n\n var access = function access(elems, fn, key, value, chainable, emptyGet, raw) {\n var i = 0,\n len = elems.length,\n bulk = key == null; // Sets many values\n\n if (toType(key) === \"object\") {\n chainable = true;\n\n for (i in key) {\n access(elems, fn, i, key[i], true, emptyGet, raw);\n } // Sets one value\n\n } else if (value !== undefined) {\n chainable = true;\n\n if (!isFunction(value)) {\n raw = true;\n }\n\n if (bulk) {\n // Bulk operations run against the entire set\n if (raw) {\n fn.call(elems, value);\n fn = null; // ...except when executing function values\n } else {\n bulk = fn;\n\n fn = function fn(elem, _key, value) {\n return bulk.call(jQuery(elem), value);\n };\n }\n }\n\n if (fn) {\n for (; i < len; i++) {\n fn(elems[i], key, raw ? value : value.call(elems[i], i, fn(elems[i], key)));\n }\n }\n }\n\n if (chainable) {\n return elems;\n } // Gets\n\n\n if (bulk) {\n return fn.call(elems);\n }\n\n return len ? fn(elems[0], key) : emptyGet;\n }; // Matches dashed string for camelizing\n\n\n var rmsPrefix = /^-ms-/,\n rdashAlpha = /-([a-z])/g; // Used by camelCase as callback to replace()\n\n function fcamelCase(_all, letter) {\n return letter.toUpperCase();\n } // Convert dashed to camelCase; used by the css and data modules\n // Support: IE <=9 - 11, Edge 12 - 15\n // Microsoft forgot to hump their vendor prefix (#9572)\n\n\n function camelCase(string) {\n return string.replace(rmsPrefix, \"ms-\").replace(rdashAlpha, fcamelCase);\n }\n\n var acceptData = function acceptData(owner) {\n // Accepts only:\n // - Node\n // - Node.ELEMENT_NODE\n // - Node.DOCUMENT_NODE\n // - Object\n // - Any\n return owner.nodeType === 1 || owner.nodeType === 9 || !+owner.nodeType;\n };\n\n function Data() {\n this.expando = jQuery.expando + Data.uid++;\n }\n\n Data.uid = 1;\n Data.prototype = {\n cache: function cache(owner) {\n // Check if the owner object already has a cache\n var value = owner[this.expando]; // If not, create one\n\n if (!value) {\n value = {}; // We can accept data for non-element nodes in modern browsers,\n // but we should not, see #8335.\n // Always return an empty object.\n\n if (acceptData(owner)) {\n // If it is a node unlikely to be stringify-ed or looped over\n // use plain assignment\n if (owner.nodeType) {\n owner[this.expando] = value; // Otherwise secure it in a non-enumerable property\n // configurable must be true to allow the property to be\n // deleted when data is removed\n } else {\n Object.defineProperty(owner, this.expando, {\n value: value,\n configurable: true\n });\n }\n }\n }\n\n return value;\n },\n set: function set(owner, data, value) {\n var prop,\n cache = this.cache(owner); // Handle: [ owner, key, value ] args\n // Always use camelCase key (gh-2257)\n\n if (typeof data === \"string\") {\n cache[camelCase(data)] = value; // Handle: [ owner, { properties } ] args\n } else {\n // Copy the properties one-by-one to the cache object\n for (prop in data) {\n cache[camelCase(prop)] = data[prop];\n }\n }\n\n return cache;\n },\n get: function get(owner, key) {\n return key === undefined ? this.cache(owner) : // Always use camelCase key (gh-2257)\n owner[this.expando] && owner[this.expando][camelCase(key)];\n },\n access: function access(owner, key, value) {\n // In cases where either:\n //\n // 1. No key was specified\n // 2. A string key was specified, but no value provided\n //\n // Take the \"read\" path and allow the get method to determine\n // which value to return, respectively either:\n //\n // 1. The entire cache object\n // 2. The data stored at the key\n //\n if (key === undefined || key && typeof key === \"string\" && value === undefined) {\n return this.get(owner, key);\n } // When the key is not a string, or both a key and value\n // are specified, set or extend (existing objects) with either:\n //\n // 1. An object of properties\n // 2. A key and value\n //\n\n\n this.set(owner, key, value); // Since the \"set\" path can have two possible entry points\n // return the expected data based on which path was taken[*]\n\n return value !== undefined ? value : key;\n },\n remove: function remove(owner, key) {\n var i,\n cache = owner[this.expando];\n\n if (cache === undefined) {\n return;\n }\n\n if (key !== undefined) {\n // Support array or space separated string of keys\n if (Array.isArray(key)) {\n // If key is an array of keys...\n // We always set camelCase keys, so remove that.\n key = key.map(camelCase);\n } else {\n key = camelCase(key); // If a key with the spaces exists, use it.\n // Otherwise, create an array by matching non-whitespace\n\n key = key in cache ? [key] : key.match(rnothtmlwhite) || [];\n }\n\n i = key.length;\n\n while (i--) {\n delete cache[key[i]];\n }\n } // Remove the expando if there's no more data\n\n\n if (key === undefined || jQuery.isEmptyObject(cache)) {\n // Support: Chrome <=35 - 45\n // Webkit & Blink performance suffers when deleting properties\n // from DOM nodes, so set to undefined instead\n // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted)\n if (owner.nodeType) {\n owner[this.expando] = undefined;\n } else {\n delete owner[this.expando];\n }\n }\n },\n hasData: function hasData(owner) {\n var cache = owner[this.expando];\n return cache !== undefined && !jQuery.isEmptyObject(cache);\n }\n };\n var dataPriv = new Data();\n var dataUser = new Data(); //\tImplementation Summary\n //\n //\t1. Enforce API surface and semantic compatibility with 1.9.x branch\n //\t2. Improve the module's maintainability by reducing the storage\n //\t\tpaths to a single mechanism.\n //\t3. Use the same single mechanism to support \"private\" and \"user\" data.\n //\t4. _Never_ expose \"private\" data to user code (TODO: Drop _data, _removeData)\n //\t5. Avoid exposing implementation details on user objects (eg. expando properties)\n //\t6. Provide a clear path for implementation upgrade to WeakMap in 2014\n\n var rbrace = /^(?:\\{[\\w\\W]*\\}|\\[[\\w\\W]*\\])$/,\n rmultiDash = /[A-Z]/g;\n\n function getData(data) {\n if (data === \"true\") {\n return true;\n }\n\n if (data === \"false\") {\n return false;\n }\n\n if (data === \"null\") {\n return null;\n } // Only convert to a number if it doesn't change the string\n\n\n if (data === +data + \"\") {\n return +data;\n }\n\n if (rbrace.test(data)) {\n return JSON.parse(data);\n }\n\n return data;\n }\n\n function dataAttr(elem, key, data) {\n var name; // If nothing was found internally, try to fetch any\n // data from the HTML5 data-* attribute\n\n if (data === undefined && elem.nodeType === 1) {\n name = \"data-\" + key.replace(rmultiDash, \"-$&\").toLowerCase();\n data = elem.getAttribute(name);\n\n if (typeof data === \"string\") {\n try {\n data = getData(data);\n } catch (e) {} // Make sure we set the data so it isn't changed later\n\n\n dataUser.set(elem, key, data);\n } else {\n data = undefined;\n }\n }\n\n return data;\n }\n\n jQuery.extend({\n hasData: function hasData(elem) {\n return dataUser.hasData(elem) || dataPriv.hasData(elem);\n },\n data: function data(elem, name, _data) {\n return dataUser.access(elem, name, _data);\n },\n removeData: function removeData(elem, name) {\n dataUser.remove(elem, name);\n },\n // TODO: Now that all calls to _data and _removeData have been replaced\n // with direct calls to dataPriv methods, these can be deprecated.\n _data: function _data(elem, name, data) {\n return dataPriv.access(elem, name, data);\n },\n _removeData: function _removeData(elem, name) {\n dataPriv.remove(elem, name);\n }\n });\n jQuery.fn.extend({\n data: function data(key, value) {\n var i,\n name,\n data,\n elem = this[0],\n attrs = elem && elem.attributes; // Gets all values\n\n if (key === undefined) {\n if (this.length) {\n data = dataUser.get(elem);\n\n if (elem.nodeType === 1 && !dataPriv.get(elem, \"hasDataAttrs\")) {\n i = attrs.length;\n\n while (i--) {\n // Support: IE 11 only\n // The attrs elements can be null (#14894)\n if (attrs[i]) {\n name = attrs[i].name;\n\n if (name.indexOf(\"data-\") === 0) {\n name = camelCase(name.slice(5));\n dataAttr(elem, name, data[name]);\n }\n }\n }\n\n dataPriv.set(elem, \"hasDataAttrs\", true);\n }\n }\n\n return data;\n } // Sets multiple values\n\n\n if (_typeof(key) === \"object\") {\n return this.each(function () {\n dataUser.set(this, key);\n });\n }\n\n return access(this, function (value) {\n var data; // The calling jQuery object (element matches) is not empty\n // (and therefore has an element appears at this[ 0 ]) and the\n // `value` parameter was not undefined. An empty jQuery object\n // will result in `undefined` for elem = this[ 0 ] which will\n // throw an exception if an attempt to read a data cache is made.\n\n if (elem && value === undefined) {\n // Attempt to get data from the cache\n // The key will always be camelCased in Data\n data = dataUser.get(elem, key);\n\n if (data !== undefined) {\n return data;\n } // Attempt to \"discover\" the data in\n // HTML5 custom data-* attrs\n\n\n data = dataAttr(elem, key);\n\n if (data !== undefined) {\n return data;\n } // We tried really hard, but the data doesn't exist.\n\n\n return;\n } // Set the data...\n\n\n this.each(function () {\n // We always store the camelCased key\n dataUser.set(this, key, value);\n });\n }, null, value, arguments.length > 1, null, true);\n },\n removeData: function removeData(key) {\n return this.each(function () {\n dataUser.remove(this, key);\n });\n }\n });\n jQuery.extend({\n queue: function queue(elem, type, data) {\n var queue;\n\n if (elem) {\n type = (type || \"fx\") + \"queue\";\n queue = dataPriv.get(elem, type); // Speed up dequeue by getting out quickly if this is just a lookup\n\n if (data) {\n if (!queue || Array.isArray(data)) {\n queue = dataPriv.access(elem, type, jQuery.makeArray(data));\n } else {\n queue.push(data);\n }\n }\n\n return queue || [];\n }\n },\n dequeue: function dequeue(elem, type) {\n type = type || \"fx\";\n\n var queue = jQuery.queue(elem, type),\n startLength = queue.length,\n fn = queue.shift(),\n hooks = jQuery._queueHooks(elem, type),\n next = function next() {\n jQuery.dequeue(elem, type);\n }; // If the fx queue is dequeued, always remove the progress sentinel\n\n\n if (fn === \"inprogress\") {\n fn = queue.shift();\n startLength--;\n }\n\n if (fn) {\n // Add a progress sentinel to prevent the fx queue from being\n // automatically dequeued\n if (type === \"fx\") {\n queue.unshift(\"inprogress\");\n } // Clear up the last queue stop function\n\n\n delete hooks.stop;\n fn.call(elem, next, hooks);\n }\n\n if (!startLength && hooks) {\n hooks.empty.fire();\n }\n },\n // Not public - generate a queueHooks object, or return the current one\n _queueHooks: function _queueHooks(elem, type) {\n var key = type + \"queueHooks\";\n return dataPriv.get(elem, key) || dataPriv.access(elem, key, {\n empty: jQuery.Callbacks(\"once memory\").add(function () {\n dataPriv.remove(elem, [type + \"queue\", key]);\n })\n });\n }\n });\n jQuery.fn.extend({\n queue: function queue(type, data) {\n var setter = 2;\n\n if (typeof type !== \"string\") {\n data = type;\n type = \"fx\";\n setter--;\n }\n\n if (arguments.length < setter) {\n return jQuery.queue(this[0], type);\n }\n\n return data === undefined ? this : this.each(function () {\n var queue = jQuery.queue(this, type, data); // Ensure a hooks for this queue\n\n jQuery._queueHooks(this, type);\n\n if (type === \"fx\" && queue[0] !== \"inprogress\") {\n jQuery.dequeue(this, type);\n }\n });\n },\n dequeue: function dequeue(type) {\n return this.each(function () {\n jQuery.dequeue(this, type);\n });\n },\n clearQueue: function clearQueue(type) {\n return this.queue(type || \"fx\", []);\n },\n // Get a promise resolved when queues of a certain type\n // are emptied (fx is the type by default)\n promise: function promise(type, obj) {\n var tmp,\n count = 1,\n defer = jQuery.Deferred(),\n elements = this,\n i = this.length,\n resolve = function resolve() {\n if (! --count) {\n defer.resolveWith(elements, [elements]);\n }\n };\n\n if (typeof type !== \"string\") {\n obj = type;\n type = undefined;\n }\n\n type = type || \"fx\";\n\n while (i--) {\n tmp = dataPriv.get(elements[i], type + \"queueHooks\");\n\n if (tmp && tmp.empty) {\n count++;\n tmp.empty.add(resolve);\n }\n }\n\n resolve();\n return defer.promise(obj);\n }\n });\n var pnum = /[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/.source;\n var rcssNum = new RegExp(\"^(?:([+-])=|)(\" + pnum + \")([a-z%]*)$\", \"i\");\n var cssExpand = [\"Top\", \"Right\", \"Bottom\", \"Left\"];\n var documentElement = document.documentElement;\n\n var isAttached = function isAttached(elem) {\n return jQuery.contains(elem.ownerDocument, elem);\n },\n composed = {\n composed: true\n }; // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only\n // Check attachment across shadow DOM boundaries when possible (gh-3504)\n // Support: iOS 10.0-10.2 only\n // Early iOS 10 versions support `attachShadow` but not `getRootNode`,\n // leading to errors. We need to check for `getRootNode`.\n\n\n if (documentElement.getRootNode) {\n isAttached = function isAttached(elem) {\n return jQuery.contains(elem.ownerDocument, elem) || elem.getRootNode(composed) === elem.ownerDocument;\n };\n }\n\n var isHiddenWithinTree = function isHiddenWithinTree(elem, el) {\n // isHiddenWithinTree might be called from jQuery#filter function;\n // in that case, element will be second argument\n elem = el || elem; // Inline style trumps all\n\n return elem.style.display === \"none\" || elem.style.display === \"\" && // Otherwise, check computed style\n // Support: Firefox <=43 - 45\n // Disconnected elements can have computed display: none, so first confirm that elem is\n // in the document.\n isAttached(elem) && jQuery.css(elem, \"display\") === \"none\";\n };\n\n function adjustCSS(elem, prop, valueParts, tween) {\n var adjusted,\n scale,\n maxIterations = 20,\n currentValue = tween ? function () {\n return tween.cur();\n } : function () {\n return jQuery.css(elem, prop, \"\");\n },\n initial = currentValue(),\n unit = valueParts && valueParts[3] || (jQuery.cssNumber[prop] ? \"\" : \"px\"),\n // Starting value computation is required for potential unit mismatches\n initialInUnit = elem.nodeType && (jQuery.cssNumber[prop] || unit !== \"px\" && +initial) && rcssNum.exec(jQuery.css(elem, prop));\n\n if (initialInUnit && initialInUnit[3] !== unit) {\n // Support: Firefox <=54\n // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144)\n initial = initial / 2; // Trust units reported by jQuery.css\n\n unit = unit || initialInUnit[3]; // Iteratively approximate from a nonzero starting point\n\n initialInUnit = +initial || 1;\n\n while (maxIterations--) {\n // Evaluate and update our best guess (doubling guesses that zero out).\n // Finish if the scale equals or crosses 1 (making the old*new product non-positive).\n jQuery.style(elem, prop, initialInUnit + unit);\n\n if ((1 - scale) * (1 - (scale = currentValue() / initial || 0.5)) <= 0) {\n maxIterations = 0;\n }\n\n initialInUnit = initialInUnit / scale;\n }\n\n initialInUnit = initialInUnit * 2;\n jQuery.style(elem, prop, initialInUnit + unit); // Make sure we update the tween properties later on\n\n valueParts = valueParts || [];\n }\n\n if (valueParts) {\n initialInUnit = +initialInUnit || +initial || 0; // Apply relative offset (+=/-=) if specified\n\n adjusted = valueParts[1] ? initialInUnit + (valueParts[1] + 1) * valueParts[2] : +valueParts[2];\n\n if (tween) {\n tween.unit = unit;\n tween.start = initialInUnit;\n tween.end = adjusted;\n }\n }\n\n return adjusted;\n }\n\n var defaultDisplayMap = {};\n\n function getDefaultDisplay(elem) {\n var temp,\n doc = elem.ownerDocument,\n nodeName = elem.nodeName,\n display = defaultDisplayMap[nodeName];\n\n if (display) {\n return display;\n }\n\n temp = doc.body.appendChild(doc.createElement(nodeName));\n display = jQuery.css(temp, \"display\");\n temp.parentNode.removeChild(temp);\n\n if (display === \"none\") {\n display = \"block\";\n }\n\n defaultDisplayMap[nodeName] = display;\n return display;\n }\n\n function showHide(elements, show) {\n var display,\n elem,\n values = [],\n index = 0,\n length = elements.length; // Determine new display value for elements that need to change\n\n for (; index < length; index++) {\n elem = elements[index];\n\n if (!elem.style) {\n continue;\n }\n\n display = elem.style.display;\n\n if (show) {\n // Since we force visibility upon cascade-hidden elements, an immediate (and slow)\n // check is required in this first loop unless we have a nonempty display value (either\n // inline or about-to-be-restored)\n if (display === \"none\") {\n values[index] = dataPriv.get(elem, \"display\") || null;\n\n if (!values[index]) {\n elem.style.display = \"\";\n }\n }\n\n if (elem.style.display === \"\" && isHiddenWithinTree(elem)) {\n values[index] = getDefaultDisplay(elem);\n }\n } else {\n if (display !== \"none\") {\n values[index] = \"none\"; // Remember what we're overwriting\n\n dataPriv.set(elem, \"display\", display);\n }\n }\n } // Set the display of the elements in a second loop to avoid constant reflow\n\n\n for (index = 0; index < length; index++) {\n if (values[index] != null) {\n elements[index].style.display = values[index];\n }\n }\n\n return elements;\n }\n\n jQuery.fn.extend({\n show: function show() {\n return showHide(this, true);\n },\n hide: function hide() {\n return showHide(this);\n },\n toggle: function toggle(state) {\n if (typeof state === \"boolean\") {\n return state ? this.show() : this.hide();\n }\n\n return this.each(function () {\n if (isHiddenWithinTree(this)) {\n jQuery(this).show();\n } else {\n jQuery(this).hide();\n }\n });\n }\n });\n var rcheckableType = /^(?:checkbox|radio)$/i;\n var rtagName = /<([a-z][^\\/\\0>\\x20\\t\\r\\n\\f]*)/i;\n var rscriptType = /^$|^module$|\\/(?:java|ecma)script/i;\n\n (function () {\n var fragment = document.createDocumentFragment(),\n div = fragment.appendChild(document.createElement(\"div\")),\n input = document.createElement(\"input\"); // Support: Android 4.0 - 4.3 only\n // Check state lost if the name is set (#11217)\n // Support: Windows Web Apps (WWA)\n // `name` and `type` must use .setAttribute for WWA (#14901)\n\n input.setAttribute(\"type\", \"radio\");\n input.setAttribute(\"checked\", \"checked\");\n input.setAttribute(\"name\", \"t\");\n div.appendChild(input); // Support: Android <=4.1 only\n // Older WebKit doesn't clone checked state correctly in fragments\n\n support.checkClone = div.cloneNode(true).cloneNode(true).lastChild.checked; // Support: IE <=11 only\n // Make sure textarea (and checkbox) defaultValue is properly cloned\n\n div.innerHTML = \"\";\n support.noCloneChecked = !!div.cloneNode(true).lastChild.defaultValue; // Support: IE <=9 only\n // IE <=9 replaces tags with their contents when inserted outside of\n // the select element.\n\n div.innerHTML = \" \";\n support.option = !!div.lastChild;\n })(); // We have to close these tags to support XHTML (#13200)\n\n\n var wrapMap = {\n // XHTML parsers do not magically insert elements in the\n // same way that tag soup parsers do. So we cannot shorten\n // this by omitting or other required elements.\n thead: [1, \"\"],\n col: [2, \"\"],\n tr: [2, \"\"],\n td: [3, \"\"],\n _default: [0, \"\", \"\"]\n };\n wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\n wrapMap.th = wrapMap.td; // Support: IE <=9 only\n\n if (!support.option) {\n wrapMap.optgroup = wrapMap.option = [1, \"\", \" \"];\n }\n\n function getAll(context, tag) {\n // Support: IE <=9 - 11 only\n // Use typeof to avoid zero-argument method invocation on host objects (#15151)\n var ret;\n\n if (typeof context.getElementsByTagName !== \"undefined\") {\n ret = context.getElementsByTagName(tag || \"*\");\n } else if (typeof context.querySelectorAll !== \"undefined\") {\n ret = context.querySelectorAll(tag || \"*\");\n } else {\n ret = [];\n }\n\n if (tag === undefined || tag && nodeName(context, tag)) {\n return jQuery.merge([context], ret);\n }\n\n return ret;\n } // Mark scripts as having already been evaluated\n\n\n function setGlobalEval(elems, refElements) {\n var i = 0,\n l = elems.length;\n\n for (; i < l; i++) {\n dataPriv.set(elems[i], \"globalEval\", !refElements || dataPriv.get(refElements[i], \"globalEval\"));\n }\n }\n\n var rhtml = /<|?\\w+;/;\n\n function buildFragment(elems, context, scripts, selection, ignored) {\n var elem,\n tmp,\n tag,\n wrap,\n attached,\n j,\n fragment = context.createDocumentFragment(),\n nodes = [],\n i = 0,\n l = elems.length;\n\n for (; i < l; i++) {\n elem = elems[i];\n\n if (elem || elem === 0) {\n // Add nodes directly\n if (toType(elem) === \"object\") {\n // Support: Android <=4.0 only, PhantomJS 1 only\n // push.apply(_, arraylike) throws on ancient WebKit\n jQuery.merge(nodes, elem.nodeType ? [elem] : elem); // Convert non-html into a text node\n } else if (!rhtml.test(elem)) {\n nodes.push(context.createTextNode(elem)); // Convert html into DOM nodes\n } else {\n tmp = tmp || fragment.appendChild(context.createElement(\"div\")); // Deserialize a standard representation\n\n tag = (rtagName.exec(elem) || [\"\", \"\"])[1].toLowerCase();\n wrap = wrapMap[tag] || wrapMap._default;\n tmp.innerHTML = wrap[1] + jQuery.htmlPrefilter(elem) + wrap[2]; // Descend through wrappers to the right content\n\n j = wrap[0];\n\n while (j--) {\n tmp = tmp.lastChild;\n } // Support: Android <=4.0 only, PhantomJS 1 only\n // push.apply(_, arraylike) throws on ancient WebKit\n\n\n jQuery.merge(nodes, tmp.childNodes); // Remember the top-level container\n\n tmp = fragment.firstChild; // Ensure the created nodes are orphaned (#12392)\n\n tmp.textContent = \"\";\n }\n }\n } // Remove wrapper from fragment\n\n\n fragment.textContent = \"\";\n i = 0;\n\n while (elem = nodes[i++]) {\n // Skip elements already in the context collection (trac-4087)\n if (selection && jQuery.inArray(elem, selection) > -1) {\n if (ignored) {\n ignored.push(elem);\n }\n\n continue;\n }\n\n attached = isAttached(elem); // Append to fragment\n\n tmp = getAll(fragment.appendChild(elem), \"script\"); // Preserve script evaluation history\n\n if (attached) {\n setGlobalEval(tmp);\n } // Capture executables\n\n\n if (scripts) {\n j = 0;\n\n while (elem = tmp[j++]) {\n if (rscriptType.test(elem.type || \"\")) {\n scripts.push(elem);\n }\n }\n }\n }\n\n return fragment;\n }\n\n var rtypenamespace = /^([^.]*)(?:\\.(.+)|)/;\n\n function returnTrue() {\n return true;\n }\n\n function returnFalse() {\n return false;\n } // Support: IE <=9 - 11+\n // focus() and blur() are asynchronous, except when they are no-op.\n // So expect focus to be synchronous when the element is already active,\n // and blur to be synchronous when the element is not already active.\n // (focus and blur are always synchronous in other supported browsers,\n // this just defines when we can count on it).\n\n\n function expectSync(elem, type) {\n return elem === safeActiveElement() === (type === \"focus\");\n } // Support: IE <=9 only\n // Accessing document.activeElement can throw unexpectedly\n // https://bugs.jquery.com/ticket/13393\n\n\n function safeActiveElement() {\n try {\n return document.activeElement;\n } catch (err) {}\n }\n\n function _on(elem, types, selector, data, fn, one) {\n var origFn, type; // Types can be a map of types/handlers\n\n if (_typeof(types) === \"object\") {\n // ( types-Object, selector, data )\n if (typeof selector !== \"string\") {\n // ( types-Object, data )\n data = data || selector;\n selector = undefined;\n }\n\n for (type in types) {\n _on(elem, type, selector, data, types[type], one);\n }\n\n return elem;\n }\n\n if (data == null && fn == null) {\n // ( types, fn )\n fn = selector;\n data = selector = undefined;\n } else if (fn == null) {\n if (typeof selector === \"string\") {\n // ( types, selector, fn )\n fn = data;\n data = undefined;\n } else {\n // ( types, data, fn )\n fn = data;\n data = selector;\n selector = undefined;\n }\n }\n\n if (fn === false) {\n fn = returnFalse;\n } else if (!fn) {\n return elem;\n }\n\n if (one === 1) {\n origFn = fn;\n\n fn = function fn(event) {\n // Can use an empty set, since event contains the info\n jQuery().off(event);\n return origFn.apply(this, arguments);\n }; // Use same guid so caller can remove using origFn\n\n\n fn.guid = origFn.guid || (origFn.guid = jQuery.guid++);\n }\n\n return elem.each(function () {\n jQuery.event.add(this, types, fn, data, selector);\n });\n }\n /*\n * Helper functions for managing events -- not part of the public interface.\n * Props to Dean Edwards' addEvent library for many of the ideas.\n */\n\n\n jQuery.event = {\n global: {},\n add: function add(elem, types, handler, data, selector) {\n var handleObjIn,\n eventHandle,\n tmp,\n events,\n t,\n handleObj,\n special,\n handlers,\n type,\n namespaces,\n origType,\n elemData = dataPriv.get(elem); // Only attach events to objects that accept data\n\n if (!acceptData(elem)) {\n return;\n } // Caller can pass in an object of custom data in lieu of the handler\n\n\n if (handler.handler) {\n handleObjIn = handler;\n handler = handleObjIn.handler;\n selector = handleObjIn.selector;\n } // Ensure that invalid selectors throw exceptions at attach time\n // Evaluate against documentElement in case elem is a non-element node (e.g., document)\n\n\n if (selector) {\n jQuery.find.matchesSelector(documentElement, selector);\n } // Make sure that the handler has a unique ID, used to find/remove it later\n\n\n if (!handler.guid) {\n handler.guid = jQuery.guid++;\n } // Init the element's event structure and main handler, if this is the first\n\n\n if (!(events = elemData.events)) {\n events = elemData.events = Object.create(null);\n }\n\n if (!(eventHandle = elemData.handle)) {\n eventHandle = elemData.handle = function (e) {\n // Discard the second event of a jQuery.event.trigger() and\n // when an event is called after a page has unloaded\n return typeof jQuery !== \"undefined\" && jQuery.event.triggered !== e.type ? jQuery.event.dispatch.apply(elem, arguments) : undefined;\n };\n } // Handle multiple events separated by a space\n\n\n types = (types || \"\").match(rnothtmlwhite) || [\"\"];\n t = types.length;\n\n while (t--) {\n tmp = rtypenamespace.exec(types[t]) || [];\n type = origType = tmp[1];\n namespaces = (tmp[2] || \"\").split(\".\").sort(); // There *must* be a type, no attaching namespace-only handlers\n\n if (!type) {\n continue;\n } // If event changes its type, use the special event handlers for the changed type\n\n\n special = jQuery.event.special[type] || {}; // If selector defined, determine special event api type, otherwise given type\n\n type = (selector ? special.delegateType : special.bindType) || type; // Update special based on newly reset type\n\n special = jQuery.event.special[type] || {}; // handleObj is passed to all event handlers\n\n handleObj = jQuery.extend({\n type: type,\n origType: origType,\n data: data,\n handler: handler,\n guid: handler.guid,\n selector: selector,\n needsContext: selector && jQuery.expr.match.needsContext.test(selector),\n namespace: namespaces.join(\".\")\n }, handleObjIn); // Init the event handler queue if we're the first\n\n if (!(handlers = events[type])) {\n handlers = events[type] = [];\n handlers.delegateCount = 0; // Only use addEventListener if the special events handler returns false\n\n if (!special.setup || special.setup.call(elem, data, namespaces, eventHandle) === false) {\n if (elem.addEventListener) {\n elem.addEventListener(type, eventHandle);\n }\n }\n }\n\n if (special.add) {\n special.add.call(elem, handleObj);\n\n if (!handleObj.handler.guid) {\n handleObj.handler.guid = handler.guid;\n }\n } // Add to the element's handler list, delegates in front\n\n\n if (selector) {\n handlers.splice(handlers.delegateCount++, 0, handleObj);\n } else {\n handlers.push(handleObj);\n } // Keep track of which events have ever been used, for event optimization\n\n\n jQuery.event.global[type] = true;\n }\n },\n // Detach an event or set of events from an element\n remove: function remove(elem, types, handler, selector, mappedTypes) {\n var j,\n origCount,\n tmp,\n events,\n t,\n handleObj,\n special,\n handlers,\n type,\n namespaces,\n origType,\n elemData = dataPriv.hasData(elem) && dataPriv.get(elem);\n\n if (!elemData || !(events = elemData.events)) {\n return;\n } // Once for each type.namespace in types; type may be omitted\n\n\n types = (types || \"\").match(rnothtmlwhite) || [\"\"];\n t = types.length;\n\n while (t--) {\n tmp = rtypenamespace.exec(types[t]) || [];\n type = origType = tmp[1];\n namespaces = (tmp[2] || \"\").split(\".\").sort(); // Unbind all events (on this namespace, if provided) for the element\n\n if (!type) {\n for (type in events) {\n jQuery.event.remove(elem, type + types[t], handler, selector, true);\n }\n\n continue;\n }\n\n special = jQuery.event.special[type] || {};\n type = (selector ? special.delegateType : special.bindType) || type;\n handlers = events[type] || [];\n tmp = tmp[2] && new RegExp(\"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.|)\") + \"(\\\\.|$)\"); // Remove matching events\n\n origCount = j = handlers.length;\n\n while (j--) {\n handleObj = handlers[j];\n\n if ((mappedTypes || origType === handleObj.origType) && (!handler || handler.guid === handleObj.guid) && (!tmp || tmp.test(handleObj.namespace)) && (!selector || selector === handleObj.selector || selector === \"**\" && handleObj.selector)) {\n handlers.splice(j, 1);\n\n if (handleObj.selector) {\n handlers.delegateCount--;\n }\n\n if (special.remove) {\n special.remove.call(elem, handleObj);\n }\n }\n } // Remove generic event handler if we removed something and no more handlers exist\n // (avoids potential for endless recursion during removal of special event handlers)\n\n\n if (origCount && !handlers.length) {\n if (!special.teardown || special.teardown.call(elem, namespaces, elemData.handle) === false) {\n jQuery.removeEvent(elem, type, elemData.handle);\n }\n\n delete events[type];\n }\n } // Remove data and the expando if it's no longer used\n\n\n if (jQuery.isEmptyObject(events)) {\n dataPriv.remove(elem, \"handle events\");\n }\n },\n dispatch: function dispatch(nativeEvent) {\n var i,\n j,\n ret,\n matched,\n handleObj,\n handlerQueue,\n args = new Array(arguments.length),\n // Make a writable jQuery.Event from the native event object\n event = jQuery.event.fix(nativeEvent),\n handlers = (dataPriv.get(this, \"events\") || Object.create(null))[event.type] || [],\n special = jQuery.event.special[event.type] || {}; // Use the fix-ed jQuery.Event rather than the (read-only) native event\n\n args[0] = event;\n\n for (i = 1; i < arguments.length; i++) {\n args[i] = arguments[i];\n }\n\n event.delegateTarget = this; // Call the preDispatch hook for the mapped type, and let it bail if desired\n\n if (special.preDispatch && special.preDispatch.call(this, event) === false) {\n return;\n } // Determine handlers\n\n\n handlerQueue = jQuery.event.handlers.call(this, event, handlers); // Run delegates first; they may want to stop propagation beneath us\n\n i = 0;\n\n while ((matched = handlerQueue[i++]) && !event.isPropagationStopped()) {\n event.currentTarget = matched.elem;\n j = 0;\n\n while ((handleObj = matched.handlers[j++]) && !event.isImmediatePropagationStopped()) {\n // If the event is namespaced, then each handler is only invoked if it is\n // specially universal or its namespaces are a superset of the event's.\n if (!event.rnamespace || handleObj.namespace === false || event.rnamespace.test(handleObj.namespace)) {\n event.handleObj = handleObj;\n event.data = handleObj.data;\n ret = ((jQuery.event.special[handleObj.origType] || {}).handle || handleObj.handler).apply(matched.elem, args);\n\n if (ret !== undefined) {\n if ((event.result = ret) === false) {\n event.preventDefault();\n event.stopPropagation();\n }\n }\n }\n }\n } // Call the postDispatch hook for the mapped type\n\n\n if (special.postDispatch) {\n special.postDispatch.call(this, event);\n }\n\n return event.result;\n },\n handlers: function handlers(event, _handlers) {\n var i,\n handleObj,\n sel,\n matchedHandlers,\n matchedSelectors,\n handlerQueue = [],\n delegateCount = _handlers.delegateCount,\n cur = event.target; // Find delegate handlers\n\n if (delegateCount && // Support: IE <=9\n // Black-hole SVG instance trees (trac-13180)\n cur.nodeType && // Support: Firefox <=42\n // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861)\n // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click\n // Support: IE 11 only\n // ...but not arrow key \"clicks\" of radio inputs, which can have `button` -1 (gh-2343)\n !(event.type === \"click\" && event.button >= 1)) {\n for (; cur !== this; cur = cur.parentNode || this) {\n // Don't check non-elements (#13208)\n // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)\n if (cur.nodeType === 1 && !(event.type === \"click\" && cur.disabled === true)) {\n matchedHandlers = [];\n matchedSelectors = {};\n\n for (i = 0; i < delegateCount; i++) {\n handleObj = _handlers[i]; // Don't conflict with Object.prototype properties (#13203)\n\n sel = handleObj.selector + \" \";\n\n if (matchedSelectors[sel] === undefined) {\n matchedSelectors[sel] = handleObj.needsContext ? jQuery(sel, this).index(cur) > -1 : jQuery.find(sel, this, null, [cur]).length;\n }\n\n if (matchedSelectors[sel]) {\n matchedHandlers.push(handleObj);\n }\n }\n\n if (matchedHandlers.length) {\n handlerQueue.push({\n elem: cur,\n handlers: matchedHandlers\n });\n }\n }\n }\n } // Add the remaining (directly-bound) handlers\n\n\n cur = this;\n\n if (delegateCount < _handlers.length) {\n handlerQueue.push({\n elem: cur,\n handlers: _handlers.slice(delegateCount)\n });\n }\n\n return handlerQueue;\n },\n addProp: function addProp(name, hook) {\n Object.defineProperty(jQuery.Event.prototype, name, {\n enumerable: true,\n configurable: true,\n get: isFunction(hook) ? function () {\n if (this.originalEvent) {\n return hook(this.originalEvent);\n }\n } : function () {\n if (this.originalEvent) {\n return this.originalEvent[name];\n }\n },\n set: function set(value) {\n Object.defineProperty(this, name, {\n enumerable: true,\n configurable: true,\n writable: true,\n value: value\n });\n }\n });\n },\n fix: function fix(originalEvent) {\n return originalEvent[jQuery.expando] ? originalEvent : new jQuery.Event(originalEvent);\n },\n special: {\n load: {\n // Prevent triggered image.load events from bubbling to window.load\n noBubble: true\n },\n click: {\n // Utilize native event to ensure correct state for checkable inputs\n setup: function setup(data) {\n // For mutual compressibility with _default, replace `this` access with a local var.\n // `|| data` is dead code meant only to preserve the variable through minification.\n var el = this || data; // Claim the first handler\n\n if (rcheckableType.test(el.type) && el.click && nodeName(el, \"input\")) {\n // dataPriv.set( el, \"click\", ... )\n leverageNative(el, \"click\", returnTrue);\n } // Return false to allow normal processing in the caller\n\n\n return false;\n },\n trigger: function trigger(data) {\n // For mutual compressibility with _default, replace `this` access with a local var.\n // `|| data` is dead code meant only to preserve the variable through minification.\n var el = this || data; // Force setup before triggering a click\n\n if (rcheckableType.test(el.type) && el.click && nodeName(el, \"input\")) {\n leverageNative(el, \"click\");\n } // Return non-false to allow normal event-path propagation\n\n\n return true;\n },\n // For cross-browser consistency, suppress native .click() on links\n // Also prevent it if we're currently inside a leveraged native-event stack\n _default: function _default(event) {\n var target = event.target;\n return rcheckableType.test(target.type) && target.click && nodeName(target, \"input\") && dataPriv.get(target, \"click\") || nodeName(target, \"a\");\n }\n },\n beforeunload: {\n postDispatch: function postDispatch(event) {\n // Support: Firefox 20+\n // Firefox doesn't alert if the returnValue field is not set.\n if (event.result !== undefined && event.originalEvent) {\n event.originalEvent.returnValue = event.result;\n }\n }\n }\n }\n }; // Ensure the presence of an event listener that handles manually-triggered\n // synthetic events by interrupting progress until reinvoked in response to\n // *native* events that it fires directly, ensuring that state changes have\n // already occurred before other listeners are invoked.\n\n function leverageNative(el, type, expectSync) {\n // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add\n if (!expectSync) {\n if (dataPriv.get(el, type) === undefined) {\n jQuery.event.add(el, type, returnTrue);\n }\n\n return;\n } // Register the controller as a special universal handler for all event namespaces\n\n\n dataPriv.set(el, type, false);\n jQuery.event.add(el, type, {\n namespace: false,\n handler: function handler(event) {\n var notAsync,\n result,\n saved = dataPriv.get(this, type);\n\n if (event.isTrigger & 1 && this[type]) {\n // Interrupt processing of the outer synthetic .trigger()ed event\n // Saved data should be false in such cases, but might be a leftover capture object\n // from an async native handler (gh-4350)\n if (!saved.length) {\n // Store arguments for use when handling the inner native event\n // There will always be at least one argument (an event object), so this array\n // will not be confused with a leftover capture object.\n saved = _slice.call(arguments);\n dataPriv.set(this, type, saved); // Trigger the native event and capture its result\n // Support: IE <=9 - 11+\n // focus() and blur() are asynchronous\n\n notAsync = expectSync(this, type);\n this[type]();\n result = dataPriv.get(this, type);\n\n if (saved !== result || notAsync) {\n dataPriv.set(this, type, false);\n } else {\n result = {};\n }\n\n if (saved !== result) {\n // Cancel the outer synthetic event\n event.stopImmediatePropagation();\n event.preventDefault(); // Support: Chrome 86+\n // In Chrome, if an element having a focusout handler is blurred by\n // clicking outside of it, it invokes the handler synchronously. If\n // that handler calls `.remove()` on the element, the data is cleared,\n // leaving `result` undefined. We need to guard against this.\n\n return result && result.value;\n } // If this is an inner synthetic event for an event with a bubbling surrogate\n // (focus or blur), assume that the surrogate already propagated from triggering the\n // native event and prevent that from happening again here.\n // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the\n // bubbling surrogate propagates *after* the non-bubbling base), but that seems\n // less bad than duplication.\n\n } else if ((jQuery.event.special[type] || {}).delegateType) {\n event.stopPropagation();\n } // If this is a native event triggered above, everything is now in order\n // Fire an inner synthetic event with the original arguments\n\n } else if (saved.length) {\n // ...and capture the result\n dataPriv.set(this, type, {\n value: jQuery.event.trigger( // Support: IE <=9 - 11+\n // Extend with the prototype to reset the above stopImmediatePropagation()\n jQuery.extend(saved[0], jQuery.Event.prototype), saved.slice(1), this)\n }); // Abort handling of the native event\n\n event.stopImmediatePropagation();\n }\n }\n });\n }\n\n jQuery.removeEvent = function (elem, type, handle) {\n // This \"if\" is needed for plain objects\n if (elem.removeEventListener) {\n elem.removeEventListener(type, handle);\n }\n };\n\n jQuery.Event = function (src, props) {\n // Allow instantiation without the 'new' keyword\n if (!(this instanceof jQuery.Event)) {\n return new jQuery.Event(src, props);\n } // Event object\n\n\n if (src && src.type) {\n this.originalEvent = src;\n this.type = src.type; // Events bubbling up the document may have been marked as prevented\n // by a handler lower down the tree; reflect the correct value.\n\n this.isDefaultPrevented = src.defaultPrevented || src.defaultPrevented === undefined && // Support: Android <=2.3 only\n src.returnValue === false ? returnTrue : returnFalse; // Create target properties\n // Support: Safari <=6 - 7 only\n // Target should not be a text node (#504, #13143)\n\n this.target = src.target && src.target.nodeType === 3 ? src.target.parentNode : src.target;\n this.currentTarget = src.currentTarget;\n this.relatedTarget = src.relatedTarget; // Event type\n } else {\n this.type = src;\n } // Put explicitly provided properties onto the event object\n\n\n if (props) {\n jQuery.extend(this, props);\n } // Create a timestamp if incoming event doesn't have one\n\n\n this.timeStamp = src && src.timeStamp || Date.now(); // Mark it as fixed\n\n this[jQuery.expando] = true;\n }; // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n // https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\n\n\n jQuery.Event.prototype = {\n constructor: jQuery.Event,\n isDefaultPrevented: returnFalse,\n isPropagationStopped: returnFalse,\n isImmediatePropagationStopped: returnFalse,\n isSimulated: false,\n preventDefault: function preventDefault() {\n var e = this.originalEvent;\n this.isDefaultPrevented = returnTrue;\n\n if (e && !this.isSimulated) {\n e.preventDefault();\n }\n },\n stopPropagation: function stopPropagation() {\n var e = this.originalEvent;\n this.isPropagationStopped = returnTrue;\n\n if (e && !this.isSimulated) {\n e.stopPropagation();\n }\n },\n stopImmediatePropagation: function stopImmediatePropagation() {\n var e = this.originalEvent;\n this.isImmediatePropagationStopped = returnTrue;\n\n if (e && !this.isSimulated) {\n e.stopImmediatePropagation();\n }\n\n this.stopPropagation();\n }\n }; // Includes all common event props including KeyEvent and MouseEvent specific props\n\n jQuery.each({\n altKey: true,\n bubbles: true,\n cancelable: true,\n changedTouches: true,\n ctrlKey: true,\n detail: true,\n eventPhase: true,\n metaKey: true,\n pageX: true,\n pageY: true,\n shiftKey: true,\n view: true,\n \"char\": true,\n code: true,\n charCode: true,\n key: true,\n keyCode: true,\n button: true,\n buttons: true,\n clientX: true,\n clientY: true,\n offsetX: true,\n offsetY: true,\n pointerId: true,\n pointerType: true,\n screenX: true,\n screenY: true,\n targetTouches: true,\n toElement: true,\n touches: true,\n which: true\n }, jQuery.event.addProp);\n jQuery.each({\n focus: \"focusin\",\n blur: \"focusout\"\n }, function (type, delegateType) {\n jQuery.event.special[type] = {\n // Utilize native event if possible so blur/focus sequence is correct\n setup: function setup() {\n // Claim the first handler\n // dataPriv.set( this, \"focus\", ... )\n // dataPriv.set( this, \"blur\", ... )\n leverageNative(this, type, expectSync); // Return false to allow normal processing in the caller\n\n return false;\n },\n trigger: function trigger() {\n // Force setup before trigger\n leverageNative(this, type); // Return non-false to allow normal event-path propagation\n\n return true;\n },\n // Suppress native focus or blur as it's already being fired\n // in leverageNative.\n _default: function _default() {\n return true;\n },\n delegateType: delegateType\n };\n }); // Create mouseenter/leave events using mouseover/out and event-time checks\n // so that event delegation works in jQuery.\n // Do the same for pointerenter/pointerleave and pointerover/pointerout\n //\n // Support: Safari 7 only\n // Safari sends mouseenter too often; see:\n // https://bugs.chromium.org/p/chromium/issues/detail?id=470258\n // for the description of the bug (it existed in older Chrome versions as well).\n\n jQuery.each({\n mouseenter: \"mouseover\",\n mouseleave: \"mouseout\",\n pointerenter: \"pointerover\",\n pointerleave: \"pointerout\"\n }, function (orig, fix) {\n jQuery.event.special[orig] = {\n delegateType: fix,\n bindType: fix,\n handle: function handle(event) {\n var ret,\n target = this,\n related = event.relatedTarget,\n handleObj = event.handleObj; // For mouseenter/leave call the handler if related is outside the target.\n // NB: No relatedTarget if the mouse left/entered the browser window\n\n if (!related || related !== target && !jQuery.contains(target, related)) {\n event.type = handleObj.origType;\n ret = handleObj.handler.apply(this, arguments);\n event.type = fix;\n }\n\n return ret;\n }\n };\n });\n jQuery.fn.extend({\n on: function on(types, selector, data, fn) {\n return _on(this, types, selector, data, fn);\n },\n one: function one(types, selector, data, fn) {\n return _on(this, types, selector, data, fn, 1);\n },\n off: function off(types, selector, fn) {\n var handleObj, type;\n\n if (types && types.preventDefault && types.handleObj) {\n // ( event ) dispatched jQuery.Event\n handleObj = types.handleObj;\n jQuery(types.delegateTarget).off(handleObj.namespace ? handleObj.origType + \".\" + handleObj.namespace : handleObj.origType, handleObj.selector, handleObj.handler);\n return this;\n }\n\n if (_typeof(types) === \"object\") {\n // ( types-object [, selector] )\n for (type in types) {\n this.off(type, selector, types[type]);\n }\n\n return this;\n }\n\n if (selector === false || typeof selector === \"function\") {\n // ( types [, fn] )\n fn = selector;\n selector = undefined;\n }\n\n if (fn === false) {\n fn = returnFalse;\n }\n\n return this.each(function () {\n jQuery.event.remove(this, types, fn, selector);\n });\n }\n });\n var // Support: IE <=10 - 11, Edge 12 - 13 only\n // In IE/Edge using regex groups here causes severe slowdowns.\n // See https://connect.microsoft.com/IE/feedback/details/1736512/\n rnoInnerhtml = /