/*
 * ATTENTION: An "eval-source-map" devtool has been used.
 * This devtool is neither made for production nor for readable output files.
 * It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
 * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
 * or disable the default devtool with "devtool: false".
 * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
 */
/******/ (function() { // webpackBootstrap
/******/ 	var __webpack_modules__ = ({

/***/ "./libs/datatables-buttons/buttons.colVis.js":
/*!***************************************************!*\
  !*** ./libs/datatables-buttons/buttons.colVis.js ***!
  \***************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var datatables_net_buttons_js_buttons_colVis__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! datatables.net-buttons/js/buttons.colVis */ "./node_modules/datatables.net-buttons/js/buttons.colVis.js");
/* harmony import */ var datatables_net_buttons_js_buttons_colVis__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(datatables_net_buttons_js_buttons_colVis__WEBPACK_IMPORTED_MODULE_0__);


/***/ }),

/***/ "./node_modules/datatables.net-buttons/js/buttons.colVis.js":
/*!******************************************************************!*\
  !*** ./node_modules/datatables.net-buttons/js/buttons.colVis.js ***!
  \******************************************************************/
/***/ (function(module, exports, __webpack_require__) {

eval("var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!\n * Column visibility buttons for Buttons and DataTables.\n * 2016 SpryMedia Ltd - datatables.net/license\n */\n\n(function( factory ){\n\tif ( true ) {\n\t\t// AMD\n\t\t!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! jquery */ \"jquery\"), __webpack_require__(/*! datatables.net */ \"datatables.net\"), __webpack_require__(/*! datatables.net-buttons */ \"./node_modules/datatables.net-buttons/js/dataTables.buttons.js\")], __WEBPACK_AMD_DEFINE_RESULT__ = (function ( $ ) {\n\t\t\treturn factory( $, window, document );\n\t\t}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),\n\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n\t}\n\telse {}\n}(function( $, window, document, undefined ) {\n'use strict';\nvar DataTable = $.fn.dataTable;\n\n\n$.extend( DataTable.ext.buttons, {\n\t// A collection of column visibility buttons\n\tcolvis: function ( dt, conf ) {\n\t\tvar node = null;\n\t\tvar buttonConf = {\n\t\t\textend: 'collection',\n\t\t\tinit: function ( dt, n ) {\n\t\t\t\tnode = n;\n\t\t\t},\n\t\t\ttext: function ( dt ) {\n\t\t\t\treturn dt.i18n( 'buttons.colvis', 'Column visibility' );\n\t\t\t},\n\t\t\tclassName: 'buttons-colvis',\n\t\t\tcloseButton: false,\n\t\t\tbuttons: [ {\n\t\t\t\textend: 'columnsToggle',\n\t\t\t\tcolumns: conf.columns,\n\t\t\t\tcolumnText: conf.columnText\n\t\t\t} ]\n\t\t};\n\n\t\t// Rebuild the collection with the new column structure if columns are reordered\n\t\tdt.on( 'column-reorder.dt'+conf.namespace, function (e, settings, details) {\n\t\t\t// console.log(node);\n\t\t\t// console.log('node', dt.button(null, node).node());\n\t\t\tdt.button(null, dt.button(null, node).node()).collectionRebuild([{\n\t\t\t\textend: 'columnsToggle',\n\t\t\t\tcolumns: conf.columns,\n\t\t\t\tcolumnText: conf.columnText\n\t\t\t}]);\n\t\t});\n\n\t\treturn buttonConf;\n\t},\n\n\t// Selected columns with individual buttons - toggle column visibility\n\tcolumnsToggle: function ( dt, conf ) {\n\t\tvar columns = dt.columns( conf.columns ).indexes().map( function ( idx ) {\n\t\t\treturn {\n\t\t\t\textend: 'columnToggle',\n\t\t\t\tcolumns: idx,\n\t\t\t\tcolumnText: conf.columnText\n\t\t\t};\n\t\t} ).toArray();\n\n\t\treturn columns;\n\t},\n\n\t// Single button to toggle column visibility\n\tcolumnToggle: function ( dt, conf ) {\n\t\treturn {\n\t\t\textend: 'columnVisibility',\n\t\t\tcolumns: conf.columns,\n\t\t\tcolumnText: conf.columnText\n\t\t};\n\t},\n\n\t// Selected columns with individual buttons - set column visibility\n\tcolumnsVisibility: function ( dt, conf ) {\n\t\tvar columns = dt.columns( conf.columns ).indexes().map( function ( idx ) {\n\t\t\treturn {\n\t\t\t\textend: 'columnVisibility',\n\t\t\t\tcolumns: idx,\n\t\t\t\tvisibility: conf.visibility,\n\t\t\t\tcolumnText: conf.columnText\n\t\t\t};\n\t\t} ).toArray();\n\n\t\treturn columns;\n\t},\n\n\t// Single button to set column visibility\n\tcolumnVisibility: {\n\t\tcolumns: undefined, // column selector\n\t\ttext: function ( dt, button, conf ) {\n\t\t\treturn conf._columnText( dt, conf );\n\t\t},\n\t\tclassName: 'buttons-columnVisibility',\n\t\taction: function ( e, dt, button, conf ) {\n\t\t\tvar col = dt.columns( conf.columns );\n\t\t\tvar curr = col.visible();\n\n\t\t\tcol.visible( conf.visibility !== undefined ?\n\t\t\t\tconf.visibility :\n\t\t\t\t! (curr.length ? curr[0] : false )\n\t\t\t);\n\t\t},\n\t\tinit: function ( dt, button, conf ) {\n\t\t\tvar that = this;\n\t\t\tbutton.attr( 'data-cv-idx', conf.columns );\n\n\t\t\tdt\n\t\t\t\t.on( 'column-visibility.dt'+conf.namespace, function (e, settings) {\n\t\t\t\t\tif ( ! settings.bDestroying && settings.nTable == dt.settings()[0].nTable ) {\n\t\t\t\t\t\tthat.active( dt.column( conf.columns ).visible() );\n\t\t\t\t\t}\n\t\t\t\t} )\n\t\t\t\t.on( 'column-reorder.dt'+conf.namespace, function (e, settings, details) {\n\t\t\t\t\t// Button has been removed from the DOM\n\t\t\t\t\tif ( conf.destroying ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( dt.columns( conf.columns ).count() !== 1 ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t// This button controls the same column index but the text for the column has\n\t\t\t\t\t// changed\n\t\t\t\t\tthat.text( conf._columnText( dt, conf ) );\n\n\t\t\t\t\t// Since its a different column, we need to check its visibility\n\t\t\t\t\tthat.active( dt.column( conf.columns ).visible() );\n\t\t\t\t} );\n\n\t\t\tthis.active( dt.column( conf.columns ).visible() );\n\t\t},\n\t\tdestroy: function ( dt, button, conf ) {\n\t\t\tdt\n\t\t\t\t.off( 'column-visibility.dt'+conf.namespace )\n\t\t\t\t.off( 'column-reorder.dt'+conf.namespace );\n\t\t},\n\n\t\t_columnText: function ( dt, conf ) {\n\t\t\t// Use DataTables' internal data structure until this is presented\n\t\t\t// is a public API. The other option is to use\n\t\t\t// `$( column(col).node() ).text()` but the node might not have been\n\t\t\t// populated when Buttons is constructed.\n\t\t\tvar idx = dt.column( conf.columns ).index();\n\t\t\tvar title = dt.settings()[0].aoColumns[ idx ].sTitle;\n\n\t\t\tif (! title) {\n\t\t\t\ttitle = dt.column(idx).header().innerHTML;\n\t\t\t}\n\n\t\t\ttitle = title\n\t\t\t\t.replace(/\\n/g,\" \")        // remove new lines\n\t\t\t\t.replace(/<br\\s*\\/?>/gi, \" \")  // replace line breaks with spaces\n\t\t\t\t.replace(/<select(.*?)<\\/select>/g, \"\") // remove select tags, including options text\n\t\t\t\t.replace(/<!\\-\\-.*?\\-\\->/g, \"\") // strip HTML comments\n\t\t\t\t.replace(/<.*?>/g, \"\")   // strip HTML\n\t\t\t\t.replace(/^\\s+|\\s+$/g,\"\"); // trim\n\n\t\t\treturn conf.columnText ?\n\t\t\t\tconf.columnText( dt, idx, title ) :\n\t\t\t\ttitle;\n\t\t}\n\t},\n\n\n\tcolvisRestore: {\n\t\tclassName: 'buttons-colvisRestore',\n\n\t\ttext: function ( dt ) {\n\t\t\treturn dt.i18n( 'buttons.colvisRestore', 'Restore visibility' );\n\t\t},\n\n\t\tinit: function ( dt, button, conf ) {\n\t\t\tconf._visOriginal = dt.columns().indexes().map( function ( idx ) {\n\t\t\t\treturn dt.column( idx ).visible();\n\t\t\t} ).toArray();\n\t\t},\n\n\t\taction: function ( e, dt, button, conf ) {\n\t\t\tdt.columns().every( function ( i ) {\n\t\t\t\t// Take into account that ColReorder might have disrupted our\n\t\t\t\t// indexes\n\t\t\t\tvar idx = dt.colReorder && dt.colReorder.transpose ?\n\t\t\t\t\tdt.colReorder.transpose( i, 'toOriginal' ) :\n\t\t\t\t\ti;\n\n\t\t\t\tthis.visible( conf._visOriginal[ idx ] );\n\t\t\t} );\n\t\t}\n\t},\n\n\n\tcolvisGroup: {\n\t\tclassName: 'buttons-colvisGroup',\n\n\t\taction: function ( e, dt, button, conf ) {\n\t\t\tdt.columns( conf.show ).visible( true, false );\n\t\t\tdt.columns( conf.hide ).visible( false, false );\n\n\t\t\tdt.columns.adjust();\n\t\t},\n\n\t\tshow: [],\n\n\t\thide: []\n\t}\n} );\n\n\nreturn DataTable.Buttons;\n}));\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,[encoded data, 11112 characters]\n//# sourceURL=webpack-internal:///./node_modules/datatables.net-buttons/js/buttons.colVis.js\n");

/***/ }),

/***/ "./node_modules/datatables.net-buttons/js/dataTables.buttons.js":
/*!**********************************************************************!*\
  !*** ./node_modules/datatables.net-buttons/js/dataTables.buttons.js ***!
  \**********************************************************************/
/***/ (function(module, exports, __webpack_require__) {

eval("var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*! Buttons for DataTables 2.2.3\n * ©2016-2022 SpryMedia Ltd - datatables.net/license\n */\n\n(function( factory ){\n\tif ( true ) {\n\t\t// AMD\n\t\t!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! jquery */ \"jquery\"), __webpack_require__(/*! datatables.net */ \"datatables.net\")], __WEBPACK_AMD_DEFINE_RESULT__ = (function ( $ ) {\n\t\t\treturn factory( $, window, document );\n\t\t}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),\n\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n\t}\n\telse {}\n}(function( $, window, document, undefined ) {\n'use strict';\nvar DataTable = $.fn.dataTable;\n\n\n// Used for namespacing events added to the document by each instance, so they\n// can be removed on destroy\nvar _instCounter = 0;\n\n// Button namespacing counter for namespacing events on individual buttons\nvar _buttonCounter = 0;\n\nvar _dtButtons = DataTable.ext.buttons;\n\n// Allow for jQuery slim\nfunction _fadeIn(el, duration, fn) {\n\tif ($.fn.animate) {\n\t\tel\n\t\t\t.stop()\n\t\t\t.fadeIn( duration, fn );\n\n\t}\n\telse {\n\t\tel.css('display', 'block');\n\n\t\tif (fn) {\n\t\t\tfn.call(el);\n\t\t}\n\t}\n}\n\nfunction _fadeOut(el, duration, fn) {\n\tif ($.fn.animate) {\n\t\tel\n\t\t\t.stop()\n\t\t\t.fadeOut( duration, fn );\n\t}\n\telse {\n\t\tel.css('display', 'none');\n\t\t\n\t\tif (fn) {\n\t\t\tfn.call(el);\n\t\t}\n\t}\n}\n\n/**\n * [Buttons description]\n * @param {[type]}\n * @param {[type]}\n */\nvar Buttons = function( dt, config )\n{\n\t// If not created with a `new` keyword then we return a wrapper function that\n\t// will take the settings object for a DT. This allows easy use of new instances\n\t// with the `layout` option - e.g. `topLeft: $.fn.dataTable.Buttons( ... )`.\n\tif ( !(this instanceof Buttons) ) {\n\t\treturn function (settings) {\n\t\t\treturn new Buttons( settings, dt ).container();\n\t\t};\n\t}\n\n\t// If there is no config set it to an empty object\n\tif ( typeof( config ) === 'undefined' ) {\n\t\tconfig = {};\t\n\t}\n\t\n\t// Allow a boolean true for defaults\n\tif ( config === true ) {\n\t\tconfig = {};\n\t}\n\n\t// For easy configuration of buttons an array can be given\n\tif ( Array.isArray( config ) ) {\n\t\tconfig = { buttons: config };\n\t}\n\n\tthis.c = $.extend( true, {}, Buttons.defaults, config );\n\n\t// Don't want a deep copy for the buttons\n\tif ( config.buttons ) {\n\t\tthis.c.buttons = config.buttons;\n\t}\n\n\tthis.s = {\n\t\tdt: new DataTable.Api( dt ),\n\t\tbuttons: [],\n\t\tlistenKeys: '',\n\t\tnamespace: 'dtb'+(_instCounter++)\n\t};\n\n\tthis.dom = {\n\t\tcontainer: $('<'+this.c.dom.container.tag+'/>')\n\t\t\t.addClass( this.c.dom.container.className )\n\t};\n\n\tthis._constructor();\n};\n\n\n$.extend( Buttons.prototype, {\n\t/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n\t * Public methods\n\t */\n\n\t/**\n\t * Get the action of a button\n\t * @param  {int|string} Button index\n\t * @return {function}\n\t *//**\n\t * Set the action of a button\n\t * @param  {node} node Button element\n\t * @param  {function} action Function to set\n\t * @return {Buttons} Self for chaining\n\t */\n\taction: function ( node, action )\n\t{\n\t\tvar button = this._nodeToButton( node );\n\n\t\tif ( action === undefined ) {\n\t\t\treturn button.conf.action;\n\t\t}\n\n\t\tbutton.conf.action = action;\n\n\t\treturn this;\n\t},\n\n\t/**\n\t * Add an active class to the button to make to look active or get current\n\t * active state.\n\t * @param  {node} node Button element\n\t * @param  {boolean} [flag] Enable / disable flag\n\t * @return {Buttons} Self for chaining or boolean for getter\n\t */\n\tactive: function ( node, flag ) {\n\t\tvar button = this._nodeToButton( node );\n\t\tvar klass = this.c.dom.button.active;\n\t\tvar jqNode = $(button.node);\n\n\t\tif ( flag === undefined ) {\n\t\t\treturn jqNode.hasClass( klass );\n\t\t}\n\n\t\tjqNode.toggleClass( klass, flag === undefined ? true : flag );\n\n\t\treturn this;\n\t},\n\n\t/**\n\t * Add a new button\n\t * @param {object} config Button configuration object, base string name or function\n\t * @param {int|string} [idx] Button index for where to insert the button\n\t * @param {boolean} [draw=true] Trigger a draw. Set a false when adding\n\t *   lots of buttons, until the last button.\n\t * @return {Buttons} Self for chaining\n\t */\n\tadd: function ( config, idx, draw )\n\t{\n\t\tvar buttons = this.s.buttons;\n\n\t\tif ( typeof idx === 'string' ) {\n\t\t\tvar split = idx.split('-');\n\t\t\tvar base = this.s;\n\n\t\t\tfor ( var i=0, ien=split.length-1 ; i<ien ; i++ ) {\n\t\t\t\tbase = base.buttons[ split[i]*1 ];\n\t\t\t}\n\n\t\t\tbuttons = base.buttons;\n\t\t\tidx = split[ split.length-1 ]*1;\n\t\t}\n\n\t\tthis._expandButton(\n\t\t\tbuttons,\n\t\t\tconfig,\n\t\t\tconfig !== undefined ? config.split : undefined,\n\t\t\t(config === undefined || config.split === undefined || config.split.length === 0) && base !== undefined,\n\t\t\tfalse,\n\t\t\tidx\n\t\t);\n\n\t\tif (draw === undefined || draw === true) {\n\t\t\tthis._draw();\n\t\t}\n\t\n\t\treturn this;\n\t},\n\n\t/**\n\t * Clear buttons from a collection and then insert new buttons\n\t */\n\tcollectionRebuild: function ( node, newButtons )\n\t{\n\t\tvar button = this._nodeToButton( node );\n\t\t\n\t\tif(newButtons !== undefined) {\n\t\t\tvar i;\n\t\t\t// Need to reverse the array\n\t\t\tfor (i=button.buttons.length-1; i>=0; i--) {\n\t\t\t\tthis.remove(button.buttons[i].node);\n\t\t\t}\n\t\n\t\t\tfor (i=0; i<newButtons.length; i++) {\n\t\t\t\tvar newBtn = newButtons[i];\n\n\t\t\t\tthis._expandButton(\n\t\t\t\t\tbutton.buttons,\n\t\t\t\t\tnewBtn,\n\t\t\t\t\tnewBtn !== undefined && newBtn.config !== undefined && newBtn.config.split !== undefined,\n\t\t\t\t\ttrue,\n\t\t\t\t\tnewBtn.parentConf !== undefined && newBtn.parentConf.split !== undefined,\n\t\t\t\t\ti,\n\t\t\t\t\tnewBtn.parentConf\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tthis._draw(button.collection, button.buttons);\n\t},\n\n\t/**\n\t * Get the container node for the buttons\n\t * @return {jQuery} Buttons node\n\t */\n\tcontainer: function ()\n\t{\n\t\treturn this.dom.container;\n\t},\n\n\t/**\n\t * Disable a button\n\t * @param  {node} node Button node\n\t * @return {Buttons} Self for chaining\n\t */\n\tdisable: function ( node ) {\n\t\tvar button = this._nodeToButton( node );\n\n\t\t$(button.node)\n\t\t\t.addClass( this.c.dom.button.disabled )\n\t\t\t.attr('disabled', true);\n\n\t\treturn this;\n\t},\n\n\t/**\n\t * Destroy the instance, cleaning up event handlers and removing DOM\n\t * elements\n\t * @return {Buttons} Self for chaining\n\t */\n\tdestroy: function ()\n\t{\n\t\t// Key event listener\n\t\t$('body').off( 'keyup.'+this.s.namespace );\n\n\t\t// Individual button destroy (so they can remove their own events if\n\t\t// needed). Take a copy as the array is modified by `remove`\n\t\tvar buttons = this.s.buttons.slice();\n\t\tvar i, ien;\n\t\t\n\t\tfor ( i=0, ien=buttons.length ; i<ien ; i++ ) {\n\t\t\tthis.remove( buttons[i].node );\n\t\t}\n\n\t\t// Container\n\t\tthis.dom.container.remove();\n\n\t\t// Remove from the settings object collection\n\t\tvar buttonInsts = this.s.dt.settings()[0];\n\n\t\tfor ( i=0, ien=buttonInsts.length ; i<ien ; i++ ) {\n\t\t\tif ( buttonInsts.inst === this ) {\n\t\t\t\tbuttonInsts.splice( i, 1 );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\t/**\n\t * Enable / disable a button\n\t * @param  {node} node Button node\n\t * @param  {boolean} [flag=true] Enable / disable flag\n\t * @return {Buttons} Self for chaining\n\t */\n\tenable: function ( node, flag )\n\t{\n\t\tif ( flag === false ) {\n\t\t\treturn this.disable( node );\n\t\t}\n\n\t\tvar button = this._nodeToButton( node );\n\t\t$(button.node)\n\t\t\t.removeClass( this.c.dom.button.disabled )\n\t\t\t.removeAttr('disabled');\n\n\t\treturn this;\n\t},\n\n\t/**\n\t * Get a button's index\n\t * \n\t * This is internally recursive\n\t * @param {element} node Button to get the index of\n\t * @return {string} Button index\n\t */\n\tindex: function ( node, nested, buttons )\n\t{\n\t\tif ( ! nested ) {\n\t\t\tnested = '';\n\t\t\tbuttons = this.s.buttons;\n\t\t}\n\n\t\tfor ( var i=0, ien=buttons.length ; i<ien ; i++ ) {\n\t\t\tvar inner = buttons[i].buttons;\n\n\t\t\tif (buttons[i].node === node) {\n\t\t\t\treturn nested + i;\n\t\t\t}\n\n\t\t\tif ( inner && inner.length ) {\n\t\t\t\tvar match = this.index(node, i + '-', inner);\n\n\t\t\t\tif (match !== null) {\n\t\t\t\t\treturn match;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t},\n\n\n\t/**\n\t * Get the instance name for the button set selector\n\t * @return {string} Instance name\n\t */\n\tname: function ()\n\t{\n\t\treturn this.c.name;\n\t},\n\n\t/**\n\t * Get a button's node of the buttons container if no button is given\n\t * @param  {node} [node] Button node\n\t * @return {jQuery} Button element, or container\n\t */\n\tnode: function ( node )\n\t{\n\t\tif ( ! node ) {\n\t\t\treturn this.dom.container;\n\t\t}\n\n\t\tvar button = this._nodeToButton( node );\n\t\treturn $(button.node);\n\t},\n\n\t/**\n\t * Set / get a processing class on the selected button\n\t * @param {element} node Triggering button node\n\t * @param  {boolean} flag true to add, false to remove, undefined to get\n\t * @return {boolean|Buttons} Getter value or this if a setter.\n\t */\n\tprocessing: function ( node, flag )\n\t{\n\t\tvar dt = this.s.dt;\n\t\tvar button = this._nodeToButton( node );\n\n\t\tif ( flag === undefined ) {\n\t\t\treturn $(button.node).hasClass( 'processing' );\n\t\t}\n\n\t\t$(button.node).toggleClass( 'processing', flag );\n\n\t\t$(dt.table().node()).triggerHandler( 'buttons-processing.dt', [\n\t\t\tflag, dt.button( node ), dt, $(node), button.conf\n\t\t] );\n\n\t\treturn this;\n\t},\n\n\t/**\n\t * Remove a button.\n\t * @param  {node} node Button node\n\t * @return {Buttons} Self for chaining\n\t */\n\tremove: function ( node )\n\t{\n\t\tvar button = this._nodeToButton( node );\n\t\tvar host = this._nodeToHost( node );\n\t\tvar dt = this.s.dt;\n\n\t\t// Remove any child buttons first\n\t\tif ( button.buttons.length ) {\n\t\t\tfor ( var i=button.buttons.length-1 ; i>=0 ; i-- ) {\n\t\t\t\tthis.remove( button.buttons[i].node );\n\t\t\t}\n\t\t}\n\n\t\tbutton.conf.destroying = true;\n\n\t\t// Allow the button to remove event handlers, etc\n\t\tif ( button.conf.destroy ) {\n\t\t\tbutton.conf.destroy.call( dt.button(node), dt, $(node), button.conf );\n\t\t}\n\n\t\tthis._removeKey( button.conf );\n\n\t\t$(button.node).remove();\n\n\t\tvar idx = $.inArray( button, host );\n\t\thost.splice( idx, 1 );\n\n\t\treturn this;\n\t},\n\n\t/**\n\t * Get the text for a button\n\t * @param  {int|string} node Button index\n\t * @return {string} Button text\n\t *//**\n\t * Set the text for a button\n\t * @param  {int|string|function} node Button index\n\t * @param  {string} label Text\n\t * @return {Buttons} Self for chaining\n\t */\n\ttext: function ( node, label )\n\t{\n\t\tvar button = this._nodeToButton( node );\n\t\tvar buttonLiner = this.c.dom.collection.buttonLiner;\n\t\tvar linerTag = button.inCollection && buttonLiner && buttonLiner.tag ?\n\t\t\tbuttonLiner.tag :\n\t\t\tthis.c.dom.buttonLiner.tag;\n\t\tvar dt = this.s.dt;\n\t\tvar jqNode = $(button.node);\n\t\tvar text = function ( opt ) {\n\t\t\treturn typeof opt === 'function' ?\n\t\t\t\topt( dt, jqNode, button.conf ) :\n\t\t\t\topt;\n\t\t};\n\n\t\tif ( label === undefined ) {\n\t\t\treturn text( button.conf.text );\n\t\t}\n\n\t\tbutton.conf.text = label;\n\n\t\tif ( linerTag ) {\n\t\t\tjqNode\n\t\t\t\t.children( linerTag )\n\t\t\t\t.eq(0)\n\t\t\t\t.filter(':not(.dt-down-arrow)')\n\t\t\t\t.html( text(label) );\n\t\t}\n\t\telse {\n\t\t\tjqNode.html( text(label) );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\n\t/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n\t * Constructor\n\t */\n\n\t/**\n\t * Buttons constructor\n\t * @private\n\t */\n\t_constructor: function ()\n\t{\n\t\tvar that = this;\n\t\tvar dt = this.s.dt;\n\t\tvar dtSettings = dt.settings()[0];\n\t\tvar buttons =  this.c.buttons;\n\n\t\tif ( ! dtSettings._buttons ) {\n\t\t\tdtSettings._buttons = [];\n\t\t}\n\n\t\tdtSettings._buttons.push( {\n\t\t\tinst: this,\n\t\t\tname: this.c.name\n\t\t} );\n\n\t\tfor ( var i=0, ien=buttons.length ; i<ien ; i++ ) {\n\t\t\tthis.add( buttons[i] );\n\t\t}\n\n\t\tdt.on( 'destroy', function ( e, settings ) {\n\t\t\tif ( settings === dtSettings ) {\n\t\t\t\tthat.destroy();\n\t\t\t}\n\t\t} );\n\n\t\t// Global key event binding to listen for button keys\n\t\t$('body').on( 'keyup.'+this.s.namespace, function ( e ) {\n\t\t\tif ( ! document.activeElement || document.activeElement === document.body ) {\n\t\t\t\t// SUse a string of characters for fast lookup of if we need to\n\t\t\t\t// handle this\n\t\t\t\tvar character = String.fromCharCode(e.keyCode).toLowerCase();\n\n\t\t\t\tif ( that.s.listenKeys.toLowerCase().indexOf( character ) !== -1 ) {\n\t\t\t\t\tthat._keypress( character, e );\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t},\n\n\n\t/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n\t * Private methods\n\t */\n\n\t/**\n\t * Add a new button to the key press listener\n\t * @param {object} conf Resolved button configuration object\n\t * @private\n\t */\n\t_addKey: function ( conf )\n\t{\n\t\tif ( conf.key ) {\n\t\t\tthis.s.listenKeys += $.isPlainObject( conf.key ) ?\n\t\t\t\tconf.key.key :\n\t\t\t\tconf.key;\n\t\t}\n\t},\n\n\t/**\n\t * Insert the buttons into the container. Call without parameters!\n\t * @param  {node} [container] Recursive only - Insert point\n\t * @param  {array} [buttons] Recursive only - Buttons array\n\t * @private\n\t */\n\t_draw: function ( container, buttons )\n\t{\n\t\tif ( ! container ) {\n\t\t\tcontainer = this.dom.container;\n\t\t\tbuttons = this.s.buttons;\n\t\t}\n\n\t\tcontainer.children().detach();\n\n\t\tfor ( var i=0, ien=buttons.length ; i<ien ; i++ ) {\n\t\t\tcontainer.append( buttons[i].inserter );\n\t\t\tcontainer.append( ' ' );\n\n\t\t\tif ( buttons[i].buttons && buttons[i].buttons.length ) {\n\t\t\t\tthis._draw( buttons[i].collection, buttons[i].buttons );\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Create buttons from an array of buttons\n\t * @param  {array} attachTo Buttons array to attach to\n\t * @param  {object} button Button definition\n\t * @param  {boolean} inCollection true if the button is in a collection\n\t * @private\n\t */\n\t_expandButton: function ( attachTo, button, split, inCollection, inSplit, attachPoint, parentConf )\n\t{\n\t\tvar dt = this.s.dt;\n\t\tvar buttonCounter = 0;\n\t\tvar isSplit = false;\n\t\tvar buttons = ! Array.isArray( button ) ?\n\t\t\t[ button ] :\n\t\t\tbutton;\n\t\t\n\t\tif(button === undefined ) {\n\t\t\tbuttons = !Array.isArray(split) ?\n\t\t\t\t[ split ] :\n\t\t\t\tsplit;\n\t\t}\n\n\t\tif (button !== undefined && button.split !== undefined) {\n\t\t\tisSplit = true;\n\t\t}\n\t\t\t\n\t\tfor ( var i=0, ien=buttons.length ; i<ien ; i++ ) {\n\t\t\tvar conf = this._resolveExtends( buttons[i] );\n\n\t\t\tif ( ! conf ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif( conf.config !== undefined && conf.config.split) {\n\t\t\t\tisSplit = true;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tisSplit = false;\n\t\t\t}\n\t\t\t\n\t\t\t// If the configuration is an array, then expand the buttons at this\n\t\t\t// point\n\t\t\tif ( Array.isArray( conf ) ) {\n\t\t\t\tthis._expandButton( attachTo, conf, built !== undefined && built.conf !== undefined ? built.conf.split : undefined, inCollection, parentConf !== undefined && parentConf.split !== undefined, attachPoint, parentConf );\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tvar built = this._buildButton( conf, inCollection, conf.split !== undefined || (conf.config !== undefined && conf.config.split !== undefined), inSplit );\n\t\t\tif ( ! built ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif ( attachPoint !== undefined && attachPoint !== null ) {\n\t\t\t\tattachTo.splice( attachPoint, 0, built );\n\t\t\t\tattachPoint++;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tattachTo.push( built );\n\t\t\t}\n\n\t\t\t\n\t\t\tif ( built.conf.buttons || built.conf.split ) {\n\t\t\t\tbuilt.collection = $('<'+(isSplit ? this.c.dom.splitCollection.tag : this.c.dom.collection.tag)+'/>');\n\n\t\t\t\tbuilt.conf._collection = built.collection;\n\n\t\t\t\tif(built.conf.split) {\n\t\t\t\t\tfor(var j = 0; j < built.conf.split.length; j++) {\n\t\t\t\t\t\tif(typeof built.conf.split[j] === \"object\") {\n\t\t\t\t\t\t\tbuilt.conf.split[j].parent = parentConf;\n\t\t\t\t\t\t\tif(built.conf.split[j].collectionLayout === undefined) {\n\t\t\t\t\t\t\t\tbuilt.conf.split[j].collectionLayout = built.conf.collectionLayout;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif(built.conf.split[j].dropup === undefined) {\n\t\t\t\t\t\t\t\tbuilt.conf.split[j].dropup = built.conf.dropup;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif(built.conf.split[j].fade === undefined) {\n\t\t\t\t\t\t\t\tbuilt.conf.split[j].fade = built.conf.fade;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t$(built.node).append($('<span class=\"dt-down-arrow\">'+this.c.dom.splitDropdown.text+'</span>'))\n\t\t\t\t}\n\n\t\t\t\tthis._expandButton( built.buttons, built.conf.buttons, built.conf.split, !isSplit, isSplit, attachPoint, built.conf );\n\t\t\t}\n\t\t\tbuilt.conf.parent = parentConf;\n\n\t\t\t// init call is made here, rather than buildButton as it needs to\n\t\t\t// be selectable, and for that it needs to be in the buttons array\n\t\t\tif ( conf.init ) {\n\t\t\t\tconf.init.call( dt.button( built.node ), dt, $(built.node), conf );\n\t\t\t}\n\n\t\t\tbuttonCounter++;\n\t\t}\n\t},\n\n\t/**\n\t * Create an individual button\n\t * @param  {object} config            Resolved button configuration\n\t * @param  {boolean} inCollection `true` if a collection button\n\t * @return {jQuery} Created button node (jQuery)\n\t * @private\n\t */\n\t_buildButton: function ( config, inCollection, isSplit, inSplit )\n\t{\n\t\tvar buttonDom = this.c.dom.button;\n\t\tvar linerDom = this.c.dom.buttonLiner;\n\t\tvar collectionDom = this.c.dom.collection;\n\t\tvar splitDom = this.c.dom.split;\n\t\tvar splitCollectionDom = this.c.dom.splitCollection;\n\t\tvar splitDropdownButton = this.c.dom.splitDropdownButton;\n\t\tvar dt = this.s.dt;\n\t\tvar text = function ( opt ) {\n\t\t\treturn typeof opt === 'function' ?\n\t\t\t\topt( dt, button, config ) :\n\t\t\t\topt;\n\t\t};\n\n\t\t// Spacers don't do much other than insert an element into the DOM\n\t\tif (config.spacer) {\n\t\t\tvar spacer = $('<span></span>')\n\t\t\t\t.addClass('dt-button-spacer ' + config.style + ' ' + buttonDom.spacerClass)\n\t\t\t\t.html(text(config.text));\n\n\t\t\treturn {\n\t\t\t\tconf:         config,\n\t\t\t\tnode:         spacer,\n\t\t\t\tinserter:     spacer,\n\t\t\t\tbuttons:      [],\n\t\t\t\tinCollection: inCollection,\n\t\t\t\tisSplit:\t  isSplit,\n\t\t\t\tinSplit:\t  inSplit,\n\t\t\t\tcollection:   null\n\t\t\t};\n\t\t}\n\n\t\tif ( !isSplit && inSplit && splitCollectionDom ) {\n\t\t\tbuttonDom = splitDropdownButton;\n\t\t}\n\t\telse if ( !isSplit && inCollection && collectionDom.button ) {\n\t\t\tbuttonDom = collectionDom.button;\n\t\t} \n\n\t\tif ( !isSplit && inSplit && splitCollectionDom.buttonLiner ) {\n\t\t\tlinerDom = splitCollectionDom.buttonLiner\n\t\t}\n\t\telse if ( !isSplit && inCollection && collectionDom.buttonLiner ) {\n\t\t\tlinerDom = collectionDom.buttonLiner;\n\t\t}\n\n\t\t// Make sure that the button is available based on whatever requirements\n\t\t// it has. For example, PDF button require pdfmake\n\t\tif ( config.available && ! config.available( dt, config ) && !config.hasOwnProperty('html') ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tvar button;\n\t\tif(!config.hasOwnProperty('html')) {\n\t\t\tvar action = function ( e, dt, button, config ) {\n\t\t\t\tconfig.action.call( dt.button( button ), e, dt, button, config );\n\t\n\t\t\t\t$(dt.table().node()).triggerHandler( 'buttons-action.dt', [\n\t\t\t\t\tdt.button( button ), dt, button, config \n\t\t\t\t] );\n\t\t\t};\n\n\t\t\tvar tag = config.tag || buttonDom.tag;\n\t\t\tvar clickBlurs = config.clickBlurs === undefined\n\t\t\t\t? true :\n\t\t\t\tconfig.clickBlurs;\n\n\t\t\tbutton = $('<'+tag+'/>')\n\t\t\t\t.addClass( buttonDom.className )\n\t\t\t\t.addClass( inSplit ? this.c.dom.splitDropdownButton.className : '')\n\t\t\t\t.attr( 'tabindex', this.s.dt.settings()[0].iTabIndex )\n\t\t\t\t.attr( 'aria-controls', this.s.dt.table().node().id )\n\t\t\t\t.on( 'click.dtb', function (e) {\n\t\t\t\t\te.preventDefault();\n\t\n\t\t\t\t\tif ( ! button.hasClass( buttonDom.disabled ) && config.action ) {\n\t\t\t\t\t\taction( e, dt, button, config );\n\t\t\t\t\t}\n\t\t\t\t\tif( clickBlurs ) {\n\t\t\t\t\t\tbutton.trigger('blur');\n\t\t\t\t\t}\n\t\t\t\t} )\n\t\t\t\t.on( 'keypress.dtb', function (e) {\n\t\t\t\t\tif ( e.keyCode === 13 ) {\n\t\t\t\t\t\te.preventDefault();\n\n\t\t\t\t\t\tif ( ! button.hasClass( buttonDom.disabled ) && config.action ) {\n\t\t\t\t\t\t\taction( e, dt, button, config );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\n\t\t\t// Make `a` tags act like a link\n\t\t\tif ( tag.toLowerCase() === 'a' ) {\n\t\t\t\tbutton.attr( 'href', '#' );\n\t\t\t}\n\t\n\t\t\t// Button tags should have `type=button` so they don't have any default behaviour\n\t\t\tif ( tag.toLowerCase() === 'button' ) {\n\t\t\t\tbutton.attr( 'type', 'button' );\n\t\t\t}\n\t\n\t\t\tif ( linerDom.tag ) {\n\t\t\t\tvar liner = $('<'+linerDom.tag+'/>')\n\t\t\t\t\t.html( text( config.text ) )\n\t\t\t\t\t.addClass( linerDom.className );\n\t\n\t\t\t\tif ( linerDom.tag.toLowerCase() === 'a' ) {\n\t\t\t\t\tliner.attr( 'href', '#' );\n\t\t\t\t}\n\t\n\t\t\t\tbutton.append( liner );\n\t\t\t}\n\t\t\telse {\n\t\t\t\tbutton.html( text( config.text ) );\n\t\t\t}\n\t\n\t\t\tif ( config.enabled === false ) {\n\t\t\t\tbutton.addClass( buttonDom.disabled );\n\t\t\t}\n\t\n\t\t\tif ( config.className ) {\n\t\t\t\tbutton.addClass( config.className );\n\t\t\t}\n\t\n\t\t\tif ( config.titleAttr ) {\n\t\t\t\tbutton.attr( 'title', text( config.titleAttr ) );\n\t\t\t}\n\t\n\t\t\tif ( config.attr ) {\n\t\t\t\tbutton.attr( config.attr );\n\t\t\t}\n\t\n\t\t\tif ( ! config.namespace ) {\n\t\t\t\tconfig.namespace = '.dt-button-'+(_buttonCounter++);\n\t\t\t}\n\n\t\t\tif  ( config.config !== undefined && config.config.split ) {\n\t\t\t\tconfig.split = config.config.split;\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tbutton = $(config.html)\n\t\t}\n\t\n\t\tvar buttonContainer = this.c.dom.buttonContainer;\n\t\tvar inserter;\n\t\tif ( buttonContainer && buttonContainer.tag ) {\n\t\t\tinserter = $('<'+buttonContainer.tag+'/>')\n\t\t\t\t.addClass( buttonContainer.className )\n\t\t\t\t.append( button );\n\t\t}\n\t\telse {\n\t\t\tinserter = button;\n\t\t}\n\n\t\tthis._addKey( config );\n\n\t\t// Style integration callback for DOM manipulation\n\t\t// Note that this is _not_ documented. It is currently\n\t\t// for style integration only\n\t\tif( this.c.buttonCreated ) {\n\t\t\tinserter = this.c.buttonCreated( config, inserter );\n\t\t}\n\n\t\tvar splitDiv;\n\t\tif(isSplit) {\n\t\t\tsplitDiv = $('<div/>').addClass(this.c.dom.splitWrapper.className)\n\t\t\tsplitDiv.append(button);\n\t\t\tvar dropButtonConfig = $.extend(config, {\n\t\t\t\ttext: this.c.dom.splitDropdown.text,\n\t\t\t\tclassName: this.c.dom.splitDropdown.className,\n\t\t\t\tcloseButton: false,\n\t\t\t\tattr: {\n\t\t\t\t\t'aria-haspopup': 'dialog',\n\t\t\t\t\t'aria-expanded': false\n\t\t\t\t},\n\t\t\t\talign: this.c.dom.splitDropdown.align,\n\t\t\t\tsplitAlignClass: this.c.dom.splitDropdown.splitAlignClass\n\t\t\t\t\n\t\t\t})\n\n\t\t\tthis._addKey(dropButtonConfig);\n\n\t\t\tvar splitAction = function ( e, dt, button, config ) {\n\t\t\t\t_dtButtons.split.action.call( dt.button($('div.dt-btn-split-wrapper')[0] ), e, dt, button, config );\n\t\n\t\t\t\t$(dt.table().node()).triggerHandler( 'buttons-action.dt', [\n\t\t\t\t\tdt.button( button ), dt, button, config \n\t\t\t\t] );\n\t\t\t\tbutton.attr('aria-expanded', true)\n\t\t\t};\n\t\t\t\n\t\t\tvar dropButton = $('<button class=\"' + this.c.dom.splitDropdown.className + ' dt-button\"><span class=\"dt-btn-split-drop-arrow\">'+this.c.dom.splitDropdown.text+'</span></button>')\n\t\t\t\t.on( 'click.dtb', function (e) {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\te.stopPropagation();\n\n\t\t\t\t\tif ( ! dropButton.hasClass( buttonDom.disabled )) {\n\t\t\t\t\t\tsplitAction( e, dt, dropButton, dropButtonConfig );\n\t\t\t\t\t}\n\t\t\t\t\tif ( clickBlurs ) {\n\t\t\t\t\t\tdropButton.trigger('blur');\n\t\t\t\t\t}\n\t\t\t\t} )\n\t\t\t\t.on( 'keypress.dtb', function (e) {\n\t\t\t\t\tif ( e.keyCode === 13 ) {\n\t\t\t\t\t\te.preventDefault();\n\n\t\t\t\t\t\tif ( ! dropButton.hasClass( buttonDom.disabled ) ) {\n\t\t\t\t\t\t\tsplitAction( e, dt, dropButton, dropButtonConfig );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} );\n\n\t\t\tif(config.split.length === 0) {\n\t\t\t\tdropButton.addClass('dtb-hide-drop');\n\t\t\t}\n\n\t\t\tsplitDiv.append(dropButton).attr(dropButtonConfig.attr);\n\t\t}\n\n\t\treturn {\n\t\t\tconf:         config,\n\t\t\tnode:         isSplit ? splitDiv.get(0) : button.get(0),\n\t\t\tinserter:     isSplit ? splitDiv : inserter,\n\t\t\tbuttons:      [],\n\t\t\tinCollection: inCollection,\n\t\t\tisSplit:\t  isSplit,\n\t\t\tinSplit:\t  inSplit,\n\t\t\tcollection:   null\n\t\t};\n\t},\n\n\t/**\n\t * Get the button object from a node (recursive)\n\t * @param  {node} node Button node\n\t * @param  {array} [buttons] Button array, uses base if not defined\n\t * @return {object} Button object\n\t * @private\n\t */\n\t_nodeToButton: function ( node, buttons )\n\t{\n\t\tif ( ! buttons ) {\n\t\t\tbuttons = this.s.buttons;\n\t\t}\n\n\t\tfor ( var i=0, ien=buttons.length ; i<ien ; i++ ) {\n\t\t\tif ( buttons[i].node === node ) {\n\t\t\t\treturn buttons[i];\n\t\t\t}\n\n\t\t\tif ( buttons[i].buttons.length ) {\n\t\t\t\tvar ret = this._nodeToButton( node, buttons[i].buttons );\n\n\t\t\t\tif ( ret ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Get container array for a button from a button node (recursive)\n\t * @param  {node} node Button node\n\t * @param  {array} [buttons] Button array, uses base if not defined\n\t * @return {array} Button's host array\n\t * @private\n\t */\n\t_nodeToHost: function ( node, buttons )\n\t{\n\t\tif ( ! buttons ) {\n\t\t\tbuttons = this.s.buttons;\n\t\t}\n\n\t\tfor ( var i=0, ien=buttons.length ; i<ien ; i++ ) {\n\t\t\tif ( buttons[i].node === node ) {\n\t\t\t\treturn buttons;\n\t\t\t}\n\n\t\t\tif ( buttons[i].buttons.length ) {\n\t\t\t\tvar ret = this._nodeToHost( node, buttons[i].buttons );\n\n\t\t\t\tif ( ret ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Handle a key press - determine if any button's key configured matches\n\t * what was typed and trigger the action if so.\n\t * @param  {string} character The character pressed\n\t * @param  {object} e Key event that triggered this call\n\t * @private\n\t */\n\t_keypress: function ( character, e )\n\t{\n\t\t// Check if this button press already activated on another instance of Buttons\n\t\tif ( e._buttonsHandled ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar run = function ( conf, node ) {\n\t\t\tif ( ! conf.key ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( conf.key === character ) {\n\t\t\t\te._buttonsHandled = true;\n\t\t\t\t$(node).click();\n\t\t\t}\n\t\t\telse if ( $.isPlainObject( conf.key ) ) {\n\t\t\t\tif ( conf.key.key !== character ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif ( conf.key.shiftKey && ! e.shiftKey ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif ( conf.key.altKey && ! e.altKey ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif ( conf.key.ctrlKey && ! e.ctrlKey ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif ( conf.key.metaKey && ! e.metaKey ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Made it this far - it is good\n\t\t\t\te._buttonsHandled = true;\n\t\t\t\t$(node).click();\n\t\t\t}\n\t\t};\n\n\t\tvar recurse = function ( a ) {\n\t\t\tfor ( var i=0, ien=a.length ; i<ien ; i++ ) {\n\t\t\t\trun( a[i].conf, a[i].node );\n\n\t\t\t\tif ( a[i].buttons.length ) {\n\t\t\t\t\trecurse( a[i].buttons );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\trecurse( this.s.buttons );\n\t},\n\n\t/**\n\t * Remove a key from the key listener for this instance (to be used when a\n\t * button is removed)\n\t * @param  {object} conf Button configuration\n\t * @private\n\t */\n\t_removeKey: function ( conf )\n\t{\n\t\tif ( conf.key ) {\n\t\t\tvar character = $.isPlainObject( conf.key ) ?\n\t\t\t\tconf.key.key :\n\t\t\t\tconf.key;\n\n\t\t\t// Remove only one character, as multiple buttons could have the\n\t\t\t// same listening key\n\t\t\tvar a = this.s.listenKeys.split('');\n\t\t\tvar idx = $.inArray( character, a );\n\t\t\ta.splice( idx, 1 );\n\t\t\tthis.s.listenKeys = a.join('');\n\t\t}\n\t},\n\n\t/**\n\t * Resolve a button configuration\n\t * @param  {string|function|object} conf Button config to resolve\n\t * @return {object} Button configuration\n\t * @private\n\t */\n\t_resolveExtends: function ( conf )\n\t{\n\t\tvar that = this;\n\t\tvar dt = this.s.dt;\n\t\tvar i, ien;\n\t\tvar toConfObject = function ( base ) {\n\t\t\tvar loop = 0;\n\n\t\t\t// Loop until we have resolved to a button configuration, or an\n\t\t\t// array of button configurations (which will be iterated\n\t\t\t// separately)\n\t\t\twhile ( ! $.isPlainObject(base) && ! Array.isArray(base) ) {\n\t\t\t\tif ( base === undefined ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif ( typeof base === 'function' ) {\n\t\t\t\t\tbase = base.call( that, dt, conf );\n\n\t\t\t\t\tif ( ! base ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if ( typeof base === 'string' ) {\n\t\t\t\t\tif ( ! _dtButtons[ base ] ) {\n\t\t\t\t\t\treturn {html: base}\n\t\t\t\t\t}\n\n\t\t\t\t\tbase = _dtButtons[ base ];\n\t\t\t\t}\n\n\t\t\t\tloop++;\n\t\t\t\tif ( loop > 30 ) {\n\t\t\t\t\t// Protect against misconfiguration killing the browser\n\t\t\t\t\tthrow 'Buttons: Too many iterations';\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn Array.isArray( base ) ?\n\t\t\t\tbase :\n\t\t\t\t$.extend( {}, base );\n\t\t};\n\n\t\tconf = toConfObject( conf );\n\n\t\twhile ( conf && conf.extend ) {\n\t\t\t// Use `toConfObject` in case the button definition being extended\n\t\t\t// is itself a string or a function\n\t\t\tif ( ! _dtButtons[ conf.extend ] ) {\n\t\t\t\tthrow 'Cannot extend unknown button type: '+conf.extend;\n\t\t\t}\n\n\t\t\tvar objArray = toConfObject( _dtButtons[ conf.extend ] );\n\t\t\tif ( Array.isArray( objArray ) ) {\n\t\t\t\treturn objArray;\n\t\t\t}\n\t\t\telse if ( ! objArray ) {\n\t\t\t\t// This is a little brutal as it might be possible to have a\n\t\t\t\t// valid button without the extend, but if there is no extend\n\t\t\t\t// then the host button would be acting in an undefined state\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Stash the current class name\n\t\t\tvar originalClassName = objArray.className;\n\n\t\t\tif (conf.config !== undefined && objArray.config !== undefined) {\n\t\t\t\tconf.config = $.extend({}, objArray.config, conf.config)\n\t\t\t}\n\n\t\t\tconf = $.extend( {}, objArray, conf );\n\n\t\t\t// The extend will have overwritten the original class name if the\n\t\t\t// `conf` object also assigned a class, but we want to concatenate\n\t\t\t// them so they are list that is combined from all extended buttons\n\t\t\tif ( originalClassName && conf.className !== originalClassName ) {\n\t\t\t\tconf.className = originalClassName+' '+conf.className;\n\t\t\t}\n\n\t\t\t// Buttons to be added to a collection  -gives the ability to define\n\t\t\t// if buttons should be added to the start or end of a collection\n\t\t\tvar postfixButtons = conf.postfixButtons;\n\t\t\tif ( postfixButtons ) {\n\t\t\t\tif ( ! conf.buttons ) {\n\t\t\t\t\tconf.buttons = [];\n\t\t\t\t}\n\n\t\t\t\tfor ( i=0, ien=postfixButtons.length ; i<ien ; i++ ) {\n\t\t\t\t\tconf.buttons.push( postfixButtons[i] );\n\t\t\t\t}\n\n\t\t\t\tconf.postfixButtons = null;\n\t\t\t}\n\n\t\t\tvar prefixButtons = conf.prefixButtons;\n\t\t\tif ( prefixButtons ) {\n\t\t\t\tif ( ! conf.buttons ) {\n\t\t\t\t\tconf.buttons = [];\n\t\t\t\t}\n\n\t\t\t\tfor ( i=0, ien=prefixButtons.length ; i<ien ; i++ ) {\n\t\t\t\t\tconf.buttons.splice( i, 0, prefixButtons[i] );\n\t\t\t\t}\n\n\t\t\t\tconf.prefixButtons = null;\n\t\t\t}\n\n\t\t\t// Although we want the `conf` object to overwrite almost all of\n\t\t\t// the properties of the object being extended, the `extend`\n\t\t\t// property should come from the object being extended\n\t\t\tconf.extend = objArray.extend;\n\t\t}\n\n\t\treturn conf;\n\t},\n\n\t/**\n\t * Display (and replace if there is an existing one) a popover attached to a button\n\t * @param {string|node} content Content to show\n\t * @param {DataTable.Api} hostButton DT API instance of the button\n\t * @param {object} inOpts Options (see object below for all options)\n\t */\n\t_popover: function ( content, hostButton, inOpts, e ) {\n\t\tvar dt = hostButton;\n\t\tvar buttonsSettings = this.c;\n\t\tvar closed = false;\n\t\tvar options = $.extend( {\n\t\t\talign: 'button-left', // button-right, dt-container, split-left, split-right\n\t\t\tautoClose: false,\n\t\t\tbackground: true,\n\t\t\tbackgroundClassName: 'dt-button-background',\n\t\t\tcloseButton: true,\n\t\t\tcontentClassName: buttonsSettings.dom.collection.className,\n\t\t\tcollectionLayout: '',\n\t\t\tcollectionTitle: '',\n\t\t\tdropup: false,\n\t\t\tfade: 400,\n\t\t\tpopoverTitle: '',\n\t\t\trightAlignClassName: 'dt-button-right',\n\t\t\ttag: buttonsSettings.dom.collection.tag\n\t\t}, inOpts );\n\n\t\tvar hostNode = hostButton.node();\n\n\t\tvar close = function () {\n\t\t\tclosed = true;\n\n\t\t\t_fadeOut(\n\t\t\t\t$('.dt-button-collection'),\n\t\t\t\toptions.fade,\n\t\t\t\tfunction () {\n\t\t\t\t\t$(this).detach();\n\t\t\t\t}\n\t\t\t);\n\n\t\t\t$(dt.buttons( '[aria-haspopup=\"dialog\"][aria-expanded=\"true\"]' ).nodes())\n\t\t\t\t.attr('aria-expanded', 'false');\n\n\t\t\t$('div.dt-button-background').off( 'click.dtb-collection' );\n\t\t\tButtons.background( false, options.backgroundClassName, options.fade, hostNode );\n\n\t\t\t$(window).off('resize.resize.dtb-collection');\n\t\t\t$('body').off( '.dtb-collection' );\n\t\t\tdt.off( 'buttons-action.b-internal' );\n\t\t\tdt.off( 'destroy' );\n\t\t};\n\n\t\tif (content === false) {\n\t\t\tclose();\n\t\t\treturn;\n\t\t}\n\n\t\tvar existingExpanded = $(dt.buttons( '[aria-haspopup=\"dialog\"][aria-expanded=\"true\"]' ).nodes());\n\t\tif ( existingExpanded.length ) {\n\t\t\t// Reuse the current position if the button that was triggered is inside an existing collection\n\t\t\tif (hostNode.closest('div.dt-button-collection').length) {\n\t\t\t\thostNode = existingExpanded.eq(0);\n\t\t\t}\n\n\t\t\tclose();\n\t\t}\n\n\t\t// Try to be smart about the layout\n\t\tvar cnt = $('.dt-button', content).length;\n\t\tvar mod = '';\n\n\t\tif (cnt === 3) {\n\t\t\tmod = 'dtb-b3';\n\t\t}\n\t\telse if (cnt === 2) {\n\t\t\tmod = 'dtb-b2';\n\t\t}\n\t\telse if (cnt === 1) {\n\t\t\tmod = 'dtb-b1';\n\t\t}\n\n\t\tvar display = $('<div/>')\n\t\t\t.addClass('dt-button-collection')\n\t\t\t.addClass(options.collectionLayout)\n\t\t\t.addClass(options.splitAlignClass)\n\t\t\t.addClass(mod)\n\t\t\t.css('display', 'none')\n\t\t\t.attr({\n\t\t\t\t'aria-modal': true,\n\t\t\t\trole: 'dialog'\n\t\t\t});\n\n\t\tcontent = $(content)\n\t\t\t.addClass(options.contentClassName)\n\t\t\t.attr('role', 'menu')\n\t\t\t.appendTo(display);\n\n\t\thostNode.attr( 'aria-expanded', 'true' );\n\n\t\tif ( hostNode.parents('body')[0] !== document.body ) {\n\t\t\thostNode = document.body.lastChild;\n\t\t}\n\n\t\tif ( options.popoverTitle ) {\n\t\t\tdisplay.prepend('<div class=\"dt-button-collection-title\">'+options.popoverTitle+'</div>');\n\t\t}\n\t\telse if ( options.collectionTitle ) {\n\t\t\tdisplay.prepend('<div class=\"dt-button-collection-title\">'+options.collectionTitle+'</div>');\n\t\t}\n\n\t\tif (options.closeButton) {\n\t\t\tdisplay.prepend('<div class=\"dtb-popover-close\">x</div>').addClass('dtb-collection-closeable')\n\t\t}\n\n\t\t_fadeIn( display.insertAfter( hostNode ), options.fade );\n\n\t\tvar tableContainer = $( hostButton.table().container() );\n\t\tvar position = display.css( 'position' );\n\n\t\tif ( options.span === 'container' || options.align === 'dt-container' ) {\n\t\t\thostNode = hostNode.parent();\n\t\t\tdisplay.css('width', tableContainer.width());\n\t\t}\n\n\t\t// Align the popover relative to the DataTables container\n\t\t// Useful for wide popovers such as SearchPanes\n\t\tif (position === 'absolute') {\n\t\t\t// Align relative to the host button\n\t\t\tvar offsetParent = $(hostNode[0].offsetParent);\n\t\t\tvar buttonPosition = hostNode.position();\n\t\t\tvar buttonOffset = hostNode.offset();\n\t\t\tvar tableSizes = offsetParent.offset();\n\t\t\tvar containerPosition = offsetParent.position();\n\t\t\tvar computed = window.getComputedStyle(offsetParent[0]);\n\n\t\t\ttableSizes.height = offsetParent.outerHeight();\n\t\t\ttableSizes.width = offsetParent.width() + parseFloat(computed.paddingLeft);\n\t\t\ttableSizes.right = tableSizes.left + tableSizes.width;\n\t\t\ttableSizes.bottom = tableSizes.top + tableSizes.height;\n\n\t\t\t// Set the initial position so we can read height / width\n\t\t\tvar top = buttonPosition.top + hostNode.outerHeight();\n\t\t\tvar left = buttonPosition.left;\n\n\t\t\tdisplay.css( {\n\t\t\t\ttop: top,\n\t\t\t\tleft: left\n\t\t\t} );\n\n\t\t\t// Get the popover position\n\t\t\tcomputed = window.getComputedStyle(display[0]);\n\t\t\tvar popoverSizes = display.offset();\n\n\t\t\tpopoverSizes.height = display.outerHeight();\n\t\t\tpopoverSizes.width = display.outerWidth();\n\t\t\tpopoverSizes.right = popoverSizes.left + popoverSizes.width;\n\t\t\tpopoverSizes.bottom = popoverSizes.top + popoverSizes.height;\n\t\t\tpopoverSizes.marginTop = parseFloat(computed.marginTop);\n\t\t\tpopoverSizes.marginBottom = parseFloat(computed.marginBottom);\n\n\t\t\t// First position per the class requirements - pop up and right align\n\t\t\tif (options.dropup) {\n\t\t\t\ttop = buttonPosition.top - popoverSizes.height - popoverSizes.marginTop - popoverSizes.marginBottom;\n\t\t\t}\n\n\t\t\tif (options.align === 'button-right' || display.hasClass( options.rightAlignClassName )) {\n\t\t\t\tleft = buttonPosition.left - popoverSizes.width + hostNode.outerWidth(); \n\t\t\t}\n\n\t\t\t// Container alignment - make sure it doesn't overflow the table container\n\t\t\tif (options.align === 'dt-container' || options.align === 'container') {\n\t\t\t\tif (left < buttonPosition.left) {\n\t\t\t\t\tleft = -buttonPosition.left;\n\t\t\t\t}\n\n\t\t\t\tif (left + popoverSizes.width > tableSizes.width) {\n\t\t\t\t\tleft = tableSizes.width - popoverSizes.width;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Window adjustment\n\t\t\tif (containerPosition.left + left + popoverSizes.width > $(window).width()) {\n\t\t\t\t// Overflowing the document to the right\n\t\t\t\tleft = $(window).width() - popoverSizes.width - containerPosition.left;\n\t\t\t}\n\n\t\t\tif (buttonOffset.left + left < 0) {\n\t\t\t\t// Off to the left of the document\n\t\t\t\tleft = -buttonOffset.left;\n\t\t\t}\n\n\t\t\tif (containerPosition.top + top + popoverSizes.height > $(window).height() + $(window).scrollTop()) {\n\t\t\t\t// Pop up if otherwise we'd need the user to scroll down\n\t\t\t\ttop = buttonPosition.top - popoverSizes.height - popoverSizes.marginTop - popoverSizes.marginBottom;\n\t\t\t}\n\n\t\t\tif (containerPosition.top + top < $(window).scrollTop()) {\n\t\t\t\t// Correction for when the top is beyond the top of the page\n\t\t\t\ttop = buttonPosition.top + hostNode.outerHeight();\n\t\t\t}\n\n\t\t\t// Calculations all done - now set it\n\t\t\tdisplay.css( {\n\t\t\t\ttop: top,\n\t\t\t\tleft: left\n\t\t\t} );\n\t\t}\n\t\telse {\n\t\t\t// Fix position - centre on screen\n\t\t\tvar position = function () {\n\t\t\t\tvar half = $(window).height() / 2;\n\n\t\t\t\tvar top = display.height() / 2;\n\t\t\t\tif ( top > half ) {\n\t\t\t\t\ttop = half;\n\t\t\t\t}\n\n\t\t\t\tdisplay.css( 'marginTop', top*-1 );\n\t\t\t};\n\n\t\t\tposition();\n\n\t\t\t$(window).on('resize.dtb-collection', function () {\n\t\t\t\tposition();\n\t\t\t});\n\t\t}\n\n\t\tif ( options.background ) {\n\t\t\tButtons.background(\n\t\t\t\ttrue,\n\t\t\t\toptions.backgroundClassName,\n\t\t\t\toptions.fade,\n\t\t\t\toptions.backgroundHost || hostNode\n\t\t\t);\n\t\t}\n\n\t\t// This is bonkers, but if we don't have a click listener on the\n\t\t// background element, iOS Safari will ignore the body click\n\t\t// listener below. An empty function here is all that is\n\t\t// required to make it work...\n\t\t$('div.dt-button-background').on( 'click.dtb-collection', function () {} );\n\n\t\tif ( options.autoClose ) {\n\t\t\tsetTimeout( function () {\n\t\t\t\tdt.on( 'buttons-action.b-internal', function (e, btn, dt, node) {\n\t\t\t\t\tif ( node[0] === hostNode[0] ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tclose();\n\t\t\t\t} );\n\t\t\t}, 0);\n\t\t}\n\t\t\n\t\t$(display).trigger('buttons-popover.dt');\n\n\n\t\tdt.on('destroy', close);\n\n\t\tsetTimeout(function() {\n\t\t\tclosed = false;\n\t\t\t$('body')\n\t\t\t\t.on( 'click.dtb-collection', function (e) {\n\t\t\t\t\tif (closed) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t// andSelf is deprecated in jQ1.8, but we want 1.7 compat\n\t\t\t\t\tvar back = $.fn.addBack ? 'addBack' : 'andSelf';\n\t\t\t\t\tvar parent = $(e.target).parent()[0];\n\t\n\t\t\t\t\tif (( ! $(e.target).parents()[back]().filter( content ).length  && !$(parent).hasClass('dt-buttons')) || $(e.target).hasClass('dt-button-background')) {\n\t\t\t\t\t\tclose();\n\t\t\t\t\t}\n\t\t\t\t} )\n\t\t\t\t.on( 'keyup.dtb-collection', function (e) {\n\t\t\t\t\tif ( e.keyCode === 27 ) {\n\t\t\t\t\t\tclose();\n\t\t\t\t\t}\n\t\t\t\t} )\n\t\t\t\t.on( 'keydown.dtb-collection', function (e) {\n\t\t\t\t\t// Focus trap for tab key\n\t\t\t\t\tvar elements = $('a, button', content);\n\t\t\t\t\tvar active = document.activeElement;\n\n\t\t\t\t\tif (e.keyCode !== 9) { // tab\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (elements.index(active) === -1) {\n\t\t\t\t\t\t// If current focus is not inside the popover\n\t\t\t\t\t\telements.first().focus();\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t}\n\t\t\t\t\telse if (e.shiftKey) {\n\t\t\t\t\t\t// Reverse tabbing order when shift key is pressed\n\t\t\t\t\t\tif (active === elements[0]) {\n\t\t\t\t\t\t\telements.last().focus();\n\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tif (active === elements.last()[0]) {\n\t\t\t\t\t\t\telements.first().focus();\n\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t}, 0);\n\t}\n} );\n\n\n\n/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n * Statics\n */\n\n/**\n * Show / hide a background layer behind a collection\n * @param  {boolean} Flag to indicate if the background should be shown or\n *   hidden \n * @param  {string} Class to assign to the background\n * @static\n */\nButtons.background = function ( show, className, fade, insertPoint ) {\n\tif ( fade === undefined ) {\n\t\tfade = 400;\n\t}\n\tif ( ! insertPoint ) {\n\t\tinsertPoint = document.body;\n\t}\n\n\tif ( show ) {\n\t\t_fadeIn(\n\t\t\t$('<div/>')\n\t\t\t\t.addClass( className )\n\t\t\t\t.css( 'display', 'none' )\n\t\t\t\t.insertAfter( insertPoint ),\n\t\t\tfade\n\t\t);\n\t}\n\telse {\n\t\t_fadeOut(\n\t\t\t$('div.'+className),\n\t\t\tfade,\n\t\t\tfunction () {\n\t\t\t\t$(this)\n\t\t\t\t\t.removeClass( className )\n\t\t\t\t\t.remove();\n\t\t\t}\n\t\t);\n\t}\n};\n\n/**\n * Instance selector - select Buttons instances based on an instance selector\n * value from the buttons assigned to a DataTable. This is only useful if\n * multiple instances are attached to a DataTable.\n * @param  {string|int|array} Instance selector - see `instance-selector`\n *   documentation on the DataTables site\n * @param  {array} Button instance array that was attached to the DataTables\n *   settings object\n * @return {array} Buttons instances\n * @static\n */\nButtons.instanceSelector = function ( group, buttons )\n{\n\tif ( group === undefined || group === null ) {\n\t\treturn $.map( buttons, function ( v ) {\n\t\t\treturn v.inst;\n\t\t} );\n\t}\n\n\tvar ret = [];\n\tvar names = $.map( buttons, function ( v ) {\n\t\treturn v.name;\n\t} );\n\n\t// Flatten the group selector into an array of single options\n\tvar process = function ( input ) {\n\t\tif ( Array.isArray( input ) ) {\n\t\t\tfor ( var i=0, ien=input.length ; i<ien ; i++ ) {\n\t\t\t\tprocess( input[i] );\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif ( typeof input === 'string' ) {\n\t\t\tif ( input.indexOf( ',' ) !== -1 ) {\n\t\t\t\t// String selector, list of names\n\t\t\t\tprocess( input.split(',') );\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// String selector individual name\n\t\t\t\tvar idx = $.inArray( input.trim(), names );\n\n\t\t\t\tif ( idx !== -1 ) {\n\t\t\t\t\tret.push( buttons[ idx ].inst );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if ( typeof input === 'number' ) {\n\t\t\t// Index selector\n\t\t\tret.push( buttons[ input ].inst );\n\t\t}\n\t\telse if ( typeof input === 'object' ) {\n\t\t\t// Actual instance selector\n\t\t\tret.push( input );\n\t\t}\n\t};\n\t\n\tprocess( group );\n\n\treturn ret;\n};\n\n/**\n * Button selector - select one or more buttons from a selector input so some\n * operation can be performed on them.\n * @param  {array} Button instances array that the selector should operate on\n * @param  {string|int|node|jQuery|array} Button selector - see\n *   `button-selector` documentation on the DataTables site\n * @return {array} Array of objects containing `inst` and `idx` properties of\n *   the selected buttons so you know which instance each button belongs to.\n * @static\n */\nButtons.buttonSelector = function ( insts, selector )\n{\n\tvar ret = [];\n\tvar nodeBuilder = function ( a, buttons, baseIdx ) {\n\t\tvar button;\n\t\tvar idx;\n\n\t\tfor ( var i=0, ien=buttons.length ; i<ien ; i++ ) {\n\t\t\tbutton = buttons[i];\n\n\t\t\tif ( button ) {\n\t\t\t\tidx = baseIdx !== undefined ?\n\t\t\t\t\tbaseIdx+i :\n\t\t\t\t\ti+'';\n\n\t\t\t\ta.push( {\n\t\t\t\t\tnode: button.node,\n\t\t\t\t\tname: button.conf.name,\n\t\t\t\t\tidx:  idx\n\t\t\t\t} );\n\n\t\t\t\tif ( button.buttons ) {\n\t\t\t\t\tnodeBuilder( a, button.buttons, idx+'-' );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\tvar run = function ( selector, inst ) {\n\t\tvar i, ien;\n\t\tvar buttons = [];\n\t\tnodeBuilder( buttons, inst.s.buttons );\n\n\t\tvar nodes = $.map( buttons, function (v) {\n\t\t\treturn v.node;\n\t\t} );\n\n\t\tif ( Array.isArray( selector ) || selector instanceof $ ) {\n\t\t\tfor ( i=0, ien=selector.length ; i<ien ; i++ ) {\n\t\t\t\trun( selector[i], inst );\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif ( selector === null || selector === undefined || selector === '*' ) {\n\t\t\t// Select all\n\t\t\tfor ( i=0, ien=buttons.length ; i<ien ; i++ ) {\n\t\t\t\tret.push( {\n\t\t\t\t\tinst: inst,\n\t\t\t\t\tnode: buttons[i].node\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\t\telse if ( typeof selector === 'number' ) {\n\t\t\t// Main button index selector\n\t\t\tif (inst.s.buttons[ selector ]) {\n\t\t\t\tret.push( {\n\t\t\t\t\tinst: inst,\n\t\t\t\t\tnode: inst.s.buttons[ selector ].node\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\t\telse if ( typeof selector === 'string' ) {\n\t\t\tif ( selector.indexOf( ',' ) !== -1 ) {\n\t\t\t\t// Split\n\t\t\t\tvar a = selector.split(',');\n\n\t\t\t\tfor ( i=0, ien=a.length ; i<ien ; i++ ) {\n\t\t\t\t\trun( a[i].trim(), inst );\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if ( selector.match( /^\\d+(\\-\\d+)*$/ ) ) {\n\t\t\t\t// Sub-button index selector\n\t\t\t\tvar indexes = $.map( buttons, function (v) {\n\t\t\t\t\treturn v.idx;\n\t\t\t\t} );\n\n\t\t\t\tret.push( {\n\t\t\t\t\tinst: inst,\n\t\t\t\t\tnode: buttons[ $.inArray( selector, indexes ) ].node\n\t\t\t\t} );\n\t\t\t}\n\t\t\telse if ( selector.indexOf( ':name' ) !== -1 ) {\n\t\t\t\t// Button name selector\n\t\t\t\tvar name = selector.replace( ':name', '' );\n\n\t\t\t\tfor ( i=0, ien=buttons.length ; i<ien ; i++ ) {\n\t\t\t\t\tif ( buttons[i].name === name ) {\n\t\t\t\t\t\tret.push( {\n\t\t\t\t\t\t\tinst: inst,\n\t\t\t\t\t\t\tnode: buttons[i].node\n\t\t\t\t\t\t} );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// jQuery selector on the nodes\n\t\t\t\t$( nodes ).filter( selector ).each( function () {\n\t\t\t\t\tret.push( {\n\t\t\t\t\t\tinst: inst,\n\t\t\t\t\t\tnode: this\n\t\t\t\t\t} );\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\t\telse if ( typeof selector === 'object' && selector.nodeName ) {\n\t\t\t// Node selector\n\t\t\tvar idx = $.inArray( selector, nodes );\n\n\t\t\tif ( idx !== -1 ) {\n\t\t\t\tret.push( {\n\t\t\t\t\tinst: inst,\n\t\t\t\t\tnode: nodes[ idx ]\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\t};\n\n\n\tfor ( var i=0, ien=insts.length ; i<ien ; i++ ) {\n\t\tvar inst = insts[i];\n\n\t\trun( selector, inst );\n\t}\n\n\treturn ret;\n};\n\n/**\n * Default function used for formatting output data.\n * @param {*} str Data to strip\n */\nButtons.stripData = function ( str, config ) {\n\tif ( typeof str !== 'string' ) {\n\t\treturn str;\n\t}\n\n\t// Always remove script tags\n\tstr = str.replace( /<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi, '' );\n\n\t// Always remove comments\n\tstr = str.replace( /<!\\-\\-.*?\\-\\->/g, '' );\n\n\tif ( ! config || config.stripHtml ) {\n\t\tstr = str.replace( /<[^>]*>/g, '' );\n\t}\n\n\tif ( ! config || config.trim ) {\n\t\tstr = str.replace( /^\\s+|\\s+$/g, '' );\n\t}\n\n\tif ( ! config || config.stripNewlines ) {\n\t\tstr = str.replace( /\\n/g, ' ' );\n\t}\n\n\tif ( ! config || config.decodeEntities ) {\n\t\t_exportTextarea.innerHTML = str;\n\t\tstr = _exportTextarea.value;\n\t}\n\n\treturn str;\n};\n\n\n/**\n * Buttons defaults. For full documentation, please refer to the docs/option\n * directory or the DataTables site.\n * @type {Object}\n * @static\n */\nButtons.defaults = {\n\tbuttons: [ 'copy', 'excel', 'csv', 'pdf', 'print' ],\n\tname: 'main',\n\ttabIndex: 0,\n\tdom: {\n\t\tcontainer: {\n\t\t\ttag: 'div',\n\t\t\tclassName: 'dt-buttons'\n\t\t},\n\t\tcollection: {\n\t\t\ttag: 'div',\n\t\t\tclassName: ''\n\t\t},\n\t\tbutton: {\n\t\t\ttag: 'button',\n\t\t\tclassName: 'dt-button',\n\t\t\tactive: 'active',\n\t\t\tdisabled: 'disabled',\n\t\t\tspacerClass: ''\n\t\t},\n\t\tbuttonLiner: {\n\t\t\ttag: 'span',\n\t\t\tclassName: ''\n\t\t},\n\t\tsplit: {\n\t\t\ttag: 'div',\n\t\t\tclassName: 'dt-button-split',\n\t\t},\n\t\tsplitWrapper: {\n\t\t\ttag: 'div',\n\t\t\tclassName: 'dt-btn-split-wrapper',\n\t\t},\n\t\tsplitDropdown: {\n\t\t\ttag: 'button',\n\t\t\ttext: '&#x25BC;',\n\t\t\tclassName: 'dt-btn-split-drop',\n\t\t\talign: 'split-right',\n\t\t\tsplitAlignClass: 'dt-button-split-left'\n\t\t},\n\t\tsplitDropdownButton: {\n\t\t\ttag: 'button',\n\t\t\tclassName: 'dt-btn-split-drop-button dt-button',\n\t\t},\n\t\tsplitCollection: {\n\t\t\ttag: 'div',\n\t\t\tclassName: 'dt-button-split-collection',\n\t\t}\n\t}\n};\n\n/**\n * Version information\n * @type {string}\n * @static\n */\nButtons.version = '2.2.3';\n\n\n$.extend( _dtButtons, {\n\tcollection: {\n\t\ttext: function ( dt ) {\n\t\t\treturn dt.i18n( 'buttons.collection', 'Collection' );\n\t\t},\n\t\tclassName: 'buttons-collection',\n\t\tcloseButton: false,\n\t\tinit: function ( dt, button, config ) {\n\t\t\tbutton.attr( 'aria-expanded', false );\n\t\t},\n\t\taction: function ( e, dt, button, config ) {\n\t\t\tif ( config._collection.parents('body').length ) {\n\t\t\t\tthis.popover(false, config);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthis.popover(config._collection, config);\n\t\t\t}\n\n\t\t\t// When activated using a key - auto focus on the\n\t\t\t// first item in the popover\n\t\t\tif (e.type === 'keypress') {\n\t\t\t\t$('a, button', config._collection).eq(0).focus();\n\t\t\t}\n\t\t},\n\t\tattr: {\n\t\t\t'aria-haspopup': 'dialog'\n\t\t}\n\t\t// Also the popover options, defined in Buttons.popover\n\t},\n\tsplit: {\n\t\ttext: function ( dt ) {\n\t\t\treturn dt.i18n( 'buttons.split', 'Split' );\n\t\t},\n\t\tclassName: 'buttons-split',\n\t\tcloseButton: false,\n\t\tinit: function ( dt, button, config ) {\n\t\t\treturn button.attr( 'aria-expanded', false );\n\t\t},\n\t\taction: function ( e, dt, button, config ) {\n\t\t\tthis.popover(config._collection, config);\n\t\t},\n\t\tattr: {\n\t\t\t'aria-haspopup': 'dialog'\n\t\t}\n\t\t// Also the popover options, defined in Buttons.popover\n\t},\n\tcopy: function ( dt, conf ) {\n\t\tif ( _dtButtons.copyHtml5 ) {\n\t\t\treturn 'copyHtml5';\n\t\t}\n\t},\n\tcsv: function ( dt, conf ) {\n\t\tif ( _dtButtons.csvHtml5 && _dtButtons.csvHtml5.available( dt, conf ) ) {\n\t\t\treturn 'csvHtml5';\n\t\t}\n\t},\n\texcel: function ( dt, conf ) {\n\t\tif ( _dtButtons.excelHtml5 && _dtButtons.excelHtml5.available( dt, conf ) ) {\n\t\t\treturn 'excelHtml5';\n\t\t}\n\t},\n\tpdf: function ( dt, conf ) {\n\t\tif ( _dtButtons.pdfHtml5 && _dtButtons.pdfHtml5.available( dt, conf ) ) {\n\t\t\treturn 'pdfHtml5';\n\t\t}\n\t},\n\tpageLength: function ( dt ) {\n\t\tvar lengthMenu = dt.settings()[0].aLengthMenu;\n\t\tvar vals = [];\n\t\tvar lang = [];\n\t\tvar text = function ( dt ) {\n\t\t\treturn dt.i18n( 'buttons.pageLength', {\n\t\t\t\t\"-1\": 'Show all rows',\n\t\t\t\t_:    'Show %d rows'\n\t\t\t}, dt.page.len() );\n\t\t};\n\n\t\t// Support for DataTables 1.x 2D array\n\t\tif (Array.isArray( lengthMenu[0] )) {\n\t\t\tvals = lengthMenu[0];\n\t\t\tlang = lengthMenu[1];\n\t\t}\n\t\telse {\n\t\t\tfor (var i=0 ; i<lengthMenu.length ; i++) {\n\t\t\t\tvar option = lengthMenu[i];\n\n\t\t\t\t// Support for DataTables 2 object in the array\n\t\t\t\tif ($.isPlainObject(option)) {\n\t\t\t\t\tvals.push(option.value);\n\t\t\t\t\tlang.push(option.label);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tvals.push(option);\n\t\t\t\t\tlang.push(option);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\textend: 'collection',\n\t\t\ttext: text,\n\t\t\tclassName: 'buttons-page-length',\n\t\t\tautoClose: true,\n\t\t\tbuttons: $.map( vals, function ( val, i ) {\n\t\t\t\treturn {\n\t\t\t\t\ttext: lang[i],\n\t\t\t\t\tclassName: 'button-page-length',\n\t\t\t\t\taction: function ( e, dt ) {\n\t\t\t\t\t\tdt.page.len( val ).draw();\n\t\t\t\t\t},\n\t\t\t\t\tinit: function ( dt, node, conf ) {\n\t\t\t\t\t\tvar that = this;\n\t\t\t\t\t\tvar fn = function () {\n\t\t\t\t\t\t\tthat.active( dt.page.len() === val );\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tdt.on( 'length.dt'+conf.namespace, fn );\n\t\t\t\t\t\tfn();\n\t\t\t\t\t},\n\t\t\t\t\tdestroy: function ( dt, node, conf ) {\n\t\t\t\t\t\tdt.off( 'length.dt'+conf.namespace );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t} ),\n\t\t\tinit: function ( dt, node, conf ) {\n\t\t\t\tvar that = this;\n\t\t\t\tdt.on( 'length.dt'+conf.namespace, function () {\n\t\t\t\t\tthat.text( conf.text );\n\t\t\t\t} );\n\t\t\t},\n\t\t\tdestroy: function ( dt, node, conf ) {\n\t\t\t\tdt.off( 'length.dt'+conf.namespace );\n\t\t\t}\n\t\t};\n\t},\n\tspacer: {\n\t\tstyle: 'empty',\n\t\tspacer: true,\n\t\ttext: function ( dt ) {\n\t\t\treturn dt.i18n( 'buttons.spacer', '' );\n\t\t}\n\t}\n} );\n\n\n/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n * DataTables API\n *\n * For complete documentation, please refer to the docs/api directory or the\n * DataTables site\n */\n\n// Buttons group and individual button selector\nDataTable.Api.register( 'buttons()', function ( group, selector ) {\n\t// Argument shifting\n\tif ( selector === undefined ) {\n\t\tselector = group;\n\t\tgroup = undefined;\n\t}\n\n\tthis.selector.buttonGroup = group;\n\n\tvar res = this.iterator( true, 'table', function ( ctx ) {\n\t\tif ( ctx._buttons ) {\n\t\t\treturn Buttons.buttonSelector(\n\t\t\t\tButtons.instanceSelector( group, ctx._buttons ),\n\t\t\t\tselector\n\t\t\t);\n\t\t}\n\t}, true );\n\n\tres._groupSelector = group;\n\treturn res;\n} );\n\n// Individual button selector\nDataTable.Api.register( 'button()', function ( group, selector ) {\n\t// just run buttons() and truncate\n\tvar buttons = this.buttons( group, selector );\n\n\tif ( buttons.length > 1 ) {\n\t\tbuttons.splice( 1, buttons.length );\n\t}\n\n\treturn buttons;\n} );\n\n// Active buttons\nDataTable.Api.registerPlural( 'buttons().active()', 'button().active()', function ( flag ) {\n\tif ( flag === undefined ) {\n\t\treturn this.map( function ( set ) {\n\t\t\treturn set.inst.active( set.node );\n\t\t} );\n\t}\n\n\treturn this.each( function ( set ) {\n\t\tset.inst.active( set.node, flag );\n\t} );\n} );\n\n// Get / set button action\nDataTable.Api.registerPlural( 'buttons().action()', 'button().action()', function ( action ) {\n\tif ( action === undefined ) {\n\t\treturn this.map( function ( set ) {\n\t\t\treturn set.inst.action( set.node );\n\t\t} );\n\t}\n\n\treturn this.each( function ( set ) {\n\t\tset.inst.action( set.node, action );\n\t} );\n} );\n\n// Collection control\nDataTable.Api.registerPlural( 'buttons().collectionRebuild()', 'button().collectionRebuild()', function ( buttons ) {\n\treturn this.each( function ( set ) {\n\t\tfor(var i = 0; i < buttons.length; i++) {\n\t\t\tif(typeof buttons[i] === 'object') {\n\t\t\t\tbuttons[i].parentConf = set;\n\t\t\t}\n\t\t}\n\t\tset.inst.collectionRebuild( set.node, buttons );\n\t} );\n} );\n\n// Enable / disable buttons\nDataTable.Api.register( ['buttons().enable()', 'button().enable()'], function ( flag ) {\n\treturn this.each( function ( set ) {\n\t\tset.inst.enable( set.node, flag );\n\t} );\n} );\n\n// Disable buttons\nDataTable.Api.register( ['buttons().disable()', 'button().disable()'], function () {\n\treturn this.each( function ( set ) {\n\t\tset.inst.disable( set.node );\n\t} );\n} );\n\n// Button index\nDataTable.Api.register( 'button().index()', function () {\n\tvar idx = null;\n\n\tthis.each( function ( set ) {\n\t\tvar res = set.inst.index( set.node );\n\n\t\tif (res !== null) {\n\t\t\tidx = res;\n\t\t}\n\t} );\n\n\treturn idx;\n} );\n\n// Get button nodes\nDataTable.Api.registerPlural( 'buttons().nodes()', 'button().node()', function () {\n\tvar jq = $();\n\n\t// jQuery will automatically reduce duplicates to a single entry\n\t$( this.each( function ( set ) {\n\t\tjq = jq.add( set.inst.node( set.node ) );\n\t} ) );\n\n\treturn jq;\n} );\n\n// Get / set button processing state\nDataTable.Api.registerPlural( 'buttons().processing()', 'button().processing()', function ( flag ) {\n\tif ( flag === undefined ) {\n\t\treturn this.map( function ( set ) {\n\t\t\treturn set.inst.processing( set.node );\n\t\t} );\n\t}\n\n\treturn this.each( function ( set ) {\n\t\tset.inst.processing( set.node, flag );\n\t} );\n} );\n\n// Get / set button text (i.e. the button labels)\nDataTable.Api.registerPlural( 'buttons().text()', 'button().text()', function ( label ) {\n\tif ( label === undefined ) {\n\t\treturn this.map( function ( set ) {\n\t\t\treturn set.inst.text( set.node );\n\t\t} );\n\t}\n\n\treturn this.each( function ( set ) {\n\t\tset.inst.text( set.node, label );\n\t} );\n} );\n\n// Trigger a button's action\nDataTable.Api.registerPlural( 'buttons().trigger()', 'button().trigger()', function () {\n\treturn this.each( function ( set ) {\n\t\tset.inst.node( set.node ).trigger( 'click' );\n\t} );\n} );\n\n// Button resolver to the popover\nDataTable.Api.register( 'button().popover()', function (content, options) {\n\treturn this.map( function ( set ) {\n\t\treturn set.inst._popover( content, this.button(this[0].node), options );\n\t} );\n} );\n\n// Get the container elements\nDataTable.Api.register( 'buttons().containers()', function () {\n\tvar jq = $();\n\tvar groupSelector = this._groupSelector;\n\n\t// We need to use the group selector directly, since if there are no buttons\n\t// the result set will be empty\n\tthis.iterator( true, 'table', function ( ctx ) {\n\t\tif ( ctx._buttons ) {\n\t\t\tvar insts = Buttons.instanceSelector( groupSelector, ctx._buttons );\n\n\t\t\tfor ( var i=0, ien=insts.length ; i<ien ; i++ ) {\n\t\t\t\tjq = jq.add( insts[i].container() );\n\t\t\t}\n\t\t}\n\t} );\n\n\treturn jq;\n} );\n\nDataTable.Api.register( 'buttons().container()', function () {\n\t// API level of nesting is `buttons()` so we can zip into the containers method\n\treturn this.containers().eq(0);\n} );\n\n// Add a new button\nDataTable.Api.register( 'button().add()', function ( idx, conf, draw ) {\n\tvar ctx = this.context;\n\n\t// Don't use `this` as it could be empty - select the instances directly\n\tif ( ctx.length ) {\n\t\tvar inst = Buttons.instanceSelector( this._groupSelector, ctx[0]._buttons );\n\n\t\tif ( inst.length ) {\n\t\t\tinst[0].add( conf, idx , draw);\n\t\t}\n\t}\n\n\treturn this.button( this._groupSelector, idx );\n} );\n\n// Destroy the button sets selected\nDataTable.Api.register( 'buttons().destroy()', function () {\n\tthis.pluck( 'inst' ).unique().each( function ( inst ) {\n\t\tinst.destroy();\n\t} );\n\n\treturn this;\n} );\n\n// Remove a button\nDataTable.Api.registerPlural( 'buttons().remove()', 'buttons().remove()', function () {\n\tthis.each( function ( set ) {\n\t\tset.inst.remove( set.node );\n\t} );\n\n\treturn this;\n} );\n\n// Information box that can be used by buttons\nvar _infoTimer;\nDataTable.Api.register( 'buttons.info()', function ( title, message, time ) {\n\tvar that = this;\n\n\tif ( title === false ) {\n\t\tthis.off('destroy.btn-info');\n\t\t_fadeOut(\n\t\t\t$('#datatables_buttons_info'),\n\t\t\t400,\n\t\t\tfunction () {\n\t\t\t\t$(this).remove();\n\t\t\t}\n\t\t);\n\t\tclearTimeout( _infoTimer );\n\t\t_infoTimer = null;\n\n\t\treturn this;\n\t}\n\n\tif ( _infoTimer ) {\n\t\tclearTimeout( _infoTimer );\n\t}\n\n\tif ( $('#datatables_buttons_info').length ) {\n\t\t$('#datatables_buttons_info').remove();\n\t}\n\n\ttitle = title ? '<h2>'+title+'</h2>' : '';\n\n\t_fadeIn(\n\t\t$('<div id=\"datatables_buttons_info\" class=\"dt-button-info\"/>')\n\t\t\t.html( title )\n\t\t\t.append( $('<div/>')[ typeof message === 'string' ? 'html' : 'append' ]( message ) )\n\t\t\t.css( 'display', 'none' )\n\t\t\t.appendTo( 'body' )\n\t);\n\n\tif ( time !== undefined && time !== 0 ) {\n\t\t_infoTimer = setTimeout( function () {\n\t\t\tthat.buttons.info( false );\n\t\t}, time );\n\t}\n\n\tthis.on('destroy.btn-info', function () {\n\t\tthat.buttons.info(false);\n\t});\n\n\treturn this;\n} );\n\n// Get data from the table for export - this is common to a number of plug-in\n// buttons so it is included in the Buttons core library\nDataTable.Api.register( 'buttons.exportData()', function ( options ) {\n\tif ( this.context.length ) {\n\t\treturn _exportData( new DataTable.Api( this.context[0] ), options );\n\t}\n} );\n\n// Get information about the export that is common to many of the export data\n// types (DRY)\nDataTable.Api.register( 'buttons.exportInfo()', function ( conf ) {\n\tif ( ! conf ) {\n\t\tconf = {};\n\t}\n\n\treturn {\n\t\tfilename: _filename( conf ),\n\t\ttitle: _title( conf ),\n\t\tmessageTop: _message(this, conf.message || conf.messageTop, 'top'),\n\t\tmessageBottom: _message(this, conf.messageBottom, 'bottom')\n\t};\n} );\n\n\n\n/**\n * Get the file name for an exported file.\n *\n * @param {object}\tconfig Button configuration\n * @param {boolean} incExtension Include the file name extension\n */\nvar _filename = function ( config )\n{\n\t// Backwards compatibility\n\tvar filename = config.filename === '*' && config.title !== '*' && config.title !== undefined && config.title !== null && config.title !== '' ?\n\t\tconfig.title :\n\t\tconfig.filename;\n\n\tif ( typeof filename === 'function' ) {\n\t\tfilename = filename();\n\t}\n\n\tif ( filename === undefined || filename === null ) {\n\t\treturn null;\n\t}\n\n\tif ( filename.indexOf( '*' ) !== -1 ) {\n\t\tfilename = filename.replace( '*', $('head > title').text() ).trim();\n\t}\n\n\t// Strip characters which the OS will object to\n\tfilename = filename.replace(/[^a-zA-Z0-9_\\u00A1-\\uFFFF\\.,\\-_ !\\(\\)]/g, \"\");\n\n\tvar extension = _stringOrFunction( config.extension );\n\tif ( ! extension ) {\n\t\textension = '';\n\t}\n\n\treturn filename + extension;\n};\n\n/**\n * Simply utility method to allow parameters to be given as a function\n *\n * @param {undefined|string|function} option Option\n * @return {null|string} Resolved value\n */\nvar _stringOrFunction = function ( option )\n{\n\tif ( option === null || option === undefined ) {\n\t\treturn null;\n\t}\n\telse if ( typeof option === 'function' ) {\n\t\treturn option();\n\t}\n\treturn option;\n};\n\n/**\n * Get the title for an exported file.\n *\n * @param {object} config\tButton configuration\n */\nvar _title = function ( config )\n{\n\tvar title = _stringOrFunction( config.title );\n\n\treturn title === null ?\n\t\tnull : title.indexOf( '*' ) !== -1 ?\n\t\t\ttitle.replace( '*', $('head > title').text() || 'Exported data' ) :\n\t\t\ttitle;\n};\n\nvar _message = function ( dt, option, position )\n{\n\tvar message = _stringOrFunction( option );\n\tif ( message === null ) {\n\t\treturn null;\n\t}\n\n\tvar caption = $('caption', dt.table().container()).eq(0);\n\tif ( message === '*' ) {\n\t\tvar side = caption.css( 'caption-side' );\n\t\tif ( side !== position ) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn caption.length ?\n\t\t\tcaption.text() :\n\t\t\t'';\n\t}\n\n\treturn message;\n};\n\n\n\n\nvar _exportTextarea = $('<textarea/>')[0];\nvar _exportData = function ( dt, inOpts )\n{\n\tvar config = $.extend( true, {}, {\n\t\trows:           null,\n\t\tcolumns:        '',\n\t\tmodifier:       {\n\t\t\tsearch: 'applied',\n\t\t\torder:  'applied'\n\t\t},\n\t\torthogonal:     'display',\n\t\tstripHtml:      true,\n\t\tstripNewlines:  true,\n\t\tdecodeEntities: true,\n\t\ttrim:           true,\n\t\tformat:         {\n\t\t\theader: function ( d ) {\n\t\t\t\treturn Buttons.stripData( d, config );\n\t\t\t},\n\t\t\tfooter: function ( d ) {\n\t\t\t\treturn Buttons.stripData( d, config );\n\t\t\t},\n\t\t\tbody: function ( d ) {\n\t\t\t\treturn Buttons.stripData( d, config );\n\t\t\t}\n\t\t},\n\t\tcustomizeData: null\n\t}, inOpts );\n\n\tvar header = dt.columns( config.columns ).indexes().map( function (idx) {\n\t\tvar el = dt.column( idx ).header();\n\t\treturn config.format.header( el.innerHTML, idx, el );\n\t} ).toArray();\n\n\tvar footer = dt.table().footer() ?\n\t\tdt.columns( config.columns ).indexes().map( function (idx) {\n\t\t\tvar el = dt.column( idx ).footer();\n\t\t\treturn config.format.footer( el ? el.innerHTML : '', idx, el );\n\t\t} ).toArray() :\n\t\tnull;\n\t\n\t// If Select is available on this table, and any rows are selected, limit the export\n\t// to the selected rows. If no rows are selected, all rows will be exported. Specify\n\t// a `selected` modifier to control directly.\n\tvar modifier = $.extend( {}, config.modifier );\n\tif ( dt.select && typeof dt.select.info === 'function' && modifier.selected === undefined ) {\n\t\tif ( dt.rows( config.rows, $.extend( { selected: true }, modifier ) ).any() ) {\n\t\t\t$.extend( modifier, { selected: true } )\n\t\t}\n\t}\n\n\tvar rowIndexes = dt.rows( config.rows, modifier ).indexes().toArray();\n\tvar selectedCells = dt.cells( rowIndexes, config.columns );\n\tvar cells = selectedCells\n\t\t.render( config.orthogonal )\n\t\t.toArray();\n\tvar cellNodes = selectedCells\n\t\t.nodes()\n\t\t.toArray();\n\n\tvar columns = header.length;\n\tvar rows = columns > 0 ? cells.length / columns : 0;\n\tvar body = [];\n\tvar cellCounter = 0;\n\n\tfor ( var i=0, ien=rows ; i<ien ; i++ ) {\n\t\tvar row = [ columns ];\n\n\t\tfor ( var j=0 ; j<columns ; j++ ) {\n\t\t\trow[j] = config.format.body( cells[ cellCounter ], i, j, cellNodes[ cellCounter ] );\n\t\t\tcellCounter++;\n\t\t}\n\n\t\tbody[i] = row;\n\t}\n\n\tvar data = {\n\t\theader: header,\n\t\tfooter: footer,\n\t\tbody:   body\n\t};\n\n\tif ( config.customizeData ) {\n\t\tconfig.customizeData( data );\n\t}\n\n\treturn data;\n};\n\n\n/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n * DataTables interface\n */\n\n// Attach to DataTables objects for global access\n$.fn.dataTable.Buttons = Buttons;\n$.fn.DataTable.Buttons = Buttons;\n\n\n\n// DataTables creation - check if the buttons have been defined for this table,\n// they will have been if the `B` option was used in `dom`, otherwise we should\n// create the buttons instance here so they can be inserted into the document\n// using the API. Listen for `init` for compatibility with pre 1.10.10, but to\n// be removed in future.\n$(document).on( 'init.dt plugin-init.dt', function (e, settings) {\n\tif ( e.namespace !== 'dt' ) {\n\t\treturn;\n\t}\n\n\tvar opts = settings.oInit.buttons || DataTable.defaults.buttons;\n\n\tif ( opts && ! settings._buttons ) {\n\t\tnew Buttons( settings, opts ).container();\n\t}\n} );\n\nfunction _init ( settings, options ) {\n\tvar api = new DataTable.Api( settings );\n\tvar opts = options\n\t\t? options\n\t\t: api.init().buttons || DataTable.defaults.buttons;\n\n\treturn new Buttons( api, opts ).container();\n}\n\n// DataTables `dom` feature option\nDataTable.ext.feature.push( {\n\tfnInit: _init,\n\tcFeature: \"B\"\n} );\n\n// DataTables 2 layout feature\nif ( DataTable.ext.features ) {\n\tDataTable.ext.features.register( 'buttons', _init );\n}\n\n\nreturn Buttons;\n}));\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,[encoded data, 110160 characters]\n//# sourceURL=webpack-internal:///./node_modules/datatables.net-buttons/js/dataTables.buttons.js\n");

/***/ }),

/***/ "datatables.net":
/*!*********************************!*\
  !*** external "$.fn.dataTable" ***!
  \*********************************/
/***/ (function(module) {

"use strict";
module.exports = window["$.fn.dataTable"];

/***/ }),

/***/ "jquery":
/*!*************************!*\
  !*** external "jQuery" ***!
  \*************************/
/***/ (function(module) {

"use strict";
module.exports = window["jQuery"];

/***/ })

/******/ 	});
/************************************************************************/
/******/ 	// The module cache
/******/ 	var __webpack_module_cache__ = {};
/******/ 	
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/ 		// Check if module is in cache
/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
/******/ 		if (cachedModule !== undefined) {
/******/ 			return cachedModule.exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = __webpack_module_cache__[moduleId] = {
/******/ 			// no module.id needed
/******/ 			// no module.loaded needed
/******/ 			exports: {}
/******/ 		};
/******/ 	
/******/ 		// Execute the module function
/******/ 		__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/ 	
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/ 	
/************************************************************************/
/******/ 	/* webpack/runtime/compat get default export */
/******/ 	!function() {
/******/ 		// getDefaultExport function for compatibility with non-harmony modules
/******/ 		__webpack_require__.n = function(module) {
/******/ 			var getter = module && module.__esModule ?
/******/ 				function() { return module['default']; } :
/******/ 				function() { return module; };
/******/ 			__webpack_require__.d(getter, { a: getter });
/******/ 			return getter;
/******/ 		};
/******/ 	}();
/******/ 	
/******/ 	/* webpack/runtime/define property getters */
/******/ 	!function() {
/******/ 		// define getter functions for harmony exports
/******/ 		__webpack_require__.d = function(exports, definition) {
/******/ 			for(var key in definition) {
/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ 				}
/******/ 			}
/******/ 		};
/******/ 	}();
/******/ 	
/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
/******/ 	!function() {
/******/ 		__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
/******/ 	}();
/******/ 	
/******/ 	/* webpack/runtime/make namespace object */
/******/ 	!function() {
/******/ 		// define __esModule on exports
/******/ 		__webpack_require__.r = function(exports) {
/******/ 			if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ 				Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ 			}
/******/ 			Object.defineProperty(exports, '__esModule', { value: true });
/******/ 		};
/******/ 	}();
/******/ 	
/************************************************************************/
/******/ 	
/******/ 	// startup
/******/ 	// Load entry module and return exports
/******/ 	// This entry module can't be inlined because the eval-source-map devtool is used.
/******/ 	var __webpack_exports__ = __webpack_require__("./libs/datatables-buttons/buttons.colVis.js");
/******/ 	var __webpack_export_target__ = window;
/******/ 	for(var i in __webpack_exports__) __webpack_export_target__[i] = __webpack_exports__[i];
/******/ 	if(__webpack_exports__.__esModule) Object.defineProperty(__webpack_export_target__, "__esModule", { value: true });
/******/ 	
/******/ })()
;