PageSourceSearch

https://www.neuchatelville.ch/typo3temp/assets/compressed/main-7e588e71fba2c40d84eec2264a88e623.js?1783607210

js neuchatelville.ch collected 2026-10-02 05:14:10 UTC 796,233 bytes, 28,219 lines download raw bytes

vendor: 3,603 bytes, lines 1-89
1/******/ (function(modules) { // webpackBootstrap
2/******/ 	// The module cache
3/******/ 	var installedModules = {};
4/******/
5/******/ 	// The require function
6/******/ 	function __webpack_require__(moduleId) {
7/******/
8/******/ 		// Check if module is in cache
9/******/ 		if(installedModules[moduleId]) {
10/******/ 			return installedModules[moduleId].exports;
11/******/ 		}
12/******/ 		// Create a new module (and put it into the cache)
13/******/ 		var module = installedModules[moduleId] = {
14/******/ 			i: moduleId,
15/******/ 			l: false,
16/******/ 			exports: {}
17/******/ 		};
18/******/
19/******/ 		// Execute the module function
20/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
21/******/
22/******/ 		// Flag the module as loaded
23/******/ 		module.l = true;
24/******/
25/******/ 		// Return the exports of the module
26/******/ 		return module.exports;
27/******/ 	}
28/******/
29/******/
30/******/ 	// expose the modules object (__webpack_modules__)
31/******/ 	__webpack_require__.m = modules;
32/******/
33/******/ 	// expose the module cache
34/******/ 	__webpack_require__.c = installedModules;
35/******/
36/******/ 	// define getter function for harmony exports
37/******/ 	__webpack_require__.d = function(exports, name, getter) {
38/******/ 		if(!__webpack_require__.o(exports, name)) {
39/******/ 			Object.defineProperty(exports, name, { enumerable: true, get: getter });
40/******/ 		}
41/******/ 	};
42/******/
43/******/ 	// define __esModule on exports
44/******/ 	__webpack_require__.r = function(exports) {
45/******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
46/******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
47/******/ 		}
48/******/ 		Object.defineProperty(exports, '__esModule', { value: true });
49/******/ 	};
50/******/
51/******/ 	// create a fake namespace object
52/******/ 	// mode & 1: value is a module id, require it
53/******/ 	// mode & 2: merge all properties of value into the ns
54/******/ 	// mode & 4: return value when already ns object
55/******/ 	// mode & 8|1: behave like require
56/******/ 	__webpack_require__.t = function(value, mode) {
57/******/ 		if(mode & 1) value = __webpack_require__(value);
58/******/ 		if(mode & 8) return value;
59/******/ 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
60/******/ 		var ns = Object.create(null);
61/******/ 		__webpack_require__.r(ns);
62/******/ 		Object.defineProperty(ns, 'default', { enumerable: true, value: value });
63/******/ 		if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
64/******/ 		return ns;
65/******/ 	};
66/******/
67/******/ 	// getDefaultExport function for compatibility with non-harmony modules
68/******/ 	__webpack_require__.n = function(module) {
69/******/ 		var getter = module && module.__esModule ?
70/******/ 			function getDefault() { return module['default']; } :
71/******/ 			function getModuleExports() { return module; };
72/******/ 		__webpack_require__.d(getter, 'a', getter);
73/******/ 		return getter;
74/******/ 	};
75/******/
76/******/ 	// Object.prototype.hasOwnProperty.call
77/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
78/******/
79/******/ 	// __webpack_public_path__
80/******/ 	__webpack_require__.p = "";
81/******/
82/******/
83/******/ 	// Load entry module and return exports
84/******/ 	return __webpack_require__(__webpack_require__.s = 0);
85/******/ })
86/************************************************************************/
87/******/ ({
88
89/***/ "./
89Frontend/JavaScript/src/public/main.js":
90/*!************************************************!*\
91  !*** ./Frontend/JavaScript/src/public/main.js ***!
92  \************************************************/
93/*! no static exports found */
94/***/ (function(module, exports, __webpack_require__) {
95
96/**
97 * JS App main file.
98 *
99 * Main file, as an entry point, for the JS Application and to bootstrap it.
100 *
101 * @author: SIEN
102 * @since:  2020.04.7
103 * dt-helper.js
104 *
105 * JS helpers for datatables
106 */
107var $ = __webpack_require__(/*! jquery */ "./node_modules/jquery/dist/jquery.js");
108
109var Datatables = __webpack_require__(/*! datatables.net */ "./node_modules/datatables.net/js/jquery.dataTables.js");
110
111__webpack_require__(/*! datatables.net-responsive */ "./node_modules/datatables.net-responsive/js/dataTables.responsive.js");
112
113$(document).ready(function () {
114  $(".tx_newspapers").DataTable({
115    order: [[0, "desc"]],
116    pagingType: "numbers",
117    bInfo: false,
118    stateSave: false,
119    sDom: '<"H"lfrp>t<"F"ip>',
120    language: {
121      processing: "Traitement en cours...",
122      search: "Rechercher&nbsp;:",
123      lengthMenu: "Afficher _MENU_ &eacute;l&eacute;ments",
124      info: "Affichage de l'&eacute;lement _START_ &agrave; _END_ sur _TOTAL_ &eacute;l&eacute;ments",
125      infoEmpty: "Affichage de l'&eacute;lement 0 &agrave; 0 sur 0 &eacute;l&eacute;ments",
126      infoFiltered: "(filtr&eacute; de _MAX_ &eacute;l&eacute;ments au total)",
127      infoPostFix: "",
128      loadingRecords: "Chargement en cours...",
129      zeroRecords: "Aucun &eacute;l&eacute;ment &agrave; afficher",
130      emptyTable: "Aucune donnée disponible dans le tableau",
131      paginate: {
132        first: "Premier",
133        previous: "Pr&eacute;c&eacute;dent",
134        next: "Suivant",
135        last: "Dernier"
136      },
137      aria: {
138        sortAscending: ": activer pour trier la colonne par ordre croissant",
139        sortDescending: ": activer pour trier la colonne par ordre décroissant"
140      }
141    }
142  });
143});
144
145/***/ }),
146
147/***/ "./Frontend/SCSS/main.scss":
148/*!*********************************!*\
149  !*** ./Frontend/SCSS/main.scss ***!
150  \*********************************/
151/*! no static exports found */
152/***/ (function(module, exports, __webpack_require__) {
153
154var api = __webpack_require__(/*! ../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js */ "./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js");
155            var content = __webpack_require__(/*! !../../node_modules/mini-css-extract-plugin/dist/loader.js!../../node_modules/css-loader/dist/cjs.js??ref--6-2!../../node_modules/postcss-loader/src??ref--6-3!../../node_modules/sass-loader/dist/cjs.js??ref--6-4!./main.scss */ "./node_modules/mini-css-extract-plugin/dist/loader.js!./node_modules/css-loader/dist/cjs.js?!./node_modules/postcss-loader/src/index.js?!./node_modules/sass-loader/dist/cjs.js?!./Frontend/SCSS/main.scss");
156
157            content = content.__esModule ? content.default : content;
158
159            if (typeof content === 'string') {
160              content = [[module.i, content, '']];
161            }
162
163var options = {};
164
165options.insert = "head";
166options.singleton = false;
167
168var update = api(content, options);
169
170
171
172module.exports = content.locals || {};
173
174/***/ }),
175
vendor: 41,064 bytes, lines 176-1644
176/***/ "./node_modules/datatables.net-responsive/js/dataTables.responsive.js":
177/*!****************************************************************************!*\
178  !*** ./node_modules/datatables.net-responsive/js/dataTables.responsive.js ***!
179  \****************************************************************************/
180/*! no static exports found */
181/***/ (function(module, exports, __webpack_require__) {
182
183var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*! Responsive 2.2.7
184 * 2014-2021 SpryMedia Ltd - datatables.net/license
185 */
186
187/**
188 * @summary     Responsive
189 * @description Responsive tables plug-in for DataTables
190 * @version     2.2.7
191 * @file        dataTables.responsive.js
192 * @author      SpryMedia Ltd (www.sprymedia.co.uk)
193 * @contact     www.sprymedia.co.uk/contact
194 * @copyright   Copyright 2014-2021 SpryMedia Ltd.
195 *
196 * This source file is free software, available under the following license:
197 *   MIT license - http://datatables.net/license/mit
198 *
199 * This source file is distributed in the hope that it will be useful, but
200 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
201 * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
202 *
203 * For details please refer to: http://www.datatables.net
204 */
205(function( factory ){
206	if ( true ) {
207		// AMD
208		!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! jquery */ "./node_modules/jquery/dist/jquery.js"), __webpack_require__(/*! datatables.net */ "./node_modules/datatables.net/js/jquery.dataTables.js")], __WEBPACK_AMD_DEFINE_RESULT__ = (function ( $ ) {
209			return factory( $, window, document );
210		}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
211				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
212	}
213	else {}
214}(function( $, window, document, undefined ) {
215'use strict';
216var DataTable = $.fn.dataTable;
217
218
219/**
220 * Responsive is a plug-in for the DataTables library that makes use of
221 * DataTables' ability to change the visibility of columns, changing the
222 * visibility of columns so the displayed columns fit into the table container.
223 * The end result is that complex tables will be dynamically adjusted to fit
224 * into the viewport, be it on a desktop, tablet or mobile browser.
225 *
226 * Responsive for DataTables has two modes of operation, which can used
227 * individually or combined:
228 *
229 * * Class name based control - columns assigned class names that match the
230 *   breakpoint logic can be shown / hidden as required for each breakpoint.
231 * * Automatic control - columns are automatically hidden when there is no
232 *   room left to display them. Columns removed from the right.
233 *
234 * In additional to column visibility control, Responsive also has built into
235 * options to use DataTables' child row display to show / hide the information
236 * from the table that has been hidden. There are also two modes of operation
237 * for this child row display:
238 *
239 * * Inline - when the control element that the user can use to show / hide
240 *   child rows is displayed inside the first column of the table.
241 * * Column - where a whole column is dedicated to be the show / hide control.
242 *
243 * Initialisation of Responsive is performed by:
244 *
245 * * Adding the class `responsive` or `dt-responsive` to the table. In this case
246 *   Responsive will automatically be initialised with the default configuration
247 *   options when the DataTable is created.
248 * * Using the `responsive` option in the DataTables configuration options. This
249 *   can also be used to specify the configuration options, or simply set to
250 *   `true` to use the defaults.
251 *
252 *  @class
253 *  @param {object} settings DataTables settings object for the host table
254 *  @param {object} [opts] Configuration options
255 *  @requires jQuery 1.7+
256 *  @requires DataTables 1.10.3+
257 *
258 *  @example
259 *      $('#example').DataTable( {
260 *        responsive: true
261 *      } );
262 *    } );
263 */
264var Responsive = function ( settings, opts ) {
265	// Sanity check that we are using DataTables 1.10 or newer
266	if ( ! DataTable.versionCheck || ! DataTable.versionCheck( '1.10.10' ) ) {
267		throw 'DataTables Responsive requires DataTables 1.10.10 or newer';
268	}
269
270	this.s = {
271		dt: new DataTable.Api( settings ),
272		columns: [],
273		current: []
274	};
275
276	// Check if responsive has already been initialised on this table
277	if ( this.s.dt.settings()[0].responsive ) {
278		return;
279	}
280
281	// details is an object, but for simplicity the user can give it as a string
282	// or a boolean
283	if ( opts && typeof opts.details === 'string' ) {
284		opts.details = { type: opts.details };
285	}
286	else if ( opts && opts.details === false ) {
287		opts.details = { type: false };
288	}
289	else if ( opts && opts.details === true ) {
290		opts.details = { type: 'inline' };
291	}
292
293	this.c = $.extend( true, {}, Responsive.defaults, DataTable.defaults.responsive, opts );
294	settings.responsive = this;
295	this._constructor();
296};
297
298$.extend( Responsive.prototype, {
299	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
300	 * Constructor
301	 */
302
303	/**
304	 * Initialise the Responsive instance
305	 *
306	 * @private
307	 */
308	_constructor: function ()
309	{
310		var that = this;
311		var dt = this.s.dt;
312		var dtPrivateSettings = dt.settings()[0];
313		var oldWindowWidth = $(window).innerWidth();
314
315		dt.settings()[0]._responsive = this;
316
317		// Use DataTables' throttle function to avoid processor thrashing on
318		// resize
319		$(window).on( 'resize.dtr orientationchange.dtr', DataTable.util.throttle( function () {
320			// iOS has a bug whereby resize can fire when only scrolling
321			// See: http://stackoverflow.com/questions/8898412
322			var width = $(window).innerWidth();
323
324			if ( width !== oldWindowWidth ) {
325				that._resize();
326				oldWindowWidth = width;
327			}
328		} ) );
329
330		// DataTables doesn't currently trigger an event when a row is added, so
331		// we need to hook into its private API to enforce the hidden rows when
332		// new data is added
333		dtPrivateSettings.oApi._fnCallbackReg( dtPrivateSettings, 'aoRowCreatedCallback', function (tr, data, idx) {
334			if ( $.inArray( false, that.s.current ) !== -1 ) {
335				$('>td, >th', tr).each( function ( i ) {
336					var idx = dt.column.index( 'toData', i );
337
338					if ( that.s.current[idx] === false ) {
339						$(this).css('display', 'none');
340					}
341				} );
342			}
343		} );
344
345		// Destroy event handler
346		dt.on( 'destroy.dtr', function () {
347			dt.off( '.dtr' );
348			$( dt.table().body() ).off( '.dtr' );
349			$(window).off( 'resize.dtr orientationchange.dtr' );
350			dt.cells('.dtr-control').nodes().to$().removeClass('dtr-control');
351
352			// Restore the columns that we've hidden
353			$.each( that.s.current, function ( i, val ) {
354				if ( val === false ) {
355					that._setColumnVis( i, true );
356				}
357			} );
358		} );
359
360		// Reorder the breakpoints array here in case they have been added out
361		// of order
362		this.c.breakpoints.sort( function (a, b) {
363			return a.width < b.width ? 1 :
364				a.width > b.width ? -1 : 0;
365		} );
366
367		this._classLogic();
368		this._resizeAuto();
369
370		// Details handler
371		var details = this.c.details;
372
373		if ( details.type !== false ) {
374			that._detailsInit();
375
376			// DataTables will trigger this event on every column it shows and
377			// hides individually
378			dt.on( 'column-visibility.dtr', function () {
379				// Use a small debounce to allow multiple columns to be set together
380				if ( that._timer ) {
381					clearTimeout( that._timer );
382				}
383
384				that._timer = setTimeout( function () {
385					that._timer = null;
386
387					that._classLogic();
388					that._resizeAuto();
389					that._resize(true);
390
391					that._redrawChildren();
392				}, 100 );
393			} );
394
395			// Redraw the details box on each draw which will happen if the data
396			// has changed. This is used until DataTables implements a native
397			// `updated` event for rows
398			dt.on( 'draw.dtr', function () {
399				that._redrawChildren();
400			} );
401
402			$(dt.table().node()).addClass( 'dtr-'+details.type );
403		}
404
405		dt.on( 'column-reorder.dtr', function (e, settings, details) {
406			that._classLogic();
407			that._resizeAuto();
408			that._resize(true);
409		} );
410
411		// Change in column sizes means we need to calc
412		dt.on( 'column-sizing.dtr', function () {
413			that._resizeAuto();
414			that._resize();
415		});
416
417		// On Ajax reload we want to reopen any child rows which are displayed
418		// by responsive
419		dt.on( 'preXhr.dtr', function () {
420			var rowIds = [];
421			dt.rows().every( function () {
422				if ( this.child.isShown() ) {
423					rowIds.push( this.id(true) );
424				}
425			} );
426
427			dt.one( 'draw.dtr', function () {
428				that._resizeAuto();
429				that._resize();
430
431				dt.rows( rowIds ).every( function () {
432					that._detailsDisplay( this, false );
433				} );
434			} );
435		});
436
437		dt
438			.on( 'draw.dtr', function () {
439				that._controlClass();
440			})
441			.on( 'init.dtr', function (e, settings, details) {
442				if ( e.namespace !== 'dt' ) {
443					return;
444				}
445
446				that._resizeAuto();
447				that._resize();
448
449				// If columns were hidden, then DataTables needs to adjust the
450				// column sizing
451				if ( $.inArray( false, that.s.current ) ) {
452					dt.columns.adjust();
453				}
454			} );
455
456		// First pass - draw the table for the current viewport size
457		this._resize();
458	},
459
460
461	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
462	 * Private methods
463	 */
464
465	/**
466	 * Calculate the visibility for the columns in a table for a given
467	 * breakpoint. The result is pre-determined based on the class logic if
468	 * class names are used to control all columns, but the width of the table
469	 * is also used if there are columns which are to be automatically shown
470	 * and hidden.
471	 *
472	 * @param  {string} breakpoint Breakpoint name to use for the calculation
473	 * @return {array} Array of boolean values initiating the visibility of each
474	 *   column.
475	 *  @private
476	 */
477	_columnsVisiblity: function ( breakpoint )
478	{
479		var dt = this.s.dt;
480		var columns = this.s.columns;
481		var i, ien;
482
483		// Create an array that defines the column ordering based first on the
484		// column's priority, and secondly the column index. This allows the
485		// columns to be removed from the right if the priority matches
486		var order = columns
487			.map( function ( col, idx ) {
488				return {
489					columnIdx: idx,
490					priority: col.priority
491				};
492			} )
493			.sort( function ( a, b ) {
494				if ( a.priority !== b.priority ) {
495					return a.priority - b.priority;
496				}
497				return a.columnIdx - b.columnIdx;
498			} );
499
500		// Class logic - determine which columns are in this breakpoint based
501		// on the classes. If no class control (i.e. `auto`) then `-` is used
502		// to indicate this to the rest of the function
503		var display = $.map( columns, function ( col, i ) {
504			if ( dt.column(i).visible() === false ) {
505				return 'not-visible';
506			}
507			return col.auto && col.minWidth === null ?
508				false :
509				col.auto === true ?
510					'-' :
511					$.inArray( breakpoint, col.includeIn ) !== -1;
512		} );
513
514		// Auto column control - first pass: how much width is taken by the
515		// ones that must be included from the non-auto columns
516		var requiredWidth = 0;
517		for ( i=0, ien=display.length ; i<ien ; i++ ) {
518			if ( display[i] === true ) {
519				requiredWidth += columns[i].minWidth;
520			}
521		}
522
523		// Second pass, use up any remaining width for other columns. For
524		// scrolling tables we need to subtract the width of the scrollbar. It
525		// may not be requires which makes this sub-optimal, but it would
526		// require another full redraw to make complete use of those extra few
527		// pixels
528		var scrolling = dt.settings()[0].oScroll;
529		var bar = scrolling.sY || scrolling.sX ? scrolling.iBarWidth : 0;
530		var widthAvailable = dt.table().container().offsetWidth - bar;
531		var usedWidth = widthAvailable - requiredWidth;
532
533		// Control column needs to always be included. This makes it sub-
534		// optimal in terms of using the available with, but to stop layout
535		// thrashing or overflow. Also we need to account for the control column
536		// width first so we know how much width is available for the other
537		// columns, since the control column might not be the first one shown
538		for ( i=0, ien=display.length ; i<ien ; i++ ) {
539			if ( columns[i].control ) {
540				usedWidth -= columns[i].minWidth;
541			}
542		}
543
544		// Allow columns to be shown (counting by priority and then right to
545		// left) until we run out of room
546		var empty = false;
547		for ( i=0, ien=order.length ; i<ien ; i++ ) {
548			var colIdx = order[i].columnIdx;
549
550			if ( display[colIdx] === '-' && ! columns[colIdx].control && columns[colIdx].minWidth ) {
551				// Once we've found a column that won't fit we don't let any
552				// others display either, or columns might disappear in the
553				// middle of the table
554				if ( empty || usedWidth - columns[colIdx].minWidth < 0 ) {
555					empty = true;
556					display[colIdx] = false;
557				}
558				else {
559					display[colIdx] = true;
560				}
561
562				usedWidth -= columns[colIdx].minWidth;
563			}
564		}
565
566		// Determine if the 'control' column should be shown (if there is one).
567		// This is the case when there is a hidden column (that is not the
568		// control column). The two loops look inefficient here, but they are
569		// trivial and will fly through. We need to know the outcome from the
570		// first , before the action in the second can be taken
571		var showControl = false;
572
573		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
574			if ( ! columns[i].control && ! columns[i].never && display[i] === false ) {
575				showControl = true;
576				break;
577			}
578		}
579
580		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
581			if ( columns[i].control ) {
582				display[i] = showControl;
583			}
584
585			// Replace not visible string with false from the control column detection above
586			if ( display[i] === 'not-visible' ) {
587				display[i] = false;
588			}
589		}
590
591		// Finally we need to make sure that there is at least one column that
592		// is visible
593		if ( $.inArray( true, display ) === -1 ) {
594			display[0] = true;
595		}
596
597		return display;
598	},
599
600
601	/**
602	 * Create the internal `columns` array with information about the columns
603	 * for the table. This includes determining which breakpoints the column
604	 * will appear in, based upon class names in the column, which makes up the
605	 * vast majority of this method.
606	 *
607	 * @private
608	 */
609	_classLogic: function ()
610	{
611		var that = this;
612		var calc = {};
613		var breakpoints = this.c.breakpoints;
614		var dt = this.s.dt;
615		var columns = dt.columns().eq(0).map( function (i) {
616			var column = this.column(i);
617			var className = column.header().className;
618			var priority = dt.settings()[0].aoColumns[i].responsivePriority;
619			var dataPriority = column.header().getAttribute('data-priority');
620
621			if ( priority === undefined ) {
622				priority = dataPriority === undefined || dataPriority === null?
623					10000 :
624					dataPriority * 1;
625			}
626
627			return {
628				className: className,
629				includeIn: [],
630				auto:      false,
631				control:   false,
632				never:     className.match(/\bnever\b/) ? true : false,
633				priority:  priority
634			};
635		} );
636
637		// Simply add a breakpoint to `includeIn` array, ensuring that there are
638		// no duplicates
639		var add = function ( colIdx, name ) {
640			var includeIn = columns[ colIdx ].includeIn;
641
642			if ( $.inArray( name, includeIn ) === -1 ) {
643				includeIn.push( name );
644			}
645		};
646
647		var column = function ( colIdx, name, operator, matched ) {
648			var size, i, ien;
649
650			if ( ! operator ) {
651				columns[ colIdx ].includeIn.push( name );
652			}
653			else if ( operator === 'max-' ) {
654				// Add this breakpoint and all smaller
655				size = that._find( name ).width;
656
657				for ( i=0, ien=breakpoints.length ; i<ien ; i++ ) {
658					if ( breakpoints[i].width <= size ) {
659						add( colIdx, breakpoints[i].name );
660					}
661				}
662			}
663			else if ( operator === 'min-' ) {
664				// Add this breakpoint and all larger
665				size = that._find( name ).width;
666
667				for ( i=0, ien=breakpoints.length ; i<ien ; i++ ) {
668					if ( breakpoints[i].width >= size ) {
669						add( colIdx, breakpoints[i].name );
670					}
671				}
672			}
673			else if ( operator === 'not-' ) {
674				// Add all but this breakpoint
675				for ( i=0, ien=breakpoints.length ; i<ien ; i++ ) {
676					if ( breakpoints[i].name.indexOf( matched ) === -1 ) {
677						add( colIdx, breakpoints[i].name );
678					}
679				}
680			}
681		};
682
683		// Loop over each column and determine if it has a responsive control
684		// class
685		columns.each( function ( col, i ) {
686			var classNames = col.className.split(' ');
687			var hasClass = false;
688
689			// Split the class name up so multiple rules can be applied if needed
690			for ( var k=0, ken=classNames.length ; k<ken ; k++ ) {
691				var className = classNames[k].trim();
692
693				if ( className === 'all' ) {
694					// Include in all
695					hasClass = true;
696					col.includeIn = $.map( breakpoints, function (a) {
697						return a.name;
698					} );
699					return;
700				}
701				else if ( className === 'none' || col.never ) {
702					// Include in none (default) and no auto
703					hasClass = true;
704					return;
705				}
706				else if ( className === 'control' || className === 'dtr-control' ) {
707					// Special column that is only visible, when one of the other
708					// columns is hidden. This is used for the details control
709					hasClass = true;
710					col.control = true;
711					return;
712				}
713
714				$.each( breakpoints, function ( j, breakpoint ) {
715					// Does this column have a class that matches this breakpoint?
716					var brokenPoint = breakpoint.name.split('-');
717					var re = new RegExp( '(min\\-|max\\-|not\\-)?('+brokenPoint[0]+')(\\-[_a-zA-Z0-9])?' );
718					var match = className.match( re );
719
720					if ( match ) {
721						hasClass = true;
722
723						if ( match[2] === brokenPoint[0] && match[3] === '-'+brokenPoint[1] ) {
724							// Class name matches breakpoint name fully
725							column( i, breakpoint.name, match[1], match[2]+match[3] );
726						}
727						else if ( match[2] === brokenPoint[0] && ! match[3] ) {
728							// Class name matched primary breakpoint name with no qualifier
729							column( i, breakpoint.name, match[1], match[2] );
730						}
731					}
732				} );
733			}
734
735			// If there was no control class, then automatic sizing is used
736			if ( ! hasClass ) {
737				col.auto = true;
738			}
739		} );
740
741		this.s.columns = columns;
742	},
743
744	/**
745	 * Update the cells to show the correct control class / button
746	 * @private
747	 */
748	_controlClass: function ()
749	{
750		if ( this.c.details.type === 'inline' ) {
751			var dt = this.s.dt;
752			var columnsVis = this.s.current;
753			var firstVisible = $.inArray(true, columnsVis);
754
755			// Remove from any cells which shouldn't have it
756			dt.cells(
757				null,
758				function(idx) {
759					return idx !== firstVisible;
760				},
761				{page: 'current'}
762			)
763				.nodes()
764				.to$()
765				.filter('.dtr-control')
766				.removeClass('dtr-control');
767
768			dt.cells(null, firstVisible, {page: 'current'})
769				.nodes()
770				.to$()
771				.addClass('dtr-control');
772		}
773	},
774
775	/**
776	 * Show the details for the child row
777	 *
778	 * @param  {DataTables.Api} row    API instance for the row
779	 * @param  {boolean}        update Update flag
780	 * @private
781	 */
782	_detailsDisplay: function ( row, update )
783	{
784		var that = this;
785		var dt = this.s.dt;
786		var details = this.c.details;
787
788		if ( details && details.type !== false ) {
789			var res = details.display( row, update, function () {
790				return details.renderer(
791					dt, row[0], that._detailsObj(row[0])
792				);
793			} );
794
795			if ( res === true || res === false ) {
796				$(dt.table().node()).triggerHandler( 'responsive-display.dt', [dt, row, res, update] );
797			}
798		}
799	},
800
801
802	/**
803	 * Initialisation for the details handler
804	 *
805	 * @private
806	 */
807	_detailsInit: function ()
808	{
809		var that    = this;
810		var dt      = this.s.dt;
811		var details = this.c.details;
812
813		// The inline type always uses the first child as the target
814		if ( details.type === 'inline' ) {
815			details.target = 'td.dtr-control, th.dtr-control';
816		}
817
818		// Keyboard accessibility
819		dt.on( 'draw.dtr', function () {
820			that._tabIndexes();
821		} );
822		that._tabIndexes(); // Initial draw has already happened
823
824		$( dt.table().body() ).on( 'keyup.dtr', 'td, th', function (e) {
825			if ( e.keyCode === 13 && $(this).data('dtr-keyboard') ) {
826				$(this).click();
827			}
828		} );
829
830		// type.target can be a string jQuery selector or a column index
831		var target   = details.target;
832		var selector = typeof target === 'string' ? target : 'td, th';
833
834		if ( target !== undefined || target !== null ) {
835			// Click handler to show / hide the details rows when they are available
836			$( dt.table().body() )
837				.on( 'click.dtr mousedown.dtr mouseup.dtr', selector, function (e) {
838					// If the table is not collapsed (i.e. there is no hidden columns)
839					// then take no action
840					if ( ! $(dt.table().node()).hasClass('collapsed' ) ) {
841						return;
842					}
843
844					// Check that the row is actually a DataTable's controlled node
845					if ( $.inArray( $(this).closest('tr').get(0), dt.rows().nodes().toArray() ) === -1 ) {
846						return;
847					}
848
849					// For column index, we determine if we should act or not in the
850					// handler - otherwise it is already okay
851					if ( typeof target === 'number' ) {
852						var targetIdx = target < 0 ?
853							dt.columns().eq(0).length + target :
854							target;
855
856						if ( dt.cell( this ).index().column !== targetIdx ) {
857							return;
858						}
859					}
860
861					// $().closest() includes itself in its check
862					var row = dt.row( $(this).closest('tr') );
863
864					// Check event type to do an action
865					if ( e.type === 'click' ) {
866						// The renderer is given as a function so the caller can execute it
867						// only when they need (i.e. if hiding there is no point is running
868						// the renderer)
869						that._detailsDisplay( row, false );
870					}
871					else if ( e.type === 'mousedown' ) {
872						// For mouse users, prevent the focus ring from showing
873						$(this).css('outline', 'none');
874					}
875					else if ( e.type === 'mouseup' ) {
876						// And then re-allow at the end of the click
877						$(this).trigger('blur').css('outline', '');
878					}
879				} );
880		}
881	},
882
883
884	/**
885	 * Get the details to pass to a renderer for a row
886	 * @param  {int} rowIdx Row index
887	 * @private
888	 */
889	_detailsObj: function ( rowIdx )
890	{
891		var that = this;
892		var dt = this.s.dt;
893
894		return $.map( this.s.columns, function( col, i ) {
895			// Never and control columns should not be passed to the renderer
896			if ( col.never || col.control ) {
897				return;
898			}
899
900			var dtCol = dt.settings()[0].aoColumns[ i ];
901
902			return {
903				className:   dtCol.sClass,
904				columnIndex: i,
905				data:        dt.cell( rowIdx, i ).render( that.c.orthogonal ),
906				hidden:      dt.column( i ).visible() && !that.s.current[ i ],
907				rowIndex:    rowIdx,
908				title:       dtCol.sTitle !== null ?
909					dtCol.sTitle :
910					$(dt.column(i).header()).text()
911			};
912		} );
913	},
914
915
916	/**
917	 * Find a breakpoint object from a name
918	 *
919	 * @param  {string} name Breakpoint name to find
920	 * @return {object}      Breakpoint description object
921	 * @private
922	 */
923	_find: function ( name )
924	{
925		var breakpoints = this.c.breakpoints;
926
927		for ( var i=0, ien=breakpoints.length ; i<ien ; i++ ) {
928			if ( breakpoints[i].name === name ) {
929				return breakpoints[i];
930			}
931		}
932	},
933
934
935	/**
936	 * Re-create the contents of the child rows as the display has changed in
937	 * some way.
938	 *
939	 * @private
940	 */
941	_redrawChildren: function ()
942	{
943		var that = this;
944		var dt = this.s.dt;
945
946		dt.rows( {page: 'current'} ).iterator( 'row', function ( settings, idx ) {
947			var row = dt.row( idx );
948
949			that._detailsDisplay( dt.row( idx ), true );
950		} );
951	},
952
953
954	/**
955	 * Alter the table display for a resized viewport. This involves first
956	 * determining what breakpoint the window currently is in, getting the
957	 * column visibilities to apply and then setting them.
958	 *
959	 * @param  {boolean} forceRedraw Force a redraw
960	 * @private
961	 */
962	_resize: function (forceRedraw)
963	{
964		var that = this;
965		var dt = this.s.dt;
966		var width = $(window).innerWidth();
967		var breakpoints = this.c.breakpoints;
968		var breakpoint = breakpoints[0].name;
969		var columns = this.s.columns;
970		var i, ien;
971		var oldVis = this.s.current.slice();
972
973		// Determine what breakpoint we are currently at
974		for ( i=breakpoints.length-1 ; i>=0 ; i-- ) {
975			if ( width <= breakpoints[i].width ) {
976				breakpoint = breakpoints[i].name;
977				break;
978			}
979		}
980		
981		// Show the columns for that break point
982		var columnsVis = this._columnsVisiblity( breakpoint );
983		this.s.current = columnsVis;
984
985		// Set the class before the column visibility is changed so event
986		// listeners know what the state is. Need to determine if there are
987		// any columns that are not visible but can be shown
988		var collapsedClass = false;
989	
990		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
991			if ( columnsVis[i] === false && ! columns[i].never && ! columns[i].control && ! dt.column(i).visible() === false ) {
992				collapsedClass = true;
993				break;
994			}
995		}
996
997		$( dt.table().node() ).toggleClass( 'collapsed', collapsedClass );
998
999		var changed = false;
1000		var visible = 0;
1001
1002		dt.columns().eq(0).each( function ( colIdx, i ) {
1003			if ( columnsVis[i] === true ) {
1004				visible++;
1005			}
1006
1007			if ( forceRedraw || columnsVis[i] !== oldVis[i] ) {
1008				changed = true;
1009				that._setColumnVis( colIdx, columnsVis[i] );
1010			}
1011		} );
1012
1013		if ( changed ) {
1014			this._redrawChildren();
1015
1016			// Inform listeners of the change
1017			$(dt.table().node()).trigger( 'responsive-resize.dt', [dt, this.s.current] );
1018
1019			// If no records, update the "No records" display element
1020			if ( dt.page.info().recordsDisplay === 0 ) {
1021				$('td', dt.table().body()).eq(0).attr('colspan', visible);
1022			}
1023		}
1024
1025		that._controlClass();
1026	},
1027
1028
1029	/**
1030	 * Determine the width of each column in the table so the auto column hiding
1031	 * has that information to work with. This method is never going to be 100%
1032	 * perfect since column widths can change slightly per page, but without
1033	 * seriously compromising performance this is quite effective.
1034	 *
1035	 * @private
1036	 */
1037	_resizeAuto: function ()
1038	{
1039		var dt = this.s.dt;
1040		var columns = this.s.columns;
1041
1042		// Are we allowed to do auto sizing?
1043		if ( ! this.c.auto ) {
1044			return;
1045		}
1046
1047		// Are there any columns that actually need auto-sizing, or do they all
1048		// have classes defined
1049		if ( $.inArray( true, $.map( columns, function (c) { return c.auto; } ) ) === -1 ) {
1050			return;
1051		}
1052
1053		// Need to restore all children. They will be reinstated by a re-render
1054		if ( ! $.isEmptyObject( _childNodeStore ) ) {
1055			$.each( _childNodeStore, function ( key ) {
1056				var idx = key.split('-');
1057
1058				_childNodesRestore( dt, idx[0]*1, idx[1]*1 );
1059			} );
1060		}
1061
1062		// Clone the table with the current data in it
1063		var tableWidth   = dt.table().node().offsetWidth;
1064		var columnWidths = dt.columns;
1065		var clonedTable  = dt.table().node().cloneNode( false );
1066		var clonedHeader = $( dt.table().header().cloneNode( false ) ).appendTo( clonedTable );
1067		var clonedBody   = $( dt.table().body() ).clone( false, false ).empty().appendTo( clonedTable ); // use jQuery because of IE8
1068
1069		clonedTable.style.width = 'auto';
1070
1071		// Header
1072		var headerCells = dt.columns()
1073			.header()
1074			.filter( function (idx) {
1075				return dt.column(idx).visible();
1076			} )
1077			.to$()
1078			.clone( false )
1079			.css( 'display', 'table-cell' )
1080			.css( 'width', 'auto' )
1081			.css( 'min-width', 0 );
1082
1083		// Body rows - we don't need to take account of DataTables' column
1084		// visibility since we implement our own here (hence the `display` set)
1085		$(clonedBody)
1086			.append( $(dt.rows( { page: 'current' } ).nodes()).clone( false ) )
1087			.find( 'th, td' ).css( 'display', '' );
1088
1089		// Footer
1090		var footer = dt.table().footer();
1091		if ( footer ) {
1092			var clonedFooter = $( footer.cloneNode( false ) ).appendTo( clonedTable );
1093			var footerCells = dt.columns()
1094				.footer()
1095				.filter( function (idx) {
1096					return dt.column(idx).visible();
1097				} )
1098				.to$()
1099				.clone( false )
1100				.css( 'display', 'table-cell' );
1101
1102			$('<tr/>')
1103				.append( footerCells )
1104				.appendTo( clonedFooter );
1105		}
1106
1107		$('<tr/>')
1108			.append( headerCells )
1109			.appendTo( clonedHeader );
1110
1111		// In the inline case extra padding is applied to the first column to
1112		// give space for the show / hide icon. We need to use this in the
1113		// calculation
1114		if ( this.c.details.type === 'inline' ) {
1115			$(clonedTable).addClass( 'dtr-inline collapsed' );
1116		}
1117		
1118		// It is unsafe to insert elements with the same name into the DOM
1119		// multiple times. For example, cloning and inserting a checked radio
1120		// clears the chcecked state of the original radio.
1121		$( clonedTable ).find( '[name]' ).removeAttr( 'name' );
1122
1123		// A position absolute table would take the table out of the flow of
1124		// our container element, bypassing the height and width (Scroller)
1125		$( clonedTable ).css( 'position', 'relative' )
1126		
1127		var inserted = $('<div/>')
1128			.css( {
1129				width: 1,
1130				height: 1,
1131				overflow: 'hidden',
1132				clear: 'both'
1133			} )
1134			.append( clonedTable );
1135
1136		inserted.insertBefore( dt.table().node() );
1137
1138		// The cloned header now contains the smallest that each column can be
1139		headerCells.each( function (i) {
1140			var idx = dt.column.index( 'fromVisible', i );
1141			columns[ idx ].minWidth =  this.offsetWidth || 0;
1142		} );
1143
1144		inserted.remove();
1145	},
1146
1147	/**
1148	 * Get the state of the current hidden columns - controlled by Responsive only
1149	 */
1150	_responsiveOnlyHidden: function ()
1151	{
1152		var dt = this.s.dt;
1153
1154		return $.map( this.s.current, function (v, i) {
1155			// If the column is hidden by DataTables then it can't be hidden by
1156			// Responsive!
1157			if ( dt.column(i).visible() === false ) {
1158				return true;
1159			}
1160			return v;
1161		} );
1162	},
1163
1164	/**
1165	 * Set a column's visibility.
1166	 *
1167	 * We don't use DataTables' column visibility controls in order to ensure
1168	 * that column visibility can Responsive can no-exist. Since only IE8+ is
1169	 * supported (and all evergreen browsers of course) the control of the
1170	 * display attribute works well.
1171	 *
1172	 * @param {integer} col      Column index
1173	 * @param {boolean} showHide Show or hide (true or false)
1174	 * @private
1175	 */
1176	_setColumnVis: function ( col, showHide )
1177	{
1178		var dt = this.s.dt;
1179		var display = showHide ? '' : 'none'; // empty string will remove the attr
1180
1181		$( dt.column( col ).header() ).css( 'display', display );
1182		$( dt.column( col ).footer() ).css( 'display', display );
1183		dt.column( col ).nodes().to$().css( 'display', display );
1184
1185		// If the are child nodes stored, we might need to reinsert them
1186		if ( ! $.isEmptyObject( _childNodeStore ) ) {
1187			dt.cells( null, col ).indexes().each( function (idx) {
1188				_childNodesRestore( dt, idx.row, idx.column );
1189			} );
1190		}
1191	},
1192
1193
1194	/**
1195	 * Update the cell tab indexes for keyboard accessibility. This is called on
1196	 * every table draw - that is potentially inefficient, but also the least
1197	 * complex option given that column visibility can change on the fly. Its a
1198	 * shame user-focus was removed from CSS 3 UI, as it would have solved this
1199	 * issue with a single CSS statement.
1200	 *
1201	 * @private
1202	 */
1203	_tabIndexes: function ()
1204	{
1205		var dt = this.s.dt;
1206		var cells = dt.cells( { page: 'current' } ).nodes().to$();
1207		var ctx = dt.settings()[0];
1208		var target = this.c.details.target;
1209
1210		cells.filter( '[data-dtr-keyboard]' ).removeData( '[data-dtr-keyboard]' );
1211
1212		if ( typeof target === 'number' ) {
1213			dt.cells( null, target, { page: 'current' } ).nodes().to$()
1214				.attr( 'tabIndex', ctx.iTabIndex )
1215				.data( 'dtr-keyboard', 1 );
1216		}
1217		else {
1218			// This is a bit of a hack - we need to limit the selected nodes to just
1219			// those of this table
1220			if ( target === 'td:first-child, th:first-child' ) {
1221				target = '>td:first-child, >th:first-child';
1222			}
1223
1224			$( target, dt.rows( { page: 'current' } ).nodes() )
1225				.attr( 'tabIndex', ctx.iTabIndex )
1226				.data( 'dtr-keyboard', 1 );
1227		}
1228	}
1229} );
1230
1231
1232/**
1233 * List of default breakpoints. Each item in the array is an object with two
1234 * properties:
1235 *
1236 * * `name` - the breakpoint name.
1237 * * `width` - the breakpoint width
1238 *
1239 * @name Responsive.breakpoints
1240 * @static
1241 */
1242Responsive.breakpoints = [
1243	{ name: 'desktop',  width: Infinity },
1244	{ name: 'tablet-l', width: 1024 },
1245	{ name: 'tablet-p', width: 768 },
1246	{ name: 'mobile-l', width: 480 },
1247	{ name: 'mobile-p', width: 320 }
1248];
1249
1250
1251/**
1252 * Display methods - functions which define how the hidden data should be shown
1253 * in the table.
1254 *
1255 * @namespace
1256 * @name Responsive.defaults
1257 * @static
1258 */
1259Responsive.display = {
1260	childRow: function ( row, update, render ) {
1261		if ( update ) {
1262			if ( $(row.node()).hasClass('parent') ) {
1263				row.child( render(), 'child' ).show();
1264
1265				return true;
1266			}
1267		}
1268		else {
1269			if ( ! row.child.isShown()  ) {
1270				row.child( render(), 'child' ).show();
1271				$( row.node() ).addClass( 'parent' );
1272
1273				return true;
1274			}
1275			else {
1276				row.child( false );
1277				$( row.node() ).removeClass( 'parent' );
1278
1279				return false;
1280			}
1281		}
1282	},
1283
1284	childRowImmediate: function ( row, update, render ) {
1285		if ( (! update && row.child.isShown()) || ! row.responsive.hasHidden() ) {
1286			// User interaction and the row is show, or nothing to show
1287			row.child( false );
1288			$( row.node() ).removeClass( 'parent' );
1289
1290			return false;
1291		}
1292		else {
1293			// Display
1294			row.child( render(), 'child' ).show();
1295			$( row.node() ).addClass( 'parent' );
1296
1297			return true;
1298		}
1299	},
1300
1301	// This is a wrapper so the modal options for Bootstrap and jQuery UI can
1302	// have options passed into them. This specific one doesn't need to be a
1303	// function but it is for consistency in the `modal` name
1304	modal: function ( options ) {
1305		return function ( row, update, render ) {
1306			if ( ! update ) {
1307				// Show a modal
1308				var close = function () {
1309					modal.remove(); // will tidy events for us
1310					$(document).off( 'keypress.dtr' );
1311				};
1312
1313				var modal = $('<div class="dtr-modal"/>')
1314					.append( $('<div class="dtr-modal-display"/>')
1315						.append( $('<div class="dtr-modal-content"/>')
1316							.append( render() )
1317						)
1318						.append( $('<div class="dtr-modal-close">&times;</div>' )
1319							.click( function () {
1320								close();
1321							} )
1322						)
1323					)
1324					.append( $('<div class="dtr-modal-background"/>')
1325						.click( function () {
1326							close();
1327						} )
1328					)
1329					.appendTo( 'body' );
1330
1331				$(document).on( 'keyup.dtr', function (e) {
1332					if ( e.keyCode === 27 ) {
1333						e.stopPropagation();
1334
1335						close();
1336					}
1337				} );
1338			}
1339			else {
1340				$('div.dtr-modal-content')
1341					.empty()
1342					.append( render() );
1343			}
1344
1345			if ( options && options.header ) {
1346				$('div.dtr-modal-content').prepend(
1347					'<h2>'+options.header( row )+'</h2>'
1348				);
1349			}
1350		};
1351	}
1352};
1353
1354
1355var _childNodeStore = {};
1356
1357function _childNodes( dt, row, col ) {
1358	var name = row+'-'+col;
1359
1360	if ( _childNodeStore[ name ] ) {
1361		return _childNodeStore[ name ];
1362	}
1363
1364	// https://jsperf.com/childnodes-array-slice-vs-loop
1365	var nodes = [];
1366	var children = dt.cell( row, col ).node().childNodes;
1367	for ( var i=0, ien=children.length ; i<ien ; i++ ) {
1368		nodes.push( children[i] );
1369	}
1370
1371	_childNodeStore[ name ] = nodes;
1372
1373	return nodes;
1374}
1375
1376function _childNodesRestore( dt, row, col ) {
1377	var name = row+'-'+col;
1378
1379	if ( ! _childNodeStore[ name ] ) {
1380		return;
1381	}
1382
1383	var node = dt.cell( row, col ).node();
1384	var store = _childNodeStore[ name ];
1385	var parent = store[0].parentNode;
1386	var parentChildren = parent.childNodes;
1387	var a = [];
1388
1389	for ( var i=0, ien=parentChildren.length ; i<ien ; i++ ) {
1390		a.push( parentChildren[i] );
1391	}
1392
1393	for ( var j=0, jen=a.length ; j<jen ; j++ ) {
1394		node.appendChild( a[j] );
1395	}
1396
1397	_childNodeStore[ name ] = undefined;
1398}
1399
1400
1401/**
1402 * Display methods - functions which define how the hidden data should be shown
1403 * in the table.
1404 *
1405 * @namespace
1406 * @name Responsive.defaults
1407 * @static
1408 */
1409Responsive.renderer = {
1410	listHiddenNodes: function () {
1411		return function ( api, rowIdx, columns ) {
1412			var ul = $('<ul data-dtr-index="'+rowIdx+'" class="dtr-details"/>');
1413			var found = false;
1414
1415			var data = $.each( columns, function ( i, col ) {
1416				if ( col.hidden ) {
1417					var klass = col.className ?
1418						'class="'+ col.className +'"' :
1419						'';
1420	
1421					$(
1422						'<li '+klass+' data-dtr-index="'+col.columnIndex+'" data-dt-row="'+col.rowIndex+'" data-dt-column="'+col.columnIndex+'">'+
1423							'<span class="dtr-title">'+
1424								col.title+
1425							'</span> '+
1426						'</li>'
1427					)
1428						.append( $('<span class="dtr-data"/>').append( _childNodes( api, col.rowIndex, col.columnIndex ) ) )// api.cell( col.rowIndex, col.columnIndex ).node().childNodes ) )
1429						.appendTo( ul );
1430
1431					found = true;
1432				}
1433			} );
1434
1435			return found ?
1436				ul :
1437				false;
1438		};
1439	},
1440
1441	listHidden: function () {
1442		return function ( api, rowIdx, columns ) {
1443			var data = $.map( columns, function ( col ) {
1444				var klass = col.className ?
1445					'class="'+ col.className +'"' :
1446					'';
1447
1448				return col.hidden ?
1449					'<li '+klass+' data-dtr-index="'+col.columnIndex+'" data-dt-row="'+col.rowIndex+'" data-dt-column="'+col.columnIndex+'">'+
1450						'<span class="dtr-title">'+
1451							col.title+
1452						'</span> '+
1453						'<span class="dtr-data">'+
1454							col.data+
1455						'</span>'+
1456					'</li>' :
1457					'';
1458			} ).join('');
1459
1460			return data ?
1461				$('<ul data-dtr-index="'+rowIdx+'" class="dtr-details"/>').append( data ) :
1462				false;
1463		}
1464	},
1465
1466	tableAll: function ( options ) {
1467		options = $.extend( {
1468			tableClass: ''
1469		}, options );
1470
1471		return function ( api, rowIdx, columns ) {
1472			var data = $.map( columns, function ( col ) {
1473				var klass = col.className ?
1474					'class="'+ col.className +'"' :
1475					'';
1476
1477				return '<tr '+klass+' data-dt-row="'+col.rowIndex+'" data-dt-column="'+col.columnIndex+'">'+
1478						'<td>'+col.title+':'+'</td> '+
1479						'<td>'+col.data+'</td>'+
1480					'</tr>';
1481			} ).join('');
1482
1483			return $('<table class="'+options.tableClass+' dtr-details" width="100%"/>').append( data );
1484		}
1485	}
1486};
1487
1488/**
1489 * Responsive default settings for initialisation
1490 *
1491 * @namespace
1492 * @name Responsive.defaults
1493 * @static
1494 */
1495Responsive.defaults = {
1496	/**
1497	 * List of breakpoints for the instance. Note that this means that each
1498	 * instance can have its own breakpoints. Additionally, the breakpoints
1499	 * cannot be changed once an instance has been creased.
1500	 *
1501	 * @type {Array}
1502	 * @default Takes the value of `Responsive.breakpoints`
1503	 */
1504	breakpoints: Responsive.breakpoints,
1505
1506	/**
1507	 * Enable / disable auto hiding calculations. It can help to increase
1508	 * performance slightly if you disable this option, but all columns would
1509	 * need to have breakpoint classes assigned to them
1510	 *
1511	 * @type {Boolean}
1512	 * @default  `true`
1513	 */
1514	auto: true,
1515
1516	/**
1517	 * Details control. If given as a string value, the `type` property of the
1518	 * default object is set to that value, and the defaults used for the rest
1519	 * of the object - this is for ease of implementation.
1520	 *
1521	 * The object consists of the following properties:
1522	 *
1523	 * * `display` - A function that is used to show and hide the hidden details
1524	 * * `renderer` - function that is called for display of the child row data.
1525	 *   The default function will show the data from the hidden columns
1526	 * * `target` - Used as the selector for what objects to attach the child
1527	 *   open / close to
1528	 * * `type` - `false` to disable the details display, `inline` or `column`
1529	 *   for the two control types
1530	 *
1531	 * @type {Object|string}
1532	 */
1533	details: {
1534		display: Responsive.display.childRow,
1535
1536		renderer: Responsive.renderer.listHidden(),
1537
1538		target: 0,
1539
1540		type: 'inline'
1541	},
1542
1543	/**
1544	 * Orthogonal data request option. This is used to define the data type
1545	 * requested when Responsive gets the data to show in the child row.
1546	 *
1547	 * @type {String}
1548	 */
1549	orthogonal: 'display'
1550};
1551
1552
1553/*
1554 * API
1555 */
1556var Api = $.fn.dataTable.Api;
1557
1558// Doesn't do anything - work around for a bug in DT... Not documented
1559Api.register( 'responsive()', function () {
1560	return this;
1561} );
1562
1563Api.register( 'responsive.index()', function ( li ) {
1564	li = $(li);
1565
1566	return {
1567		column: li.data('dtr-index'),
1568		row:    li.parent().data('dtr-index')
1569	};
1570} );
1571
1572Api.register( 'responsive.rebuild()', function () {
1573	return this.iterator( 'table', function ( ctx ) {
1574		if ( ctx._responsive ) {
1575			ctx._responsive._classLogic();
1576		}
1577	} );
1578} );
1579
1580Api.register( 'responsive.recalc()', function () {
1581	return this.iterator( 'table', function ( ctx ) {
1582		if ( ctx._responsive ) {
1583			ctx._responsive._resizeAuto();
1584			ctx._responsive._resize();
1585		}
1586	} );
1587} );
1588
1589Api.register( 'responsive.hasHidden()', function () {
1590	var ctx = this.context[0];
1591
1592	return ctx._responsive ?
1593		$.inArray( false, ctx._responsive._responsiveOnlyHidden() ) !== -1 :
1594		false;
1595} );
1596
1597Api.registerPlural( 'columns().responsiveHidden()', 'column().responsiveHidden()', function () {
1598	return this.iterator( 'column', function ( settings, column ) {
1599		return settings._responsive ?
1600			settings._responsive._responsiveOnlyHidden()[ column ] :
1601			false;
1602	}, 1 );
1603} );
1604
1605
1606/**
1607 * Version information
1608 *
1609 * @name Responsive.version
1610 * @static
1611 */
1612Responsive.version = '2.2.7';
1613
1614
1615$.fn.dataTable.Responsive = Responsive;
1616$.fn.DataTable.Responsive = Responsive;
1617
1618// Attach a listener to the document which listens for DataTables initialisation
1619// events so we can automatically initialise
1620$(document).on( 'preInit.dt.dtr', function (e, settings, json) {
1621	if ( e.namespace !== 'dt' ) {
1622		return;
1623	}
1624
1625	if ( $(settings.nTable).hasClass( 'responsive' ) ||
1626		 $(settings.nTable).hasClass( 'dt-responsive' ) ||
1627		 settings.oInit.responsive ||
1628		 DataTable.defaults.responsive
1629	) {
1630		var init = settings.oInit.responsive;
1631
1632		if ( init !== false ) {
1633			new Responsive( settings, $.isPlainObject( init ) ? init : {}  );
1634		}
1635	}
1636} );
1637
1638
1639return Responsive;
1640}));
1641
1642
1643/***/ }),
1644
vendor: 450,516 bytes, lines 1645-17022
1645/***/ "./node_modules/datatables.net/js/jquery.dataTables.js":
1646/*!*************************************************************!*\
1647  !*** ./node_modules/datatables.net/js/jquery.dataTables.js ***!
1648  \*************************************************************/
1649/*! no static exports found */
1650/***/ (function(module, exports, __webpack_require__) {
1651
1652var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*! DataTables 1.10.24
1653 * ©2008-2021 SpryMedia Ltd - datatables.net/license
1654 */
1655
1656/**
1657 * @summary     DataTables
1658 * @description Paginate, search and order HTML tables
1659 * @version     1.10.24
1660 * @file        jquery.dataTables.js
1661 * @author      SpryMedia Ltd
1662 * @contact     www.datatables.net
1663 * @copyright   Copyright 2008-2021 SpryMedia Ltd.
1664 *
1665 * This source file is free software, available under the following license:
1666 *   MIT license - http://datatables.net/license
1667 *
1668 * This source file is distributed in the hope that it will be useful, but
1669 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1670 * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
1671 *
1672 * For details please refer to: http://www.datatables.net
1673 */
1674
1675/*jslint evil: true, undef: true, browser: true */
1676/*globals $,require,jQuery,define,_selector_run,_selector_opts,_selector_first,_selector_row_indexes,_ext,_Api,_api_register,_api_registerPlural,_re_new_lines,_re_html,_re_formatted_numeric,_re_escape_regex,_empty,_intVal,_numToDecimal,_isNumber,_isHtml,_htmlNumeric,_pluck,_pluck_order,_range,_stripHtml,_unique,_fnBuildAjax,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnAjaxDataSrc,_fnAddColumn,_fnColumnOptions,_fnAdjustColumnSizing,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnVisbleColumns,_fnGetColumns,_fnColumnTypes,_fnApplyColumnDefs,_fnHungarianMap,_fnCamelToHungarian,_fnLanguageCompat,_fnBrowserDetect,_fnAddData,_fnAddTr,_fnNodeToDataIndex,_fnNodeToColumnIndex,_fnGetCellData,_fnSetCellData,_fnSplitObjNotation,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnGetDataMaster,_fnClearTable,_fnDeleteIndex,_fnInvalidate,_fnGetRowElements,_fnCreateTr,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAddOptionsHtml,_fnDetectHeader,_fnGetUniqueThs,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnFilterCreateSearch,_fnEscapeRegex,_fnFilterData,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnInfoMacros,_fnInitialise,_fnInitComplete,_fnLengthChange,_fnFeatureHtmlLength,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnFeatureHtmlTable,_fnScrollDraw,_fnApplyToChildren,_fnCalculateColumnWidths,_fnThrottle,_fnConvertToWidth,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnSortFlatten,_fnSort,_fnSortAria,_fnSortListener,_fnSortAttachListener,_fnSortingClasses,_fnSortData,_fnSaveState,_fnLoadState,_fnSettingsFromNode,_fnLog,_fnMap,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnLengthOverflow,_fnRenderer,_fnDataSource,_fnRowAttributes*/
1677
1678(function( factory ) {
1679	"use strict";
1680
1681	if ( true ) {
1682		// AMD
1683		!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! jquery */ "./node_modules/jquery/dist/jquery.js")], __WEBPACK_AMD_DEFINE_RESULT__ = (function ( $ ) {
1684			return factory( $, window, document );
1685		}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
1686				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
1687	}
1688	else {}
1689}
1690(function( $, window, document, undefined ) {
1691	"use strict";
1692
1693	/**
1694	 * DataTables is a plug-in for the jQuery Javascript library. It is a highly
1695	 * flexible tool, based upon the foundations of progressive enhancement,
1696	 * which will add advanced interaction controls to any HTML table. For a
1697	 * full list of features please refer to
1698	 * [DataTables.net](href="http://datatables.net).
1699	 *
1700	 * Note that the `DataTable` object is not a global variable but is aliased
1701	 * to `jQuery.fn.DataTable` and `jQuery.fn.dataTable` through which it may
1702	 * be  accessed.
1703	 *
1704	 *  @class
1705	 *  @param {object} [init={}] Configuration object for DataTables. Options
1706	 *    are defined by {@link DataTable.defaults}
1707	 *  @requires jQuery 1.7+
1708	 *
1709	 *  @example
1710	 *    // Basic initialisation
1711	 *    $(document).ready( function {
1712	 *      $('#example').dataTable();
1713	 *    } );
1714	 *
1715	 *  @example
1716	 *    // Initialisation with configuration options - in this case, disable
1717	 *    // pagination and sorting.
1718	 *    $(document).ready( function {
1719	 *      $('#example').dataTable( {
1720	 *        "paginate": false,
1721	 *        "sort": false
1722	 *      } );
1723	 *    } );
1724	 */
1725	var DataTable = function ( options )
1726	{
1727		/**
1728		 * Perform a jQuery selector action on the table's TR elements (from the tbody) and
1729		 * return the resulting jQuery object.
1730		 *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
1731		 *  @param {object} [oOpts] Optional parameters for modifying the rows to be included
1732		 *  @param {string} [oOpts.filter=none] Select TR elements that meet the current filter
1733		 *    criterion ("applied") or all TR elements (i.e. no filter).
1734		 *  @param {string} [oOpts.order=current] Order of the TR elements in the processed array.
1735		 *    Can be either 'current', whereby the current sorting of the table is used, or
1736		 *    'original' whereby the original order the data was read into the table is used.
1737		 *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
1738		 *    ("current") or not ("all"). If 'current' is given, then order is assumed to be
1739		 *    'current' and filter is 'applied', regardless of what they might be given as.
1740		 *  @returns {object} jQuery object, filtered by the given selector.
1741		 *  @dtopt API
1742		 *  @deprecated Since v1.10
1743		 *
1744		 *  @example
1745		 *    $(document).ready(function() {
1746		 *      var oTable = $('#example').dataTable();
1747		 *
1748		 *      // Highlight every second row
1749		 *      oTable.$('tr:odd').css('backgroundColor', 'blue');
1750		 *    } );
1751		 *
1752		 *  @example
1753		 *    $(document).ready(function() {
1754		 *      var oTable = $('#example').dataTable();
1755		 *
1756		 *      // Filter to rows with 'Webkit' in them, add a background colour and then
1757		 *      // remove the filter, thus highlighting the 'Webkit' rows only.
1758		 *      oTable.fnFilter('Webkit');
1759		 *      oTable.$('tr', {"search": "applied"}).css('backgroundColor', 'blue');
1760		 *      oTable.fnFilter('');
1761		 *    } );
1762		 */
1763		this.$ = function ( sSelector, oOpts )
1764		{
1765			return this.api(true).$( sSelector, oOpts );
1766		};
1767		
1768		
1769		/**
1770		 * Almost identical to $ in operation, but in this case returns the data for the matched
1771		 * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes
1772		 * rather than any descendants, so the data can be obtained for the row/cell. If matching
1773		 * rows are found, the data returned is the original data array/object that was used to
1774		 * create the row (or a generated array if from a DOM source).
1775		 *
1776		 * This method is often useful in-combination with $ where both functions are given the
1777		 * same parameters and the array indexes will match identically.
1778		 *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
1779		 *  @param {object} [oOpts] Optional parameters for modifying the rows to be included
1780		 *  @param {string} [oOpts.filter=none] Select elements that meet the current filter
1781		 *    criterion ("applied") or all elements (i.e. no filter).
1782		 *  @param {string} [oOpts.order=current] Order of the data in the processed array.
1783		 *    Can be either 'current', whereby the current sorting of the table is used, or
1784		 *    'original' whereby the original order the data was read into the table is used.
1785		 *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
1786		 *    ("current") or not ("all"). If 'current' is given, then order is assumed to be
1787		 *    'current' and filter is 'applied', regardless of what they might be given as.
1788		 *  @returns {array} Data for the matched elements. If any elements, as a result of the
1789		 *    selector, were not TR, TD or TH elements in the DataTable, they will have a null
1790		 *    entry in the array.
1791		 *  @dtopt API
1792		 *  @deprecated Since v1.10
1793		 *
1794		 *  @example
1795		 *    $(document).ready(function() {
1796		 *      var oTable = $('#example').dataTable();
1797		 *
1798		 *      // Get the data from the first row in the table
1799		 *      var data = oTable._('tr:first');
1800		 *
1801		 *      // Do something useful with the data
1802		 *      alert( "First cell is: "+data[0] );
1803		 *    } );
1804		 *
1805		 *  @example
1806		 *    $(document).ready(function() {
1807		 *      var oTable = $('#example').dataTable();
1808		 *
1809		 *      // Filter to 'Webkit' and get all data for
1810		 *      oTable.fnFilter('Webkit');
1811		 *      var data = oTable._('tr', {"search": "applied"});
1812		 *
1813		 *      // Do something with the data
1814		 *      alert( data.length+" rows matched the search" );
1815		 *    } );
1816		 */
1817		this._ = function ( sSelector, oOpts )
1818		{
1819			return this.api(true).rows( sSelector, oOpts ).data();
1820		};
1821		
1822		
1823		/**
1824		 * Create a DataTables Api instance, with the currently selected tables for
1825		 * the Api's context.
1826		 * @param {boolean} [traditional=false] Set the API instance's context to be
1827		 *   only the table referred to by the `DataTable.ext.iApiIndex` option, as was
1828		 *   used in the API presented by DataTables 1.9- (i.e. the traditional mode),
1829		 *   or if all tables captured in the jQuery object should be used.
1830		 * @return {DataTables.Api}
1831		 */
1832		this.api = function ( traditional )
1833		{
1834			return traditional ?
1835				new _Api(
1836					_fnSettingsFromNode( this[ _ext.iApiIndex ] )
1837				) :
1838				new _Api( this );
1839		};
1840		
1841		
1842		/**
1843		 * Add a single new row or multiple rows of data to the table. Please note
1844		 * that this is suitable for client-side processing only - if you are using
1845		 * server-side processing (i.e. "bServerSide": true), then to add data, you
1846		 * must add it to the data source, i.e. the server-side, through an Ajax call.
1847		 *  @param {array|object} data The data to be added to the table. This can be:
1848		 *    <ul>
1849		 *      <li>1D array of data - add a single row with the data provided</li>
1850		 *      <li>2D array of arrays - add multiple rows in a single call</li>
1851		 *      <li>object - data object when using <i>mData</i></li>
1852		 *      <li>array of objects - multiple data objects when using <i>mData</i></li>
1853		 *    </ul>
1854		 *  @param {bool} [redraw=true] redraw the table or not
1855		 *  @returns {array} An array of integers, representing the list of indexes in
1856		 *    <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to
1857		 *    the table.
1858		 *  @dtopt API
1859		 *  @deprecated Since v1.10
1860		 *
1861		 *  @example
1862		 *    // Global var for counter
1863		 *    var giCount = 2;
1864		 *
1865		 *    $(document).ready(function() {
1866		 *      $('#example').dataTable();
1867		 *    } );
1868		 *
1869		 *    function fnClickAddRow() {
1870		 *      $('#example').dataTable().fnAddData( [
1871		 *        giCount+".1",
1872		 *        giCount+".2",
1873		 *        giCount+".3",
1874		 *        giCount+".4" ]
1875		 *      );
1876		 *
1877		 *      giCount++;
1878		 *    }
1879		 */
1880		this.fnAddData = function( data, redraw )
1881		{
1882			var api = this.api( true );
1883		
1884			/* Check if we want to add multiple rows or not */
1885			var rows = Array.isArray(data) && ( Array.isArray(data[0]) || $.isPlainObject(data[0]) ) ?
1886				api.rows.add( data ) :
1887				api.row.add( data );
1888		
1889			if ( redraw === undefined || redraw ) {
1890				api.draw();
1891			}
1892		
1893			return rows.flatten().toArray();
1894		};
1895		
1896		
1897		/**
1898		 * This function will make DataTables recalculate the column sizes, based on the data
1899		 * contained in the table and the sizes applied to the columns (in the DOM, CSS or
1900		 * through the sWidth parameter). This can be useful when the width of the table's
1901		 * parent element changes (for example a window resize).
1902		 *  @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to
1903		 *  @dtopt API
1904		 *  @deprecated Since v1.10
1905		 *
1906		 *  @example
1907		 *    $(document).ready(function() {
1908		 *      var oTable = $('#example').dataTable( {
1909		 *        "sScrollY": "200px",
1910		 *        "bPaginate": false
1911		 *      } );
1912		 *
1913		 *      $(window).on('resize', function () {
1914		 *        oTable.fnAdjustColumnSizing();
1915		 *      } );
1916		 *    } );
1917		 */
1918		this.fnAdjustColumnSizing = function ( bRedraw )
1919		{
1920			var api = this.api( true ).columns.adjust();
1921			var settings = api.settings()[0];
1922			var scroll = settings.oScroll;
1923		
1924			if ( bRedraw === undefined || bRedraw ) {
1925				api.draw( false );
1926			}
1927			else if ( scroll.sX !== "" || scroll.sY !== "" ) {
1928				/* If not redrawing, but scrolling, we want to apply the new column sizes anyway */
1929				_fnScrollDraw( settings );
1930			}
1931		};
1932		
1933		
1934		/**
1935		 * Quickly and simply clear a table
1936		 *  @param {bool} [bRedraw=true] redraw the table or not
1937		 *  @dtopt API
1938		 *  @deprecated Since v1.10
1939		 *
1940		 *  @example
1941		 *    $(document).ready(function() {
1942		 *      var oTable = $('#example').dataTable();
1943		 *
1944		 *      // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...)
1945		 *      oTable.fnClearTable();
1946		 *    } );
1947		 */
1948		this.fnClearTable = function( bRedraw )
1949		{
1950			var api = this.api( true ).clear();
1951		
1952			if ( bRedraw === undefined || bRedraw ) {
1953				api.draw();
1954			}
1955		};
1956		
1957		
1958		/**
1959		 * The exact opposite of 'opening' a row, this function will close any rows which
1960		 * are currently 'open'.
1961		 *  @param {node} nTr the table row to 'close'
1962		 *  @returns {int} 0 on success, or 1 if failed (can't find the row)
1963		 *  @dtopt API
1964		 *  @deprecated Since v1.10
1965		 *
1966		 *  @example
1967		 *    $(document).ready(function() {
1968		 *      var oTable;
1969		 *
1970		 *      // 'open' an information row when a row is clicked on
1971		 *      $('#example tbody tr').click( function () {
1972		 *        if ( oTable.fnIsOpen(this) ) {
1973		 *          oTable.fnClose( this );
1974		 *        } else {
1975		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
1976		 *        }
1977		 *      } );
1978		 *
1979		 *      oTable = $('#example').dataTable();
1980		 *    } );
1981		 */
1982		this.fnClose = function( nTr )
1983		{
1984			this.api( true ).row( nTr ).child.hide();
1985		};
1986		
1987		
1988		/**
1989		 * Remove a row for the table
1990		 *  @param {mixed} target The index of the row from aoData to be deleted, or
1991		 *    the TR element you want to delete
1992		 *  @param {function|null} [callBack] Callback function
1993		 *  @param {bool} [redraw=true] Redraw the table or not
1994		 *  @returns {array} The row that was deleted
1995		 *  @dtopt API
1996		 *  @deprecated Since v1.10
1997		 *
1998		 *  @example
1999		 *    $(document).ready(function() {
2000		 *      var oTable = $('#example').dataTable();
2001		 *
2002		 *      // Immediately remove the first row
2003		 *      oTable.fnDeleteRow( 0 );
2004		 *    } );
2005		 */
2006		this.fnDeleteRow = function( target, callback, redraw )
2007		{
2008			var api = this.api( true );
2009			var rows = api.rows( target );
2010			var settings = rows.settings()[0];
2011			var data = settings.aoData[ rows[0][0] ];
2012		
2013			rows.remove();
2014		
2015			if ( callback ) {
2016				callback.call( this, settings, data );
2017			}
2018		
2019			if ( redraw === undefined || redraw ) {
2020				api.draw();
2021			}
2022		
2023			return data;
2024		};
2025		
2026		
2027		/**
2028		 * Restore the table to it's original state in the DOM by removing all of DataTables
2029		 * enhancements, alterations to the DOM structure of the table and event listeners.
2030		 *  @param {boolean} [remove=false] Completely remove the table from the DOM
2031		 *  @dtopt API
2032		 *  @deprecated Since v1.10
2033		 *
2034		 *  @example
2035		 *    $(document).ready(function() {
2036		 *      // This example is fairly pointless in reality, but shows how fnDestroy can be used
2037		 *      var oTable = $('#example').dataTable();
2038		 *      oTable.fnDestroy();
2039		 *    } );
2040		 */
2041		this.fnDestroy = function ( remove )
2042		{
2043			this.api( true ).destroy( remove );
2044		};
2045		
2046		
2047		/**
2048		 * Redraw the table
2049		 *  @param {bool} [complete=true] Re-filter and resort (if enabled) the table before the draw.
2050		 *  @dtopt API
2051		 *  @deprecated Since v1.10
2052		 *
2053		 *  @example
2054		 *    $(document).ready(function() {
2055		 *      var oTable = $('#example').dataTable();
2056		 *
2057		 *      // Re-draw the table - you wouldn't want to do it here, but it's an example :-)
2058		 *      oTable.fnDraw();
2059		 *    } );
2060		 */
2061		this.fnDraw = function( complete )
2062		{
2063			// Note that this isn't an exact match to the old call to _fnDraw - it takes
2064			// into account the new data, but can hold position.
2065			this.api( true ).draw( complete );
2066		};
2067		
2068		
2069		/**
2070		 * Filter the input based on data
2071		 *  @param {string} sInput String to filter the table on
2072		 *  @param {int|null} [iColumn] Column to limit filtering to
2073		 *  @param {bool} [bRegex=false] Treat as regular expression or not
2074		 *  @param {bool} [bSmart=true] Perform smart filtering or not
2075		 *  @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es)
2076		 *  @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false)
2077		 *  @dtopt API
2078		 *  @deprecated Since v1.10
2079		 *
2080		 *  @example
2081		 *    $(document).ready(function() {
2082		 *      var oTable = $('#example').dataTable();
2083		 *
2084		 *      // Sometime later - filter...
2085		 *      oTable.fnFilter( 'test string' );
2086		 *    } );
2087		 */
2088		this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive )
2089		{
2090			var api = this.api( true );
2091		
2092			if ( iColumn === null || iColumn === undefined ) {
2093				api.search( sInput, bRegex, bSmart, bCaseInsensitive );
2094			}
2095			else {
2096				api.column( iColumn ).search( sInput, bRegex, bSmart, bCaseInsensitive );
2097			}
2098		
2099			api.draw();
2100		};
2101		
2102		
2103		/**
2104		 * Get the data for the whole table, an individual row or an individual cell based on the
2105		 * provided parameters.
2106		 *  @param {int|node} [src] A TR row node, TD/TH cell node or an integer. If given as
2107		 *    a TR node then the data source for the whole row will be returned. If given as a
2108		 *    TD/TH cell node then iCol will be automatically calculated and the data for the
2109		 *    cell returned. If given as an integer, then this is treated as the aoData internal
2110		 *    data index for the row (see fnGetPosition) and the data for that row used.
2111		 *  @param {int} [col] Optional column index that you want the data of.
2112		 *  @returns {array|object|string} If mRow is undefined, then the data for all rows is
2113		 *    returned. If mRow is defined, just data for that row, and is iCol is
2114		 *    defined, only data for the designated cell is returned.
2115		 *  @dtopt API
2116		 *  @deprecated Since v1.10
2117		 *
2118		 *  @example
2119		 *    // Row data
2120		 *    $(document).ready(function() {
2121		 *      oTable = $('#example').dataTable();
2122		 *
2123		 *      oTable.$('tr').click( function () {
2124		 *        var data = oTable.fnGetData( this );
2125		 *        // ... do something with the array / object of data for the row
2126		 *      } );
2127		 *    } );
2128		 *
2129		 *  @example
2130		 *    // Individual cell data
2131		 *    $(document).ready(function() {
2132		 *      oTable = $('#example').dataTable();
2133		 *
2134		 *      oTable.$('td').click( function () {
2135		 *        var sData = oTable.fnGetData( this );
2136		 *        alert( 'The cell clicked on had the value of '+sData );
2137		 *      } );
2138		 *    } );
2139		 */
2140		this.fnGetData = function( src, col )
2141		{
2142			var api = this.api( true );
2143		
2144			if ( src !== undefined ) {
2145				var type = src.nodeName ? src.nodeName.toLowerCase() : '';
2146		
2147				return col !== undefined || type == 'td' || type == 'th' ?
2148					api.cell( src, col ).data() :
2149					api.row( src ).data() || null;
2150			}
2151		
2152			return api.data().toArray();
2153		};
2154		
2155		
2156		/**
2157		 * Get an array of the TR nodes that are used in the table's body. Note that you will
2158		 * typically want to use the '$' API method in preference to this as it is more
2159		 * flexible.
2160		 *  @param {int} [iRow] Optional row index for the TR element you want
2161		 *  @returns {array|node} If iRow is undefined, returns an array of all TR elements
2162		 *    in the table's body, or iRow is defined, just the TR element requested.
2163		 *  @dtopt API
2164		 *  @deprecated Since v1.10
2165		 *
2166		 *  @example
2167		 *    $(document).ready(function() {
2168		 *      var oTable = $('#example').dataTable();
2169		 *
2170		 *      // Get the nodes from the table
2171		 *      var nNodes = oTable.fnGetNodes( );
2172		 *    } );
2173		 */
2174		this.fnGetNodes = function( iRow )
2175		{
2176			var api = this.api( true );
2177		
2178			return iRow !== undefined ?
2179				api.row( iRow ).node() :
2180				api.rows().nodes().flatten().toArray();
2181		};
2182		
2183		
2184		/**
2185		 * Get the array indexes of a particular cell from it's DOM element
2186		 * and column index including hidden columns
2187		 *  @param {node} node this can either be a TR, TD or TH in the table's body
2188		 *  @returns {int} If nNode is given as a TR, then a single index is returned, or
2189		 *    if given as a cell, an array of [row index, column index (visible),
2190		 *    column index (all)] is given.
2191		 *  @dtopt API
2192		 *  @deprecated Since v1.10
2193		 *
2194		 *  @example
2195		 *    $(document).ready(function() {
2196		 *      $('#example tbody td').click( function () {
2197		 *        // Get the position of the current data from the node
2198		 *        var aPos = oTable.fnGetPosition( this );
2199		 *
2200		 *        // Get the data array for this row
2201		 *        var aData = oTable.fnGetData( aPos[0] );
2202		 *
2203		 *        // Update the data array and return the value
2204		 *        aData[ aPos[1] ] = 'clicked';
2205		 *        this.innerHTML = 'clicked';
2206		 *      } );
2207		 *
2208		 *      // Init DataTables
2209		 *      oTable = $('#example').dataTable();
2210		 *    } );
2211		 */
2212		this.fnGetPosition = function( node )
2213		{
2214			var api = this.api( true );
2215			var nodeName = node.nodeName.toUpperCase();
2216		
2217			if ( nodeName == 'TR' ) {
2218				return api.row( node ).index();
2219			}
2220			else if ( nodeName == 'TD' || nodeName == 'TH' ) {
2221				var cell = api.cell( node ).index();
2222		
2223				return [
2224					cell.row,
2225					cell.columnVisible,
2226					cell.column
2227				];
2228			}
2229			return null;
2230		};
2231		
2232		
2233		/**
2234		 * Check to see if a row is 'open' or not.
2235		 *  @param {node} nTr the table row to check
2236		 *  @returns {boolean} true if the row is currently open, false otherwise
2237		 *  @dtopt API
2238		 *  @deprecated Since v1.10
2239		 *
2240		 *  @example
2241		 *    $(document).ready(function() {
2242		 *      var oTable;
2243		 *
2244		 *      // 'open' an information row when a row is clicked on
2245		 *      $('#example tbody tr').click( function () {
2246		 *        if ( oTable.fnIsOpen(this) ) {
2247		 *          oTable.fnClose( this );
2248		 *        } else {
2249		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
2250		 *        }
2251		 *      } );
2252		 *
2253		 *      oTable = $('#example').dataTable();
2254		 *    } );
2255		 */
2256		this.fnIsOpen = function( nTr )
2257		{
2258			return this.api( true ).row( nTr ).child.isShown();
2259		};
2260		
2261		
2262		/**
2263		 * This function will place a new row directly after a row which is currently
2264		 * on display on the page, with the HTML contents that is passed into the
2265		 * function. This can be used, for example, to ask for confirmation that a
2266		 * particular record should be deleted.
2267		 *  @param {node} nTr The table row to 'open'
2268		 *  @param {string|node|jQuery} mHtml The HTML to put into the row
2269		 *  @param {string} sClass Class to give the new TD cell
2270		 *  @returns {node} The row opened. Note that if the table row passed in as the
2271		 *    first parameter, is not found in the table, this method will silently
2272		 *    return.
2273		 *  @dtopt API
2274		 *  @deprecated Since v1.10
2275		 *
2276		 *  @example
2277		 *    $(document).ready(function() {
2278		 *      var oTable;
2279		 *
2280		 *      // 'open' an information row when a row is clicked on
2281		 *      $('#example tbody tr').click( function () {
2282		 *        if ( oTable.fnIsOpen(this) ) {
2283		 *          oTable.fnClose( this );
2284		 *        } else {
2285		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
2286		 *        }
2287		 *      } );
2288		 *
2289		 *      oTable = $('#example').dataTable();
2290		 *    } );
2291		 */
2292		this.fnOpen = function( nTr, mHtml, sClass )
2293		{
2294			return this.api( true )
2295				.row( nTr )
2296				.child( mHtml, sClass )
2297				.show()
2298				.child()[0];
2299		};
2300		
2301		
2302		/**
2303		 * Change the pagination - provides the internal logic for pagination in a simple API
2304		 * function. With this function you can have a DataTables table go to the next,
2305		 * previous, first or last pages.
2306		 *  @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
2307		 *    or page number to jump to (integer), note that page 0 is the first page.
2308		 *  @param {bool} [bRedraw=true] Redraw the table or not
2309		 *  @dtopt API
2310		 *  @deprecated Since v1.10
2311		 *
2312		 *  @example
2313		 *    $(document).ready(function() {
2314		 *      var oTable = $('#example').dataTable();
2315		 *      oTable.fnPageChange( 'next' );
2316		 *    } );
2317		 */
2318		this.fnPageChange = function ( mAction, bRedraw )
2319		{
2320			var api = this.api( true ).page( mAction );
2321		
2322			if ( bRedraw === undefined || bRedraw ) {
2323				api.draw(false);
2324			}
2325		};
2326		
2327		
2328		/**
2329		 * Show a particular column
2330		 *  @param {int} iCol The column whose display should be changed
2331		 *  @param {bool} bShow Show (true) or hide (false) the column
2332		 *  @param {bool} [bRedraw=true] Redraw the table or not
2333		 *  @dtopt API
2334		 *  @deprecated Since v1.10
2335		 *
2336		 *  @example
2337		 *    $(document).ready(function() {
2338		 *      var oTable = $('#example').dataTable();
2339		 *
2340		 *      // Hide the second column after initialisation
2341		 *      oTable.fnSetColumnVis( 1, false );
2342		 *    } );
2343		 */
2344		this.fnSetColumnVis = function ( iCol, bShow, bRedraw )
2345		{
2346			var api = this.api( true ).column( iCol ).visible( bShow );
2347		
2348			if ( bRedraw === undefined || bRedraw ) {
2349				api.columns.adjust().draw();
2350			}
2351		};
2352		
2353		
2354		/**
2355		 * Get the settings for a particular table for external manipulation
2356		 *  @returns {object} DataTables settings object. See
2357		 *    {@link DataTable.models.oSettings}
2358		 *  @dtopt API
2359		 *  @deprecated Since v1.10
2360		 *
2361		 *  @example
2362		 *    $(document).ready(function() {
2363		 *      var oTable = $('#example').dataTable();
2364		 *      var oSettings = oTable.fnSettings();
2365		 *
2366		 *      // Show an example parameter from the settings
2367		 *      alert( oSettings._iDisplayStart );
2368		 *    } );
2369		 */
2370		this.fnSettings = function()
2371		{
2372			return _fnSettingsFromNode( this[_ext.iApiIndex] );
2373		};
2374		
2375		
2376		/**
2377		 * Sort the table by a particular column
2378		 *  @param {int} iCol the data index to sort on. Note that this will not match the
2379		 *    'display index' if you have hidden data entries
2380		 *  @dtopt API
2381		 *  @deprecated Since v1.10
2382		 *
2383		 *  @example
2384		 *    $(document).ready(function() {
2385		 *      var oTable = $('#example').dataTable();
2386		 *
2387		 *      // Sort immediately with columns 0 and 1
2388		 *      oTable.fnSort( [ [0,'asc'], [1,'asc'] ] );
2389		 *    } );
2390		 */
2391		this.fnSort = function( aaSort )
2392		{
2393			this.api( true ).order( aaSort ).draw();
2394		};
2395		
2396		
2397		/**
2398		 * Attach a sort listener to an element for a given column
2399		 *  @param {node} nNode the element to attach the sort listener to
2400		 *  @param {int} iColumn the column that a click on this node will sort on
2401		 *  @param {function} [fnCallback] callback function when sort is run
2402		 *  @dtopt API
2403		 *  @deprecated Since v1.10
2404		 *
2405		 *  @example
2406		 *    $(document).ready(function() {
2407		 *      var oTable = $('#example').dataTable();
2408		 *
2409		 *      // Sort on column 1, when 'sorter' is clicked on
2410		 *      oTable.fnSortListener( document.getElementById('sorter'), 1 );
2411		 *    } );
2412		 */
2413		this.fnSortListener = function( nNode, iColumn, fnCallback )
2414		{
2415			this.api( true ).order.listener( nNode, iColumn, fnCallback );
2416		};
2417		
2418		
2419		/**
2420		 * Update a table cell or row - this method will accept either a single value to
2421		 * update the cell with, an array of values with one element for each column or
2422		 * an object in the same format as the original data source. The function is
2423		 * self-referencing in order to make the multi column updates easier.
2424		 *  @param {object|array|string} mData Data to update the cell/row with
2425		 *  @param {node|int} mRow TR element you want to update or the aoData index
2426		 *  @param {int} [iColumn] The column to update, give as null or undefined to
2427		 *    update a whole row.
2428		 *  @param {bool} [bRedraw=true] Redraw the table or not
2429		 *  @param {bool} [bAction=true] Perform pre-draw actions or not
2430		 *  @returns {int} 0 on success, 1 on error
2431		 *  @dtopt API
2432		 *  @deprecated Since v1.10
2433		 *
2434		 *  @example
2435		 *    $(document).ready(function() {
2436		 *      var oTable = $('#example').dataTable();
2437		 *      oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell
2438		 *      oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], $('tbody tr')[0] ); // Row
2439		 *    } );
2440		 */
2441		this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction )
2442		{
2443			var api = this.api( true );
2444		
2445			if ( iColumn === undefined || iColumn === null ) {
2446				api.row( mRow ).data( mData );
2447			}
2448			else {
2449				api.cell( mRow, iColumn ).data( mData );
2450			}
2451		
2452			if ( bAction === undefined || bAction ) {
2453				api.columns.adjust();
2454			}
2455		
2456			if ( bRedraw === undefined || bRedraw ) {
2457				api.draw();
2458			}
2459			return 0;
2460		};
2461		
2462		
2463		/**
2464		 * Provide a common method for plug-ins to check the version of DataTables being used, in order
2465		 * to ensure compatibility.
2466		 *  @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the
2467		 *    formats "X" and "X.Y" are also acceptable.
2468		 *  @returns {boolean} true if this version of DataTables is greater or equal to the required
2469		 *    version, or false if this version of DataTales is not suitable
2470		 *  @method
2471		 *  @dtopt API
2472		 *  @deprecated Since v1.10
2473		 *
2474		 *  @example
2475		 *    $(document).ready(function() {
2476		 *      var oTable = $('#example').dataTable();
2477		 *      alert( oTable.fnVersionCheck( '1.9.0' ) );
2478		 *    } );
2479		 */
2480		this.fnVersionCheck = _ext.fnVersionCheck;
2481		
2482
2483		var _that = this;
2484		var emptyInit = options === undefined;
2485		var len = this.length;
2486
2487		if ( emptyInit ) {
2488			options = {};
2489		}
2490
2491		this.oApi = this.internal = _ext.internal;
2492
2493		// Extend with old style plug-in API methods
2494		for ( var fn in DataTable.ext.internal ) {
2495			if ( fn ) {
2496				this[fn] = _fnExternApiFunc(fn);
2497			}
2498		}
2499
2500		this.each(function() {
2501			// For each initialisation we want to give it a clean initialisation
2502			// object that can be bashed around
2503			var o = {};
2504			var oInit = len > 1 ? // optimisation for single table case
2505				_fnExtend( o, options, true ) :
2506				options;
2507
2508			/*global oInit,_that,emptyInit*/
2509			var i=0, iLen, j, jLen, k, kLen;
2510			var sId = this.getAttribute( 'id' );
2511			var bInitHandedOff = false;
2512			var defaults = DataTable.defaults;
2513			var $this = $(this);
2514			
2515			
2516			/* Sanity check */
2517			if ( this.nodeName.toLowerCase() != 'table' )
2518			{
2519				_fnLog( null, 0, 'Non-table node initialisation ('+this.nodeName+')', 2 );
2520				return;
2521			}
2522			
2523			/* Backwards compatibility for the defaults */
2524			_fnCompatOpts( defaults );
2525			_fnCompatCols( defaults.column );
2526			
2527			/* Convert the camel-case defaults to Hungarian */
2528			_fnCamelToHungarian( defaults, defaults, true );
2529			_fnCamelToHungarian( defaults.column, defaults.column, true );
2530			
2531			/* Setting up the initialisation object */
2532			_fnCamelToHungarian( defaults, $.extend( oInit, $this.data() ), true );
2533			
2534			
2535			
2536			/* Check to see if we are re-initialising a table */
2537			var allSettings = DataTable.settings;
2538			for ( i=0, iLen=allSettings.length ; i<iLen ; i++ )
2539			{
2540				var s = allSettings[i];
2541			
2542				/* Base check on table node */
2543				if (
2544					s.nTable == this ||
2545					(s.nTHead && s.nTHead.parentNode == this) ||
2546					(s.nTFoot && s.nTFoot.parentNode == this)
2547				) {
2548					var bRetrieve = oInit.bRetrieve !== undefined ? oInit.bRetrieve : defaults.bRetrieve;
2549					var bDestroy = oInit.bDestroy !== undefined ? oInit.bDestroy : defaults.bDestroy;
2550			
2551					if ( emptyInit || bRetrieve )
2552					{
2553						return s.oInstance;
2554					}
2555					else if ( bDestroy )
2556					{
2557						s.oInstance.fnDestroy();
2558						break;
2559					}
2560					else
2561					{
2562						_fnLog( s, 0, 'Cannot reinitialise DataTable', 3 );
2563						return;
2564					}
2565				}
2566			
2567				/* If the element we are initialising has the same ID as a table which was previously
2568				 * initialised, but the table nodes don't match (from before) then we destroy the old
2569				 * instance by simply deleting it. This is under the assumption that the table has been
2570				 * destroyed by other methods. Anyone using non-id selectors will need to do this manually
2571				 */
2572				if ( s.sTableId == this.id )
2573				{
2574					allSettings.splice( i, 1 );
2575					break;
2576				}
2577			}
2578			
2579			/* Ensure the table has an ID - required for accessibility */
2580			if ( sId === null || sId === "" )
2581			{
2582				sId = "DataTables_Table_"+(DataTable.ext._unique++);
2583				this.id = sId;
2584			}
2585			
2586			/* Create the settings object for this table and set some of the default parameters */
2587			var oSettings = $.extend( true, {}, DataTable.models.oSettings, {
2588				"sDestroyWidth": $this[0].style.width,
2589				"sInstance":     sId,
2590				"sTableId":      sId
2591			} );
2592			oSettings.nTable = this;
2593			oSettings.oApi   = _that.internal;
2594			oSettings.oInit  = oInit;
2595			
2596			allSettings.push( oSettings );
2597			
2598			// Need to add the instance after the instance after the settings object has been added
2599			// to the settings array, so we can self reference the table instance if more than one
2600			oSettings.oInstance = (_that.length===1) ? _that : $this.dataTable();
2601			
2602			// Backwards compatibility, before we apply all the defaults
2603			_fnCompatOpts( oInit );
2604			_fnLanguageCompat( oInit.oLanguage );
2605			
2606			// If the length menu is given, but the init display length is not, use the length menu
2607			if ( oInit.aLengthMenu && ! oInit.iDisplayLength )
2608			{
2609				oInit.iDisplayLength = Array.isArray( oInit.aLengthMenu[0] ) ?
2610					oInit.aLengthMenu[0][0] : oInit.aLengthMenu[0];
2611			}
2612			
2613			// Apply the defaults and init options to make a single init object will all
2614			// options defined from defaults and instance options.
2615			oInit = _fnExtend( $.extend( true, {}, defaults ), oInit );
2616			
2617			
2618			// Map the initialisation options onto the settings object
2619			_fnMap( oSettings.oFeatures, oInit, [
2620				"bPaginate",
2621				"bLengthChange",
2622				"bFilter",
2623				"bSort",
2624				"bSortMulti",
2625				"bInfo",
2626				"bProcessing",
2627				"bAutoWidth",
2628				"bSortClasses",
2629				"bServerSide",
2630				"bDeferRender"
2631			] );
2632			_fnMap( oSettings, oInit, [
2633				"asStripeClasses",
2634				"ajax",
2635				"fnServerData",
2636				"fnFormatNumber",
2637				"sServerMethod",
2638				"aaSorting",
2639				"aaSortingFixed",
2640				"aLengthMenu",
2641				"sPaginationType",
2642				"sAjaxSource",
2643				"sAjaxDataProp",
2644				"iStateDuration",
2645				"sDom",
2646				"bSortCellsTop",
2647				"iTabIndex",
2648				"fnStateLoadCallback",
2649				"fnStateSaveCallback",
2650				"renderer",
2651				"searchDelay",
2652				"rowId",
2653				[ "iCookieDuration", "iStateDuration" ], // backwards compat
2654				[ "oSearch", "oPreviousSearch" ],
2655				[ "aoSearchCols", "aoPreSearchCols" ],
2656				[ "iDisplayLength", "_iDisplayLength" ]
2657			] );
2658			_fnMap( oSettings.oScroll, oInit, [
2659				[ "sScrollX", "sX" ],
2660				[ "sScrollXInner", "sXInner" ],
2661				[ "sScrollY", "sY" ],
2662				[ "bScrollCollapse", "bCollapse" ]
2663			] );
2664			_fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" );
2665			
2666			/* Callback functions which are array driven */
2667			_fnCallbackReg( oSettings, 'aoDrawCallback',       oInit.fnDrawCallback,      'user' );
2668			_fnCallbackReg( oSettings, 'aoServerParams',       oInit.fnServerParams,      'user' );
2669			_fnCallbackReg( oSettings, 'aoStateSaveParams',    oInit.fnStateSaveParams,   'user' );
2670			_fnCallbackReg( oSettings, 'aoStateLoadParams',    oInit.fnStateLoadParams,   'user' );
2671			_fnCallbackReg( oSettings, 'aoStateLoaded',        oInit.fnStateLoaded,       'user' );
2672			_fnCallbackReg( oSettings, 'aoRowCallback',        oInit.fnRowCallback,       'user' );
2673			_fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow,        'user' );
2674			_fnCallbackReg( oSettings, 'aoHeaderCallback',     oInit.fnHeaderCallback,    'user' );
2675			_fnCallbackReg( oSettings, 'aoFooterCallback',     oInit.fnFooterCallback,    'user' );
2676			_fnCallbackReg( oSettings, 'aoInitComplete',       oInit.fnInitComplete,      'user' );
2677			_fnCallbackReg( oSettings, 'aoPreDrawCallback',    oInit.fnPreDrawCallback,   'user' );
2678			
2679			oSettings.rowIdFn = _fnGetObjectDataFn( oInit.rowId );
2680			
2681			/* Browser support detection */
2682			_fnBrowserDetect( oSettings );
2683			
2684			var oClasses = oSettings.oClasses;
2685			
2686			$.extend( oClasses, DataTable.ext.classes, oInit.oClasses );
2687			$this.addClass( oClasses.sTable );
2688			
2689			
2690			if ( oSettings.iInitDisplayStart === undefined )
2691			{
2692				/* Display start point, taking into account the save saving */
2693				oSettings.iInitDisplayStart = oInit.iDisplayStart;
2694				oSettings._iDisplayStart = oInit.iDisplayStart;
2695			}
2696			
2697			if ( oInit.iDeferLoading !== null )
2698			{
2699				oSettings.bDeferLoading = true;
2700				var tmp = Array.isArray( oInit.iDeferLoading );
2701				oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading;
2702				oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading;
2703			}
2704			
2705			/* Language definitions */
2706			var oLanguage = oSettings.oLanguage;
2707			$.extend( true, oLanguage, oInit.oLanguage );
2708			
2709			if ( oLanguage.sUrl )
2710			{
2711				/* Get the language definitions from a file - because this Ajax call makes the language
2712				 * get async to the remainder of this function we use bInitHandedOff to indicate that
2713				 * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor
2714				 */
2715				$.ajax( {
2716					dataType: 'json',
2717					url: oLanguage.sUrl,
2718					success: function ( json ) {
2719						_fnLanguageCompat( json );
2720						_fnCamelToHungarian( defaults.oLanguage, json );
2721						$.extend( true, oLanguage, json );
2722			
2723						_fnCallbackFire( oSettings, null, 'i18n', [oSettings]);
2724						_fnInitialise( oSettings );
2725					},
2726					error: function () {
2727						// Error occurred loading language file, continue on as best we can
2728						_fnInitialise( oSettings );
2729					}
2730				} );
2731				bInitHandedOff = true;
2732			}
2733			else {
2734				_fnCallbackFire( oSettings, null, 'i18n', [oSettings]);
2735			}
2736			
2737			/*
2738			 * Stripes
2739			 */
2740			if ( oInit.asStripeClasses === null )
2741			{
2742				oSettings.asStripeClasses =[
2743					oClasses.sStripeOdd,
2744					oClasses.sStripeEven
2745				];
2746			}
2747			
2748			/* Remove row stripe classes if they are already on the table row */
2749			var stripeClasses = oSettings.asStripeClasses;
2750			var rowOne = $this.children('tbody').find('tr').eq(0);
2751			if ( $.inArray( true, $.map( stripeClasses, function(el, i) {
2752				return rowOne.hasClass(el);
2753			} ) ) !== -1 ) {
2754				$('tbody tr', this).removeClass( stripeClasses.join(' ') );
2755				oSettings.asDestroyStripes = stripeClasses.slice();
2756			}
2757			
2758			/*
2759			 * Columns
2760			 * See if we should load columns automatically or use defined ones
2761			 */
2762			var anThs = [];
2763			var aoColumnsInit;
2764			var nThead = this.getElementsByTagName('thead');
2765			if ( nThead.length !== 0 )
2766			{
2767				_fnDetectHeader( oSettings.aoHeader, nThead[0] );
2768				anThs = _fnGetUniqueThs( oSettings );
2769			}
2770			
2771			/* If not given a column array, generate one with nulls */
2772			if ( oInit.aoColumns === null )
2773			{
2774				aoColumnsInit = [];
2775				for ( i=0, iLen=anThs.length ; i<iLen ; i++ )
2776				{
2777					aoColumnsInit.push( null );
2778				}
2779			}
2780			else
2781			{
2782				aoColumnsInit = oInit.aoColumns;
2783			}
2784			
2785			/* Add the columns */
2786			for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ )
2787			{
2788				_fnAddColumn( oSettings, anThs ? anThs[i] : null );
2789			}
2790			
2791			/* Apply the column definitions */
2792			_fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) {
2793				_fnColumnOptions( oSettings, iCol, oDef );
2794			} );
2795			
2796			/* HTML5 attribute detection - build an mData object automatically if the
2797			 * attributes are found
2798			 */
2799			if ( rowOne.length ) {
2800				var a = function ( cell, name ) {
2801					return cell.getAttribute( 'data-'+name ) !== null ? name : null;
2802				};
2803			
2804				$( rowOne[0] ).children('th, td').each( function (i, cell) {
2805					var col = oSettings.aoColumns[i];
2806			
2807					if ( col.mData === i ) {
2808						var sort = a( cell, 'sort' ) || a( cell, 'order' );
2809						var filter = a( cell, 'filter' ) || a( cell, 'search' );
2810			
2811						if ( sort !== null || filter !== null ) {
2812							col.mData = {
2813								_:      i+'.display',
2814								sort:   sort !== null   ? i+'.@data-'+sort   : undefined,
2815								type:   sort !== null   ? i+'.@data-'+sort   : undefined,
2816								filter: filter !== null ? i+'.@data-'+filter : undefined
2817							};
2818			
2819							_fnColumnOptions( oSettings, i );
2820						}
2821					}
2822				} );
2823			}
2824			
2825			var features = oSettings.oFeatures;
2826			var loadedInit = function () {
2827				/*
2828				 * Sorting
2829				 * @todo For modularisation (1.11) this needs to do into a sort start up handler
2830				 */
2831			
2832				// If aaSorting is not defined, then we use the first indicator in asSorting
2833				// in case that has been altered, so the default sort reflects that option
2834				if ( oInit.aaSorting === undefined ) {
2835					var sorting = oSettings.aaSorting;
2836					for ( i=0, iLen=sorting.length ; i<iLen ; i++ ) {
2837						sorting[i][1] = oSettings.aoColumns[ i ].asSorting[0];
2838					}
2839				}
2840			
2841				/* Do a first pass on the sorting classes (allows any size changes to be taken into
2842				 * account, and also will apply sorting disabled classes if disabled
2843				 */
2844				_fnSortingClasses( oSettings );
2845			
2846				if ( features.bSort ) {
2847					_fnCallbackReg( oSettings, 'aoDrawCallback', function () {
2848						if ( oSettings.bSorted ) {
2849							var aSort = _fnSortFlatten( oSettings );
2850							var sortedColumns = {};
2851			
2852							$.each( aSort, function (i, val) {
2853								sortedColumns[ val.src ] = val.dir;
2854							} );
2855			
2856							_fnCallbackFire( oSettings, null, 'order', [oSettings, aSort, sortedColumns] );
2857							_fnSortAria( oSettings );
2858						}
2859					} );
2860				}
2861			
2862				_fnCallbackReg( oSettings, 'aoDrawCallback', function () {
2863					if ( oSettings.bSorted || _fnDataSource( oSettings ) === 'ssp' || features.bDeferRender ) {
2864						_fnSortingClasses( oSettings );
2865					}
2866				}, 'sc' );
2867			
2868			
2869				/*
2870				 * Final init
2871				 * Cache the header, body and footer as required, creating them if needed
2872				 */
2873			
2874				// Work around for Webkit bug 83867 - store the caption-side before removing from doc
2875				var captions = $this.children('caption').each( function () {
2876					this._captionSide = $(this).css('caption-side');
2877				} );
2878			
2879				var thead = $this.children('thead');
2880				if ( thead.length === 0 ) {
2881					thead = $('<thead/>').appendTo($this);
2882				}
2883				oSettings.nTHead = thead[0];
2884			
2885				var tbody = $this.children('tbody');
2886				if ( tbody.length === 0 ) {
2887					tbody = $('<tbody/>').appendTo($this);
2888				}
2889				oSettings.nTBody = tbody[0];
2890			
2891				var tfoot = $this.children('tfoot');
2892				if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") ) {
2893					// If we are a scrolling table, and no footer has been given, then we need to create
2894					// a tfoot element for the caption element to be appended to
2895					tfoot = $('<tfoot/>').appendTo($this);
2896				}
2897			
2898				if ( tfoot.length === 0 || tfoot.children().length === 0 ) {
2899					$this.addClass( oClasses.sNoFooter );
2900				}
2901				else if ( tfoot.length > 0 ) {
2902					oSettings.nTFoot = tfoot[0];
2903					_fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );
2904				}
2905			
2906				/* Check if there is data passing into the constructor */
2907				if ( oInit.aaData ) {
2908					for ( i=0 ; i<oInit.aaData.length ; i++ ) {
2909						_fnAddData( oSettings, oInit.aaData[ i ] );
2910					}
2911				}
2912				else if ( oSettings.bDeferLoading || _fnDataSource( oSettings ) == 'dom' ) {
2913					/* Grab the data from the page - only do this when deferred loading or no Ajax
2914					 * source since there is no point in reading the DOM data if we are then going
2915					 * to replace it with Ajax data
2916					 */
2917					_fnAddTr( oSettings, $(oSettings.nTBody).children('tr') );
2918				}
2919			
2920				/* Copy the data index array */
2921				oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
2922			
2923				/* Initialisation complete - table can be drawn */
2924				oSettings.bInitialised = true;
2925			
2926				/* Check if we need to initialise the table (it might not have been handed off to the
2927				 * language processor)
2928				 */
2929				if ( bInitHandedOff === false ) {
2930					_fnInitialise( oSettings );
2931				}
2932			};
2933			
2934			/* Must be done after everything which can be overridden by the state saving! */
2935			if ( oInit.bStateSave )
2936			{
2937				features.bStateSave = true;
2938				_fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' );
2939				_fnLoadState( oSettings, oInit, loadedInit );
2940			}
2941			else {
2942				loadedInit();
2943			}
2944			
2945		} );
2946		_that = null;
2947		return this;
2948	};
2949
2950	
2951	/*
2952	 * It is useful to have variables which are scoped locally so only the
2953	 * DataTables functions can access them and they don't leak into global space.
2954	 * At the same time these functions are often useful over multiple files in the
2955	 * core and API, so we list, or at least document, all variables which are used
2956	 * by DataTables as private variables here. This also ensures that there is no
2957	 * clashing of variable names and that they can easily referenced for reuse.
2958	 */
2959	
2960	
2961	// Defined else where
2962	//  _selector_run
2963	//  _selector_opts
2964	//  _selector_first
2965	//  _selector_row_indexes
2966	
2967	var _ext; // DataTable.ext
2968	var _Api; // DataTable.Api
2969	var _api_register; // DataTable.Api.register
2970	var _api_registerPlural; // DataTable.Api.registerPlural
2971	
2972	var _re_dic = {};
2973	var _re_new_lines = /[\r\n\u2028]/g;
2974	var _re_html = /<.*?>/g;
2975	
2976	// This is not strict ISO8601 - Date.parse() is quite lax, although
2977	// implementations differ between browsers.
2978	var _re_date = /^\d{2,4}[\.\/\-]\d{1,2}[\.\/\-]\d{1,2}([T ]{1}\d{1,2}[:\.]\d{2}([\.:]\d{2})?)?$/;
2979	
2980	// Escape regular expression special characters
2981	var _re_escape_regex = new RegExp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' );
2982	
2983	// http://en.wikipedia.org/wiki/Foreign_exchange_market
2984	// - \u20BD - Russian ruble.
2985	// - \u20a9 - South Korean Won
2986	// - \u20BA - Turkish Lira
2987	// - \u20B9 - Indian Rupee
2988	// - R - Brazil (R$) and South Africa
2989	// - fr - Swiss Franc
2990	// - kr - Swedish krona, Norwegian krone and Danish krone
2991	// - \u2009 is thin space and \u202F is narrow no-break space, both used in many
2992	// - Ƀ - Bitcoin
2993	// - Ξ - Ethereum
2994	//   standards as thousands separators.
2995	var _re_formatted_numeric = /['\u00A0,$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfkɃΞ]/gi;
2996	
2997	
2998	var _empty = function ( d ) {
2999		return !d || d === true || d === '-' ? true : false;
3000	};
3001	
3002	
3003	var _intVal = function ( s ) {
3004		var integer = parseInt( s, 10 );
3005		return !isNaN(integer) && isFinite(s) ? integer : null;
3006	};
3007	
3008	// Convert from a formatted number with characters other than `.` as the
3009	// decimal place, to a Javascript number
3010	var _numToDecimal = function ( num, decimalPoint ) {
3011		// Cache created regular expressions for speed as this function is called often
3012		if ( ! _re_dic[ decimalPoint ] ) {
3013			_re_dic[ decimalPoint ] = new RegExp( _fnEscapeRegex( decimalPoint ), 'g' );
3014		}
3015		return typeof num === 'string' && decimalPoint !== '.' ?
3016			num.replace( /\./g, '' ).replace( _re_dic[ decimalPoint ], '.' ) :
3017			num;
3018	};
3019	
3020	
3021	var _isNumber = function ( d, decimalPoint, formatted ) {
3022		var strType = typeof d === 'string';
3023	
3024		// If empty return immediately so there must be a number if it is a
3025		// formatted string (this stops the string "k", or "kr", etc being detected
3026		// as a formatted number for currency
3027		if ( _empty( d ) ) {
3028			return true;
3029		}
3030	
3031		if ( decimalPoint && strType ) {
3032			d = _numToDecimal( d, decimalPoint );
3033		}
3034	
3035		if ( formatted && strType ) {
3036			d = d.replace( _re_formatted_numeric, '' );
3037		}
3038	
3039		return !isNaN( parseFloat(d) ) && isFinite( d );
3040	};
3041	
3042	
3043	// A string without HTML in it can be considered to be HTML still
3044	var _isHtml = function ( d ) {
3045		return _empty( d ) || typeof d === 'string';
3046	};
3047	
3048	
3049	var _htmlNumeric = function ( d, decimalPoint, formatted ) {
3050		if ( _empty( d ) ) {
3051			return true;
3052		}
3053	
3054		var html = _isHtml( d );
3055		return ! html ?
3056			null :
3057			_isNumber( _stripHtml( d ), decimalPoint, formatted ) ?
3058				true :
3059				null;
3060	};
3061	
3062	
3063	var _pluck = function ( a, prop, prop2 ) {
3064		var out = [];
3065		var i=0, ien=a.length;
3066	
3067		// Could have the test in the loop for slightly smaller code, but speed
3068		// is essential here
3069		if ( prop2 !== undefined ) {
3070			for ( ; i<ien ; i++ ) {
3071				if ( a[i] && a[i][ prop ] ) {
3072					out.push( a[i][ prop ][ prop2 ] );
3073				}
3074			}
3075		}
3076		else {
3077			for ( ; i<ien ; i++ ) {
3078				if ( a[i] ) {
3079					out.push( a[i][ prop ] );
3080				}
3081			}
3082		}
3083	
3084		return out;
3085	};
3086	
3087	
3088	// Basically the same as _pluck, but rather than looping over `a` we use `order`
3089	// as the indexes to pick from `a`
3090	var _pluck_order = function ( a, order, prop, prop2 )
3091	{
3092		var out = [];
3093		var i=0, ien=order.length;
3094	
3095		// Could have the test in the loop for slightly smaller code, but speed
3096		// is essential here
3097		if ( prop2 !== undefined ) {
3098			for ( ; i<ien ; i++ ) {
3099				if ( a[ order[i] ][ prop ] ) {
3100					out.push( a[ order[i] ][ prop ][ prop2 ] );
3101				}
3102			}
3103		}
3104		else {
3105			for ( ; i<ien ; i++ ) {
3106				out.push( a[ order[i] ][ prop ] );
3107			}
3108		}
3109	
3110		return out;
3111	};
3112	
3113	
3114	var _range = function ( len, start )
3115	{
3116		var out = [];
3117		var end;
3118	
3119		if ( start === undefined ) {
3120			start = 0;
3121			end = len;
3122		}
3123		else {
3124			end = start;
3125			start = len;
3126		}
3127	
3128		for ( var i=start ; i<end ; i++ ) {
3129			out.push( i );
3130		}
3131	
3132		return out;
3133	};
3134	
3135	
3136	var _removeEmpty = function ( a )
3137	{
3138		var out = [];
3139	
3140		for ( var i=0, ien=a.length ; i<ien ; i++ ) {
3141			if ( a[i] ) { // careful - will remove all falsy values!
3142				out.push( a[i] );
3143			}
3144		}
3145	
3146		return out;
3147	};
3148	
3149	
3150	var _stripHtml = function ( d ) {
3151		return d.replace( _re_html, '' );
3152	};
3153	
3154	
3155	/**
3156	 * Determine if all values in the array are unique. This means we can short
3157	 * cut the _unique method at the cost of a single loop. A sorted array is used
3158	 * to easily check the values.
3159	 *
3160	 * @param  {array} src Source array
3161	 * @return {boolean} true if all unique, false otherwise
3162	 * @ignore
3163	 */
3164	var _areAllUnique = function ( src ) {
3165		if ( src.length < 2 ) {
3166			return true;
3167		}
3168	
3169		var sorted = src.slice().sort();
3170		var last = sorted[0];
3171	
3172		for ( var i=1, ien=sorted.length ; i<ien ; i++ ) {
3173			if ( sorted[i] === last ) {
3174				return false;
3175			}
3176	
3177			last = sorted[i];
3178		}
3179	
3180		return true;
3181	};
3182	
3183	
3184	/**
3185	 * Find the unique elements in a source array.
3186	 *
3187	 * @param  {array} src Source array
3188	 * @return {array} Array of unique items
3189	 * @ignore
3190	 */
3191	var _unique = function ( src )
3192	{
3193		if ( _areAllUnique( src ) ) {
3194			return src.slice();
3195		}
3196	
3197		// A faster unique method is to use object keys to identify used values,
3198		// but this doesn't work with arrays or objects, which we must also
3199		// consider. See jsperf.com/compare-array-unique-versions/4 for more
3200		// information.
3201		var
3202			out = [],
3203			val,
3204			i, ien=src.length,
3205			j, k=0;
3206	
3207		again: for ( i=0 ; i<ien ; i++ ) {
3208			val = src[i];
3209	
3210			for ( j=0 ; j<k ; j++ ) {
3211				if ( out[j] === val ) {
3212					continue again;
3213				}
3214			}
3215	
3216			out.push( val );
3217			k++;
3218		}
3219	
3220		return out;
3221	};
3222	
3223	// Surprisingly this is faster than [].concat.apply
3224	// https://jsperf.com/flatten-an-array-loop-vs-reduce/2
3225	var _flatten = function (out, val) {
3226		if (Array.isArray(val)) {
3227			for (var i=0 ; i<val.length ; i++) {
3228				_flatten(out, val[i]);
3229			}
3230		}
3231		else {
3232			out.push(val);
3233		}
3234	  
3235		return out;
3236	}
3237	
3238	// Array.isArray polyfill.
3239	// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
3240	if (! Array.isArray) {
3241	    Array.isArray = function(arg) {
3242	        return Object.prototype.toString.call(arg) === '[object Array]';
3243	    };
3244	}
3245	
3246	// .trim() polyfill
3247	// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trim
3248	if (!String.prototype.trim) {
3249	  String.prototype.trim = function () {
3250	    return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
3251	  };
3252	}
3253	
3254	/**
3255	 * DataTables utility methods
3256	 * 
3257	 * This namespace provides helper methods that DataTables uses internally to
3258	 * create a DataTable, but which are not exclusively used only for DataTables.
3259	 * These methods can be used by extension authors to save the duplication of
3260	 * code.
3261	 *
3262	 *  @namespace
3263	 */
3264	DataTable.util = {
3265		/**
3266		 * Throttle the calls to a function. Arguments and context are maintained
3267		 * for the throttled function.
3268		 *
3269		 * @param {function} fn Function to be called
3270		 * @param {integer} freq Call frequency in mS
3271		 * @return {function} Wrapped function
3272		 */
3273		throttle: function ( fn, freq ) {
3274			var
3275				frequency = freq !== undefined ? freq : 200,
3276				last,
3277				timer;
3278	
3279			return function () {
3280				var
3281					that = this,
3282					now  = +new Date(),
3283					args = arguments;
3284	
3285				if ( last && now < last + frequency ) {
3286					clearTimeout( timer );
3287	
3288					timer = setTimeout( function () {
3289						last = undefined;
3290						fn.apply( that, args );
3291					}, frequency );
3292				}
3293				else {
3294					last = now;
3295					fn.apply( that, args );
3296				}
3297			};
3298		},
3299	
3300	
3301		/**
3302		 * Escape a string such that it can be used in a regular expression
3303		 *
3304		 *  @param {string} val string to escape
3305		 *  @returns {string} escaped string
3306		 */
3307		escapeRegex: function ( val ) {
3308			return val.replace( _re_escape_regex, '\\$1' );
3309		}
3310	};
3311	
3312	
3313	
3314	/**
3315	 * Create a mapping object that allows camel case parameters to be looked up
3316	 * for their Hungarian counterparts. The mapping is stored in a private
3317	 * parameter called `_hungarianMap` which can be accessed on the source object.
3318	 *  @param {object} o
3319	 *  @memberof DataTable#oApi
3320	 */
3321	function _fnHungarianMap ( o )
3322	{
3323		var
3324			hungarian = 'a aa ai ao as b fn i m o s ',
3325			match,
3326			newKey,
3327			map = {};
3328	
3329		$.each( o, function (key, val) {
3330			match = key.match(/^([^A-Z]+?)([A-Z])/);
3331	
3332			if ( match && hungarian.indexOf(match[1]+' ') !== -1 )
3333			{
3334				newKey = key.replace( match[0], match[2].toLowerCase() );
3335				map[ newKey ] = key;
3336	
3337				if ( match[1] === 'o' )
3338				{
3339					_fnHungarianMap( o[key] );
3340				}
3341			}
3342		} );
3343	
3344		o._hungarianMap = map;
3345	}
3346	
3347	
3348	/**
3349	 * Convert from camel case parameters to Hungarian, based on a Hungarian map
3350	 * created by _fnHungarianMap.
3351	 *  @param {object} src The model object which holds all parameters that can be
3352	 *    mapped.
3353	 *  @param {object} user The object to convert from camel case to Hungarian.
3354	 *  @param {boolean} force When set to `true`, properties which already have a
3355	 *    Hungarian value in the `user` object will be overwritten. Otherwise they
3356	 *    won't be.
3357	 *  @memberof DataTable#oApi
3358	 */
3359	function _fnCamelToHungarian ( src, user, force )
3360	{
3361		if ( ! src._hungarianMap ) {
3362			_fnHungarianMap( src );
3363		}
3364	
3365		var hungarianKey;
3366	
3367		$.each( user, function (key, val) {
3368			hungarianKey = src._hungarianMap[ key ];
3369	
3370			if ( hungarianKey !== undefined && (force || user[hungarianKey] === undefined) )
3371			{
3372				// For objects, we need to buzz down into the object to copy parameters
3373				if ( hungarianKey.charAt(0) === 'o' )
3374				{
3375					// Copy the camelCase options over to the hungarian
3376					if ( ! user[ hungarianKey ] ) {
3377						user[ hungarianKey ] = {};
3378					}
3379					$.extend( true, user[hungarianKey], user[key] );
3380	
3381					_fnCamelToHungarian( src[hungarianKey], user[hungarianKey], force );
3382				}
3383				else {
3384					user[hungarianKey] = user[ key ];
3385				}
3386			}
3387		} );
3388	}
3389	
3390	
3391	/**
3392	 * Language compatibility - when certain options are given, and others aren't, we
3393	 * need to duplicate the values over, in order to provide backwards compatibility
3394	 * with older language files.
3395	 *  @param {object} oSettings dataTables settings object
3396	 *  @memberof DataTable#oApi
3397	 */
3398	function _fnLanguageCompat( lang )
3399	{
3400		// Note the use of the Hungarian notation for the parameters in this method as
3401		// this is called after the mapping of camelCase to Hungarian
3402		var defaults = DataTable.defaults.oLanguage;
3403	
3404		// Default mapping
3405		var defaultDecimal = defaults.sDecimal;
3406		if ( defaultDecimal ) {
3407			_addNumericSort( defaultDecimal );
3408		}
3409	
3410		if ( lang ) {
3411			var zeroRecords = lang.sZeroRecords;
3412	
3413			// Backwards compatibility - if there is no sEmptyTable given, then use the same as
3414			// sZeroRecords - assuming that is given.
3415			if ( ! lang.sEmptyTable && zeroRecords &&
3416				defaults.sEmptyTable === "No data available in table" )
3417			{
3418				_fnMap( lang, lang, 'sZeroRecords', 'sEmptyTable' );
3419			}
3420	
3421			// Likewise with loading records
3422			if ( ! lang.sLoadingRecords && zeroRecords &&
3423				defaults.sLoadingRecords === "Loading..." )
3424			{
3425				_fnMap( lang, lang, 'sZeroRecords', 'sLoadingRecords' );
3426			}
3427	
3428			// Old parameter name of the thousands separator mapped onto the new
3429			if ( lang.sInfoThousands ) {
3430				lang.sThousands = lang.sInfoThousands;
3431			}
3432	
3433			var decimal = lang.sDecimal;
3434			if ( decimal && defaultDecimal !== decimal ) {
3435				_addNumericSort( decimal );
3436			}
3437		}
3438	}
3439	
3440	
3441	/**
3442	 * Map one parameter onto another
3443	 *  @param {object} o Object to map
3444	 *  @param {*} knew The new parameter name
3445	 *  @param {*} old The old parameter name
3446	 */
3447	var _fnCompatMap = function ( o, knew, old ) {
3448		if ( o[ knew ] !== undefined ) {
3449			o[ old ] = o[ knew ];
3450		}
3451	};
3452	
3453	
3454	/**
3455	 * Provide backwards compatibility for the main DT options. Note that the new
3456	 * options are mapped onto the old parameters, so this is an external interface
3457	 * change only.
3458	 *  @param {object} init Object to map
3459	 */
3460	function _fnCompatOpts ( init )
3461	{
3462		_fnCompatMap( init, 'ordering',      'bSort' );
3463		_fnCompatMap( init, 'orderMulti',    'bSortMulti' );
3464		_fnCompatMap( init, 'orderClasses',  'bSortClasses' );
3465		_fnCompatMap( init, 'orderCellsTop', 'bSortCellsTop' );
3466		_fnCompatMap( init, 'order',         'aaSorting' );
3467		_fnCompatMap( init, 'orderFixed',    'aaSortingFixed' );
3468		_fnCompatMap( init, 'paging',        'bPaginate' );
3469		_fnCompatMap( init, 'pagingType',    'sPaginationType' );
3470		_fnCompatMap( init, 'pageLength',    'iDisplayLength' );
3471		_fnCompatMap( init, 'searching',     'bFilter' );
3472	
3473		// Boolean initialisation of x-scrolling
3474		if ( typeof init.sScrollX === 'boolean' ) {
3475			init.sScrollX = init.sScrollX ? '100%' : '';
3476		}
3477		if ( typeof init.scrollX === 'boolean' ) {
3478			init.scrollX = init.scrollX ? '100%' : '';
3479		}
3480	
3481		// Column search objects are in an array, so it needs to be converted
3482		// element by element
3483		var searchCols = init.aoSearchCols;
3484	
3485		if ( searchCols ) {
3486			for ( var i=0, ien=searchCols.length ; i<ien ; i++ ) {
3487				if ( searchCols[i] ) {
3488					_fnCamelToHungarian( DataTable.models.oSearch, searchCols[i] );
3489				}
3490			}
3491		}
3492	}
3493	
3494	
3495	/**
3496	 * Provide backwards compatibility for column options. Note that the new options
3497	 * are mapped onto the old parameters, so this is an external interface change
3498	 * only.
3499	 *  @param {object} init Object to map
3500	 */
3501	function _fnCompatCols ( init )
3502	{
3503		_fnCompatMap( init, 'orderable',     'bSortable' );
3504		_fnCompatMap( init, 'orderData',     'aDataSort' );
3505		_fnCompatMap( init, 'orderSequence', 'asSorting' );
3506		_fnCompatMap( init, 'orderDataType', 'sortDataType' );
3507	
3508		// orderData can be given as an integer
3509		var dataSort = init.aDataSort;
3510		if ( typeof dataSort === 'number' && ! Array.isArray( dataSort ) ) {
3511			init.aDataSort = [ dataSort ];
3512		}
3513	}
3514	
3515	
3516	/**
3517	 * Browser feature detection for capabilities, quirks
3518	 *  @param {object} settings dataTables settings object
3519	 *  @memberof DataTable#oApi
3520	 */
3521	function _fnBrowserDetect( settings )
3522	{
3523		// We don't need to do this every time DataTables is constructed, the values
3524		// calculated are specific to the browser and OS configuration which we
3525		// don't expect to change between initialisations
3526		if ( ! DataTable.__browser ) {
3527			var browser = {};
3528			DataTable.__browser = browser;
3529	
3530			// Scrolling feature / quirks detection
3531			var n = $('<div/>')
3532				.css( {
3533					position: 'fixed',
3534					top: 0,
3535					left: $(window).scrollLeft()*-1, // allow for scrolling
3536					height: 1,
3537					width: 1,
3538					overflow: 'hidden'
3539				} )
3540				.append(
3541					$('<div/>')
3542						.css( {
3543							position: 'absolute',
3544							top: 1,
3545							left: 1,
3546							width: 100,
3547							overflow: 'scroll'
3548						} )
3549						.append(
3550							$('<div/>')
3551								.css( {
3552									width: '100%',
3553									height: 10
3554								} )
3555						)
3556				)
3557				.appendTo( 'body' );
3558	
3559			var outer = n.children();
3560			var inner = outer.children();
3561	
3562			// Numbers below, in order, are:
3563			// inner.offsetWidth, inner.clientWidth, outer.offsetWidth, outer.clientWidth
3564			//
3565			// IE6 XP:                           100 100 100  83
3566			// IE7 Vista:                        100 100 100  83
3567			// IE 8+ Windows:                     83  83 100  83
3568			// Evergreen Windows:                 83  83 100  83
3569			// Evergreen Mac with scrollbars:     85  85 100  85
3570			// Evergreen Mac without scrollbars: 100 100 100 100
3571	
3572			// Get scrollbar width
3573			browser.barWidth = outer[0].offsetWidth - outer[0].clientWidth;
3574	
3575			// IE6/7 will oversize a width 100% element inside a scrolling element, to
3576			// include the width of the scrollbar, while other browsers ensure the inner
3577			// element is contained without forcing scrolling
3578			browser.bScrollOversize = inner[0].offsetWidth === 100 && outer[0].clientWidth !== 100;
3579	
3580			// In rtl text layout, some browsers (most, but not all) will place the
3581			// scrollbar on the left, rather than the right.
3582			browser.bScrollbarLeft = Math.round( inner.offset().left ) !== 1;
3583	
3584			// IE8- don't provide height and width for getBoundingClientRect
3585			browser.bBounding = n[0].getBoundingClientRect().width ? true : false;
3586	
3587			n.remove();
3588		}
3589	
3590		$.extend( settings.oBrowser, DataTable.__browser );
3591		settings.oScroll.iBarWidth = DataTable.__browser.barWidth;
3592	}
3593	
3594	
3595	/**
3596	 * Array.prototype reduce[Right] method, used for browsers which don't support
3597	 * JS 1.6. Done this way to reduce code size, since we iterate either way
3598	 *  @param {object} settings dataTables settings object
3599	 *  @memberof DataTable#oApi
3600	 */
3601	function _fnReduce ( that, fn, init, start, end, inc )
3602	{
3603		var
3604			i = start,
3605			value,
3606			isSet = false;
3607	
3608		if ( init !== undefined ) {
3609			value = init;
3610			isSet = true;
3611		}
3612	
3613		while ( i !== end ) {
3614			if ( ! that.hasOwnProperty(i) ) {
3615				continue;
3616			}
3617	
3618			value = isSet ?
3619				fn( value, that[i], i, that ) :
3620				that[i];
3621	
3622			isSet = true;
3623			i += inc;
3624		}
3625	
3626		return value;
3627	}
3628	
3629	/**
3630	 * Add a column to the list used for the table with default values
3631	 *  @param {object} oSettings dataTables settings object
3632	 *  @param {node} nTh The th element for this column
3633	 *  @memberof DataTable#oApi
3634	 */
3635	function _fnAddColumn( oSettings, nTh )
3636	{
3637		// Add column to aoColumns array
3638		var oDefaults = DataTable.defaults.column;
3639		var iCol = oSettings.aoColumns.length;
3640		var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {
3641			"nTh": nTh ? nTh : document.createElement('th'),
3642			"sTitle":    oDefaults.sTitle    ? oDefaults.sTitle    : nTh ? nTh.innerHTML : '',
3643			"aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],
3644			"mData": oDefaults.mData ? oDefaults.mData : iCol,
3645			idx: iCol
3646		} );
3647		oSettings.aoColumns.push( oCol );
3648	
3649		// Add search object for column specific search. Note that the `searchCols[ iCol ]`
3650		// passed into extend can be undefined. This allows the user to give a default
3651		// with only some of the parameters defined, and also not give a default
3652		var searchCols = oSettings.aoPreSearchCols;
3653		searchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] );
3654	
3655		// Use the default column options function to initialise classes etc
3656		_fnColumnOptions( oSettings, iCol, $(nTh).data() );
3657	}
3658	
3659	
3660	/**
3661	 * Apply options for a column
3662	 *  @param {object} oSettings dataTables settings object
3663	 *  @param {int} iCol column index to consider
3664	 *  @param {object} oOptions object with sType, bVisible and bSearchable etc
3665	 *  @memberof DataTable#oApi
3666	 */
3667	function _fnColumnOptions( oSettings, iCol, oOptions )
3668	{
3669		var oCol = oSettings.aoColumns[ iCol ];
3670		var oClasses = oSettings.oClasses;
3671		var th = $(oCol.nTh);
3672	
3673		// Try to get width information from the DOM. We can't get it from CSS
3674		// as we'd need to parse the CSS stylesheet. `width` option can override
3675		if ( ! oCol.sWidthOrig ) {
3676			// Width attribute
3677			oCol.sWidthOrig = th.attr('width') || null;
3678	
3679			// Style attribute
3680			var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/);
3681			if ( t ) {
3682				oCol.sWidthOrig = t[1];
3683			}
3684		}
3685	
3686		/* User specified column options */
3687		if ( oOptions !== undefined && oOptions !== null )
3688		{
3689			// Backwards compatibility
3690			_fnCompatCols( oOptions );
3691	
3692			// Map camel case parameters to their Hungarian counterparts
3693			_fnCamelToHungarian( DataTable.defaults.column, oOptions, true );
3694	
3695			/* Backwards compatibility for mDataProp */
3696			if ( oOptions.mDataProp !== undefined && !oOptions.mData )
3697			{
3698				oOptions.mData = oOptions.mDataProp;
3699			}
3700	
3701			if ( oOptions.sType )
3702			{
3703				oCol._sManualType = oOptions.sType;
3704			}
3705	
3706			// `class` is a reserved word in Javascript, so we need to provide
3707			// the ability to use a valid name for the camel case input
3708			if ( oOptions.className && ! oOptions.sClass )
3709			{
3710				oOptions.sClass = oOptions.className;
3711			}
3712			if ( oOptions.sClass ) {
3713				th.addClass( oOptions.sClass );
3714			}
3715	
3716			$.extend( oCol, oOptions );
3717			_fnMap( oCol, oOptions, "sWidth", "sWidthOrig" );
3718	
3719			/* iDataSort to be applied (backwards compatibility), but aDataSort will take
3720			 * priority if defined
3721			 */
3722			if ( oOptions.iDataSort !== undefined )
3723			{
3724				oCol.aDataSort = [ oOptions.iDataSort ];
3725			}
3726			_fnMap( oCol, oOptions, "aDataSort" );
3727		}
3728	
3729		/* Cache the data get and set functions for speed */
3730		var mDataSrc = oCol.mData;
3731		var mData = _fnGetObjectDataFn( mDataSrc );
3732		var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null;
3733	
3734		var attrTest = function( src ) {
3735			return typeof src === 'string' && src.indexOf('@') !== -1;
3736		};
3737		oCol._bAttrSrc = $.isPlainObject( mDataSrc ) && (
3738			attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter)
3739		);
3740		oCol._setter = null;
3741	
3742		oCol.fnGetData = function (rowData, type, meta) {
3743			var innerData = mData( rowData, type, undefined, meta );
3744	
3745			return mRender && type ?
3746				mRender( innerData, type, rowData, meta ) :
3747				innerData;
3748		};
3749		oCol.fnSetData = function ( rowData, val, meta ) {
3750			return _fnSetObjectDataFn( mDataSrc )( rowData, val, meta );
3751		};
3752	
3753		// Indicate if DataTables should read DOM data as an object or array
3754		// Used in _fnGetRowElements
3755		if ( typeof mDataSrc !== 'number' ) {
3756			oSettings._rowReadObject = true;
3757		}
3758	
3759		/* Feature sorting overrides column specific when off */
3760		if ( !oSettings.oFeatures.bSort )
3761		{
3762			oCol.bSortable = false;
3763			th.addClass( oClasses.sSortableNone ); // Have to add class here as order event isn't called
3764		}
3765	
3766		/* Check that the class assignment is correct for sorting */
3767		var bAsc = $.inArray('asc', oCol.asSorting) !== -1;
3768		var bDesc = $.inArray('desc', oCol.asSorting) !== -1;
3769		if ( !oCol.bSortable || (!bAsc && !bDesc) )
3770		{
3771			oCol.sSortingClass = oClasses.sSortableNone;
3772			oCol.sSortingClassJUI = "";
3773		}
3774		else if ( bAsc && !bDesc )
3775		{
3776			oCol.sSortingClass = oClasses.sSortableAsc;
3777			oCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed;
3778		}
3779		else if ( !bAsc && bDesc )
3780		{
3781			oCol.sSortingClass = oClasses.sSortableDesc;
3782			oCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed;
3783		}
3784		else
3785		{
3786			oCol.sSortingClass = oClasses.sSortable;
3787			oCol.sSortingClassJUI = oClasses.sSortJUI;
3788		}
3789	}
3790	
3791	
3792	/**
3793	 * Adjust the table column widths for new data. Note: you would probably want to
3794	 * do a redraw after calling this function!
3795	 *  @param {object} settings dataTables settings object
3796	 *  @memberof DataTable#oApi
3797	 */
3798	function _fnAdjustColumnSizing ( settings )
3799	{
3800		/* Not interested in doing column width calculation if auto-width is disabled */
3801		if ( settings.oFeatures.bAutoWidth !== false )
3802		{
3803			var columns = settings.aoColumns;
3804	
3805			_fnCalculateColumnWidths( settings );
3806			for ( var i=0 , iLen=columns.length ; i<iLen ; i++ )
3807			{
3808				columns[i].nTh.style.width = columns[i].sWidth;
3809			}
3810		}
3811	
3812		var scroll = settings.oScroll;
3813		if ( scroll.sY !== '' || scroll.sX !== '')
3814		{
3815			_fnScrollDraw( settings );
3816		}
3817	
3818		_fnCallbackFire( settings, null, 'column-sizing', [settings] );
3819	}
3820	
3821	
3822	/**
3823	 * Covert the index of a visible column to the index in the data array (take account
3824	 * of hidden columns)
3825	 *  @param {object} oSettings dataTables settings object
3826	 *  @param {int} iMatch Visible column index to lookup
3827	 *  @returns {int} i the data index
3828	 *  @memberof DataTable#oApi
3829	 */
3830	function _fnVisibleToColumnIndex( oSettings, iMatch )
3831	{
3832		var aiVis = _fnGetColumns( oSettings, 'bVisible' );
3833	
3834		return typeof aiVis[iMatch] === 'number' ?
3835			aiVis[iMatch] :
3836			null;
3837	}
3838	
3839	
3840	/**
3841	 * Covert the index of an index in the data array and convert it to the visible
3842	 *   column index (take account of hidden columns)
3843	 *  @param {int} iMatch Column index to lookup
3844	 *  @param {object} oSettings dataTables settings object
3845	 *  @returns {int} i the data index
3846	 *  @memberof DataTable#oApi
3847	 */
3848	function _fnColumnIndexToVisible( oSettings, iMatch )
3849	{
3850		var aiVis = _fnGetColumns( oSettings, 'bVisible' );
3851		var iPos = $.inArray( iMatch, aiVis );
3852	
3853		return iPos !== -1 ? iPos : null;
3854	}
3855	
3856	
3857	/**
3858	 * Get the number of visible columns
3859	 *  @param {object} oSettings dataTables settings object
3860	 *  @returns {int} i the number of visible columns
3861	 *  @memberof DataTable#oApi
3862	 */
3863	function _fnVisbleColumns( oSettings )
3864	{
3865		var vis = 0;
3866	
3867		// No reduce in IE8, use a loop for now
3868		$.each( oSettings.aoColumns, function ( i, col ) {
3869			if ( col.bVisible && $(col.nTh).css('display') !== 'none' ) {
3870				vis++;
3871			}
3872		} );
3873	
3874		return vis;
3875	}
3876	
3877	
3878	/**
3879	 * Get an array of column indexes that match a given property
3880	 *  @param {object} oSettings dataTables settings object
3881	 *  @param {string} sParam Parameter in aoColumns to look for - typically
3882	 *    bVisible or bSearchable
3883	 *  @returns {array} Array of indexes with matched properties
3884	 *  @memberof DataTable#oApi
3885	 */
3886	function _fnGetColumns( oSettings, sParam )
3887	{
3888		var a = [];
3889	
3890		$.map( oSettings.aoColumns, function(val, i) {
3891			if ( val[sParam] ) {
3892				a.push( i );
3893			}
3894		} );
3895	
3896		return a;
3897	}
3898	
3899	
3900	/**
3901	 * Calculate the 'type' of a column
3902	 *  @param {object} settings dataTables settings object
3903	 *  @memberof DataTable#oApi
3904	 */
3905	function _fnColumnTypes ( settings )
3906	{
3907		var columns = settings.aoColumns;
3908		var data = settings.aoData;
3909		var types = DataTable.ext.type.detect;
3910		var i, ien, j, jen, k, ken;
3911		var col, cell, detectedType, cache;
3912	
3913		// For each column, spin over the 
3914		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
3915			col = columns[i];
3916			cache = [];
3917	
3918			if ( ! col.sType && col._sManualType ) {
3919				col.sType = col._sManualType;
3920			}
3921			else if ( ! col.sType ) {
3922				for ( j=0, jen=types.length ; j<jen ; j++ ) {
3923					for ( k=0, ken=data.length ; k<ken ; k++ ) {
3924						// Use a cache array so we only need to get the type data
3925						// from the formatter once (when using multiple detectors)
3926						if ( cache[k] === undefined ) {
3927							cache[k] = _fnGetCellData( settings, k, i, 'type' );
3928						}
3929	
3930						detectedType = types[j]( cache[k], settings );
3931	
3932						// If null, then this type can't apply to this column, so
3933						// rather than testing all cells, break out. There is an
3934						// exception for the last type which is `html`. We need to
3935						// scan all rows since it is possible to mix string and HTML
3936						// types
3937						if ( ! detectedType && j !== types.length-1 ) {
3938							break;
3939						}
3940	
3941						// Only a single match is needed for html type since it is
3942						// bottom of the pile and very similar to string
3943						if ( detectedType === 'html' ) {
3944							break;
3945						}
3946					}
3947	
3948					// Type is valid for all data points in the column - use this
3949					// type
3950					if ( detectedType ) {
3951						col.sType = detectedType;
3952						break;
3953					}
3954				}
3955	
3956				// Fall back - if no type was detected, always use string
3957				if ( ! col.sType ) {
3958					col.sType = 'string';
3959				}
3960			}
3961		}
3962	}
3963	
3964	
3965	/**
3966	 * Take the column definitions and static columns arrays and calculate how
3967	 * they relate to column indexes. The callback function will then apply the
3968	 * definition found for a column to a suitable configuration object.
3969	 *  @param {object} oSettings dataTables settings object
3970	 *  @param {array} aoColDefs The aoColumnDefs array that is to be applied
3971	 *  @param {array} aoCols The aoColumns array that defines columns individually
3972	 *  @param {function} fn Callback function - takes two parameters, the calculated
3973	 *    column index and the definition for that column.
3974	 *  @memberof DataTable#oApi
3975	 */
3976	function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )
3977	{
3978		var i, iLen, j, jLen, k, kLen, def;
3979		var columns = oSettings.aoColumns;
3980	
3981		// Column definitions with aTargets
3982		if ( aoColDefs )
3983		{
3984			/* Loop over the definitions array - loop in reverse so first instance has priority */
3985			for ( i=aoColDefs.length-1 ; i>=0 ; i-- )
3986			{
3987				def = aoColDefs[i];
3988	
3989				/* Each definition can target multiple columns, as it is an array */
3990				var aTargets = def.targets !== undefined ?
3991					def.targets :
3992					def.aTargets;
3993	
3994				if ( ! Array.isArray( aTargets ) )
3995				{
3996					aTargets = [ aTargets ];
3997				}
3998	
3999				for ( j=0, jLen=aTargets.length ; j<jLen ; j++ )
4000				{
4001					if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 )
4002					{
4003						/* Add columns that we don't yet know about */
4004						while( columns.length <= aTargets[j] )
4005						{
4006							_fnAddColumn( oSettings );
4007						}
4008	
4009						/* Integer, basic index */
4010						fn( aTargets[j], def );
4011					}
4012					else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 )
4013					{
4014						/* Negative integer, right to left column counting */
4015						fn( columns.length+aTargets[j], def );
4016					}
4017					else if ( typeof aTargets[j] === 'string' )
4018					{
4019						/* Class name matching on TH element */
4020						for ( k=0, kLen=columns.length ; k<kLen ; k++ )
4021						{
4022							if ( aTargets[j] == "_all" ||
4023							     $(columns[k].nTh).hasClass( aTargets[j] ) )
4024							{
4025								fn( k, def );
4026							}
4027						}
4028					}
4029				}
4030			}
4031		}
4032	
4033		// Statically defined columns array
4034		if ( aoCols )
4035		{
4036			for ( i=0, iLen=aoCols.length ; i<iLen ; i++ )
4037			{
4038				fn( i, aoCols[i] );
4039			}
4040		}
4041	}
4042	
4043	/**
4044	 * Add a data array to the table, creating DOM node etc. This is the parallel to
4045	 * _fnGatherData, but for adding rows from a Javascript source, rather than a
4046	 * DOM source.
4047	 *  @param {object} oSettings dataTables settings object
4048	 *  @param {array} aData data array to be added
4049	 *  @param {node} [nTr] TR element to add to the table - optional. If not given,
4050	 *    DataTables will create a row automatically
4051	 *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
4052	 *    if nTr is.
4053	 *  @returns {int} >=0 if successful (index of new aoData entry), -1 if failed
4054	 *  @memberof DataTable#oApi
4055	 */
4056	function _fnAddData ( oSettings, aDataIn, nTr, anTds )
4057	{
4058		/* Create the object for storing information about this new row */
4059		var iRow = oSettings.aoData.length;
4060		var oData = $.extend( true, {}, DataTable.models.oRow, {
4061			src: nTr ? 'dom' : 'data',
4062			idx: iRow
4063		} );
4064	
4065		oData._aData = aDataIn;
4066		oSettings.aoData.push( oData );
4067	
4068		/* Create the cells */
4069		var nTd, sThisType;
4070		var columns = oSettings.aoColumns;
4071	
4072		// Invalidate the column types as the new data needs to be revalidated
4073		for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
4074		{
4075			columns[i].sType = null;
4076		}
4077	
4078		/* Add to the display array */
4079		oSettings.aiDisplayMaster.push( iRow );
4080	
4081		var id = oSettings.rowIdFn( aDataIn );
4082		if ( id !== undefined ) {
4083			oSettings.aIds[ id ] = oData;
4084		}
4085	
4086		/* Create the DOM information, or register it if already present */
4087		if ( nTr || ! oSettings.oFeatures.bDeferRender )
4088		{
4089			_fnCreateTr( oSettings, iRow, nTr, anTds );
4090		}
4091	
4092		return iRow;
4093	}
4094	
4095	
4096	/**
4097	 * Add one or more TR elements to the table. Generally we'd expect to
4098	 * use this for reading data from a DOM sourced table, but it could be
4099	 * used for an TR element. Note that if a TR is given, it is used (i.e.
4100	 * it is not cloned).
4101	 *  @param {object} settings dataTables settings object
4102	 *  @param {array|node|jQuery} trs The TR element(s) to add to the table
4103	 *  @returns {array} Array of indexes for the added rows
4104	 *  @memberof DataTable#oApi
4105	 */
4106	function _fnAddTr( settings, trs )
4107	{
4108		var row;
4109	
4110		// Allow an individual node to be passed in
4111		if ( ! (trs instanceof $) ) {
4112			trs = $(trs);
4113		}
4114	
4115		return trs.map( function (i, el) {
4116			row = _fnGetRowElements( settings, el );
4117			return _fnAddData( settings, row.data, el, row.cells );
4118		} );
4119	}
4120	
4121	
4122	/**
4123	 * Take a TR element and convert it to an index in aoData
4124	 *  @param {object} oSettings dataTables settings object
4125	 *  @param {node} n the TR element to find
4126	 *  @returns {int} index if the node is found, null if not
4127	 *  @memberof DataTable#oApi
4128	 */
4129	function _fnNodeToDataIndex( oSettings, n )
4130	{
4131		return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null;
4132	}
4133	
4134	
4135	/**
4136	 * Take a TD element and convert it into a column data index (not the visible index)
4137	 *  @param {object} oSettings dataTables settings object
4138	 *  @param {int} iRow The row number the TD/TH can be found in
4139	 *  @param {node} n The TD/TH element to find
4140	 *  @returns {int} index if the node is found, -1 if not
4141	 *  @memberof DataTable#oApi
4142	 */
4143	function _fnNodeToColumnIndex( oSettings, iRow, n )
4144	{
4145		return $.inArray( n, oSettings.aoData[ iRow ].anCells );
4146	}
4147	
4148	
4149	/**
4150	 * Get the data for a given cell from the internal cache, taking into account data mapping
4151	 *  @param {object} settings dataTables settings object
4152	 *  @param {int} rowIdx aoData row id
4153	 *  @param {int} colIdx Column index
4154	 *  @param {string} type data get type ('display', 'type' 'filter' 'sort')
4155	 *  @returns {*} Cell data
4156	 *  @memberof DataTable#oApi
4157	 */
4158	function _fnGetCellData( settings, rowIdx, colIdx, type )
4159	{
4160		var draw           = settings.iDraw;
4161		var col            = settings.aoColumns[colIdx];
4162		var rowData        = settings.aoData[rowIdx]._aData;
4163		var defaultContent = col.sDefaultContent;
4164		var cellData       = col.fnGetData( rowData, type, {
4165			settings: settings,
4166			row:      rowIdx,
4167			col:      colIdx
4168		} );
4169	
4170		if ( cellData === undefined ) {
4171			if ( settings.iDrawError != draw && defaultContent === null ) {
4172				_fnLog( settings, 0, "Requested unknown parameter "+
4173					(typeof col.mData=='function' ? '{function}' : "'"+col.mData+"'")+
4174					" for row "+rowIdx+", column "+colIdx, 4 );
4175				settings.iDrawError = draw;
4176			}
4177			return defaultContent;
4178		}
4179	
4180		// When the data source is null and a specific data type is requested (i.e.
4181		// not the original data), we can use default column data
4182		if ( (cellData === rowData || cellData === null) && defaultContent !== null && type !== undefined ) {
4183			cellData = defaultContent;
4184		}
4185		else if ( typeof cellData === 'function' ) {
4186			// If the data source is a function, then we run it and use the return,
4187			// executing in the scope of the data object (for instances)
4188			return cellData.call( rowData );
4189		}
4190	
4191		if ( cellData === null && type == 'display' ) {
4192			return '';
4193		}
4194		return cellData;
4195	}
4196	
4197	
4198	/**
4199	 * Set the value for a specific cell, into the internal data cache
4200	 *  @param {object} settings dataTables settings object
4201	 *  @param {int} rowIdx aoData row id
4202	 *  @param {int} colIdx Column index
4203	 *  @param {*} val Value to set
4204	 *  @memberof DataTable#oApi
4205	 */
4206	function _fnSetCellData( settings, rowIdx, colIdx, val )
4207	{
4208		var col     = settings.aoColumns[colIdx];
4209		var rowData = settings.aoData[rowIdx]._aData;
4210	
4211		col.fnSetData( rowData, val, {
4212			settings: settings,
4213			row:      rowIdx,
4214			col:      colIdx
4215		}  );
4216	}
4217	
4218	
4219	// Private variable that is used to match action syntax in the data property object
4220	var __reArray = /\[.*?\]$/;
4221	var __reFn = /\(\)$/;
4222	
4223	/**
4224	 * Split string on periods, taking into account escaped periods
4225	 * @param  {string} str String to split
4226	 * @return {array} Split string
4227	 */
4228	function _fnSplitObjNotation( str )
4229	{
4230		return $.map( str.match(/(\\.|[^\.])+/g) || [''], function ( s ) {
4231			return s.replace(/\\\./g, '.');
4232		} );
4233	}
4234	
4235	
4236	/**
4237	 * Return a function that can be used to get data from a source object, taking
4238	 * into account the ability to use nested objects as a source
4239	 *  @param {string|int|function} mSource The data source for the object
4240	 *  @returns {function} Data get function
4241	 *  @memberof DataTable#oApi
4242	 */
4243	function _fnGetObjectDataFn( mSource )
4244	{
4245		if ( $.isPlainObject( mSource ) )
4246		{
4247			/* Build an object of get functions, and wrap them in a single call */
4248			var o = {};
4249			$.each( mSource, function (key, val) {
4250				if ( val ) {
4251					o[key] = _fnGetObjectDataFn( val );
4252				}
4253			} );
4254	
4255			return function (data, type, row, meta) {
4256				var t = o[type] || o._;
4257				return t !== undefined ?
4258					t(data, type, row, meta) :
4259					data;
4260			};
4261		}
4262		else if ( mSource === null )
4263		{
4264			/* Give an empty string for rendering / sorting etc */
4265			return function (data) { // type, row and meta also passed, but not used
4266				return data;
4267			};
4268		}
4269		else if ( typeof mSource === 'function' )
4270		{
4271			return function (data, type, row, meta) {
4272				return mSource( data, type, row, meta );
4273			};
4274		}
4275		else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
4276			      mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
4277		{
4278			/* If there is a . in the source string then the data source is in a
4279			 * nested object so we loop over the data for each level to get the next
4280			 * level down. On each loop we test for undefined, and if found immediately
4281			 * return. This allows entire objects to be missing and sDefaultContent to
4282			 * be used if defined, rather than throwing an error
4283			 */
4284			var fetchData = function (data, type, src) {
4285				var arrayNotation, funcNotation, out, innerSrc;
4286	
4287				if ( src !== "" )
4288				{
4289					var a = _fnSplitObjNotation( src );
4290	
4291					for ( var i=0, iLen=a.length ; i<iLen ; i++ )
4292					{
4293						// Check if we are dealing with special notation
4294						arrayNotation = a[i].match(__reArray);
4295						funcNotation = a[i].match(__reFn);
4296	
4297						if ( arrayNotation )
4298						{
4299							// Array notation
4300							a[i] = a[i].replace(__reArray, '');
4301	
4302							// Condition allows simply [] to be passed in
4303							if ( a[i] !== "" ) {
4304								data = data[ a[i] ];
4305							}
4306							out = [];
4307	
4308							// Get the remainder of the nested object to get
4309							a.splice( 0, i+1 );
4310							innerSrc = a.join('.');
4311	
4312							// Traverse each entry in the array getting the properties requested
4313							if ( Array.isArray( data ) ) {
4314								for ( var j=0, jLen=data.length ; j<jLen ; j++ ) {
4315									out.push( fetchData( data[j], type, innerSrc ) );
4316								}
4317							}
4318	
4319							// If a string is given in between the array notation indicators, that
4320							// is used to join the strings together, otherwise an array is returned
4321							var join = arrayNotation[0].substring(1, arrayNotation[0].length-1);
4322							data = (join==="") ? out : out.join(join);
4323	
4324							// The inner call to fetchData has already traversed through the remainder
4325							// of the source requested, so we exit from the loop
4326							break;
4327						}
4328						else if ( funcNotation )
4329						{
4330							// Function call
4331							a[i] = a[i].replace(__reFn, '');
4332							data = data[ a[i] ]();
4333							continue;
4334						}
4335	
4336						if ( data === null || data[ a[i] ] === undefined )
4337						{
4338							return undefined;
4339						}
4340						data = data[ a[i] ];
4341					}
4342				}
4343	
4344				return data;
4345			};
4346	
4347			return function (data, type) { // row and meta also passed, but not used
4348				return fetchData( data, type, mSource );
4349			};
4350		}
4351		else
4352		{
4353			/* Array or flat object mapping */
4354			return function (data, type) { // row and meta also passed, but not used
4355				return data[mSource];
4356			};
4357		}
4358	}
4359	
4360	
4361	/**
4362	 * Return a function that can be used to set data from a source object, taking
4363	 * into account the ability to use nested objects as a source
4364	 *  @param {string|int|function} mSource The data source for the object
4365	 *  @returns {function} Data set function
4366	 *  @memberof DataTable#oApi
4367	 */
4368	function _fnSetObjectDataFn( mSource )
4369	{
4370		if ( $.isPlainObject( mSource ) )
4371		{
4372			/* Unlike get, only the underscore (global) option is used for for
4373			 * setting data since we don't know the type here. This is why an object
4374			 * option is not documented for `mData` (which is read/write), but it is
4375			 * for `mRender` which is read only.
4376			 */
4377			return _fnSetObjectDataFn( mSource._ );
4378		}
4379		else if ( mSource === null )
4380		{
4381			/* Nothing to do when the data source is null */
4382			return function () {};
4383		}
4384		else if ( typeof mSource === 'function' )
4385		{
4386			return function (data, val, meta) {
4387				mSource( data, 'set', val, meta );
4388			};
4389		}
4390		else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
4391			      mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
4392		{
4393			/* Like the get, we need to get data from a nested object */
4394			var setData = function (data, val, src) {
4395				var a = _fnSplitObjNotation( src ), b;
4396				var aLast = a[a.length-1];
4397				var arrayNotation, funcNotation, o, innerSrc;
4398	
4399				for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ )
4400				{
4401					// Protect against prototype pollution
4402					if (a[i] === '__proto__' || a[i] === 'constructor') {
4403						throw new Error('Cannot set prototype values');
4404					}
4405	
4406					// Check if we are dealing with an array notation request
4407					arrayNotation = a[i].match(__reArray);
4408					funcNotation = a[i].match(__reFn);
4409	
4410					if ( arrayNotation )
4411					{
4412						a[i] = a[i].replace(__reArray, '');
4413						data[ a[i] ] = [];
4414	
4415						// Get the remainder of the nested object to set so we can recurse
4416						b = a.slice();
4417						b.splice( 0, i+1 );
4418						innerSrc = b.join('.');
4419	
4420						// Traverse each entry in the array setting the properties requested
4421						if ( Array.isArray( val ) )
4422						{
4423							for ( var j=0, jLen=val.length ; j<jLen ; j++ )
4424							{
4425								o = {};
4426								setData( o, val[j], innerSrc );
4427								data[ a[i] ].push( o );
4428							}
4429						}
4430						else
4431						{
4432							// We've been asked to save data to an array, but it
4433							// isn't array data to be saved. Best that can be done
4434							// is to just save the value.
4435							data[ a[i] ] = val;
4436						}
4437	
4438						// The inner call to setData has already traversed through the remainder
4439						// of the source and has set the data, thus we can exit here
4440						return;
4441					}
4442					else if ( funcNotation )
4443					{
4444						// Function call
4445						a[i] = a[i].replace(__reFn, '');
4446						data = data[ a[i] ]( val );
4447					}
4448	
4449					// If the nested object doesn't currently exist - since we are
4450					// trying to set the value - create it
4451					if ( data[ a[i] ] === null || data[ a[i] ] === undefined )
4452					{
4453						data[ a[i] ] = {};
4454					}
4455					data = data[ a[i] ];
4456				}
4457	
4458				// Last item in the input - i.e, the actual set
4459				if ( aLast.match(__reFn ) )
4460				{
4461					// Function call
4462					data = data[ aLast.replace(__reFn, '') ]( val );
4463				}
4464				else
4465				{
4466					// If array notation is used, we just want to strip it and use the property name
4467					// and assign the value. If it isn't used, then we get the result we want anyway
4468					data[ aLast.replace(__reArray, '') ] = val;
4469				}
4470			};
4471	
4472			return function (data, val) { // meta is also passed in, but not used
4473				return setData( data, val, mSource );
4474			};
4475		}
4476		else
4477		{
4478			/* Array or flat object mapping */
4479			return function (data, val) { // meta is also passed in, but not used
4480				data[mSource] = val;
4481			};
4482		}
4483	}
4484	
4485	
4486	/**
4487	 * Return an array with the full table data
4488	 *  @param {object} oSettings dataTables settings object
4489	 *  @returns array {array} aData Master data array
4490	 *  @memberof DataTable#oApi
4491	 */
4492	function _fnGetDataMaster ( settings )
4493	{
4494		return _pluck( settings.aoData, '_aData' );
4495	}
4496	
4497	
4498	/**
4499	 * Nuke the table
4500	 *  @param {object} oSettings dataTables settings object
4501	 *  @memberof DataTable#oApi
4502	 */
4503	function _fnClearTable( settings )
4504	{
4505		settings.aoData.length = 0;
4506		settings.aiDisplayMaster.length = 0;
4507		settings.aiDisplay.length = 0;
4508		settings.aIds = {};
4509	}
4510	
4511	
4512	 /**
4513	 * Take an array of integers (index array) and remove a target integer (value - not
4514	 * the key!)
4515	 *  @param {array} a Index array to target
4516	 *  @param {int} iTarget value to find
4517	 *  @memberof DataTable#oApi
4518	 */
4519	function _fnDeleteIndex( a, iTarget, splice )
4520	{
4521		var iTargetIndex = -1;
4522	
4523		for ( var i=0, iLen=a.length ; i<iLen ; i++ )
4524		{
4525			if ( a[i] == iTarget )
4526			{
4527				iTargetIndex = i;
4528			}
4529			else if ( a[i] > iTarget )
4530			{
4531				a[i]--;
4532			}
4533		}
4534	
4535		if ( iTargetIndex != -1 && splice === undefined )
4536		{
4537			a.splice( iTargetIndex, 1 );
4538		}
4539	}
4540	
4541	
4542	/**
4543	 * Mark cached data as invalid such that a re-read of the data will occur when
4544	 * the cached data is next requested. Also update from the data source object.
4545	 *
4546	 * @param {object} settings DataTables settings object
4547	 * @param {int}    rowIdx   Row index to invalidate
4548	 * @param {string} [src]    Source to invalidate from: undefined, 'auto', 'dom'
4549	 *     or 'data'
4550	 * @param {int}    [colIdx] Column index to invalidate. If undefined the whole
4551	 *     row will be invalidated
4552	 * @memberof DataTable#oApi
4553	 *
4554	 * @todo For the modularisation of v1.11 this will need to become a callback, so
4555	 *   the sort and filter methods can subscribe to it. That will required
4556	 *   initialisation options for sorting, which is why it is not already baked in
4557	 */
4558	function _fnInvalidate( settings, rowIdx, src, colIdx )
4559	{
4560		var row = settings.aoData[ rowIdx ];
4561		var i, ien;
4562		var cellWrite = function ( cell, col ) {
4563			// This is very frustrating, but in IE if you just write directly
4564			// to innerHTML, and elements that are overwritten are GC'ed,
4565			// even if there is a reference to them elsewhere
4566			while ( cell.childNodes.length ) {
4567				cell.removeChild( cell.firstChild );
4568			}
4569	
4570			cell.innerHTML = _fnGetCellData( settings, rowIdx, col, 'display' );
4571		};
4572	
4573		// Are we reading last data from DOM or the data object?
4574		if ( src === 'dom' || ((! src || src === 'auto') && row.src === 'dom') ) {
4575			// Read the data from the DOM
4576			row._aData = _fnGetRowElements(
4577					settings, row, colIdx, colIdx === undefined ? undefined : row._aData
4578				)
4579				.data;
4580		}
4581		else {
4582			// Reading from data object, update the DOM
4583			var cells = row.anCells;
4584	
4585			if ( cells ) {
4586				if ( colIdx !== undefined ) {
4587					cellWrite( cells[colIdx], colIdx );
4588				}
4589				else {
4590					for ( i=0, ien=cells.length ; i<ien ; i++ ) {
4591						cellWrite( cells[i], i );
4592					}
4593				}
4594			}
4595		}
4596	
4597		// For both row and cell invalidation, the cached data for sorting and
4598		// filtering is nulled out
4599		row._aSortData = null;
4600		row._aFilterData = null;
4601	
4602		// Invalidate the type for a specific column (if given) or all columns since
4603		// the data might have changed
4604		var cols = settings.aoColumns;
4605		if ( colIdx !== undefined ) {
4606			cols[ colIdx ].sType = null;
4607		}
4608		else {
4609			for ( i=0, ien=cols.length ; i<ien ; i++ ) {
4610				cols[i].sType = null;
4611			}
4612	
4613			// Update DataTables special `DT_*` attributes for the row
4614			_fnRowAttributes( settings, row );
4615		}
4616	}
4617	
4618	
4619	/**
4620	 * Build a data source object from an HTML row, reading the contents of the
4621	 * cells that are in the row.
4622	 *
4623	 * @param {object} settings DataTables settings object
4624	 * @param {node|object} TR element from which to read data or existing row
4625	 *   object from which to re-read the data from the cells
4626	 * @param {int} [colIdx] Optional column index
4627	 * @param {array|object} [d] Data source object. If `colIdx` is given then this
4628	 *   parameter should also be given and will be used to write the data into.
4629	 *   Only the column in question will be written
4630	 * @returns {object} Object with two parameters: `data` the data read, in
4631	 *   document order, and `cells` and array of nodes (they can be useful to the
4632	 *   caller, so rather than needing a second traversal to get them, just return
4633	 *   them from here).
4634	 * @memberof DataTable#oApi
4635	 */
4636	function _fnGetRowElements( settings, row, colIdx, d )
4637	{
4638		var
4639			tds = [],
4640			td = row.firstChild,
4641			name, col, o, i=0, contents,
4642			columns = settings.aoColumns,
4643			objectRead = settings._rowReadObject;
4644	
4645		// Allow the data object to be passed in, or construct
4646		d = d !== undefined ?
4647			d :
4648			objectRead ?
4649				{} :
4650				[];
4651	
4652		var attr = function ( str, td  ) {
4653			if ( typeof str === 'string' ) {
4654				var idx = str.indexOf('@');
4655	
4656				if ( idx !== -1 ) {
4657					var attr = str.substring( idx+1 );
4658					var setter = _fnSetObjectDataFn( str );
4659					setter( d, td.getAttribute( attr ) );
4660				}
4661			}
4662		};
4663	
4664		// Read data from a cell and store into the data object
4665		var cellProcess = function ( cell ) {
4666			if ( colIdx === undefined || colIdx === i ) {
4667				col = columns[i];
4668				contents = (cell.innerHTML).trim();
4669	
4670				if ( col && col._bAttrSrc ) {
4671					var setter = _fnSetObjectDataFn( col.mData._ );
4672					setter( d, contents );
4673	
4674					attr( col.mData.sort, cell );
4675					attr( col.mData.type, cell );
4676					attr( col.mData.filter, cell );
4677				}
4678				else {
4679					// Depending on the `data` option for the columns the data can
4680					// be read to either an object or an array.
4681					if ( objectRead ) {
4682						if ( ! col._setter ) {
4683							// Cache the setter function
4684							col._setter = _fnSetObjectDataFn( col.mData );
4685						}
4686						col._setter( d, contents );
4687					}
4688					else {
4689						d[i] = contents;
4690					}
4691				}
4692			}
4693	
4694			i++;
4695		};
4696	
4697		if ( td ) {
4698			// `tr` element was passed in
4699			while ( td ) {
4700				name = td.nodeName.toUpperCase();
4701	
4702				if ( name == "TD" || name == "TH" ) {
4703					cellProcess( td );
4704					tds.push( td );
4705				}
4706	
4707				td = td.nextSibling;
4708			}
4709		}
4710		else {
4711			// Existing row object passed in
4712			tds = row.anCells;
4713	
4714			for ( var j=0, jen=tds.length ; j<jen ; j++ ) {
4715				cellProcess( tds[j] );
4716			}
4717		}
4718	
4719		// Read the ID from the DOM if present
4720		var rowNode = row.firstChild ? row : row.nTr;
4721	
4722		if ( rowNode ) {
4723			var id = rowNode.getAttribute( 'id' );
4724	
4725			if ( id ) {
4726				_fnSetObjectDataFn( settings.rowId )( d, id );
4727			}
4728		}
4729	
4730		return {
4731			data: d,
4732			cells: tds
4733		};
4734	}
4735	/**
4736	 * Create a new TR element (and it's TD children) for a row
4737	 *  @param {object} oSettings dataTables settings object
4738	 *  @param {int} iRow Row to consider
4739	 *  @param {node} [nTrIn] TR element to add to the table - optional. If not given,
4740	 *    DataTables will create a row automatically
4741	 *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
4742	 *    if nTr is.
4743	 *  @memberof DataTable#oApi
4744	 */
4745	function _fnCreateTr ( oSettings, iRow, nTrIn, anTds )
4746	{
4747		var
4748			row = oSettings.aoData[iRow],
4749			rowData = row._aData,
4750			cells = [],
4751			nTr, nTd, oCol,
4752			i, iLen, create;
4753	
4754		if ( row.nTr === null )
4755		{
4756			nTr = nTrIn || document.createElement('tr');
4757	
4758			row.nTr = nTr;
4759			row.anCells = cells;
4760	
4761			/* Use a private property on the node to allow reserve mapping from the node
4762			 * to the aoData array for fast look up
4763			 */
4764			nTr._DT_RowIndex = iRow;
4765	
4766			/* Special parameters can be given by the data source to be used on the row */
4767			_fnRowAttributes( oSettings, row );
4768	
4769			/* Process each column */
4770			for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
4771			{
4772				oCol = oSettings.aoColumns[i];
4773				create = nTrIn ? false : true;
4774	
4775				nTd = create ? document.createElement( oCol.sCellType ) : anTds[i];
4776				nTd._DT_CellIndex = {
4777					row: iRow,
4778					column: i
4779				};
4780				
4781				cells.push( nTd );
4782	
4783				// Need to create the HTML if new, or if a rendering function is defined
4784				if ( create || ((oCol.mRender || oCol.mData !== i) &&
4785					 (!$.isPlainObject(oCol.mData) || oCol.mData._ !== i+'.display')
4786				)) {
4787					nTd.innerHTML = _fnGetCellData( oSettings, iRow, i, 'display' );
4788				}
4789	
4790				/* Add user defined class */
4791				if ( oCol.sClass )
4792				{
4793					nTd.className += ' '+oCol.sClass;
4794				}
4795	
4796				// Visibility - add or remove as required
4797				if ( oCol.bVisible && ! nTrIn )
4798				{
4799					nTr.appendChild( nTd );
4800				}
4801				else if ( ! oCol.bVisible && nTrIn )
4802				{
4803					nTd.parentNode.removeChild( nTd );
4804				}
4805	
4806				if ( oCol.fnCreatedCell )
4807				{
4808					oCol.fnCreatedCell.call( oSettings.oInstance,
4809						nTd, _fnGetCellData( oSettings, iRow, i ), rowData, iRow, i
4810					);
4811				}
4812			}
4813	
4814			_fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow, cells] );
4815		}
4816	}
4817	
4818	
4819	/**
4820	 * Add attributes to a row based on the special `DT_*` parameters in a data
4821	 * source object.
4822	 *  @param {object} settings DataTables settings object
4823	 *  @param {object} DataTables row object for the row to be modified
4824	 *  @memberof DataTable#oApi
4825	 */
4826	function _fnRowAttributes( settings, row )
4827	{
4828		var tr = row.nTr;
4829		var data = row._aData;
4830	
4831		if ( tr ) {
4832			var id = settings.rowIdFn( data );
4833	
4834			if ( id ) {
4835				tr.id = id;
4836			}
4837	
4838			if ( data.DT_RowClass ) {
4839				// Remove any classes added by DT_RowClass before
4840				var a = data.DT_RowClass.split(' ');
4841				row.__rowc = row.__rowc ?
4842					_unique( row.__rowc.concat( a ) ) :
4843					a;
4844	
4845				$(tr)
4846					.removeClass( row.__rowc.join(' ') )
4847					.addClass( data.DT_RowClass );
4848			}
4849	
4850			if ( data.DT_RowAttr ) {
4851				$(tr).attr( data.DT_RowAttr );
4852			}
4853	
4854			if ( data.DT_RowData ) {
4855				$(tr).data( data.DT_RowData );
4856			}
4857		}
4858	}
4859	
4860	
4861	/**
4862	 * Create the HTML header for the table
4863	 *  @param {object} oSettings dataTables settings object
4864	 *  @memberof DataTable#oApi
4865	 */
4866	function _fnBuildHead( oSettings )
4867	{
4868		var i, ien, cell, row, column;
4869		var thead = oSettings.nTHead;
4870		var tfoot = oSettings.nTFoot;
4871		var createHeader = $('th, td', thead).length === 0;
4872		var classes = oSettings.oClasses;
4873		var columns = oSettings.aoColumns;
4874	
4875		if ( createHeader ) {
4876			row = $('<tr/>').appendTo( thead );
4877		}
4878	
4879		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
4880			column = columns[i];
4881			cell = $( column.nTh ).addClass( column.sClass );
4882	
4883			if ( createHeader ) {
4884				cell.appendTo( row );
4885			}
4886	
4887			// 1.11 move into sorting
4888			if ( oSettings.oFeatures.bSort ) {
4889				cell.addClass( column.sSortingClass );
4890	
4891				if ( column.bSortable !== false ) {
4892					cell
4893						.attr( 'tabindex', oSettings.iTabIndex )
4894						.attr( 'aria-controls', oSettings.sTableId );
4895	
4896					_fnSortAttachListener( oSettings, column.nTh, i );
4897				}
4898			}
4899	
4900			if ( column.sTitle != cell[0].innerHTML ) {
4901				cell.html( column.sTitle );
4902			}
4903	
4904			_fnRenderer( oSettings, 'header' )(
4905				oSettings, cell, column, classes
4906			);
4907		}
4908	
4909		if ( createHeader ) {
4910			_fnDetectHeader( oSettings.aoHeader, thead );
4911		}
4912		
4913		/* ARIA role for the rows */
4914		$(thead).children('tr').attr('role', 'row');
4915	
4916		/* Deal with the footer - add classes if required */
4917		$(thead).children('tr').children('th, td').addClass( classes.sHeaderTH );
4918		$(tfoot).children('tr').children('th, td').addClass( classes.sFooterTH );
4919	
4920		// Cache the footer cells. Note that we only take the cells from the first
4921		// row in the footer. If there is more than one row the user wants to
4922		// interact with, they need to use the table().foot() method. Note also this
4923		// allows cells to be used for multiple columns using colspan
4924		if ( tfoot !== null ) {
4925			var cells = oSettings.aoFooter[0];
4926	
4927			for ( i=0, ien=cells.length ; i<ien ; i++ ) {
4928				column = columns[i];
4929				column.nTf = cells[i].cell;
4930	
4931				if ( column.sClass ) {
4932					$(column.nTf).addClass( column.sClass );
4933				}
4934			}
4935		}
4936	}
4937	
4938	
4939	/**
4940	 * Draw the header (or footer) element based on the column visibility states. The
4941	 * methodology here is to use the layout array from _fnDetectHeader, modified for
4942	 * the instantaneous column visibility, to construct the new layout. The grid is
4943	 * traversed over cell at a time in a rows x columns grid fashion, although each
4944	 * cell insert can cover multiple elements in the grid - which is tracks using the
4945	 * aApplied array. Cell inserts in the grid will only occur where there isn't
4946	 * already a cell in that position.
4947	 *  @param {object} oSettings dataTables settings object
4948	 *  @param array {objects} aoSource Layout array from _fnDetectHeader
4949	 *  @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,
4950	 *  @memberof DataTable#oApi
4951	 */
4952	function _fnDrawHead( oSettings, aoSource, bIncludeHidden )
4953	{
4954		var i, iLen, j, jLen, k, kLen, n, nLocalTr;
4955		var aoLocal = [];
4956		var aApplied = [];
4957		var iColumns = oSettings.aoColumns.length;
4958		var iRowspan, iColspan;
4959	
4960		if ( ! aoSource )
4961		{
4962			return;
4963		}
4964	
4965		if (  bIncludeHidden === undefined )
4966		{
4967			bIncludeHidden = false;
4968		}
4969	
4970		/* Make a copy of the master layout array, but without the visible columns in it */
4971		for ( i=0, iLen=aoSource.length ; i<iLen ; i++ )
4972		{
4973			aoLocal[i] = aoSource[i].slice();
4974			aoLocal[i].nTr = aoSource[i].nTr;
4975	
4976			/* Remove any columns which are currently hidden */
4977			for ( j=iColumns-1 ; j>=0 ; j-- )
4978			{
4979				if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden )
4980				{
4981					aoLocal[i].splice( j, 1 );
4982				}
4983			}
4984	
4985			/* Prep the applied array - it needs an element for each row */
4986			aApplied.push( [] );
4987		}
4988	
4989		for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ )
4990		{
4991			nLocalTr = aoLocal[i].nTr;
4992	
4993			/* All cells are going to be replaced, so empty out the row */
4994			if ( nLocalTr )
4995			{
4996				while( (n = nLocalTr.firstChild) )
4997				{
4998					nLocalTr.removeChild( n );
4999				}
5000			}
5001	
5002			for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ )
5003			{
5004				iRowspan = 1;
5005				iColspan = 1;
5006	
5007				/* Check to see if there is already a cell (row/colspan) covering our target
5008				 * insert point. If there is, then there is nothing to do.
5009				 */
5010				if ( aApplied[i][j] === undefined )
5011				{
5012					nLocalTr.appendChild( aoLocal[i][j].cell );
5013					aApplied[i][j] = 1;
5014	
5015					/* Expand the cell to cover as many rows as needed */
5016					while ( aoLocal[i+iRowspan] !== undefined &&
5017					        aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell )
5018					{
5019						aApplied[i+iRowspan][j] = 1;
5020						iRowspan++;
5021					}
5022	
5023					/* Expand the cell to cover as many columns as needed */
5024					while ( aoLocal[i][j+iColspan] !== undefined &&
5025					        aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell )
5026					{
5027						/* Must update the applied array over the rows for the columns */
5028						for ( k=0 ; k<iRowspan ; k++ )
5029						{
5030							aApplied[i+k][j+iColspan] = 1;
5031						}
5032						iColspan++;
5033					}
5034	
5035					/* Do the actual expansion in the DOM */
5036					$(aoLocal[i][j].cell)
5037						.attr('rowspan', iRowspan)
5038						.attr('colspan', iColspan);
5039				}
5040			}
5041		}
5042	}
5043	
5044	
5045	/**
5046	 * Insert the required TR nodes into the table for display
5047	 *  @param {object} oSettings dataTables settings object
5048	 *  @memberof DataTable#oApi
5049	 */
5050	function _fnDraw( oSettings )
5051	{
5052		/* Provide a pre-callback function which can be used to cancel the draw is false is returned */
5053		var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] );
5054		if ( $.inArray( false, aPreDraw ) !== -1 )
5055		{
5056			_fnProcessingDisplay( oSettings, false );
5057			return;
5058		}
5059	
5060		var i, iLen, n;
5061		var anRows = [];
5062		var iRowCount = 0;
5063		var asStripeClasses = oSettings.asStripeClasses;
5064		var iStripes = asStripeClasses.length;
5065		var iOpenRows = oSettings.aoOpenRows.length;
5066		var oLang = oSettings.oLanguage;
5067		var iInitDisplayStart = oSettings.iInitDisplayStart;
5068		var bServerSide = _fnDataSource( oSettings ) == 'ssp';
5069		var aiDisplay = oSettings.aiDisplay;
5070	
5071		oSettings.bDrawing = true;
5072	
5073		/* Check and see if we have an initial draw position from state saving */
5074		if ( iInitDisplayStart !== undefined && iInitDisplayStart !== -1 )
5075		{
5076			oSettings._iDisplayStart = bServerSide ?
5077				iInitDisplayStart :
5078				iInitDisplayStart >= oSettings.fnRecordsDisplay() ?
5079					0 :
5080					iInitDisplayStart;
5081	
5082			oSettings.iInitDisplayStart = -1;
5083		}
5084	
5085		var iDisplayStart = oSettings._iDisplayStart;
5086		var iDisplayEnd = oSettings.fnDisplayEnd();
5087	
5088		/* Server-side processing draw intercept */
5089		if ( oSettings.bDeferLoading )
5090		{
5091			oSettings.bDeferLoading = false;
5092			oSettings.iDraw++;
5093			_fnProcessingDisplay( oSettings, false );
5094		}
5095		else if ( !bServerSide )
5096		{
5097			oSettings.iDraw++;
5098		}
5099		else if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) )
5100		{
5101			return;
5102		}
5103	
5104		if ( aiDisplay.length !== 0 )
5105		{
5106			var iStart = bServerSide ? 0 : iDisplayStart;
5107			var iEnd = bServerSide ? oSettings.aoData.length : iDisplayEnd;
5108	
5109			for ( var j=iStart ; j<iEnd ; j++ )
5110			{
5111				var iDataIndex = aiDisplay[j];
5112				var aoData = oSettings.aoData[ iDataIndex ];
5113				if ( aoData.nTr === null )
5114				{
5115					_fnCreateTr( oSettings, iDataIndex );
5116				}
5117	
5118				var nRow = aoData.nTr;
5119	
5120				/* Remove the old striping classes and then add the new one */
5121				if ( iStripes !== 0 )
5122				{
5123					var sStripe = asStripeClasses[ iRowCount % iStripes ];
5124					if ( aoData._sRowStripe != sStripe )
5125					{
5126						$(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe );
5127						aoData._sRowStripe = sStripe;
5128					}
5129				}
5130	
5131				// Row callback functions - might want to manipulate the row
5132				// iRowCount and j are not currently documented. Are they at all
5133				// useful?
5134				_fnCallbackFire( oSettings, 'aoRowCallback', null,
5135					[nRow, aoData._aData, iRowCount, j, iDataIndex] );
5136	
5137				anRows.push( nRow );
5138				iRowCount++;
5139			}
5140		}
5141		else
5142		{
5143			/* Table is empty - create a row with an empty message in it */
5144			var sZero = oLang.sZeroRecords;
5145			if ( oSettings.iDraw == 1 &&  _fnDataSource( oSettings ) == 'ajax' )
5146			{
5147				sZero = oLang.sLoadingRecords;
5148			}
5149			else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 )
5150			{
5151				sZero = oLang.sEmptyTable;
5152			}
5153	
5154			anRows[ 0 ] = $( '<tr/>', { 'class': iStripes ? asStripeClasses[0] : '' } )
5155				.append( $('<td />', {
5156					'valign':  'top',
5157					'colSpan': _fnVisbleColumns( oSettings ),
5158					'class':   oSettings.oClasses.sRowEmpty
5159				} ).html( sZero ) )[0];
5160		}
5161	
5162		/* Header and footer callbacks */
5163		_fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0],
5164			_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
5165	
5166		_fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0],
5167			_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
5168	
5169		var body = $(oSettings.nTBody);
5170	
5171		body.children().detach();
5172		body.append( $(anRows) );
5173	
5174		/* Call all required callback functions for the end of a draw */
5175		_fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] );
5176	
5177		/* Draw is complete, sorting and filtering must be as well */
5178		oSettings.bSorted = false;
5179		oSettings.bFiltered = false;
5180		oSettings.bDrawing = false;
5181	}
5182	
5183	
5184	/**
5185	 * Redraw the table - taking account of the various features which are enabled
5186	 *  @param {object} oSettings dataTables settings object
5187	 *  @param {boolean} [holdPosition] Keep the current paging position. By default
5188	 *    the paging is reset to the first page
5189	 *  @memberof DataTable#oApi
5190	 */
5191	function _fnReDraw( settings, holdPosition )
5192	{
5193		var
5194			features = settings.oFeatures,
5195			sort     = features.bSort,
5196			filter   = features.bFilter;
5197	
5198		if ( sort ) {
5199			_fnSort( settings );
5200		}
5201	
5202		if ( filter ) {
5203			_fnFilterComplete( settings, settings.oPreviousSearch );
5204		}
5205		else {
5206			// No filtering, so we want to just use the display master
5207			settings.aiDisplay = settings.aiDisplayMaster.slice();
5208		}
5209	
5210		if ( holdPosition !== true ) {
5211			settings._iDisplayStart = 0;
5212		}
5213	
5214		// Let any modules know about the draw hold position state (used by
5215		// scrolling internally)
5216		settings._drawHold = holdPosition;
5217	
5218		_fnDraw( settings );
5219	
5220		settings._drawHold = false;
5221	}
5222	
5223	
5224	/**
5225	 * Add the options to the page HTML for the table
5226	 *  @param {object} oSettings dataTables settings object
5227	 *  @memberof DataTable#oApi
5228	 */
5229	function _fnAddOptionsHtml ( oSettings )
5230	{
5231		var classes = oSettings.oClasses;
5232		var table = $(oSettings.nTable);
5233		var holding = $('<div/>').insertBefore( table ); // Holding element for speed
5234		var features = oSettings.oFeatures;
5235	
5236		// All DataTables are wrapped in a div
5237		var insert = $('<div/>', {
5238			id:      oSettings.sTableId+'_wrapper',
5239			'class': classes.sWrapper + (oSettings.nTFoot ? '' : ' '+classes.sNoFooter)
5240		} );
5241	
5242		oSettings.nHolding = holding[0];
5243		oSettings.nTableWrapper = insert[0];
5244		oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;
5245	
5246		/* Loop over the user set positioning and place the elements as needed */
5247		var aDom = oSettings.sDom.split('');
5248		var featureNode, cOption, nNewNode, cNext, sAttr, j;
5249		for ( var i=0 ; i<aDom.length ; i++ )
5250		{
5251			featureNode = null;
5252			cOption = aDom[i];
5253	
5254			if ( cOption == '<' )
5255			{
5256				/* New container div */
5257				nNewNode = $('<div/>')[0];
5258	
5259				/* Check to see if we should append an id and/or a class name to the container */
5260				cNext = aDom[i+1];
5261				if ( cNext == "'" || cNext == '"' )
5262				{
5263					sAttr = "";
5264					j = 2;
5265					while ( aDom[i+j] != cNext )
5266					{
5267						sAttr += aDom[i+j];
5268						j++;
5269					}
5270	
5271					/* Replace jQuery UI constants @todo depreciated */
5272					if ( sAttr == "H" )
5273					{
5274						sAttr = classes.sJUIHeader;
5275					}
5276					else if ( sAttr == "F" )
5277					{
5278						sAttr = classes.sJUIFooter;
5279					}
5280	
5281					/* The attribute can be in the format of "#id.class", "#id" or "class" This logic
5282					 * breaks the string into parts and applies them as needed
5283					 */
5284					if ( sAttr.indexOf('.') != -1 )
5285					{
5286						var aSplit = sAttr.split('.');
5287						nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);
5288						nNewNode.className = aSplit[1];
5289					}
5290					else if ( sAttr.charAt(0) == "#" )
5291					{
5292						nNewNode.id = sAttr.substr(1, sAttr.length-1);
5293					}
5294					else
5295					{
5296						nNewNode.className = sAttr;
5297					}
5298	
5299					i += j; /* Move along the position array */
5300				}
5301	
5302				insert.append( nNewNode );
5303				insert = $(nNewNode);
5304			}
5305			else if ( cOption == '>' )
5306			{
5307				/* End container div */
5308				insert = insert.parent();
5309			}
5310			// @todo Move options into their own plugins?
5311			else if ( cOption == 'l' && features.bPaginate && features.bLengthChange )
5312			{
5313				/* Length */
5314				featureNode = _fnFeatureHtmlLength( oSettings );
5315			}
5316			else if ( cOption == 'f' && features.bFilter )
5317			{
5318				/* Filter */
5319				featureNode = _fnFeatureHtmlFilter( oSettings );
5320			}
5321			else if ( cOption == 'r' && features.bProcessing )
5322			{
5323				/* pRocessing */
5324				featureNode = _fnFeatureHtmlProcessing( oSettings );
5325			}
5326			else if ( cOption == 't' )
5327			{
5328				/* Table */
5329				featureNode = _fnFeatureHtmlTable( oSettings );
5330			}
5331			else if ( cOption ==  'i' && features.bInfo )
5332			{
5333				/* Info */
5334				featureNode = _fnFeatureHtmlInfo( oSettings );
5335			}
5336			else if ( cOption == 'p' && features.bPaginate )
5337			{
5338				/* Pagination */
5339				featureNode = _fnFeatureHtmlPaginate( oSettings );
5340			}
5341			else if ( DataTable.ext.feature.length !== 0 )
5342			{
5343				/* Plug-in features */
5344				var aoFeatures = DataTable.ext.feature;
5345				for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )
5346				{
5347					if ( cOption == aoFeatures[k].cFeature )
5348					{
5349						featureNode = aoFeatures[k].fnInit( oSettings );
5350						break;
5351					}
5352				}
5353			}
5354	
5355			/* Add to the 2D features array */
5356			if ( featureNode )
5357			{
5358				var aanFeatures = oSettings.aanFeatures;
5359	
5360				if ( ! aanFeatures[cOption] )
5361				{
5362					aanFeatures[cOption] = [];
5363				}
5364	
5365				aanFeatures[cOption].push( featureNode );
5366				insert.append( featureNode );
5367			}
5368		}
5369	
5370		/* Built our DOM structure - replace the holding div with what we want */
5371		holding.replaceWith( insert );
5372		oSettings.nHolding = null;
5373	}
5374	
5375	
5376	/**
5377	 * Use the DOM source to create up an array of header cells. The idea here is to
5378	 * create a layout grid (array) of rows x columns, which contains a reference
5379	 * to the cell that that point in the grid (regardless of col/rowspan), such that
5380	 * any column / row could be removed and the new grid constructed
5381	 *  @param array {object} aLayout Array to store the calculated layout in
5382	 *  @param {node} nThead The header/footer element for the table
5383	 *  @memberof DataTable#oApi
5384	 */
5385	function _fnDetectHeader ( aLayout, nThead )
5386	{
5387		var nTrs = $(nThead).children('tr');
5388		var nTr, nCell;
5389		var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan;
5390		var bUnique;
5391		var fnShiftCol = function ( a, i, j ) {
5392			var k = a[i];
5393	                while ( k[j] ) {
5394				j++;
5395			}
5396			return j;
5397		};
5398	
5399		aLayout.splice( 0, aLayout.length );
5400	
5401		/* We know how many rows there are in the layout - so prep it */
5402		for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
5403		{
5404			aLayout.push( [] );
5405		}
5406	
5407		/* Calculate a layout array */
5408		for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
5409		{
5410			nTr = nTrs[i];
5411			iColumn = 0;
5412	
5413			/* For every cell in the row... */
5414			nCell = nTr.firstChild;
5415			while ( nCell ) {
5416				if ( nCell.nodeName.toUpperCase() == "TD" ||
5417				     nCell.nodeName.toUpperCase() == "TH" )
5418				{
5419					/* Get the col and rowspan attributes from the DOM and sanitise them */
5420					iColspan = nCell.getAttribute('colspan') * 1;
5421					iRowspan = nCell.getAttribute('rowspan') * 1;
5422					iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan;
5423					iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan;
5424	
5425					/* There might be colspan cells already in this row, so shift our target
5426					 * accordingly
5427					 */
5428					iColShifted = fnShiftCol( aLayout, i, iColumn );
5429	
5430					/* Cache calculation for unique columns */
5431					bUnique = iColspan === 1 ? true : false;
5432	
5433					/* If there is col / rowspan, copy the information into the layout grid */
5434					for ( l=0 ; l<iColspan ; l++ )
5435					{
5436						for ( k=0 ; k<iRowspan ; k++ )
5437						{
5438							aLayout[i+k][iColShifted+l] = {
5439								"cell": nCell,
5440								"unique": bUnique
5441							};
5442							aLayout[i+k].nTr = nTr;
5443						}
5444					}
5445				}
5446				nCell = nCell.nextSibling;
5447			}
5448		}
5449	}
5450	
5451	
5452	/**
5453	 * Get an array of unique th elements, one for each column
5454	 *  @param {object} oSettings dataTables settings object
5455	 *  @param {node} nHeader automatically detect the layout from this node - optional
5456	 *  @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional
5457	 *  @returns array {node} aReturn list of unique th's
5458	 *  @memberof DataTable#oApi
5459	 */
5460	function _fnGetUniqueThs ( oSettings, nHeader, aLayout )
5461	{
5462		var aReturn = [];
5463		if ( !aLayout )
5464		{
5465			aLayout = oSettings.aoHeader;
5466			if ( nHeader )
5467			{
5468				aLayout = [];
5469				_fnDetectHeader( aLayout, nHeader );
5470			}
5471		}
5472	
5473		for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ )
5474		{
5475			for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ )
5476			{
5477				if ( aLayout[i][j].unique &&
5478					 (!aReturn[j] || !oSettings.bSortCellsTop) )
5479				{
5480					aReturn[j] = aLayout[i][j].cell;
5481				}
5482			}
5483		}
5484	
5485		return aReturn;
5486	}
5487	
5488	/**
5489	 * Create an Ajax call based on the table's settings, taking into account that
5490	 * parameters can have multiple forms, and backwards compatibility.
5491	 *
5492	 * @param {object} oSettings dataTables settings object
5493	 * @param {array} data Data to send to the server, required by
5494	 *     DataTables - may be augmented by developer callbacks
5495	 * @param {function} fn Callback function to run when data is obtained
5496	 */
5497	function _fnBuildAjax( oSettings, data, fn )
5498	{
5499		// Compatibility with 1.9-, allow fnServerData and event to manipulate
5500		_fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [data] );
5501	
5502		// Convert to object based for 1.10+ if using the old array scheme which can
5503		// come from server-side processing or serverParams
5504		if ( data && Array.isArray(data) ) {
5505			var tmp = {};
5506			var rbracket = /(.*?)\[\]$/;
5507	
5508			$.each( data, function (key, val) {
5509				var match = val.name.match(rbracket);
5510	
5511				if ( match ) {
5512					// Support for arrays
5513					var name = match[0];
5514	
5515					if ( ! tmp[ name ] ) {
5516						tmp[ name ] = [];
5517					}
5518					tmp[ name ].push( val.value );
5519				}
5520				else {
5521					tmp[val.name] = val.value;
5522				}
5523			} );
5524			data = tmp;
5525		}
5526	
5527		var ajaxData;
5528		var ajax = oSettings.ajax;
5529		var instance = oSettings.oInstance;
5530		var callback = function ( json ) {
5531			_fnCallbackFire( oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR] );
5532			fn( json );
5533		};
5534	
5535		if ( $.isPlainObject( ajax ) && ajax.data )
5536		{
5537			ajaxData = ajax.data;
5538	
5539			var newData = typeof ajaxData === 'function' ?
5540				ajaxData( data, oSettings ) :  // fn can manipulate data or return
5541				ajaxData;                      // an object object or array to merge
5542	
5543			// If the function returned something, use that alone
5544			data = typeof ajaxData === 'function' && newData ?
5545				newData :
5546				$.extend( true, data, newData );
5547	
5548			// Remove the data property as we've resolved it already and don't want
5549			// jQuery to do it again (it is restored at the end of the function)
5550			delete ajax.data;
5551		}
5552	
5553		var baseAjax = {
5554			"data": data,
5555			"success": function (json) {
5556				var error = json.error || json.sError;
5557				if ( error ) {
5558					_fnLog( oSettings, 0, error );
5559				}
5560	
5561				oSettings.json = json;
5562				callback( json );
5563			},
5564			"dataType": "json",
5565			"cache": false,
5566			"type": oSettings.sServerMethod,
5567			"error": function (xhr, error, thrown) {
5568				var ret = _fnCallbackFire( oSettings, null, 'xhr', [oSettings, null, oSettings.jqXHR] );
5569	
5570				if ( $.inArray( true, ret ) === -1 ) {
5571					if ( error == "parsererror" ) {
5572						_fnLog( oSettings, 0, 'Invalid JSON response', 1 );
5573					}
5574					else if ( xhr.readyState === 4 ) {
5575						_fnLog( oSettings, 0, 'Ajax error', 7 );
5576					}
5577				}
5578	
5579				_fnProcessingDisplay( oSettings, false );
5580			}
5581		};
5582	
5583		// Store the data submitted for the API
5584		oSettings.oAjaxData = data;
5585	
5586		// Allow plug-ins and external processes to modify the data
5587		_fnCallbackFire( oSettings, null, 'preXhr', [oSettings, data] );
5588	
5589		if ( oSettings.fnServerData )
5590		{
5591			// DataTables 1.9- compatibility
5592			oSettings.fnServerData.call( instance,
5593				oSettings.sAjaxSource,
5594				$.map( data, function (val, key) { // Need to convert back to 1.9 trad format
5595					return { name: key, value: val };
5596				} ),
5597				callback,
5598				oSettings
5599			);
5600		}
5601		else if ( oSettings.sAjaxSource || typeof ajax === 'string' )
5602		{
5603			// DataTables 1.9- compatibility
5604			oSettings.jqXHR = $.ajax( $.extend( baseAjax, {
5605				url: ajax || oSettings.sAjaxSource
5606			} ) );
5607		}
5608		else if ( typeof ajax === 'function' )
5609		{
5610			// Is a function - let the caller define what needs to be done
5611			oSettings.jqXHR = ajax.call( instance, data, callback, oSettings );
5612		}
5613		else
5614		{
5615			// Object to extend the base settings
5616			oSettings.jqXHR = $.ajax( $.extend( baseAjax, ajax ) );
5617	
5618			// Restore for next time around
5619			ajax.data = ajaxData;
5620		}
5621	}
5622	
5623	
5624	/**
5625	 * Update the table using an Ajax call
5626	 *  @param {object} settings dataTables settings object
5627	 *  @returns {boolean} Block the table drawing or not
5628	 *  @memberof DataTable#oApi
5629	 */
5630	function _fnAjaxUpdate( settings )
5631	{
5632		if ( settings.bAjaxDataGet ) {
5633			settings.iDraw++;
5634			_fnProcessingDisplay( settings, true );
5635	
5636			_fnBuildAjax(
5637				settings,
5638				_fnAjaxParameters( settings ),
5639				function(json) {
5640					_fnAjaxUpdateDraw( settings, json );
5641				}
5642			);
5643	
5644			return false;
5645		}
5646		return true;
5647	}
5648	
5649	
5650	/**
5651	 * Build up the parameters in an object needed for a server-side processing
5652	 * request. Note that this is basically done twice, is different ways - a modern
5653	 * method which is used by default in DataTables 1.10 which uses objects and
5654	 * arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if
5655	 * the sAjaxSource option is used in the initialisation, or the legacyAjax
5656	 * option is set.
5657	 *  @param {object} oSettings dataTables settings object
5658	 *  @returns {bool} block the table drawing or not
5659	 *  @memberof DataTable#oApi
5660	 */
5661	function _fnAjaxParameters( settings )
5662	{
5663		var
5664			columns = settings.aoColumns,
5665			columnCount = columns.length,
5666			features = settings.oFeatures,
5667			preSearch = settings.oPreviousSearch,
5668			preColSearch = settings.aoPreSearchCols,
5669			i, data = [], dataProp, column, columnSearch,
5670			sort = _fnSortFlatten( settings ),
5671			displayStart = settings._iDisplayStart,
5672			displayLength = features.bPaginate !== false ?
5673				settings._iDisplayLength :
5674				-1;
5675	
5676		var param = function ( name, value ) {
5677			data.push( { 'name': name, 'value': value } );
5678		};
5679	
5680		// DataTables 1.9- compatible method
5681		param( 'sEcho',          settings.iDraw );
5682		param( 'iColumns',       columnCount );
5683		param( 'sColumns',       _pluck( columns, 'sName' ).join(',') );
5684		param( 'iDisplayStart',  displayStart );
5685		param( 'iDisplayLength', displayLength );
5686	
5687		// DataTables 1.10+ method
5688		var d = {
5689			draw:    settings.iDraw,
5690			columns: [],
5691			order:   [],
5692			start:   displayStart,
5693			length:  displayLength,
5694			search:  {
5695				value: preSearch.sSearch,
5696				regex: preSearch.bRegex
5697			}
5698		};
5699	
5700		for ( i=0 ; i<columnCount ; i++ ) {
5701			column = columns[i];
5702			columnSearch = preColSearch[i];
5703			dataProp = typeof column.mData=="function" ? 'function' : column.mData ;
5704	
5705			d.columns.push( {
5706				data:       dataProp,
5707				name:       column.sName,
5708				searchable: column.bSearchable,
5709				orderable:  column.bSortable,
5710				search:     {
5711					value: columnSearch.sSearch,
5712					regex: columnSearch.bRegex
5713				}
5714			} );
5715	
5716			param( "mDataProp_"+i, dataProp );
5717	
5718			if ( features.bFilter ) {
5719				param( 'sSearch_'+i,     columnSearch.sSearch );
5720				param( 'bRegex_'+i,      columnSearch.bRegex );
5721				param( 'bSearchable_'+i, column.bSearchable );
5722			}
5723	
5724			if ( features.bSort ) {
5725				param( 'bSortable_'+i, column.bSortable );
5726			}
5727		}
5728	
5729		if ( features.bFilter ) {
5730			param( 'sSearch', preSearch.sSearch );
5731			param( 'bRegex', preSearch.bRegex );
5732		}
5733	
5734		if ( features.bSort ) {
5735			$.each( sort, function ( i, val ) {
5736				d.order.push( { column: val.col, dir: val.dir } );
5737	
5738				param( 'iSortCol_'+i, val.col );
5739				param( 'sSortDir_'+i, val.dir );
5740			} );
5741	
5742			param( 'iSortingCols', sort.length );
5743		}
5744	
5745		// If the legacy.ajax parameter is null, then we automatically decide which
5746		// form to use, based on sAjaxSource
5747		var legacy = DataTable.ext.legacy.ajax;
5748		if ( legacy === null ) {
5749			return settings.sAjaxSource ? data : d;
5750		}
5751	
5752		// Otherwise, if legacy has been specified then we use that to decide on the
5753		// form
5754		return legacy ? data : d;
5755	}
5756	
5757	
5758	/**
5759	 * Data the data from the server (nuking the old) and redraw the table
5760	 *  @param {object} oSettings dataTables settings object
5761	 *  @param {object} json json data return from the server.
5762	 *  @param {string} json.sEcho Tracking flag for DataTables to match requests
5763	 *  @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering
5764	 *  @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering
5765	 *  @param {array} json.aaData The data to display on this page
5766	 *  @param {string} [json.sColumns] Column ordering (sName, comma separated)
5767	 *  @memberof DataTable#oApi
5768	 */
5769	function _fnAjaxUpdateDraw ( settings, json )
5770	{
5771		// v1.10 uses camelCase variables, while 1.9 uses Hungarian notation.
5772		// Support both
5773		var compat = function ( old, modern ) {
5774			return json[old] !== undefined ? json[old] : json[modern];
5775		};
5776	
5777		var data = _fnAjaxDataSrc( settings, json );
5778		var draw            = compat( 'sEcho',                'draw' );
5779		var recordsTotal    = compat( 'iTotalRecords',        'recordsTotal' );
5780		var recordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' );
5781	
5782		if ( draw !== undefined ) {
5783			// Protect against out of sequence returns
5784			if ( draw*1 < settings.iDraw ) {
5785				return;
5786			}
5787			settings.iDraw = draw * 1;
5788		}
5789	
5790		_fnClearTable( settings );
5791		settings._iRecordsTotal   = parseInt(recordsTotal, 10);
5792		settings._iRecordsDisplay = parseInt(recordsFiltered, 10);
5793	
5794		for ( var i=0, ien=data.length ; i<ien ; i++ ) {
5795			_fnAddData( settings, data[i] );
5796		}
5797		settings.aiDisplay = settings.aiDisplayMaster.slice();
5798	
5799		settings.bAjaxDataGet = false;
5800		_fnDraw( settings );
5801	
5802		if ( ! settings._bInitComplete ) {
5803			_fnInitComplete( settings, json );
5804		}
5805	
5806		settings.bAjaxDataGet = true;
5807		_fnProcessingDisplay( settings, false );
5808	}
5809	
5810	
5811	/**
5812	 * Get the data from the JSON data source to use for drawing a table. Using
5813	 * `_fnGetObjectDataFn` allows the data to be sourced from a property of the
5814	 * source object, or from a processing function.
5815	 *  @param {object} oSettings dataTables settings object
5816	 *  @param  {object} json Data source object / array from the server
5817	 *  @return {array} Array of data to use
5818	 */
5819	function _fnAjaxDataSrc ( oSettings, json )
5820	{
5821		var dataSrc = $.isPlainObject( oSettings.ajax ) && oSettings.ajax.dataSrc !== undefined ?
5822			oSettings.ajax.dataSrc :
5823			oSettings.sAjaxDataProp; // Compatibility with 1.9-.
5824	
5825		// Compatibility with 1.9-. In order to read from aaData, check if the
5826		// default has been changed, if not, check for aaData
5827		if ( dataSrc === 'data' ) {
5828			return json.aaData || json[dataSrc];
5829		}
5830	
5831		return dataSrc !== "" ?
5832			_fnGetObjectDataFn( dataSrc )( json ) :
5833			json;
5834	}
5835	
5836	/**
5837	 * Generate the node required for filtering text
5838	 *  @returns {node} Filter control element
5839	 *  @param {object} oSettings dataTables settings object
5840	 *  @memberof DataTable#oApi
5841	 */
5842	function _fnFeatureHtmlFilter ( settings )
5843	{
5844		var classes = settings.oClasses;
5845		var tableId = settings.sTableId;
5846		var language = settings.oLanguage;
5847		var previousSearch = settings.oPreviousSearch;
5848		var features = settings.aanFeatures;
5849		var input = '<input type="search" class="'+classes.sFilterInput+'"/>';
5850	
5851		var str = language.sSearch;
5852		str = str.match(/_INPUT_/) ?
5853			str.replace('_INPUT_', input) :
5854			str+input;
5855	
5856		var filter = $('<div/>', {
5857				'id': ! features.f ? tableId+'_filter' : null,
5858				'class': classes.sFilter
5859			} )
5860			.append( $('<label/>' ).append( str ) );
5861	
5862		var searchFn = function() {
5863			/* Update all other filter input elements for the new display */
5864			var n = features.f;
5865			var val = !this.value ? "" : this.value; // mental IE8 fix :-(
5866	
5867			/* Now do the filter */
5868			if ( val != previousSearch.sSearch ) {
5869				_fnFilterComplete( settings, {
5870					"sSearch": val,
5871					"bRegex": previousSearch.bRegex,
5872					"bSmart": previousSearch.bSmart ,
5873					"bCaseInsensitive": previousSearch.bCaseInsensitive
5874				} );
5875	
5876				// Need to redraw, without resorting
5877				settings._iDisplayStart = 0;
5878				_fnDraw( settings );
5879			}
5880		};
5881	
5882		var searchDelay = settings.searchDelay !== null ?
5883			settings.searchDelay :
5884			_fnDataSource( settings ) === 'ssp' ?
5885				400 :
5886				0;
5887	
5888		var jqFilter = $('input', filter)
5889			.val( previousSearch.sSearch )
5890			.attr( 'placeholder', language.sSearchPlaceholder )
5891			.on(
5892				'keyup.DT search.DT input.DT paste.DT cut.DT',
5893				searchDelay ?
5894					_fnThrottle( searchFn, searchDelay ) :
5895					searchFn
5896			)
5897			.on( 'mouseup', function(e) {
5898				// Edge fix! Edge 17 does not trigger anything other than mouse events when clicking
5899				// on the clear icon (Edge bug 17584515). This is safe in other browsers as `searchFn`
5900				// checks the value to see if it has changed. In other browsers it won't have.
5901				setTimeout( function () {
5902					searchFn.call(jqFilter[0]);
5903				}, 10);
5904			} )
5905			.on( 'keypress.DT', function(e) {
5906				/* Prevent form submission */
5907				if ( e.keyCode == 13 ) {
5908					return false;
5909				}
5910			} )
5911			.attr('aria-controls', tableId);
5912	
5913		// Update the input elements whenever the table is filtered
5914		$(settings.nTable).on( 'search.dt.DT', function ( ev, s ) {
5915			if ( settings === s ) {
5916				// IE9 throws an 'unknown error' if document.activeElement is used
5917				// inside an iframe or frame...
5918				try {
5919					if ( jqFilter[0] !== document.activeElement ) {
5920						jqFilter.val( previousSearch.sSearch );
5921					}
5922				}
5923				catch ( e ) {}
5924			}
5925		} );
5926	
5927		return filter[0];
5928	}
5929	
5930	
5931	/**
5932	 * Filter the table using both the global filter and column based filtering
5933	 *  @param {object} oSettings dataTables settings object
5934	 *  @param {object} oSearch search information
5935	 *  @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)
5936	 *  @memberof DataTable#oApi
5937	 */
5938	function _fnFilterComplete ( oSettings, oInput, iForce )
5939	{
5940		var oPrevSearch = oSettings.oPreviousSearch;
5941		var aoPrevSearch = oSettings.aoPreSearchCols;
5942		var fnSaveFilter = function ( oFilter ) {
5943			/* Save the filtering values */
5944			oPrevSearch.sSearch = oFilter.sSearch;
5945			oPrevSearch.bRegex = oFilter.bRegex;
5946			oPrevSearch.bSmart = oFilter.bSmart;
5947			oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive;
5948		};
5949		var fnRegex = function ( o ) {
5950			// Backwards compatibility with the bEscapeRegex option
5951			return o.bEscapeRegex !== undefined ? !o.bEscapeRegex : o.bRegex;
5952		};
5953	
5954		// Resolve any column types that are unknown due to addition or invalidation
5955		// @todo As per sort - can this be moved into an event handler?
5956		_fnColumnTypes( oSettings );
5957	
5958		/* In server-side processing all filtering is done by the server, so no point hanging around here */
5959		if ( _fnDataSource( oSettings ) != 'ssp' )
5960		{
5961			/* Global filter */
5962			_fnFilter( oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive );
5963			fnSaveFilter( oInput );
5964	
5965			/* Now do the individual column filter */
5966			for ( var i=0 ; i<aoPrevSearch.length ; i++ )
5967			{
5968				_fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, fnRegex(aoPrevSearch[i]),
5969					aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive );
5970			}
5971	
5972			/* Custom filtering */
5973			_fnFilterCustom( oSettings );
5974		}
5975		else
5976		{
5977			fnSaveFilter( oInput );
5978		}
5979	
5980		/* Tell the draw function we have been filtering */
5981		oSettings.bFiltered = true;
5982		_fnCallbackFire( oSettings, null, 'search', [oSettings] );
5983	}
5984	
5985	
5986	/**
5987	 * Apply custom filtering functions
5988	 *  @param {object} oSettings dataTables settings object
5989	 *  @memberof DataTable#oApi
5990	 */
5991	function _fnFilterCustom( settings )
5992	{
5993		var filters = DataTable.ext.search;
5994		var displayRows = settings.aiDisplay;
5995		var row, rowIdx;
5996	
5997		for ( var i=0, ien=filters.length ; i<ien ; i++ ) {
5998			var rows = [];
5999	
6000			// Loop over each row and see if it should be included
6001			for ( var j=0, jen=displayRows.length ; j<jen ; j++ ) {
6002				rowIdx = displayRows[ j ];
6003				row = settings.aoData[ rowIdx ];
6004	
6005				if ( filters[i]( settings, row._aFilterData, rowIdx, row._aData, j ) ) {
6006					rows.push( rowIdx );
6007				}
6008			}
6009	
6010			// So the array reference doesn't break set the results into the
6011			// existing array
6012			displayRows.length = 0;
6013			$.merge( displayRows, rows );
6014		}
6015	}
6016	
6017	
6018	/**
6019	 * Filter the table on a per-column basis
6020	 *  @param {object} oSettings dataTables settings object
6021	 *  @param {string} sInput string to filter on
6022	 *  @param {int} iColumn column to filter
6023	 *  @param {bool} bRegex treat search string as a regular expression or not
6024	 *  @param {bool} bSmart use smart filtering or not
6025	 *  @param {bool} bCaseInsensitive Do case insenstive matching or not
6026	 *  @memberof DataTable#oApi
6027	 */
6028	function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, caseInsensitive )
6029	{
6030		if ( searchStr === '' ) {
6031			return;
6032		}
6033	
6034		var data;
6035		var out = [];
6036		var display = settings.aiDisplay;
6037		var rpSearch = _fnFilterCreateSearch( searchStr, regex, smart, caseInsensitive );
6038	
6039		for ( var i=0 ; i<display.length ; i++ ) {
6040			data = settings.aoData[ display[i] ]._aFilterData[ colIdx ];
6041	
6042			if ( rpSearch.test( data ) ) {
6043				out.push( display[i] );
6044			}
6045		}
6046	
6047		settings.aiDisplay = out;
6048	}
6049	
6050	
6051	/**
6052	 * Filter the data table based on user input and draw the table
6053	 *  @param {object} settings dataTables settings object
6054	 *  @param {string} input string to filter on
6055	 *  @param {int} force optional - force a research of the master array (1) or not (undefined or 0)
6056	 *  @param {bool} regex treat as a regular expression or not
6057	 *  @param {bool} smart perform smart filtering or not
6058	 *  @param {bool} caseInsensitive Do case insenstive matching or not
6059	 *  @memberof DataTable#oApi
6060	 */
6061	function _fnFilter( settings, input, force, regex, smart, caseInsensitive )
6062	{
6063		var rpSearch = _fnFilterCreateSearch( input, regex, smart, caseInsensitive );
6064		var prevSearch = settings.oPreviousSearch.sSearch;
6065		var displayMaster = settings.aiDisplayMaster;
6066		var display, invalidated, i;
6067		var filtered = [];
6068	
6069		// Need to take account of custom filtering functions - always filter
6070		if ( DataTable.ext.search.length !== 0 ) {
6071			force = true;
6072		}
6073	
6074		// Check if any of the rows were invalidated
6075		invalidated = _fnFilterData( settings );
6076	
6077		// If the input is blank - we just want the full data set
6078		if ( input.length <= 0 ) {
6079			settings.aiDisplay = displayMaster.slice();
6080		}
6081		else {
6082			// New search - start from the master array
6083			if ( invalidated ||
6084				 force ||
6085				 regex ||
6086				 prevSearch.length > input.length ||
6087				 input.indexOf(prevSearch) !== 0 ||
6088				 settings.bSorted // On resort, the display master needs to be
6089				                  // re-filtered since indexes will have changed
6090			) {
6091				settings.aiDisplay = displayMaster.slice();
6092			}
6093	
6094			// Search the display array
6095			display = settings.aiDisplay;
6096	
6097			for ( i=0 ; i<display.length ; i++ ) {
6098				if ( rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) {
6099					filtered.push( display[i] );
6100				}
6101			}
6102	
6103			settings.aiDisplay = filtered;
6104		}
6105	}
6106	
6107	
6108	/**
6109	 * Build a regular expression object suitable for searching a table
6110	 *  @param {string} sSearch string to search for
6111	 *  @param {bool} bRegex treat as a regular expression or not
6112	 *  @param {bool} bSmart perform smart filtering or not
6113	 *  @param {bool} bCaseInsensitive Do case insensitive matching or not
6114	 *  @returns {RegExp} constructed object
6115	 *  @memberof DataTable#oApi
6116	 */
6117	function _fnFilterCreateSearch( search, regex, smart, caseInsensitive )
6118	{
6119		search = regex ?
6120			search :
6121			_fnEscapeRegex( search );
6122		
6123		if ( smart ) {
6124			/* For smart filtering we want to allow the search to work regardless of
6125			 * word order. We also want double quoted text to be preserved, so word
6126			 * order is important - a la google. So this is what we want to
6127			 * generate:
6128			 * 
6129			 * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$
6130			 */
6131			var a = $.map( search.match( /"[^"]+"|[^ ]+/g ) || [''], function ( word ) {
6132				if ( word.charAt(0) === '"' ) {
6133					var m = word.match( /^"(.*)"$/ );
6134					word = m ? m[1] : word;
6135				}
6136	
6137				return word.replace('"', '');
6138			} );
6139	
6140			search = '^(?=.*?'+a.join( ')(?=.*?' )+').*$';
6141		}
6142	
6143		return new RegExp( search, caseInsensitive ? 'i' : '' );
6144	}
6145	
6146	
6147	/**
6148	 * Escape a string such that it can be used in a regular expression
6149	 *  @param {string} sVal string to escape
6150	 *  @returns {string} escaped string
6151	 *  @memberof DataTable#oApi
6152	 */
6153	var _fnEscapeRegex = DataTable.util.escapeRegex;
6154	
6155	var __filter_div = $('<div>')[0];
6156	var __filter_div_textContent = __filter_div.textContent !== undefined;
6157	
6158	// Update the filtering data for each row if needed (by invalidation or first run)
6159	function _fnFilterData ( settings )
6160	{
6161		var columns = settings.aoColumns;
6162		var column;
6163		var i, j, ien, jen, filterData, cellData, row;
6164		var fomatters = DataTable.ext.type.search;
6165		var wasInvalidated = false;
6166	
6167		for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
6168			row = settings.aoData[i];
6169	
6170			if ( ! row._aFilterData ) {
6171				filterData = [];
6172	
6173				for ( j=0, jen=columns.length ; j<jen ; j++ ) {
6174					column = columns[j];
6175	
6176					if ( column.bSearchable ) {
6177						cellData = _fnGetCellData( settings, i, j, 'filter' );
6178	
6179						if ( fomatters[ column.sType ] ) {
6180							cellData = fomatters[ column.sType ]( cellData );
6181						}
6182	
6183						// Search in DataTables 1.10 is string based. In 1.11 this
6184						// should be altered to also allow strict type checking.
6185						if ( cellData === null ) {
6186							cellData = '';
6187						}
6188	
6189						if ( typeof cellData !== 'string' && cellData.toString ) {
6190							cellData = cellData.toString();
6191						}
6192					}
6193					else {
6194						cellData = '';
6195					}
6196	
6197					// If it looks like there is an HTML entity in the string,
6198					// attempt to decode it so sorting works as expected. Note that
6199					// we could use a single line of jQuery to do this, but the DOM
6200					// method used here is much faster http://jsperf.com/html-decode
6201					if ( cellData.indexOf && cellData.indexOf('&') !== -1 ) {
6202						__filter_div.innerHTML = cellData;
6203						cellData = __filter_div_textContent ?
6204							__filter_div.textContent :
6205							__filter_div.innerText;
6206					}
6207	
6208					if ( cellData.replace ) {
6209						cellData = cellData.replace(/[\r\n\u2028]/g, '');
6210					}
6211	
6212					filterData.push( cellData );
6213				}
6214	
6215				row._aFilterData = filterData;
6216				row._sFilterRow = filterData.join('  ');
6217				wasInvalidated = true;
6218			}
6219		}
6220	
6221		return wasInvalidated;
6222	}
6223	
6224	
6225	/**
6226	 * Convert from the internal Hungarian notation to camelCase for external
6227	 * interaction
6228	 *  @param {object} obj Object to convert
6229	 *  @returns {object} Inverted object
6230	 *  @memberof DataTable#oApi
6231	 */
6232	function _fnSearchToCamel ( obj )
6233	{
6234		return {
6235			search:          obj.sSearch,
6236			smart:           obj.bSmart,
6237			regex:           obj.bRegex,
6238			caseInsensitive: obj.bCaseInsensitive
6239		};
6240	}
6241	
6242	
6243	
6244	/**
6245	 * Convert from camelCase notation to the internal Hungarian. We could use the
6246	 * Hungarian convert function here, but this is cleaner
6247	 *  @param {object} obj Object to convert
6248	 *  @returns {object} Inverted object
6249	 *  @memberof DataTable#oApi
6250	 */
6251	function _fnSearchToHung ( obj )
6252	{
6253		return {
6254			sSearch:          obj.search,
6255			bSmart:           obj.smart,
6256			bRegex:           obj.regex,
6257			bCaseInsensitive: obj.caseInsensitive
6258		};
6259	}
6260	
6261	/**
6262	 * Generate the node required for the info display
6263	 *  @param {object} oSettings dataTables settings object
6264	 *  @returns {node} Information element
6265	 *  @memberof DataTable#oApi
6266	 */
6267	function _fnFeatureHtmlInfo ( settings )
6268	{
6269		var
6270			tid = settings.sTableId,
6271			nodes = settings.aanFeatures.i,
6272			n = $('<div/>', {
6273				'class': settings.oClasses.sInfo,
6274				'id': ! nodes ? tid+'_info' : null
6275			} );
6276	
6277		if ( ! nodes ) {
6278			// Update display on each draw
6279			settings.aoDrawCallback.push( {
6280				"fn": _fnUpdateInfo,
6281				"sName": "information"
6282			} );
6283	
6284			n
6285				.attr( 'role', 'status' )
6286				.attr( 'aria-live', 'polite' );
6287	
6288			// Table is described by our info div
6289			$(settings.nTable).attr( 'aria-describedby', tid+'_info' );
6290		}
6291	
6292		return n[0];
6293	}
6294	
6295	
6296	/**
6297	 * Update the information elements in the display
6298	 *  @param {object} settings dataTables settings object
6299	 *  @memberof DataTable#oApi
6300	 */
6301	function _fnUpdateInfo ( settings )
6302	{
6303		/* Show information about the table */
6304		var nodes = settings.aanFeatures.i;
6305		if ( nodes.length === 0 ) {
6306			return;
6307		}
6308	
6309		var
6310			lang  = settings.oLanguage,
6311			start = settings._iDisplayStart+1,
6312			end   = settings.fnDisplayEnd(),
6313			max   = settings.fnRecordsTotal(),
6314			total = settings.fnRecordsDisplay(),
6315			out   = total ?
6316				lang.sInfo :
6317				lang.sInfoEmpty;
6318	
6319		if ( total !== max ) {
6320			/* Record set after filtering */
6321			out += ' ' + lang.sInfoFiltered;
6322		}
6323	
6324		// Convert the macros
6325		out += lang.sInfoPostFix;
6326		out = _fnInfoMacros( settings, out );
6327	
6328		var callback = lang.fnInfoCallback;
6329		if ( callback !== null ) {
6330			out = callback.call( settings.oInstance,
6331				settings, start, end, max, total, out
6332			);
6333		}
6334	
6335		$(nodes).html( out );
6336	}
6337	
6338	
6339	function _fnInfoMacros ( settings, str )
6340	{
6341		// When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
6342		// internally
6343		var
6344			formatter  = settings.fnFormatNumber,
6345			start      = settings._iDisplayStart+1,
6346			len        = settings._iDisplayLength,
6347			vis        = settings.fnRecordsDisplay(),
6348			all        = len === -1;
6349	
6350		return str.
6351			replace(/_START_/g, formatter.call( settings, start ) ).
6352			replace(/_END_/g,   formatter.call( settings, settings.fnDisplayEnd() ) ).
6353			replace(/_MAX_/g,   formatter.call( settings, settings.fnRecordsTotal() ) ).
6354			replace(/_TOTAL_/g, formatter.call( settings, vis ) ).
6355			replace(/_PAGE_/g,  formatter.call( settings, all ? 1 : Math.ceil( start / len ) ) ).
6356			replace(/_PAGES_/g, formatter.call( settings, all ? 1 : Math.ceil( vis / len ) ) );
6357	}
6358	
6359	
6360	
6361	/**
6362	 * Draw the table for the first time, adding all required features
6363	 *  @param {object} settings dataTables settings object
6364	 *  @memberof DataTable#oApi
6365	 */
6366	function _fnInitialise ( settings )
6367	{
6368		var i, iLen, iAjaxStart=settings.iInitDisplayStart;
6369		var columns = settings.aoColumns, column;
6370		var features = settings.oFeatures;
6371		var deferLoading = settings.bDeferLoading; // value modified by the draw
6372	
6373		/* Ensure that the table data is fully initialised */
6374		if ( ! settings.bInitialised ) {
6375			setTimeout( function(){ _fnInitialise( settings ); }, 200 );
6376			return;
6377		}
6378	
6379		/* Show the display HTML options */
6380		_fnAddOptionsHtml( settings );
6381	
6382		/* Build and draw the header / footer for the table */
6383		_fnBuildHead( settings );
6384		_fnDrawHead( settings, settings.aoHeader );
6385		_fnDrawHead( settings, settings.aoFooter );
6386	
6387		/* Okay to show that something is going on now */
6388		_fnProcessingDisplay( settings, true );
6389	
6390		/* Calculate sizes for columns */
6391		if ( features.bAutoWidth ) {
6392			_fnCalculateColumnWidths( settings );
6393		}
6394	
6395		for ( i=0, iLen=columns.length ; i<iLen ; i++ ) {
6396			column = columns[i];
6397	
6398			if ( column.sWidth ) {
6399				column.nTh.style.width = _fnStringToCss( column.sWidth );
6400			}
6401		}
6402	
6403		_fnCallbackFire( settings, null, 'preInit', [settings] );
6404	
6405		// If there is default sorting required - let's do it. The sort function
6406		// will do the drawing for us. Otherwise we draw the table regardless of the
6407		// Ajax source - this allows the table to look initialised for Ajax sourcing
6408		// data (show 'loading' message possibly)
6409		_fnReDraw( settings );
6410	
6411		// Server-side processing init complete is done by _fnAjaxUpdateDraw
6412		var dataSrc = _fnDataSource( settings );
6413		if ( dataSrc != 'ssp' || deferLoading ) {
6414			// if there is an ajax source load the data
6415			if ( dataSrc == 'ajax' ) {
6416				_fnBuildAjax( settings, [], function(json) {
6417					var aData = _fnAjaxDataSrc( settings, json );
6418	
6419					// Got the data - add it to the table
6420					for ( i=0 ; i<aData.length ; i++ ) {
6421						_fnAddData( settings, aData[i] );
6422					}
6423	
6424					// Reset the init display for cookie saving. We've already done
6425					// a filter, and therefore cleared it before. So we need to make
6426					// it appear 'fresh'
6427					settings.iInitDisplayStart = iAjaxStart;
6428	
6429					_fnReDraw( settings );
6430	
6431					_fnProcessingDisplay( settings, false );
6432					_fnInitComplete( settings, json );
6433				}, settings );
6434			}
6435			else {
6436				_fnProcessingDisplay( settings, false );
6437				_fnInitComplete( settings );
6438			}
6439		}
6440	}
6441	
6442	
6443	/**
6444	 * Draw the table for the first time, adding all required features
6445	 *  @param {object} oSettings dataTables settings object
6446	 *  @param {object} [json] JSON from the server that completed the table, if using Ajax source
6447	 *    with client-side processing (optional)
6448	 *  @memberof DataTable#oApi
6449	 */
6450	function _fnInitComplete ( settings, json )
6451	{
6452		settings._bInitComplete = true;
6453	
6454		// When data was added after the initialisation (data or Ajax) we need to
6455		// calculate the column sizing
6456		if ( json || settings.oInit.aaData ) {
6457			_fnAdjustColumnSizing( settings );
6458		}
6459	
6460		_fnCallbackFire( settings, null, 'plugin-init', [settings, json] );
6461		_fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] );
6462	}
6463	
6464	
6465	function _fnLengthChange ( settings, val )
6466	{
6467		var len = parseInt( val, 10 );
6468		settings._iDisplayLength = len;
6469	
6470		_fnLengthOverflow( settings );
6471	
6472		// Fire length change event
6473		_fnCallbackFire( settings, null, 'length', [settings, len] );
6474	}
6475	
6476	
6477	/**
6478	 * Generate the node required for user display length changing
6479	 *  @param {object} settings dataTables settings object
6480	 *  @returns {node} Display length feature node
6481	 *  @memberof DataTable#oApi
6482	 */
6483	function _fnFeatureHtmlLength ( settings )
6484	{
6485		var
6486			classes  = settings.oClasses,
6487			tableId  = settings.sTableId,
6488			menu     = settings.aLengthMenu,
6489			d2       = Array.isArray( menu[0] ),
6490			lengths  = d2 ? menu[0] : menu,
6491			language = d2 ? menu[1] : menu;
6492	
6493		var select = $('<select/>', {
6494			'name':          tableId+'_length',
6495			'aria-controls': tableId,
6496			'class':         classes.sLengthSelect
6497		} );
6498	
6499		for ( var i=0, ien=lengths.length ; i<ien ; i++ ) {
6500			select[0][ i ] = new Option(
6501				typeof language[i] === 'number' ?
6502					settings.fnFormatNumber( language[i] ) :
6503					language[i],
6504				lengths[i]
6505			);
6506		}
6507	
6508		var div = $('<div><label/></div>').addClass( classes.sLength );
6509		if ( ! settings.aanFeatures.l ) {
6510			div[0].id = tableId+'_length';
6511		}
6512	
6513		div.children().append(
6514			settings.oLanguage.sLengthMenu.replace( '_MENU_', select[0].outerHTML )
6515		);
6516	
6517		// Can't use `select` variable as user might provide their own and the
6518		// reference is broken by the use of outerHTML
6519		$('select', div)
6520			.val( settings._iDisplayLength )
6521			.on( 'change.DT', function(e) {
6522				_fnLengthChange( settings, $(this).val() );
6523				_fnDraw( settings );
6524			} );
6525	
6526		// Update node value whenever anything changes the table's length
6527		$(settings.nTable).on( 'length.dt.DT', function (e, s, len) {
6528			if ( settings === s ) {
6529				$('select', div).val( len );
6530			}
6531		} );
6532	
6533		return div[0];
6534	}
6535	
6536	
6537	
6538	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
6539	 * Note that most of the paging logic is done in
6540	 * DataTable.ext.pager
6541	 */
6542	
6543	/**
6544	 * Generate the node required for default pagination
6545	 *  @param {object} oSettings dataTables settings object
6546	 *  @returns {node} Pagination feature node
6547	 *  @memberof DataTable#oApi
6548	 */
6549	function _fnFeatureHtmlPaginate ( settings )
6550	{
6551		var
6552			type   = settings.sPaginationType,
6553			plugin = DataTable.ext.pager[ type ],
6554			modern = typeof plugin === 'function',
6555			redraw = function( settings ) {
6556				_fnDraw( settings );
6557			},
6558			node = $('<div/>').addClass( settings.oClasses.sPaging + type )[0],
6559			features = settings.aanFeatures;
6560	
6561		if ( ! modern ) {
6562			plugin.fnInit( settings, node, redraw );
6563		}
6564	
6565		/* Add a draw callback for the pagination on first instance, to update the paging display */
6566		if ( ! features.p )
6567		{
6568			node.id = settings.sTableId+'_paginate';
6569	
6570			settings.aoDrawCallback.push( {
6571				"fn": function( settings ) {
6572					if ( modern ) {
6573						var
6574							start      = settings._iDisplayStart,
6575							len        = settings._iDisplayLength,
6576							visRecords = settings.fnRecordsDisplay(),
6577							all        = len === -1,
6578							page = all ? 0 : Math.ceil( start / len ),
6579							pages = all ? 1 : Math.ceil( visRecords / len ),
6580							buttons = plugin(page, pages),
6581							i, ien;
6582	
6583						for ( i=0, ien=features.p.length ; i<ien ; i++ ) {
6584							_fnRenderer( settings, 'pageButton' )(
6585								settings, features.p[i], i, buttons, page, pages
6586							);
6587						}
6588					}
6589					else {
6590						plugin.fnUpdate( settings, redraw );
6591					}
6592				},
6593				"sName": "pagination"
6594			} );
6595		}
6596	
6597		return node;
6598	}
6599	
6600	
6601	/**
6602	 * Alter the display settings to change the page
6603	 *  @param {object} settings DataTables settings object
6604	 *  @param {string|int} action Paging action to take: "first", "previous",
6605	 *    "next" or "last" or page number to jump to (integer)
6606	 *  @param [bool] redraw Automatically draw the update or not
6607	 *  @returns {bool} true page has changed, false - no change
6608	 *  @memberof DataTable#oApi
6609	 */
6610	function _fnPageChange ( settings, action, redraw )
6611	{
6612		var
6613			start     = settings._iDisplayStart,
6614			len       = settings._iDisplayLength,
6615			records   = settings.fnRecordsDisplay();
6616	
6617		if ( records === 0 || len === -1 )
6618		{
6619			start = 0;
6620		}
6621		else if ( typeof action === "number" )
6622		{
6623			start = action * len;
6624	
6625			if ( start > records )
6626			{
6627				start = 0;
6628			}
6629		}
6630		else if ( action == "first" )
6631		{
6632			start = 0;
6633		}
6634		else if ( action == "previous" )
6635		{
6636			start = len >= 0 ?
6637				start - len :
6638				0;
6639	
6640			if ( start < 0 )
6641			{
6642			  start = 0;
6643			}
6644		}
6645		else if ( action == "next" )
6646		{
6647			if ( start + len < records )
6648			{
6649				start += len;
6650			}
6651		}
6652		else if ( action == "last" )
6653		{
6654			start = Math.floor( (records-1) / len) * len;
6655		}
6656		else
6657		{
6658			_fnLog( settings, 0, "Unknown paging action: "+action, 5 );
6659		}
6660	
6661		var changed = settings._iDisplayStart !== start;
6662		settings._iDisplayStart = start;
6663	
6664		if ( changed ) {
6665			_fnCallbackFire( settings, null, 'page', [settings] );
6666	
6667			if ( redraw ) {
6668				_fnDraw( settings );
6669			}
6670		}
6671	
6672		return changed;
6673	}
6674	
6675	
6676	
6677	/**
6678	 * Generate the node required for the processing node
6679	 *  @param {object} settings dataTables settings object
6680	 *  @returns {node} Processing element
6681	 *  @memberof DataTable#oApi
6682	 */
6683	function _fnFeatureHtmlProcessing ( settings )
6684	{
6685		return $('<div/>', {
6686				'id': ! settings.aanFeatures.r ? settings.sTableId+'_processing' : null,
6687				'class': settings.oClasses.sProcessing
6688			} )
6689			.html( settings.oLanguage.sProcessing )
6690			.insertBefore( settings.nTable )[0];
6691	}
6692	
6693	
6694	/**
6695	 * Display or hide the processing indicator
6696	 *  @param {object} settings dataTables settings object
6697	 *  @param {bool} show Show the processing indicator (true) or not (false)
6698	 *  @memberof DataTable#oApi
6699	 */
6700	function _fnProcessingDisplay ( settings, show )
6701	{
6702		if ( settings.oFeatures.bProcessing ) {
6703			$(settings.aanFeatures.r).css( 'display', show ? 'block' : 'none' );
6704		}
6705	
6706		_fnCallbackFire( settings, null, 'processing', [settings, show] );
6707	}
6708	
6709	/**
6710	 * Add any control elements for the table - specifically scrolling
6711	 *  @param {object} settings dataTables settings object
6712	 *  @returns {node} Node to add to the DOM
6713	 *  @memberof DataTable#oApi
6714	 */
6715	function _fnFeatureHtmlTable ( settings )
6716	{
6717		var table = $(settings.nTable);
6718	
6719		// Add the ARIA grid role to the table
6720		table.attr( 'role', 'grid' );
6721	
6722		// Scrolling from here on in
6723		var scroll = settings.oScroll;
6724	
6725		if ( scroll.sX === '' && scroll.sY === '' ) {
6726			return settings.nTable;
6727		}
6728	
6729		var scrollX = scroll.sX;
6730		var scrollY = scroll.sY;
6731		var classes = settings.oClasses;
6732		var caption = table.children('caption');
6733		var captionSide = caption.length ? caption[0]._captionSide : null;
6734		var headerClone = $( table[0].cloneNode(false) );
6735		var footerClone = $( table[0].cloneNode(false) );
6736		var footer = table.children('tfoot');
6737		var _div = '<div/>';
6738		var size = function ( s ) {
6739			return !s ? null : _fnStringToCss( s );
6740		};
6741	
6742		if ( ! footer.length ) {
6743			footer = null;
6744		}
6745	
6746		/*
6747		 * The HTML structure that we want to generate in this function is:
6748		 *  div - scroller
6749		 *    div - scroll head
6750		 *      div - scroll head inner
6751		 *        table - scroll head table
6752		 *          thead - thead
6753		 *    div - scroll body
6754		 *      table - table (master table)
6755		 *        thead - thead clone for sizing
6756		 *        tbody - tbody
6757		 *    div - scroll foot
6758		 *      div - scroll foot inner
6759		 *        table - scroll foot table
6760		 *          tfoot - tfoot
6761		 */
6762		var scroller = $( _div, { 'class': classes.sScrollWrapper } )
6763			.append(
6764				$(_div, { 'class': classes.sScrollHead } )
6765					.css( {
6766						overflow: 'hidden',
6767						position: 'relative',
6768						border: 0,
6769						width: scrollX ? size(scrollX) : '100%'
6770					} )
6771					.append(
6772						$(_div, { 'class': classes.sScrollHeadInner } )
6773							.css( {
6774								'box-sizing': 'content-box',
6775								width: scroll.sXInner || '100%'
6776							} )
6777							.append(
6778								headerClone
6779									.removeAttr('id')
6780									.css( 'margin-left', 0 )
6781									.append( captionSide === 'top' ? caption : null )
6782									.append(
6783										table.children('thead')
6784									)
6785							)
6786					)
6787			)
6788			.append(
6789				$(_div, { 'class': classes.sScrollBody } )
6790					.css( {
6791						position: 'relative',
6792						overflow: 'auto',
6793						width: size( scrollX )
6794					} )
6795					.append( table )
6796			);
6797	
6798		if ( footer ) {
6799			scroller.append(
6800				$(_div, { 'class': classes.sScrollFoot } )
6801					.css( {
6802						overflow: 'hidden',
6803						border: 0,
6804						width: scrollX ? size(scrollX) : '100%'
6805					} )
6806					.append(
6807						$(_div, { 'class': classes.sScrollFootInner } )
6808							.append(
6809								footerClone
6810									.removeAttr('id')
6811									.css( 'margin-left', 0 )
6812									.append( captionSide === 'bottom' ? caption : null )
6813									.append(
6814										table.children('tfoot')
6815									)
6816							)
6817					)
6818			);
6819		}
6820	
6821		var children = scroller.children();
6822		var scrollHead = children[0];
6823		var scrollBody = children[1];
6824		var scrollFoot = footer ? children[2] : null;
6825	
6826		// When the body is scrolled, then we also want to scroll the headers
6827		if ( scrollX ) {
6828			$(scrollBody).on( 'scroll.DT', function (e) {
6829				var scrollLeft = this.scrollLeft;
6830	
6831				scrollHead.scrollLeft = scrollLeft;
6832	
6833				if ( footer ) {
6834					scrollFoot.scrollLeft = scrollLeft;
6835				}
6836			} );
6837		}
6838	
6839		$(scrollBody).css('max-height', scrollY);
6840		if (! scroll.bCollapse) {
6841			$(scrollBody).css('height', scrollY);
6842		}
6843	
6844		settings.nScrollHead = scrollHead;
6845		settings.nScrollBody = scrollBody;
6846		settings.nScrollFoot = scrollFoot;
6847	
6848		// On redraw - align columns
6849		settings.aoDrawCallback.push( {
6850			"fn": _fnScrollDraw,
6851			"sName": "scrolling"
6852		} );
6853	
6854		return scroller[0];
6855	}
6856	
6857	
6858	
6859	/**
6860	 * Update the header, footer and body tables for resizing - i.e. column
6861	 * alignment.
6862	 *
6863	 * Welcome to the most horrible function DataTables. The process that this
6864	 * function follows is basically:
6865	 *   1. Re-create the table inside the scrolling div
6866	 *   2. Take live measurements from the DOM
6867	 *   3. Apply the measurements to align the columns
6868	 *   4. Clean up
6869	 *
6870	 *  @param {object} settings dataTables settings object
6871	 *  @memberof DataTable#oApi
6872	 */
6873	function _fnScrollDraw ( settings )
6874	{
6875		// Given that this is such a monster function, a lot of variables are use
6876		// to try and keep the minimised size as small as possible
6877		var
6878			scroll         = settings.oScroll,
6879			scrollX        = scroll.sX,
6880			scrollXInner   = scroll.sXInner,
6881			scrollY        = scroll.sY,
6882			barWidth       = scroll.iBarWidth,
6883			divHeader      = $(settings.nScrollHead),
6884			divHeaderStyle = divHeader[0].style,
6885			divHeaderInner = divHeader.children('div'),
6886			divHeaderInnerStyle = divHeaderInner[0].style,
6887			divHeaderTable = divHeaderInner.children('table'),
6888			divBodyEl      = settings.nScrollBody,
6889			divBody        = $(divBodyEl),
6890			divBodyStyle   = divBodyEl.style,
6891			divFooter      = $(settings.nScrollFoot),
6892			divFooterInner = divFooter.children('div'),
6893			divFooterTable = divFooterInner.children('table'),
6894			header         = $(settings.nTHead),
6895			table          = $(settings.nTable),
6896			tableEl        = table[0],
6897			tableStyle     = tableEl.style,
6898			footer         = settings.nTFoot ? $(settings.nTFoot) : null,
6899			browser        = settings.oBrowser,
6900			ie67           = browser.bScrollOversize,
6901			dtHeaderCells  = _pluck( settings.aoColumns, 'nTh' ),
6902			headerTrgEls, footerTrgEls,
6903			headerSrcEls, footerSrcEls,
6904			headerCopy, footerCopy,
6905			headerWidths=[], footerWidths=[],
6906			headerContent=[], footerContent=[],
6907			idx, correction, sanityWidth,
6908			zeroOut = function(nSizer) {
6909				var style = nSizer.style;
6910				style.paddingTop = "0";
6911				style.paddingBottom = "0";
6912				style.borderTopWidth = "0";
6913				style.borderBottomWidth = "0";
6914				style.height = 0;
6915			};
6916	
6917		// If the scrollbar visibility has changed from the last draw, we need to
6918		// adjust the column sizes as the table width will have changed to account
6919		// for the scrollbar
6920		var scrollBarVis = divBodyEl.scrollHeight > divBodyEl.clientHeight;
6921		
6922		if ( settings.scrollBarVis !== scrollBarVis && settings.scrollBarVis !== undefined ) {
6923			settings.scrollBarVis = scrollBarVis;
6924			_fnAdjustColumnSizing( settings );
6925			return; // adjust column sizing will call this function again
6926		}
6927		else {
6928			settings.scrollBarVis = scrollBarVis;
6929		}
6930	
6931		/*
6932		 * 1. Re-create the table inside the scrolling div
6933		 */
6934	
6935		// Remove the old minimised thead and tfoot elements in the inner table
6936		table.children('thead, tfoot').remove();
6937	
6938		if ( footer ) {
6939			footerCopy = footer.clone().prependTo( table );
6940			footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized
6941			footerSrcEls = footerCopy.find('tr');
6942		}
6943	
6944		// Clone the current header and footer elements and then place it into the inner table
6945		headerCopy = header.clone().prependTo( table );
6946		headerTrgEls = header.find('tr'); // original header is in its own table
6947		headerSrcEls = headerCopy.find('tr');
6948		headerCopy.find('th, td').removeAttr('tabindex');
6949	
6950	
6951		/*
6952		 * 2. Take live measurements from the DOM - do not alter the DOM itself!
6953		 */
6954	
6955		// Remove old sizing and apply the calculated column widths
6956		// Get the unique column headers in the newly created (cloned) header. We want to apply the
6957		// calculated sizes to this header
6958		if ( ! scrollX )
6959		{
6960			divBodyStyle.width = '100%';
6961			divHeader[0].style.width = '100%';
6962		}
6963	
6964		$.each( _fnGetUniqueThs( settings, headerCopy ), function ( i, el ) {
6965			idx = _fnVisibleToColumnIndex( settings, i );
6966			el.style.width = settings.aoColumns[idx].sWidth;
6967		} );
6968	
6969		if ( footer ) {
6970			_fnApplyToChildren( function(n) {
6971				n.style.width = "";
6972			}, footerSrcEls );
6973		}
6974	
6975		// Size the table as a whole
6976		sanityWidth = table.outerWidth();
6977		if ( scrollX === "" ) {
6978			// No x scrolling
6979			tableStyle.width = "100%";
6980	
6981			// IE7 will make the width of the table when 100% include the scrollbar
6982			// - which is shouldn't. When there is a scrollbar we need to take this
6983			// into account.
6984			if ( ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight ||
6985				divBody.css('overflow-y') == "scroll")
6986			) {
6987				tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth);
6988			}
6989	
6990			// Recalculate the sanity width
6991			sanityWidth = table.outerWidth();
6992		}
6993		else if ( scrollXInner !== "" ) {
6994			// legacy x scroll inner has been given - use it
6995			tableStyle.width = _fnStringToCss(scrollXInner);
6996	
6997			// Recalculate the sanity width
6998			sanityWidth = table.outerWidth();
6999		}
7000	
7001		// Hidden header should have zero height, so remove padding and borders. Then
7002		// set the width based on the real headers
7003	
7004		// Apply all styles in one pass
7005		_fnApplyToChildren( zeroOut, headerSrcEls );
7006	
7007		// Read all widths in next pass
7008		_fnApplyToChildren( function(nSizer) {
7009			headerContent.push( nSizer.innerHTML );
7010			headerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
7011		}, headerSrcEls );
7012	
7013		// Apply all widths in final pass
7014		_fnApplyToChildren( function(nToSize, i) {
7015			// Only apply widths to the DataTables detected header cells - this
7016			// prevents complex headers from having contradictory sizes applied
7017			if ( $.inArray( nToSize, dtHeaderCells ) !== -1 ) {
7018				nToSize.style.width = headerWidths[i];
7019			}
7020		}, headerTrgEls );
7021	
7022		$(headerSrcEls).height(0);
7023	
7024		/* Same again with the footer if we have one */
7025		if ( footer )
7026		{
7027			_fnApplyToChildren( zeroOut, footerSrcEls );
7028	
7029			_fnApplyToChildren( function(nSizer) {
7030				footerContent.push( nSizer.innerHTML );
7031				footerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
7032			}, footerSrcEls );
7033	
7034			_fnApplyToChildren( function(nToSize, i) {
7035				nToSize.style.width = footerWidths[i];
7036			}, footerTrgEls );
7037	
7038			$(footerSrcEls).height(0);
7039		}
7040	
7041	
7042		/*
7043		 * 3. Apply the measurements
7044		 */
7045	
7046		// "Hide" the header and footer that we used for the sizing. We need to keep
7047		// the content of the cell so that the width applied to the header and body
7048		// both match, but we want to hide it completely. We want to also fix their
7049		// width to what they currently are
7050		_fnApplyToChildren( function(nSizer, i) {
7051			nSizer.innerHTML = '<div class="dataTables_sizing">'+headerContent[i]+'</div>';
7052			nSizer.childNodes[0].style.height = "0";
7053			nSizer.childNodes[0].style.overflow = "hidden";
7054			nSizer.style.width = headerWidths[i];
7055		}, headerSrcEls );
7056	
7057		if ( footer )
7058		{
7059			_fnApplyToChildren( function(nSizer, i) {
7060				nSizer.innerHTML = '<div class="dataTables_sizing">'+footerContent[i]+'</div>';
7061				nSizer.childNodes[0].style.height = "0";
7062				nSizer.childNodes[0].style.overflow = "hidden";
7063				nSizer.style.width = footerWidths[i];
7064			}, footerSrcEls );
7065		}
7066	
7067		// Sanity check that the table is of a sensible width. If not then we are going to get
7068		// misalignment - try to prevent this by not allowing the table to shrink below its min width
7069		if ( table.outerWidth() < sanityWidth )
7070		{
7071			// The min width depends upon if we have a vertical scrollbar visible or not */
7072			correction = ((divBodyEl.scrollHeight > divBodyEl.offsetHeight ||
7073				divBody.css('overflow-y') == "scroll")) ?
7074					sanityWidth+barWidth :
7075					sanityWidth;
7076	
7077			// IE6/7 are a law unto themselves...
7078			if ( ie67 && (divBodyEl.scrollHeight >
7079				divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll")
7080			) {
7081				tableStyle.width = _fnStringToCss( correction-barWidth );
7082			}
7083	
7084			// And give the user a warning that we've stopped the table getting too small
7085			if ( scrollX === "" || scrollXInner !== "" ) {
7086				_fnLog( settings, 1, 'Possible column misalignment', 6 );
7087			}
7088		}
7089		else
7090		{
7091			correction = '100%';
7092		}
7093	
7094		// Apply to the container elements
7095		divBodyStyle.width = _fnStringToCss( correction );
7096		divHeaderStyle.width = _fnStringToCss( correction );
7097	
7098		if ( footer ) {
7099			settings.nScrollFoot.style.width = _fnStringToCss( correction );
7100		}
7101	
7102	
7103		/*
7104		 * 4. Clean up
7105		 */
7106		if ( ! scrollY ) {
7107			/* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
7108			 * the scrollbar height from the visible display, rather than adding it on. We need to
7109			 * set the height in order to sort this. Don't want to do it in any other browsers.
7110			 */
7111			if ( ie67 ) {
7112				divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+barWidth );
7113			}
7114		}
7115	
7116		/* Finally set the width's of the header and footer tables */
7117		var iOuterWidth = table.outerWidth();
7118		divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth );
7119		divHeaderInnerStyle.width = _fnStringToCss( iOuterWidth );
7120	
7121		// Figure out if there are scrollbar present - if so then we need a the header and footer to
7122		// provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
7123		var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll";
7124		var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' );
7125		divHeaderInnerStyle[ padding ] = bScrolling ? barWidth+"px" : "0px";
7126	
7127		if ( footer ) {
7128			divFooterTable[0].style.width = _fnStringToCss( iOuterWidth );
7129			divFooterInner[0].style.width = _fnStringToCss( iOuterWidth );
7130			divFooterInner[0].style[padding] = bScrolling ? barWidth+"px" : "0px";
7131		}
7132	
7133		// Correct DOM ordering for colgroup - comes before the thead
7134		table.children('colgroup').insertBefore( table.children('thead') );
7135	
7136		/* Adjust the position of the header in case we loose the y-scrollbar */
7137		divBody.trigger('scroll');
7138	
7139		// If sorting or filtering has occurred, jump the scrolling back to the top
7140		// only if we aren't holding the position
7141		if ( (settings.bSorted || settings.bFiltered) && ! settings._drawHold ) {
7142			divBodyEl.scrollTop = 0;
7143		}
7144	}
7145	
7146	
7147	
7148	/**
7149	 * Apply a given function to the display child nodes of an element array (typically
7150	 * TD children of TR rows
7151	 *  @param {function} fn Method to apply to the objects
7152	 *  @param array {nodes} an1 List of elements to look through for display children
7153	 *  @param array {nodes} an2 Another list (identical structure to the first) - optional
7154	 *  @memberof DataTable#oApi
7155	 */
7156	function _fnApplyToChildren( fn, an1, an2 )
7157	{
7158		var index=0, i=0, iLen=an1.length;
7159		var nNode1, nNode2;
7160	
7161		while ( i < iLen ) {
7162			nNode1 = an1[i].firstChild;
7163			nNode2 = an2 ? an2[i].firstChild : null;
7164	
7165			while ( nNode1 ) {
7166				if ( nNode1.nodeType === 1 ) {
7167					if ( an2 ) {
7168						fn( nNode1, nNode2, index );
7169					}
7170					else {
7171						fn( nNode1, index );
7172					}
7173	
7174					index++;
7175				}
7176	
7177				nNode1 = nNode1.nextSibling;
7178				nNode2 = an2 ? nNode2.nextSibling : null;
7179			}
7180	
7181			i++;
7182		}
7183	}
7184	
7185	
7186	
7187	var __re_html_remove = /<.*?>/g;
7188	
7189	
7190	/**
7191	 * Calculate the width of columns for the table
7192	 *  @param {object} oSettings dataTables settings object
7193	 *  @memberof DataTable#oApi
7194	 */
7195	function _fnCalculateColumnWidths ( oSettings )
7196	{
7197		var
7198			table = oSettings.nTable,
7199			columns = oSettings.aoColumns,
7200			scroll = oSettings.oScroll,
7201			scrollY = scroll.sY,
7202			scrollX = scroll.sX,
7203			scrollXInner = scroll.sXInner,
7204			columnCount = columns.length,
7205			visibleColumns = _fnGetColumns( oSettings, 'bVisible' ),
7206			headerCells = $('th', oSettings.nTHead),
7207			tableWidthAttr = table.getAttribute('width'), // from DOM element
7208			tableContainer = table.parentNode,
7209			userInputs = false,
7210			i, column, columnIdx, width, outerWidth,
7211			browser = oSettings.oBrowser,
7212			ie67 = browser.bScrollOversize;
7213	
7214		var styleWidth = table.style.width;
7215		if ( styleWidth && styleWidth.indexOf('%') !== -1 ) {
7216			tableWidthAttr = styleWidth;
7217		}
7218	
7219		/* Convert any user input sizes into pixel sizes */
7220		for ( i=0 ; i<visibleColumns.length ; i++ ) {
7221			column = columns[ visibleColumns[i] ];
7222	
7223			if ( column.sWidth !== null ) {
7224				column.sWidth = _fnConvertToWidth( column.sWidthOrig, tableContainer );
7225	
7226				userInputs = true;
7227			}
7228		}
7229	
7230		/* If the number of columns in the DOM equals the number that we have to
7231		 * process in DataTables, then we can use the offsets that are created by
7232		 * the web- browser. No custom sizes can be set in order for this to happen,
7233		 * nor scrolling used
7234		 */
7235		if ( ie67 || ! userInputs && ! scrollX && ! scrollY &&
7236		     columnCount == _fnVisbleColumns( oSettings ) &&
7237		     columnCount == headerCells.length
7238		) {
7239			for ( i=0 ; i<columnCount ; i++ ) {
7240				var colIdx = _fnVisibleToColumnIndex( oSettings, i );
7241	
7242				if ( colIdx !== null ) {
7243					columns[ colIdx ].sWidth = _fnStringToCss( headerCells.eq(i).width() );
7244				}
7245			}
7246		}
7247		else
7248		{
7249			// Otherwise construct a single row, worst case, table with the widest
7250			// node in the data, assign any user defined widths, then insert it into
7251			// the DOM and allow the browser to do all the hard work of calculating
7252			// table widths
7253			var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table
7254				.css( 'visibility', 'hidden' )
7255				.removeAttr( 'id' );
7256	
7257			// Clean up the table body
7258			tmpTable.find('tbody tr').remove();
7259			var tr = $('<tr/>').appendTo( tmpTable.find('tbody') );
7260	
7261			// Clone the table header and footer - we can't use the header / footer
7262			// from the cloned table, since if scrolling is active, the table's
7263			// real header and footer are contained in different table tags
7264			tmpTable.find('thead, tfoot').remove();
7265			tmpTable
7266				.append( $(oSettings.nTHead).clone() )
7267				.append( $(oSettings.nTFoot).clone() );
7268	
7269			// Remove any assigned widths from the footer (from scrolling)
7270			tmpTable.find('tfoot th, tfoot td').css('width', '');
7271	
7272			// Apply custom sizing to the cloned header
7273			headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] );
7274	
7275			for ( i=0 ; i<visibleColumns.length ; i++ ) {
7276				column = columns[ visibleColumns[i] ];
7277	
7278				headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ?
7279					_fnStringToCss( column.sWidthOrig ) :
7280					'';
7281	
7282				// For scrollX we need to force the column width otherwise the
7283				// browser will collapse it. If this width is smaller than the
7284				// width the column requires, then it will have no effect
7285				if ( column.sWidthOrig && scrollX ) {
7286					$( headerCells[i] ).append( $('<div/>').css( {
7287						width: column.sWidthOrig,
7288						margin: 0,
7289						padding: 0,
7290						border: 0,
7291						height: 1
7292					} ) );
7293				}
7294			}
7295	
7296			// Find the widest cell for each column and put it into the table
7297			if ( oSettings.aoData.length ) {
7298				for ( i=0 ; i<visibleColumns.length ; i++ ) {
7299					columnIdx = visibleColumns[i];
7300					column = columns[ columnIdx ];
7301	
7302					$( _fnGetWidestNode( oSettings, columnIdx ) )
7303						.clone( false )
7304						.append( column.sContentPadding )
7305						.appendTo( tr );
7306				}
7307			}
7308	
7309			// Tidy the temporary table - remove name attributes so there aren't
7310			// duplicated in the dom (radio elements for example)
7311			$('[name]', tmpTable).removeAttr('name');
7312	
7313			// Table has been built, attach to the document so we can work with it.
7314			// A holding element is used, positioned at the top of the container
7315			// with minimal height, so it has no effect on if the container scrolls
7316			// or not. Otherwise it might trigger scrolling when it actually isn't
7317			// needed
7318			var holder = $('<div/>').css( scrollX || scrollY ?
7319					{
7320						position: 'absolute',
7321						top: 0,
7322						left: 0,
7323						height: 1,
7324						right: 0,
7325						overflow: 'hidden'
7326					} :
7327					{}
7328				)
7329				.append( tmpTable )
7330				.appendTo( tableContainer );
7331	
7332			// When scrolling (X or Y) we want to set the width of the table as 
7333			// appropriate. However, when not scrolling leave the table width as it
7334			// is. This results in slightly different, but I think correct behaviour
7335			if ( scrollX && scrollXInner ) {
7336				tmpTable.width( scrollXInner );
7337			}
7338			else if ( scrollX ) {
7339				tmpTable.css( 'width', 'auto' );
7340				tmpTable.removeAttr('width');
7341	
7342				// If there is no width attribute or style, then allow the table to
7343				// collapse
7344				if ( tmpTable.width() < tableContainer.clientWidth && tableWidthAttr ) {
7345					tmpTable.width( tableContainer.clientWidth );
7346				}
7347			}
7348			else if ( scrollY ) {
7349				tmpTable.width( tableContainer.clientWidth );
7350			}
7351			else if ( tableWidthAttr ) {
7352				tmpTable.width( tableWidthAttr );
7353			}
7354	
7355			// Get the width of each column in the constructed table - we need to
7356			// know the inner width (so it can be assigned to the other table's
7357			// cells) and the outer width so we can calculate the full width of the
7358			// table. This is safe since DataTables requires a unique cell for each
7359			// column, but if ever a header can span multiple columns, this will
7360			// need to be modified.
7361			var total = 0;
7362			for ( i=0 ; i<visibleColumns.length ; i++ ) {
7363				var cell = $(headerCells[i]);
7364				var border = cell.outerWidth() - cell.width();
7365	
7366				// Use getBounding... where possible (not IE8-) because it can give
7367				// sub-pixel accuracy, which we then want to round up!
7368				var bounding = browser.bBounding ?
7369					Math.ceil( headerCells[i].getBoundingClientRect().width ) :
7370					cell.outerWidth();
7371	
7372				// Total is tracked to remove any sub-pixel errors as the outerWidth
7373				// of the table might not equal the total given here (IE!).
7374				total += bounding;
7375	
7376				// Width for each column to use
7377				columns[ visibleColumns[i] ].sWidth = _fnStringToCss( bounding - border );
7378			}
7379	
7380			table.style.width = _fnStringToCss( total );
7381	
7382			// Finished with the table - ditch it
7383			holder.remove();
7384		}
7385	
7386		// If there is a width attr, we want to attach an event listener which
7387		// allows the table sizing to automatically adjust when the window is
7388		// resized. Use the width attr rather than CSS, since we can't know if the
7389		// CSS is a relative value or absolute - DOM read is always px.
7390		if ( tableWidthAttr ) {
7391			table.style.width = _fnStringToCss( tableWidthAttr );
7392		}
7393	
7394		if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) {
7395			var bindResize = function () {
7396				$(window).on('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {
7397					_fnAdjustColumnSizing( oSettings );
7398				} ) );
7399			};
7400	
7401			// IE6/7 will crash if we bind a resize event handler on page load.
7402			// To be removed in 1.11 which drops IE6/7 support
7403			if ( ie67 ) {
7404				setTimeout( bindResize, 1000 );
7405			}
7406			else {
7407				bindResize();
7408			}
7409	
7410			oSettings._reszEvt = true;
7411		}
7412	}
7413	
7414	
7415	/**
7416	 * Throttle the calls to a function. Arguments and context are maintained for
7417	 * the throttled function
7418	 *  @param {function} fn Function to be called
7419	 *  @param {int} [freq=200] call frequency in mS
7420	 *  @returns {function} wrapped function
7421	 *  @memberof DataTable#oApi
7422	 */
7423	var _fnThrottle = DataTable.util.throttle;
7424	
7425	
7426	/**
7427	 * Convert a CSS unit width to pixels (e.g. 2em)
7428	 *  @param {string} width width to be converted
7429	 *  @param {node} parent parent to get the with for (required for relative widths) - optional
7430	 *  @returns {int} width in pixels
7431	 *  @memberof DataTable#oApi
7432	 */
7433	function _fnConvertToWidth ( width, parent )
7434	{
7435		if ( ! width ) {
7436			return 0;
7437		}
7438	
7439		var n = $('<div/>')
7440			.css( 'width', _fnStringToCss( width ) )
7441			.appendTo( parent || document.body );
7442	
7443		var val = n[0].offsetWidth;
7444		n.remove();
7445	
7446		return val;
7447	}
7448	
7449	
7450	/**
7451	 * Get the widest node
7452	 *  @param {object} settings dataTables settings object
7453	 *  @param {int} colIdx column of interest
7454	 *  @returns {node} widest table node
7455	 *  @memberof DataTable#oApi
7456	 */
7457	function _fnGetWidestNode( settings, colIdx )
7458	{
7459		var idx = _fnGetMaxLenString( settings, colIdx );
7460		if ( idx < 0 ) {
7461			return null;
7462		}
7463	
7464		var data = settings.aoData[ idx ];
7465		return ! data.nTr ? // Might not have been created when deferred rendering
7466			$('<td/>').html( _fnGetCellData( settings, idx, colIdx, 'display' ) )[0] :
7467			data.anCells[ colIdx ];
7468	}
7469	
7470	
7471	/**
7472	 * Get the maximum strlen for each data column
7473	 *  @param {object} settings dataTables settings object
7474	 *  @param {int} colIdx column of interest
7475	 *  @returns {string} max string length for each column
7476	 *  @memberof DataTable#oApi
7477	 */
7478	function _fnGetMaxLenString( settings, colIdx )
7479	{
7480		var s, max=-1, maxIdx = -1;
7481	
7482		for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
7483			s = _fnGetCellData( settings, i, colIdx, 'display' )+'';
7484			s = s.replace( __re_html_remove, '' );
7485			s = s.replace( /&nbsp;/g, ' ' );
7486	
7487			if ( s.length > max ) {
7488				max = s.length;
7489				maxIdx = i;
7490			}
7491		}
7492	
7493		return maxIdx;
7494	}
7495	
7496	
7497	/**
7498	 * Append a CSS unit (only if required) to a string
7499	 *  @param {string} value to css-ify
7500	 *  @returns {string} value with css unit
7501	 *  @memberof DataTable#oApi
7502	 */
7503	function _fnStringToCss( s )
7504	{
7505		if ( s === null ) {
7506			return '0px';
7507		}
7508	
7509		if ( typeof s == 'number' ) {
7510			return s < 0 ?
7511				'0px' :
7512				s+'px';
7513		}
7514	
7515		// Check it has a unit character already
7516		return s.match(/\d$/) ?
7517			s+'px' :
7518			s;
7519	}
7520	
7521	
7522	
7523	function _fnSortFlatten ( settings )
7524	{
7525		var
7526			i, iLen, k, kLen,
7527			aSort = [],
7528			aiOrig = [],
7529			aoColumns = settings.aoColumns,
7530			aDataSort, iCol, sType, srcCol,
7531			fixed = settings.aaSortingFixed,
7532			fixedObj = $.isPlainObject( fixed ),
7533			nestedSort = [],
7534			add = function ( a ) {
7535				if ( a.length && ! Array.isArray( a[0] ) ) {
7536					// 1D array
7537					nestedSort.push( a );
7538				}
7539				else {
7540					// 2D array
7541					$.merge( nestedSort, a );
7542				}
7543			};
7544	
7545		// Build the sort array, with pre-fix and post-fix options if they have been
7546		// specified
7547		if ( Array.isArray( fixed ) ) {
7548			add( fixed );
7549		}
7550	
7551		if ( fixedObj && fixed.pre ) {
7552			add( fixed.pre );
7553		}
7554	
7555		add( settings.aaSorting );
7556	
7557		if (fixedObj && fixed.post ) {
7558			add( fixed.post );
7559		}
7560	
7561		for ( i=0 ; i<nestedSort.length ; i++ )
7562		{
7563			srcCol = nestedSort[i][0];
7564			aDataSort = aoColumns[ srcCol ].aDataSort;
7565	
7566			for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ )
7567			{
7568				iCol = aDataSort[k];
7569				sType = aoColumns[ iCol ].sType || 'string';
7570	
7571				if ( nestedSort[i]._idx === undefined ) {
7572					nestedSort[i]._idx = $.inArray( nestedSort[i][1], aoColumns[iCol].asSorting );
7573				}
7574	
7575				aSort.push( {
7576					src:       srcCol,
7577					col:       iCol,
7578					dir:       nestedSort[i][1],
7579					index:     nestedSort[i]._idx,
7580					type:      sType,
7581					formatter: DataTable.ext.type.order[ sType+"-pre" ]
7582				} );
7583			}
7584		}
7585	
7586		return aSort;
7587	}
7588	
7589	/**
7590	 * Change the order of the table
7591	 *  @param {object} oSettings dataTables settings object
7592	 *  @memberof DataTable#oApi
7593	 *  @todo This really needs split up!
7594	 */
7595	function _fnSort ( oSettings )
7596	{
7597		var
7598			i, ien, iLen, j, jLen, k, kLen,
7599			sDataType, nTh,
7600			aiOrig = [],
7601			oExtSort = DataTable.ext.type.order,
7602			aoData = oSettings.aoData,
7603			aoColumns = oSettings.aoColumns,
7604			aDataSort, data, iCol, sType, oSort,
7605			formatters = 0,
7606			sortCol,
7607			displayMaster = oSettings.aiDisplayMaster,
7608			aSort;
7609	
7610		// Resolve any column types that are unknown due to addition or invalidation
7611		// @todo Can this be moved into a 'data-ready' handler which is called when
7612		//   data is going to be used in the table?
7613		_fnColumnTypes( oSettings );
7614	
7615		aSort = _fnSortFlatten( oSettings );
7616	
7617		for ( i=0, ien=aSort.length ; i<ien ; i++ ) {
7618			sortCol = aSort[i];
7619	
7620			// Track if we can use the fast sort algorithm
7621			if ( sortCol.formatter ) {
7622				formatters++;
7623			}
7624	
7625			// Load the data needed for the sort, for each cell
7626			_fnSortData( oSettings, sortCol.col );
7627		}
7628	
7629		/* No sorting required if server-side or no sorting array */
7630		if ( _fnDataSource( oSettings ) != 'ssp' && aSort.length !== 0 )
7631		{
7632			// Create a value - key array of the current row positions such that we can use their
7633			// current position during the sort, if values match, in order to perform stable sorting
7634			for ( i=0, iLen=displayMaster.length ; i<iLen ; i++ ) {
7635				aiOrig[ displayMaster[i] ] = i;
7636			}
7637	
7638			/* Do the sort - here we want multi-column sorting based on a given data source (column)
7639			 * and sorting function (from oSort) in a certain direction. It's reasonably complex to
7640			 * follow on it's own, but this is what we want (example two column sorting):
7641			 *  fnLocalSorting = function(a,b){
7642			 *    var iTest;
7643			 *    iTest = oSort['string-asc']('data11', 'data12');
7644			 *      if (iTest !== 0)
7645			 *        return iTest;
7646			 *    iTest = oSort['numeric-desc']('data21', 'data22');
7647			 *    if (iTest !== 0)
7648			 *      return iTest;
7649			 *    return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
7650			 *  }
7651			 * Basically we have a test for each sorting column, if the data in that column is equal,
7652			 * test the next column. If all columns match, then we use a numeric sort on the row
7653			 * positions in the original data array to provide a stable sort.
7654			 *
7655			 * Note - I know it seems excessive to have two sorting methods, but the first is around
7656			 * 15% faster, so the second is only maintained for backwards compatibility with sorting
7657			 * methods which do not have a pre-sort formatting function.
7658			 */
7659			if ( formatters === aSort.length ) {
7660				// All sort types have formatting functions
7661				displayMaster.sort( function ( a, b ) {
7662					var
7663						x, y, k, test, sort,
7664						len=aSort.length,
7665						dataA = aoData[a]._aSortData,
7666						dataB = aoData[b]._aSortData;
7667	
7668					for ( k=0 ; k<len ; k++ ) {
7669						sort = aSort[k];
7670	
7671						x = dataA[ sort.col ];
7672						y = dataB[ sort.col ];
7673	
7674						test = x<y ? -1 : x>y ? 1 : 0;
7675						if ( test !== 0 ) {
7676							return sort.dir === 'asc' ? test : -test;
7677						}
7678					}
7679	
7680					x = aiOrig[a];
7681					y = aiOrig[b];
7682					return x<y ? -1 : x>y ? 1 : 0;
7683				} );
7684			}
7685			else {
7686				// Depreciated - remove in 1.11 (providing a plug-in option)
7687				// Not all sort types have formatting methods, so we have to call their sorting
7688				// methods.
7689				displayMaster.sort( function ( a, b ) {
7690					var
7691						x, y, k, l, test, sort, fn,
7692						len=aSort.length,
7693						dataA = aoData[a]._aSortData,
7694						dataB = aoData[b]._aSortData;
7695	
7696					for ( k=0 ; k<len ; k++ ) {
7697						sort = aSort[k];
7698	
7699						x = dataA[ sort.col ];
7700						y = dataB[ sort.col ];
7701	
7702						fn = oExtSort[ sort.type+"-"+sort.dir ] || oExtSort[ "string-"+sort.dir ];
7703						test = fn( x, y );
7704						if ( test !== 0 ) {
7705							return test;
7706						}
7707					}
7708	
7709					x = aiOrig[a];
7710					y = aiOrig[b];
7711					return x<y ? -1 : x>y ? 1 : 0;
7712				} );
7713			}
7714		}
7715	
7716		/* Tell the draw function that we have sorted the data */
7717		oSettings.bSorted = true;
7718	}
7719	
7720	
7721	function _fnSortAria ( settings )
7722	{
7723		var label;
7724		var nextSort;
7725		var columns = settings.aoColumns;
7726		var aSort = _fnSortFlatten( settings );
7727		var oAria = settings.oLanguage.oAria;
7728	
7729		// ARIA attributes - need to loop all columns, to update all (removing old
7730		// attributes as needed)
7731		for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
7732		{
7733			var col = columns[i];
7734			var asSorting = col.asSorting;
7735			var sTitle = col.sTitle.replace( /<.*?>/g, "" );
7736			var th = col.nTh;
7737	
7738			// IE7 is throwing an error when setting these properties with jQuery's
7739			// attr() and removeAttr() methods...
7740			th.removeAttribute('aria-sort');
7741	
7742			/* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
7743			if ( col.bSortable ) {
7744				if ( aSort.length > 0 && aSort[0].col == i ) {
7745					th.setAttribute('aria-sort', aSort[0].dir=="asc" ? "ascending" : "descending" );
7746					nextSort = asSorting[ aSort[0].index+1 ] || asSorting[0];
7747				}
7748				else {
7749					nextSort = asSorting[0];
7750				}
7751	
7752				label = sTitle + ( nextSort === "asc" ?
7753					oAria.sSortAscending :
7754					oAria.sSortDescending
7755				);
7756			}
7757			else {
7758				label = sTitle;
7759			}
7760	
7761			th.setAttribute('aria-label', label);
7762		}
7763	}
7764	
7765	
7766	/**
7767	 * Function to run on user sort request
7768	 *  @param {object} settings dataTables settings object
7769	 *  @param {node} attachTo node to attach the handler to
7770	 *  @param {int} colIdx column sorting index
7771	 *  @param {boolean} [append=false] Append the requested sort to the existing
7772	 *    sort if true (i.e. multi-column sort)
7773	 *  @param {function} [callback] callback function
7774	 *  @memberof DataTable#oApi
7775	 */
7776	function _fnSortListener ( settings, colIdx, append, callback )
7777	{
7778		var col = settings.aoColumns[ colIdx ];
7779		var sorting = settings.aaSorting;
7780		var asSorting = col.asSorting;
7781		var nextSortIdx;
7782		var next = function ( a, overflow ) {
7783			var idx = a._idx;
7784			if ( idx === undefined ) {
7785				idx = $.inArray( a[1], asSorting );
7786			}
7787	
7788			return idx+1 < asSorting.length ?
7789				idx+1 :
7790				overflow ?
7791					null :
7792					0;
7793		};
7794	
7795		// Convert to 2D array if needed
7796		if ( typeof sorting[0] === 'number' ) {
7797			sorting = settings.aaSorting = [ sorting ];
7798		}
7799	
7800		// If appending the sort then we are multi-column sorting
7801		if ( append && settings.oFeatures.bSortMulti ) {
7802			// Are we already doing some kind of sort on this column?
7803			var sortIdx = $.inArray( colIdx, _pluck(sorting, '0') );
7804	
7805			if ( sortIdx !== -1 ) {
7806				// Yes, modify the sort
7807				nextSortIdx = next( sorting[sortIdx], true );
7808	
7809				if ( nextSortIdx === null && sorting.length === 1 ) {
7810					nextSortIdx = 0; // can't remove sorting completely
7811				}
7812	
7813				if ( nextSortIdx === null ) {
7814					sorting.splice( sortIdx, 1 );
7815				}
7816				else {
7817					sorting[sortIdx][1] = asSorting[ nextSortIdx ];
7818					sorting[sortIdx]._idx = nextSortIdx;
7819				}
7820			}
7821			else {
7822				// No sort on this column yet
7823				sorting.push( [ colIdx, asSorting[0], 0 ] );
7824				sorting[sorting.length-1]._idx = 0;
7825			}
7826		}
7827		else if ( sorting.length && sorting[0][0] == colIdx ) {
7828			// Single column - already sorting on this column, modify the sort
7829			nextSortIdx = next( sorting[0] );
7830	
7831			sorting.length = 1;
7832			sorting[0][1] = asSorting[ nextSortIdx ];
7833			sorting[0]._idx = nextSortIdx;
7834		}
7835		else {
7836			// Single column - sort only on this column
7837			sorting.length = 0;
7838			sorting.push( [ colIdx, asSorting[0] ] );
7839			sorting[0]._idx = 0;
7840		}
7841	
7842		// Run the sort by calling a full redraw
7843		_fnReDraw( settings );
7844	
7845		// callback used for async user interaction
7846		if ( typeof callback == 'function' ) {
7847			callback( settings );
7848		}
7849	}
7850	
7851	
7852	/**
7853	 * Attach a sort handler (click) to a node
7854	 *  @param {object} settings dataTables settings object
7855	 *  @param {node} attachTo node to attach the handler to
7856	 *  @param {int} colIdx column sorting index
7857	 *  @param {function} [callback] callback function
7858	 *  @memberof DataTable#oApi
7859	 */
7860	function _fnSortAttachListener ( settings, attachTo, colIdx, callback )
7861	{
7862		var col = settings.aoColumns[ colIdx ];
7863	
7864		_fnBindAction( attachTo, {}, function (e) {
7865			/* If the column is not sortable - don't to anything */
7866			if ( col.bSortable === false ) {
7867				return;
7868			}
7869	
7870			// If processing is enabled use a timeout to allow the processing
7871			// display to be shown - otherwise to it synchronously
7872			if ( settings.oFeatures.bProcessing ) {
7873				_fnProcessingDisplay( settings, true );
7874	
7875				setTimeout( function() {
7876					_fnSortListener( settings, colIdx, e.shiftKey, callback );
7877	
7878					// In server-side processing, the draw callback will remove the
7879					// processing display
7880					if ( _fnDataSource( settings ) !== 'ssp' ) {
7881						_fnProcessingDisplay( settings, false );
7882					}
7883				}, 0 );
7884			}
7885			else {
7886				_fnSortListener( settings, colIdx, e.shiftKey, callback );
7887			}
7888		} );
7889	}
7890	
7891	
7892	/**
7893	 * Set the sorting classes on table's body, Note: it is safe to call this function
7894	 * when bSort and bSortClasses are false
7895	 *  @param {object} oSettings dataTables settings object
7896	 *  @memberof DataTable#oApi
7897	 */
7898	function _fnSortingClasses( settings )
7899	{
7900		var oldSort = settings.aLastSort;
7901		var sortClass = settings.oClasses.sSortColumn;
7902		var sort = _fnSortFlatten( settings );
7903		var features = settings.oFeatures;
7904		var i, ien, colIdx;
7905	
7906		if ( features.bSort && features.bSortClasses ) {
7907			// Remove old sorting classes
7908			for ( i=0, ien=oldSort.length ; i<ien ; i++ ) {
7909				colIdx = oldSort[i].src;
7910	
7911				// Remove column sorting
7912				$( _pluck( settings.aoData, 'anCells', colIdx ) )
7913					.removeClass( sortClass + (i<2 ? i+1 : 3) );
7914			}
7915	
7916			// Add new column sorting
7917			for ( i=0, ien=sort.length ; i<ien ; i++ ) {
7918				colIdx = sort[i].src;
7919	
7920				$( _pluck( settings.aoData, 'anCells', colIdx ) )
7921					.addClass( sortClass + (i<2 ? i+1 : 3) );
7922			}
7923		}
7924	
7925		settings.aLastSort = sort;
7926	}
7927	
7928	
7929	// Get the data to sort a column, be it from cache, fresh (populating the
7930	// cache), or from a sort formatter
7931	function _fnSortData( settings, idx )
7932	{
7933		// Custom sorting function - provided by the sort data type
7934		var column = settings.aoColumns[ idx ];
7935		var customSort = DataTable.ext.order[ column.sSortDataType ];
7936		var customData;
7937	
7938		if ( customSort ) {
7939			customData = customSort.call( settings.oInstance, settings, idx,
7940				_fnColumnIndexToVisible( settings, idx )
7941			);
7942		}
7943	
7944		// Use / populate cache
7945		var row, cellData;
7946		var formatter = DataTable.ext.type.order[ column.sType+"-pre" ];
7947	
7948		for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
7949			row = settings.aoData[i];
7950	
7951			if ( ! row._aSortData ) {
7952				row._aSortData = [];
7953			}
7954	
7955			if ( ! row._aSortData[idx] || customSort ) {
7956				cellData = customSort ?
7957					customData[i] : // If there was a custom sort function, use data from there
7958					_fnGetCellData( settings, i, idx, 'sort' );
7959	
7960				row._aSortData[ idx ] = formatter ?
7961					formatter( cellData ) :
7962					cellData;
7963			}
7964		}
7965	}
7966	
7967	
7968	
7969	/**
7970	 * Save the state of a table
7971	 *  @param {object} oSettings dataTables settings object
7972	 *  @memberof DataTable#oApi
7973	 */
7974	function _fnSaveState ( settings )
7975	{
7976		if ( !settings.oFeatures.bStateSave || settings.bDestroying )
7977		{
7978			return;
7979		}
7980	
7981		/* Store the interesting variables */
7982		var state = {
7983			time:    +new Date(),
7984			start:   settings._iDisplayStart,
7985			length:  settings._iDisplayLength,
7986			order:   $.extend( true, [], settings.aaSorting ),
7987			search:  _fnSearchToCamel( settings.oPreviousSearch ),
7988			columns: $.map( settings.aoColumns, function ( col, i ) {
7989				return {
7990					visible: col.bVisible,
7991					search: _fnSearchToCamel( settings.aoPreSearchCols[i] )
7992				};
7993			} )
7994		};
7995	
7996		_fnCallbackFire( settings, "aoStateSaveParams", 'stateSaveParams', [settings, state] );
7997	
7998		settings.oSavedState = state;
7999		settings.fnStateSaveCallback.call( settings.oInstance, settings, state );
8000	}
8001	
8002	
8003	/**
8004	 * Attempt to load a saved table state
8005	 *  @param {object} oSettings dataTables settings object
8006	 *  @param {object} oInit DataTables init object so we can override settings
8007	 *  @param {function} callback Callback to execute when the state has been loaded
8008	 *  @memberof DataTable#oApi
8009	 */
8010	function _fnLoadState ( settings, oInit, callback )
8011	{
8012		var i, ien;
8013		var columns = settings.aoColumns;
8014		var loaded = function ( s ) {
8015			if ( ! s || ! s.time ) {
8016				callback();
8017				return;
8018			}
8019	
8020			// Allow custom and plug-in manipulation functions to alter the saved data set and
8021			// cancelling of loading by returning false
8022			var abStateLoad = _fnCallbackFire( settings, 'aoStateLoadParams', 'stateLoadParams', [settings, s] );
8023			if ( $.inArray( false, abStateLoad ) !== -1 ) {
8024				callback();
8025				return;
8026			}
8027	
8028			// Reject old data
8029			var duration = settings.iStateDuration;
8030			if ( duration > 0 && s.time < +new Date() - (duration*1000) ) {
8031				callback();
8032				return;
8033			}
8034	
8035			// Number of columns have changed - all bets are off, no restore of settings
8036			if ( s.columns && columns.length !== s.columns.length ) {
8037				callback();
8038				return;
8039			}
8040	
8041			// Store the saved state so it might be accessed at any time
8042			settings.oLoadedState = $.extend( true, {}, s );
8043	
8044			// Restore key features - todo - for 1.11 this needs to be done by
8045			// subscribed events
8046			if ( s.start !== undefined ) {
8047				settings._iDisplayStart    = s.start;
8048				settings.iInitDisplayStart = s.start;
8049			}
8050			if ( s.length !== undefined ) {
8051				settings._iDisplayLength   = s.length;
8052			}
8053	
8054			// Order
8055			if ( s.order !== undefined ) {
8056				settings.aaSorting = [];
8057				$.each( s.order, function ( i, col ) {
8058					settings.aaSorting.push( col[0] >= columns.length ?
8059						[ 0, col[1] ] :
8060						col
8061					);
8062				} );
8063			}
8064	
8065			// Search
8066			if ( s.search !== undefined ) {
8067				$.extend( settings.oPreviousSearch, _fnSearchToHung( s.search ) );
8068			}
8069	
8070			// Columns
8071			//
8072			if ( s.columns ) {
8073				for ( i=0, ien=s.columns.length ; i<ien ; i++ ) {
8074					var col = s.columns[i];
8075	
8076					// Visibility
8077					if ( col.visible !== undefined ) {
8078						columns[i].bVisible = col.visible;
8079					}
8080	
8081					// Search
8082					if ( col.search !== undefined ) {
8083						$.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) );
8084					}
8085				}
8086			}
8087	
8088			_fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, s] );
8089			callback();
8090		};
8091	
8092		if ( ! settings.oFeatures.bStateSave ) {
8093			callback();
8094			return;
8095		}
8096	
8097		var state = settings.fnStateLoadCallback.call( settings.oInstance, settings, loaded );
8098	
8099		if ( state !== undefined ) {
8100			loaded( state );
8101		}
8102		// otherwise, wait for the loaded callback to be executed
8103	}
8104	
8105	
8106	/**
8107	 * Return the settings object for a particular table
8108	 *  @param {node} table table we are using as a dataTable
8109	 *  @returns {object} Settings object - or null if not found
8110	 *  @memberof DataTable#oApi
8111	 */
8112	function _fnSettingsFromNode ( table )
8113	{
8114		var settings = DataTable.settings;
8115		var idx = $.inArray( table, _pluck( settings, 'nTable' ) );
8116	
8117		return idx !== -1 ?
8118			settings[ idx ] :
8119			null;
8120	}
8121	
8122	
8123	/**
8124	 * Log an error message
8125	 *  @param {object} settings dataTables settings object
8126	 *  @param {int} level log error messages, or display them to the user
8127	 *  @param {string} msg error message
8128	 *  @param {int} tn Technical note id to get more information about the error.
8129	 *  @memberof DataTable#oApi
8130	 */
8131	function _fnLog( settings, level, msg, tn )
8132	{
8133		msg = 'DataTables warning: '+
8134			(settings ? 'table id='+settings.sTableId+' - ' : '')+msg;
8135	
8136		if ( tn ) {
8137			msg += '. For more information about this error, please see '+
8138			'http://datatables.net/tn/'+tn;
8139		}
8140	
8141		if ( ! level  ) {
8142			// Backwards compatibility pre 1.10
8143			var ext = DataTable.ext;
8144			var type = ext.sErrMode || ext.errMode;
8145	
8146			if ( settings ) {
8147				_fnCallbackFire( settings, null, 'error', [ settings, tn, msg ] );
8148			}
8149	
8150			if ( type == 'alert' ) {
8151				alert( msg );
8152			}
8153			else if ( type == 'throw' ) {
8154				throw new Error(msg);
8155			}
8156			else if ( typeof type == 'function' ) {
8157				type( settings, tn, msg );
8158			}
8159		}
8160		else if ( window.console && console.log ) {
8161			console.log( msg );
8162		}
8163	}
8164	
8165	
8166	/**
8167	 * See if a property is defined on one object, if so assign it to the other object
8168	 *  @param {object} ret target object
8169	 *  @param {object} src source object
8170	 *  @param {string} name property
8171	 *  @param {string} [mappedName] name to map too - optional, name used if not given
8172	 *  @memberof DataTable#oApi
8173	 */
8174	function _fnMap( ret, src, name, mappedName )
8175	{
8176		if ( Array.isArray( name ) ) {
8177			$.each( name, function (i, val) {
8178				if ( Array.isArray( val ) ) {
8179					_fnMap( ret, src, val[0], val[1] );
8180				}
8181				else {
8182					_fnMap( ret, src, val );
8183				}
8184			} );
8185	
8186			return;
8187		}
8188	
8189		if ( mappedName === undefined ) {
8190			mappedName = name;
8191		}
8192	
8193		if ( src[name] !== undefined ) {
8194			ret[mappedName] = src[name];
8195		}
8196	}
8197	
8198	
8199	/**
8200	 * Extend objects - very similar to jQuery.extend, but deep copy objects, and
8201	 * shallow copy arrays. The reason we need to do this, is that we don't want to
8202	 * deep copy array init values (such as aaSorting) since the dev wouldn't be
8203	 * able to override them, but we do want to deep copy arrays.
8204	 *  @param {object} out Object to extend
8205	 *  @param {object} extender Object from which the properties will be applied to
8206	 *      out
8207	 *  @param {boolean} breakRefs If true, then arrays will be sliced to take an
8208	 *      independent copy with the exception of the `data` or `aaData` parameters
8209	 *      if they are present. This is so you can pass in a collection to
8210	 *      DataTables and have that used as your data source without breaking the
8211	 *      references
8212	 *  @returns {object} out Reference, just for convenience - out === the return.
8213	 *  @memberof DataTable#oApi
8214	 *  @todo This doesn't take account of arrays inside the deep copied objects.
8215	 */
8216	function _fnExtend( out, extender, breakRefs )
8217	{
8218		var val;
8219	
8220		for ( var prop in extender ) {
8221			if ( extender.hasOwnProperty(prop) ) {
8222				val = extender[prop];
8223	
8224				if ( $.isPlainObject( val ) ) {
8225					if ( ! $.isPlainObject( out[prop] ) ) {
8226						out[prop] = {};
8227					}
8228					$.extend( true, out[prop], val );
8229				}
8230				else if ( breakRefs && prop !== 'data' && prop !== 'aaData' && Array.isArray(val) ) {
8231					out[prop] = val.slice();
8232				}
8233				else {
8234					out[prop] = val;
8235				}
8236			}
8237		}
8238	
8239		return out;
8240	}
8241	
8242	
8243	/**
8244	 * Bind an event handers to allow a click or return key to activate the callback.
8245	 * This is good for accessibility since a return on the keyboard will have the
8246	 * same effect as a click, if the element has focus.
8247	 *  @param {element} n Element to bind the action to
8248	 *  @param {object} oData Data object to pass to the triggered function
8249	 *  @param {function} fn Callback function for when the event is triggered
8250	 *  @memberof DataTable#oApi
8251	 */
8252	function _fnBindAction( n, oData, fn )
8253	{
8254		$(n)
8255			.on( 'click.DT', oData, function (e) {
8256					$(n).trigger('blur'); // Remove focus outline for mouse users
8257					fn(e);
8258				} )
8259			.on( 'keypress.DT', oData, function (e){
8260					if ( e.which === 13 ) {
8261						e.preventDefault();
8262						fn(e);
8263					}
8264				} )
8265			.on( 'selectstart.DT', function () {
8266					/* Take the brutal approach to cancelling text selection */
8267					return false;
8268				} );
8269	}
8270	
8271	
8272	/**
8273	 * Register a callback function. Easily allows a callback function to be added to
8274	 * an array store of callback functions that can then all be called together.
8275	 *  @param {object} oSettings dataTables settings object
8276	 *  @param {string} sStore Name of the array storage for the callbacks in oSettings
8277	 *  @param {function} fn Function to be called back
8278	 *  @param {string} sName Identifying name for the callback (i.e. a label)
8279	 *  @memberof DataTable#oApi
8280	 */
8281	function _fnCallbackReg( oSettings, sStore, fn, sName )
8282	{
8283		if ( fn )
8284		{
8285			oSettings[sStore].push( {
8286				"fn": fn,
8287				"sName": sName
8288			} );
8289		}
8290	}
8291	
8292	
8293	/**
8294	 * Fire callback functions and trigger events. Note that the loop over the
8295	 * callback array store is done backwards! Further note that you do not want to
8296	 * fire off triggers in time sensitive applications (for example cell creation)
8297	 * as its slow.
8298	 *  @param {object} settings dataTables settings object
8299	 *  @param {string} callbackArr Name of the array storage for the callbacks in
8300	 *      oSettings
8301	 *  @param {string} eventName Name of the jQuery custom event to trigger. If
8302	 *      null no trigger is fired
8303	 *  @param {array} args Array of arguments to pass to the callback function /
8304	 *      trigger
8305	 *  @memberof DataTable#oApi
8306	 */
8307	function _fnCallbackFire( settings, callbackArr, eventName, args )
8308	{
8309		var ret = [];
8310	
8311		if ( callbackArr ) {
8312			ret = $.map( settings[callbackArr].slice().reverse(), function (val, i) {
8313				return val.fn.apply( settings.oInstance, args );
8314			} );
8315		}
8316	
8317		if ( eventName !== null ) {
8318			var e = $.Event( eventName+'.dt' );
8319	
8320			$(settings.nTable).trigger( e, args );
8321	
8322			ret.push( e.result );
8323		}
8324	
8325		return ret;
8326	}
8327	
8328	
8329	function _fnLengthOverflow ( settings )
8330	{
8331		var
8332			start = settings._iDisplayStart,
8333			end = settings.fnDisplayEnd(),
8334			len = settings._iDisplayLength;
8335	
8336		/* If we have space to show extra rows (backing up from the end point - then do so */
8337		if ( start >= end )
8338		{
8339			start = end - len;
8340		}
8341	
8342		// Keep the start record on the current page
8343		start -= (start % len);
8344	
8345		if ( len === -1 || start < 0 )
8346		{
8347			start = 0;
8348		}
8349	
8350		settings._iDisplayStart = start;
8351	}
8352	
8353	
8354	function _fnRenderer( settings, type )
8355	{
8356		var renderer = settings.renderer;
8357		var host = DataTable.ext.renderer[type];
8358	
8359		if ( $.isPlainObject( renderer ) && renderer[type] ) {
8360			// Specific renderer for this type. If available use it, otherwise use
8361			// the default.
8362			return host[renderer[type]] || host._;
8363		}
8364		else if ( typeof renderer === 'string' ) {
8365			// Common renderer - if there is one available for this type use it,
8366			// otherwise use the default
8367			return host[renderer] || host._;
8368		}
8369	
8370		// Use the default
8371		return host._;
8372	}
8373	
8374	
8375	/**
8376	 * Detect the data source being used for the table. Used to simplify the code
8377	 * a little (ajax) and to make it compress a little smaller.
8378	 *
8379	 *  @param {object} settings dataTables settings object
8380	 *  @returns {string} Data source
8381	 *  @memberof DataTable#oApi
8382	 */
8383	function _fnDataSource ( settings )
8384	{
8385		if ( settings.oFeatures.bServerSide ) {
8386			return 'ssp';
8387		}
8388		else if ( settings.ajax || settings.sAjaxSource ) {
8389			return 'ajax';
8390		}
8391		return 'dom';
8392	}
8393	
8394
8395	
8396	
8397	/**
8398	 * Computed structure of the DataTables API, defined by the options passed to
8399	 * `DataTable.Api.register()` when building the API.
8400	 *
8401	 * The structure is built in order to speed creation and extension of the Api
8402	 * objects since the extensions are effectively pre-parsed.
8403	 *
8404	 * The array is an array of objects with the following structure, where this
8405	 * base array represents the Api prototype base:
8406	 *
8407	 *     [
8408	 *       {
8409	 *         name:      'data'                -- string   - Property name
8410	 *         val:       function () {},       -- function - Api method (or undefined if just an object
8411	 *         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
8412	 *         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
8413	 *       },
8414	 *       {
8415	 *         name:     'row'
8416	 *         val:       {},
8417	 *         methodExt: [ ... ],
8418	 *         propExt:   [
8419	 *           {
8420	 *             name:      'data'
8421	 *             val:       function () {},
8422	 *             methodExt: [ ... ],
8423	 *             propExt:   [ ... ]
8424	 *           },
8425	 *           ...
8426	 *         ]
8427	 *       }
8428	 *     ]
8429	 *
8430	 * @type {Array}
8431	 * @ignore
8432	 */
8433	var __apiStruct = [];
8434	
8435	
8436	/**
8437	 * `Array.prototype` reference.
8438	 *
8439	 * @type object
8440	 * @ignore
8441	 */
8442	var __arrayProto = Array.prototype;
8443	
8444	
8445	/**
8446	 * Abstraction for `context` parameter of the `Api` constructor to allow it to
8447	 * take several different forms for ease of use.
8448	 *
8449	 * Each of the input parameter types will be converted to a DataTables settings
8450	 * object where possible.
8451	 *
8452	 * @param  {string|node|jQuery|object} mixed DataTable identifier. Can be one
8453	 *   of:
8454	 *
8455	 *   * `string` - jQuery selector. Any DataTables' matching the given selector
8456	 *     with be found and used.
8457	 *   * `node` - `TABLE` node which has already been formed into a DataTable.
8458	 *   * `jQuery` - A jQuery object of `TABLE` nodes.
8459	 *   * `object` - DataTables settings object
8460	 *   * `DataTables.Api` - API instance
8461	 * @return {array|null} Matching DataTables settings objects. `null` or
8462	 *   `undefined` is returned if no matching DataTable is found.
8463	 * @ignore
8464	 */
8465	var _toSettings = function ( mixed )
8466	{
8467		var idx, jq;
8468		var settings = DataTable.settings;
8469		var tables = $.map( settings, function (el, i) {
8470			return el.nTable;
8471		} );
8472	
8473		if ( ! mixed ) {
8474			return [];
8475		}
8476		else if ( mixed.nTable && mixed.oApi ) {
8477			// DataTables settings object
8478			return [ mixed ];
8479		}
8480		else if ( mixed.nodeName && mixed.nodeName.toLowerCase() === 'table' ) {
8481			// Table node
8482			idx = $.inArray( mixed, tables );
8483			return idx !== -1 ? [ settings[idx] ] : null;
8484		}
8485		else if ( mixed && typeof mixed.settings === 'function' ) {
8486			return mixed.settings().toArray();
8487		}
8488		else if ( typeof mixed === 'string' ) {
8489			// jQuery selector
8490			jq = $(mixed);
8491		}
8492		else if ( mixed instanceof $ ) {
8493			// jQuery object (also DataTables instance)
8494			jq = mixed;
8495		}
8496	
8497		if ( jq ) {
8498			return jq.map( function(i) {
8499				idx = $.inArray( this, tables );
8500				return idx !== -1 ? settings[idx] : null;
8501			} ).toArray();
8502		}
8503	};
8504	
8505	
8506	/**
8507	 * DataTables API class - used to control and interface with  one or more
8508	 * DataTables enhanced tables.
8509	 *
8510	 * The API class is heavily based on jQuery, presenting a chainable interface
8511	 * that you can use to interact with tables. Each instance of the API class has
8512	 * a "context" - i.e. the tables that it will operate on. This could be a single
8513	 * table, all tables on a page or a sub-set thereof.
8514	 *
8515	 * Additionally the API is designed to allow you to easily work with the data in
8516	 * the tables, retrieving and manipulating it as required. This is done by
8517	 * presenting the API class as an array like interface. The contents of the
8518	 * array depend upon the actions requested by each method (for example
8519	 * `rows().nodes()` will return an array of nodes, while `rows().data()` will
8520	 * return an array of objects or arrays depending upon your table's
8521	 * configuration). The API object has a number of array like methods (`push`,
8522	 * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`,
8523	 * `unique` etc) to assist your working with the data held in a table.
8524	 *
8525	 * Most methods (those which return an Api instance) are chainable, which means
8526	 * the return from a method call also has all of the methods available that the
8527	 * top level object had. For example, these two calls are equivalent:
8528	 *
8529	 *     // Not chained
8530	 *     api.row.add( {...} );
8531	 *     api.draw();
8532	 *
8533	 *     // Chained
8534	 *     api.row.add( {...} ).draw();
8535	 *
8536	 * @class DataTable.Api
8537	 * @param {array|object|string|jQuery} context DataTable identifier. This is
8538	 *   used to define which DataTables enhanced tables this API will operate on.
8539	 *   Can be one of:
8540	 *
8541	 *   * `string` - jQuery selector. Any DataTables' matching the given selector
8542	 *     with be found and used.
8543	 *   * `node` - `TABLE` node which has already been formed into a DataTable.
8544	 *   * `jQuery` - A jQuery object of `TABLE` nodes.
8545	 *   * `object` - DataTables settings object
8546	 * @param {array} [data] Data to initialise the Api instance with.
8547	 *
8548	 * @example
8549	 *   // Direct initialisation during DataTables construction
8550	 *   var api = $('#example').DataTable();
8551	 *
8552	 * @example
8553	 *   // Initialisation using a DataTables jQuery object
8554	 *   var api = $('#example').dataTable().api();
8555	 *
8556	 * @example
8557	 *   // Initialisation as a constructor
8558	 *   var api = new $.fn.DataTable.Api( 'table.dataTable' );
8559	 */
8560	_Api = function ( context, data )
8561	{
8562		if ( ! (this instanceof _Api) ) {
8563			return new _Api( context, data );
8564		}
8565	
8566		var settings = [];
8567		var ctxSettings = function ( o ) {
8568			var a = _toSettings( o );
8569			if ( a ) {
8570				settings.push.apply( settings, a );
8571			}
8572		};
8573	
8574		if ( Array.isArray( context ) ) {
8575			for ( var i=0, ien=context.length ; i<ien ; i++ ) {
8576				ctxSettings( context[i] );
8577			}
8578		}
8579		else {
8580			ctxSettings( context );
8581		}
8582	
8583		// Remove duplicates
8584		this.context = _unique( settings );
8585	
8586		// Initial data
8587		if ( data ) {
8588			$.merge( this, data );
8589		}
8590	
8591		// selector
8592		this.selector = {
8593			rows: null,
8594			cols: null,
8595			opts: null
8596		};
8597	
8598		_Api.extend( this, this, __apiStruct );
8599	};
8600	
8601	DataTable.Api = _Api;
8602	
8603	// Don't destroy the existing prototype, just extend it. Required for jQuery 2's
8604	// isPlainObject.
8605	$.extend( _Api.prototype, {
8606		any: function ()
8607		{
8608			return this.count() !== 0;
8609		},
8610	
8611	
8612		concat:  __arrayProto.concat,
8613	
8614	
8615		context: [], // array of table settings objects
8616	
8617	
8618		count: function ()
8619		{
8620			return this.flatten().length;
8621		},
8622	
8623	
8624		each: function ( fn )
8625		{
8626			for ( var i=0, ien=this.length ; i<ien; i++ ) {
8627				fn.call( this, this[i], i, this );
8628			}
8629	
8630			return this;
8631		},
8632	
8633	
8634		eq: function ( idx )
8635		{
8636			var ctx = this.context;
8637	
8638			return ctx.length > idx ?
8639				new _Api( ctx[idx], this[idx] ) :
8640				null;
8641		},
8642	
8643	
8644		filter: function ( fn )
8645		{
8646			var a = [];
8647	
8648			if ( __arrayProto.filter ) {
8649				a = __arrayProto.filter.call( this, fn, this );
8650			}
8651			else {
8652				// Compatibility for browsers without EMCA-252-5 (JS 1.6)
8653				for ( var i=0, ien=this.length ; i<ien ; i++ ) {
8654					if ( fn.call( this, this[i], i, this ) ) {
8655						a.push( this[i] );
8656					}
8657				}
8658			}
8659	
8660			return new _Api( this.context, a );
8661		},
8662	
8663	
8664		flatten: function ()
8665		{
8666			var a = [];
8667			return new _Api( this.context, a.concat.apply( a, this.toArray() ) );
8668		},
8669	
8670	
8671		join:    __arrayProto.join,
8672	
8673	
8674		indexOf: __arrayProto.indexOf || function (obj, start)
8675		{
8676			for ( var i=(start || 0), ien=this.length ; i<ien ; i++ ) {
8677				if ( this[i] === obj ) {
8678					return i;
8679				}
8680			}
8681			return -1;
8682		},
8683	
8684		iterator: function ( flatten, type, fn, alwaysNew ) {
8685			var
8686				a = [], ret,
8687				i, ien, j, jen,
8688				context = this.context,
8689				rows, items, item,
8690				selector = this.selector;
8691	
8692			// Argument shifting
8693			if ( typeof flatten === 'string' ) {
8694				alwaysNew = fn;
8695				fn = type;
8696				type = flatten;
8697				flatten = false;
8698			}
8699	
8700			for ( i=0, ien=context.length ; i<ien ; i++ ) {
8701				var apiInst = new _Api( context[i] );
8702	
8703				if ( type === 'table' ) {
8704					ret = fn.call( apiInst, context[i], i );
8705	
8706					if ( ret !== undefined ) {
8707						a.push( ret );
8708					}
8709				}
8710				else if ( type === 'columns' || type === 'rows' ) {
8711					// this has same length as context - one entry for each table
8712					ret = fn.call( apiInst, context[i], this[i], i );
8713	
8714					if ( ret !== undefined ) {
8715						a.push( ret );
8716					}
8717				}
8718				else if ( type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell' ) {
8719					// columns and rows share the same structure.
8720					// 'this' is an array of column indexes for each context
8721					items = this[i];
8722	
8723					if ( type === 'column-rows' ) {
8724						rows = _selector_row_indexes( context[i], selector.opts );
8725					}
8726	
8727					for ( j=0, jen=items.length ; j<jen ; j++ ) {
8728						item = items[j];
8729	
8730						if ( type === 'cell' ) {
8731							ret = fn.call( apiInst, context[i], item.row, item.column, i, j );
8732						}
8733						else {
8734							ret = fn.call( apiInst, context[i], item, i, j, rows );
8735						}
8736	
8737						if ( ret !== undefined ) {
8738							a.push( ret );
8739						}
8740					}
8741				}
8742			}
8743	
8744			if ( a.length || alwaysNew ) {
8745				var api = new _Api( context, flatten ? a.concat.apply( [], a ) : a );
8746				var apiSelector = api.selector;
8747				apiSelector.rows = selector.rows;
8748				apiSelector.cols = selector.cols;
8749				apiSelector.opts = selector.opts;
8750				return api;
8751			}
8752			return this;
8753		},
8754	
8755	
8756		lastIndexOf: __arrayProto.lastIndexOf || function (obj, start)
8757		{
8758			// Bit cheeky...
8759			return this.indexOf.apply( this.toArray.reverse(), arguments );
8760		},
8761	
8762	
8763		length:  0,
8764	
8765	
8766		map: function ( fn )
8767		{
8768			var a = [];
8769	
8770			if ( __arrayProto.map ) {
8771				a = __arrayProto.map.call( this, fn, this );
8772			}
8773			else {
8774				// Compatibility for browsers without EMCA-252-5 (JS 1.6)
8775				for ( var i=0, ien=this.length ; i<ien ; i++ ) {
8776					a.push( fn.call( this, this[i], i ) );
8777				}
8778			}
8779	
8780			return new _Api( this.context, a );
8781		},
8782	
8783	
8784		pluck: function ( prop )
8785		{
8786			return this.map( function ( el ) {
8787				return el[ prop ];
8788			} );
8789		},
8790	
8791		pop:     __arrayProto.pop,
8792	
8793	
8794		push:    __arrayProto.push,
8795	
8796	
8797		// Does not return an API instance
8798		reduce: __arrayProto.reduce || function ( fn, init )
8799		{
8800			return _fnReduce( this, fn, init, 0, this.length, 1 );
8801		},
8802	
8803	
8804		reduceRight: __arrayProto.reduceRight || function ( fn, init )
8805		{
8806			return _fnReduce( this, fn, init, this.length-1, -1, -1 );
8807		},
8808	
8809	
8810		reverse: __arrayProto.reverse,
8811	
8812	
8813		// Object with rows, columns and opts
8814		selector: null,
8815	
8816	
8817		shift:   __arrayProto.shift,
8818	
8819	
8820		slice: function () {
8821			return new _Api( this.context, this );
8822		},
8823	
8824	
8825		sort:    __arrayProto.sort, // ? name - order?
8826	
8827	
8828		splice:  __arrayProto.splice,
8829	
8830	
8831		toArray: function ()
8832		{
8833			return __arrayProto.slice.call( this );
8834		},
8835	
8836	
8837		to$: function ()
8838		{
8839			return $( this );
8840		},
8841	
8842	
8843		toJQuery: function ()
8844		{
8845			return $( this );
8846		},
8847	
8848	
8849		unique: function ()
8850		{
8851			return new _Api( this.context, _unique(this) );
8852		},
8853	
8854	
8855		unshift: __arrayProto.unshift
8856	} );
8857	
8858	
8859	_Api.extend = function ( scope, obj, ext )
8860	{
8861		// Only extend API instances and static properties of the API
8862		if ( ! ext.length || ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) {
8863			return;
8864		}
8865	
8866		var
8867			i, ien,
8868			struct,
8869			methodScoping = function ( scope, fn, struc ) {
8870				return function () {
8871					var ret = fn.apply( scope, arguments );
8872	
8873					// Method extension
8874					_Api.extend( ret, ret, struc.methodExt );
8875					return ret;
8876				};
8877			};
8878	
8879		for ( i=0, ien=ext.length ; i<ien ; i++ ) {
8880			struct = ext[i];
8881	
8882			// Value
8883			obj[ struct.name ] = struct.type === 'function' ?
8884				methodScoping( scope, struct.val, struct ) :
8885				struct.type === 'object' ?
8886					{} :
8887					struct.val;
8888	
8889			obj[ struct.name ].__dt_wrapper = true;
8890	
8891			// Property extension
8892			_Api.extend( scope, obj[ struct.name ], struct.propExt );
8893		}
8894	};
8895	
8896	
8897	// @todo - Is there need for an augment function?
8898	// _Api.augment = function ( inst, name )
8899	// {
8900	// 	// Find src object in the structure from the name
8901	// 	var parts = name.split('.');
8902	
8903	// 	_Api.extend( inst, obj );
8904	// };
8905	
8906	
8907	//     [
8908	//       {
8909	//         name:      'data'                -- string   - Property name
8910	//         val:       function () {},       -- function - Api method (or undefined if just an object
8911	//         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
8912	//         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
8913	//       },
8914	//       {
8915	//         name:     'row'
8916	//         val:       {},
8917	//         methodExt: [ ... ],
8918	//         propExt:   [
8919	//           {
8920	//             name:      'data'
8921	//             val:       function () {},
8922	//             methodExt: [ ... ],
8923	//             propExt:   [ ... ]
8924	//           },
8925	//           ...
8926	//         ]
8927	//       }
8928	//     ]
8929	
8930	_Api.register = _api_register = function ( name, val )
8931	{
8932		if ( Array.isArray( name ) ) {
8933			for ( var j=0, jen=name.length ; j<jen ; j++ ) {
8934				_Api.register( name[j], val );
8935			}
8936			return;
8937		}
8938	
8939		var
8940			i, ien,
8941			heir = name.split('.'),
8942			struct = __apiStruct,
8943			key, method;
8944	
8945		var find = function ( src, name ) {
8946			for ( var i=0, ien=src.length ; i<ien ; i++ ) {
8947				if ( src[i].name === name ) {
8948					return src[i];
8949				}
8950			}
8951			return null;
8952		};
8953	
8954		for ( i=0, ien=heir.length ; i<ien ; i++ ) {
8955			method = heir[i].indexOf('()') !== -1;
8956			key = method ?
8957				heir[i].replace('()', '') :
8958				heir[i];
8959	
8960			var src = find( struct, key );
8961			if ( ! src ) {
8962				src = {
8963					name:      key,
8964					val:       {},
8965					methodExt: [],
8966					propExt:   [],
8967					type:      'object'
8968				};
8969				struct.push( src );
8970			}
8971	
8972			if ( i === ien-1 ) {
8973				src.val = val;
8974				src.type = typeof val === 'function' ?
8975					'function' :
8976					$.isPlainObject( val ) ?
8977						'object' :
8978						'other';
8979			}
8980			else {
8981				struct = method ?
8982					src.methodExt :
8983					src.propExt;
8984			}
8985		}
8986	};
8987	
8988	_Api.registerPlural = _api_registerPlural = function ( pluralName, singularName, val ) {
8989		_Api.register( pluralName, val );
8990	
8991		_Api.register( singularName, function () {
8992			var ret = val.apply( this, arguments );
8993	
8994			if ( ret === this ) {
8995				// Returned item is the API instance that was passed in, return it
8996				return this;
8997			}
8998			else if ( ret instanceof _Api ) {
8999				// New API instance returned, want the value from the first item
9000				// in the returned array for the singular result.
9001				return ret.length ?
9002					Array.isArray( ret[0] ) ?
9003						new _Api( ret.context, ret[0] ) : // Array results are 'enhanced'
9004						ret[0] :
9005					undefined;
9006			}
9007	
9008			// Non-API return - just fire it back
9009			return ret;
9010		} );
9011	};
9012	
9013	
9014	/**
9015	 * Selector for HTML tables. Apply the given selector to the give array of
9016	 * DataTables settings objects.
9017	 *
9018	 * @param {string|integer} [selector] jQuery selector string or integer
9019	 * @param  {array} Array of DataTables settings objects to be filtered
9020	 * @return {array}
9021	 * @ignore
9022	 */
9023	var __table_selector = function ( selector, a )
9024	{
9025		if ( Array.isArray(selector) ) {
9026			return $.map( selector, function (item) {
9027				return __table_selector(item, a);
9028			} );
9029		}
9030	
9031		// Integer is used to pick out a table by index
9032		if ( typeof selector === 'number' ) {
9033			return [ a[ selector ] ];
9034		}
9035	
9036		// Perform a jQuery selector on the table nodes
9037		var nodes = $.map( a, function (el, i) {
9038			return el.nTable;
9039		} );
9040	
9041		return $(nodes)
9042			.filter( selector )
9043			.map( function (i) {
9044				// Need to translate back from the table node to the settings
9045				var idx = $.inArray( this, nodes );
9046				return a[ idx ];
9047			} )
9048			.toArray();
9049	};
9050	
9051	
9052	
9053	/**
9054	 * Context selector for the API's context (i.e. the tables the API instance
9055	 * refers to.
9056	 *
9057	 * @name    DataTable.Api#tables
9058	 * @param {string|integer} [selector] Selector to pick which tables the iterator
9059	 *   should operate on. If not given, all tables in the current context are
9060	 *   used. This can be given as a jQuery selector (for example `':gt(0)'`) to
9061	 *   select multiple tables or as an integer to select a single table.
9062	 * @returns {DataTable.Api} Returns a new API instance if a selector is given.
9063	 */
9064	_api_register( 'tables()', function ( selector ) {
9065		// A new instance is created if there was a selector specified
9066		return selector !== undefined && selector !== null ?
9067			new _Api( __table_selector( selector, this.context ) ) :
9068			this;
9069	} );
9070	
9071	
9072	_api_register( 'table()', function ( selector ) {
9073		var tables = this.tables( selector );
9074		var ctx = tables.context;
9075	
9076		// Truncate to the first matched table
9077		return ctx.length ?
9078			new _Api( ctx[0] ) :
9079			tables;
9080	} );
9081	
9082	
9083	_api_registerPlural( 'tables().nodes()', 'table().node()' , function () {
9084		return this.iterator( 'table', function ( ctx ) {
9085			return ctx.nTable;
9086		}, 1 );
9087	} );
9088	
9089	
9090	_api_registerPlural( 'tables().body()', 'table().body()' , function () {
9091		return this.iterator( 'table', function ( ctx ) {
9092			return ctx.nTBody;
9093		}, 1 );
9094	} );
9095	
9096	
9097	_api_registerPlural( 'tables().header()', 'table().header()' , function () {
9098		return this.iterator( 'table', function ( ctx ) {
9099			return ctx.nTHead;
9100		}, 1 );
9101	} );
9102	
9103	
9104	_api_registerPlural( 'tables().footer()', 'table().footer()' , function () {
9105		return this.iterator( 'table', function ( ctx ) {
9106			return ctx.nTFoot;
9107		}, 1 );
9108	} );
9109	
9110	
9111	_api_registerPlural( 'tables().containers()', 'table().container()' , function () {
9112		return this.iterator( 'table', function ( ctx ) {
9113			return ctx.nTableWrapper;
9114		}, 1 );
9115	} );
9116	
9117	
9118	
9119	/**
9120	 * Redraw the tables in the current context.
9121	 */
9122	_api_register( 'draw()', function ( paging ) {
9123		return this.iterator( 'table', function ( settings ) {
9124			if ( paging === 'page' ) {
9125				_fnDraw( settings );
9126			}
9127			else {
9128				if ( typeof paging === 'string' ) {
9129					paging = paging === 'full-hold' ?
9130						false :
9131						true;
9132				}
9133	
9134				_fnReDraw( settings, paging===false );
9135			}
9136		} );
9137	} );
9138	
9139	
9140	
9141	/**
9142	 * Get the current page index.
9143	 *
9144	 * @return {integer} Current page index (zero based)
9145	 *//**
9146	 * Set the current page.
9147	 *
9148	 * Note that if you attempt to show a page which does not exist, DataTables will
9149	 * not throw an error, but rather reset the paging.
9150	 *
9151	 * @param {integer|string} action The paging action to take. This can be one of:
9152	 *  * `integer` - The page index to jump to
9153	 *  * `string` - An action to take:
9154	 *    * `first` - Jump to first page.
9155	 *    * `next` - Jump to the next page
9156	 *    * `previous` - Jump to previous page
9157	 *    * `last` - Jump to the last page.
9158	 * @returns {DataTables.Api} this
9159	 */
9160	_api_register( 'page()', function ( action ) {
9161		if ( action === undefined ) {
9162			return this.page.info().page; // not an expensive call
9163		}
9164	
9165		// else, have an action to take on all tables
9166		return this.iterator( 'table', function ( settings ) {
9167			_fnPageChange( settings, action );
9168		} );
9169	} );
9170	
9171	
9172	/**
9173	 * Paging information for the first table in the current context.
9174	 *
9175	 * If you require paging information for another table, use the `table()` method
9176	 * with a suitable selector.
9177	 *
9178	 * @return {object} Object with the following properties set:
9179	 *  * `page` - Current page index (zero based - i.e. the first page is `0`)
9180	 *  * `pages` - Total number of pages
9181	 *  * `start` - Display index for the first record shown on the current page
9182	 *  * `end` - Display index for the last record shown on the current page
9183	 *  * `length` - Display length (number of records). Note that generally `start
9184	 *    + length = end`, but this is not always true, for example if there are
9185	 *    only 2 records to show on the final page, with a length of 10.
9186	 *  * `recordsTotal` - Full data set length
9187	 *  * `recordsDisplay` - Data set length once the current filtering criterion
9188	 *    are applied.
9189	 */
9190	_api_register( 'page.info()', function ( action ) {
9191		if ( this.context.length === 0 ) {
9192			return undefined;
9193		}
9194	
9195		var
9196			settings   = this.context[0],
9197			start      = settings._iDisplayStart,
9198			len        = settings.oFeatures.bPaginate ? settings._iDisplayLength : -1,
9199			visRecords = settings.fnRecordsDisplay(),
9200			all        = len === -1;
9201	
9202		return {
9203			"page":           all ? 0 : Math.floor( start / len ),
9204			"pages":          all ? 1 : Math.ceil( visRecords / len ),
9205			"start":          start,
9206			"end":            settings.fnDisplayEnd(),
9207			"length":         len,
9208			"recordsTotal":   settings.fnRecordsTotal(),
9209			"recordsDisplay": visRecords,
9210			"serverSide":     _fnDataSource( settings ) === 'ssp'
9211		};
9212	} );
9213	
9214	
9215	/**
9216	 * Get the current page length.
9217	 *
9218	 * @return {integer} Current page length. Note `-1` indicates that all records
9219	 *   are to be shown.
9220	 *//**
9221	 * Set the current page length.
9222	 *
9223	 * @param {integer} Page length to set. Use `-1` to show all records.
9224	 * @returns {DataTables.Api} this
9225	 */
9226	_api_register( 'page.len()', function ( len ) {
9227		// Note that we can't call this function 'length()' because `length`
9228		// is a Javascript property of functions which defines how many arguments
9229		// the function expects.
9230		if ( len === undefined ) {
9231			return this.context.length !== 0 ?
9232				this.context[0]._iDisplayLength :
9233				undefined;
9234		}
9235	
9236		// else, set the page length
9237		return this.iterator( 'table', function ( settings ) {
9238			_fnLengthChange( settings, len );
9239		} );
9240	} );
9241	
9242	
9243	
9244	var __reload = function ( settings, holdPosition, callback ) {
9245		// Use the draw event to trigger a callback
9246		if ( callback ) {
9247			var api = new _Api( settings );
9248	
9249			api.one( 'draw', function () {
9250				callback( api.ajax.json() );
9251			} );
9252		}
9253	
9254		if ( _fnDataSource( settings ) == 'ssp' ) {
9255			_fnReDraw( settings, holdPosition );
9256		}
9257		else {
9258			_fnProcessingDisplay( settings, true );
9259	
9260			// Cancel an existing request
9261			var xhr = settings.jqXHR;
9262			if ( xhr && xhr.readyState !== 4 ) {
9263				xhr.abort();
9264			}
9265	
9266			// Trigger xhr
9267			_fnBuildAjax( settings, [], function( json ) {
9268				_fnClearTable( settings );
9269	
9270				var data = _fnAjaxDataSrc( settings, json );
9271				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
9272					_fnAddData( settings, data[i] );
9273				}
9274	
9275				_fnReDraw( settings, holdPosition );
9276				_fnProcessingDisplay( settings, false );
9277			} );
9278		}
9279	};
9280	
9281	
9282	/**
9283	 * Get the JSON response from the last Ajax request that DataTables made to the
9284	 * server. Note that this returns the JSON from the first table in the current
9285	 * context.
9286	 *
9287	 * @return {object} JSON received from the server.
9288	 */
9289	_api_register( 'ajax.json()', function () {
9290		var ctx = this.context;
9291	
9292		if ( ctx.length > 0 ) {
9293			return ctx[0].json;
9294		}
9295	
9296		// else return undefined;
9297	} );
9298	
9299	
9300	/**
9301	 * Get the data submitted in the last Ajax request
9302	 */
9303	_api_register( 'ajax.params()', function () {
9304		var ctx = this.context;
9305	
9306		if ( ctx.length > 0 ) {
9307			return ctx[0].oAjaxData;
9308		}
9309	
9310		// else return undefined;
9311	} );
9312	
9313	
9314	/**
9315	 * Reload tables from the Ajax data source. Note that this function will
9316	 * automatically re-draw the table when the remote data has been loaded.
9317	 *
9318	 * @param {boolean} [reset=true] Reset (default) or hold the current paging
9319	 *   position. A full re-sort and re-filter is performed when this method is
9320	 *   called, which is why the pagination reset is the default action.
9321	 * @returns {DataTables.Api} this
9322	 */
9323	_api_register( 'ajax.reload()', function ( callback, resetPaging ) {
9324		return this.iterator( 'table', function (settings) {
9325			__reload( settings, resetPaging===false, callback );
9326		} );
9327	} );
9328	
9329	
9330	/**
9331	 * Get the current Ajax URL. Note that this returns the URL from the first
9332	 * table in the current context.
9333	 *
9334	 * @return {string} Current Ajax source URL
9335	 *//**
9336	 * Set the Ajax URL. Note that this will set the URL for all tables in the
9337	 * current context.
9338	 *
9339	 * @param {string} url URL to set.
9340	 * @returns {DataTables.Api} this
9341	 */
9342	_api_register( 'ajax.url()', function ( url ) {
9343		var ctx = this.context;
9344	
9345		if ( url === undefined ) {
9346			// get
9347			if ( ctx.length === 0 ) {
9348				return undefined;
9349			}
9350			ctx = ctx[0];
9351	
9352			return ctx.ajax ?
9353				$.isPlainObject( ctx.ajax ) ?
9354					ctx.ajax.url :
9355					ctx.ajax :
9356				ctx.sAjaxSource;
9357		}
9358	
9359		// set
9360		return this.iterator( 'table', function ( settings ) {
9361			if ( $.isPlainObject( settings.ajax ) ) {
9362				settings.ajax.url = url;
9363			}
9364			else {
9365				settings.ajax = url;
9366			}
9367			// No need to consider sAjaxSource here since DataTables gives priority
9368			// to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any
9369			// value of `sAjaxSource` redundant.
9370		} );
9371	} );
9372	
9373	
9374	/**
9375	 * Load data from the newly set Ajax URL. Note that this method is only
9376	 * available when `ajax.url()` is used to set a URL. Additionally, this method
9377	 * has the same effect as calling `ajax.reload()` but is provided for
9378	 * convenience when setting a new URL. Like `ajax.reload()` it will
9379	 * automatically redraw the table once the remote data has been loaded.
9380	 *
9381	 * @returns {DataTables.Api} this
9382	 */
9383	_api_register( 'ajax.url().load()', function ( callback, resetPaging ) {
9384		// Same as a reload, but makes sense to present it for easy access after a
9385		// url change
9386		return this.iterator( 'table', function ( ctx ) {
9387			__reload( ctx, resetPaging===false, callback );
9388		} );
9389	} );
9390	
9391	
9392	
9393	
9394	var _selector_run = function ( type, selector, selectFn, settings, opts )
9395	{
9396		var
9397			out = [], res,
9398			a, i, ien, j, jen,
9399			selectorType = typeof selector;
9400	
9401		// Can't just check for isArray here, as an API or jQuery instance might be
9402		// given with their array like look
9403		if ( ! selector || selectorType === 'string' || selectorType === 'function' || selector.length === undefined ) {
9404			selector = [ selector ];
9405		}
9406	
9407		for ( i=0, ien=selector.length ; i<ien ; i++ ) {
9408			// Only split on simple strings - complex expressions will be jQuery selectors
9409			a = selector[i] && selector[i].split && ! selector[i].match(/[\[\(:]/) ?
9410				selector[i].split(',') :
9411				[ selector[i] ];
9412	
9413			for ( j=0, jen=a.length ; j<jen ; j++ ) {
9414				res = selectFn( typeof a[j] === 'string' ? (a[j]).trim() : a[j] );
9415	
9416				if ( res && res.length ) {
9417					out = out.concat( res );
9418				}
9419			}
9420		}
9421	
9422		// selector extensions
9423		var ext = _ext.selector[ type ];
9424		if ( ext.length ) {
9425			for ( i=0, ien=ext.length ; i<ien ; i++ ) {
9426				out = ext[i]( settings, opts, out );
9427			}
9428		}
9429	
9430		return _unique( out );
9431	};
9432	
9433	
9434	var _selector_opts = function ( opts )
9435	{
9436		if ( ! opts ) {
9437			opts = {};
9438		}
9439	
9440		// Backwards compatibility for 1.9- which used the terminology filter rather
9441		// than search
9442		if ( opts.filter && opts.search === undefined ) {
9443			opts.search = opts.filter;
9444		}
9445	
9446		return $.extend( {
9447			search: 'none',
9448			order: 'current',
9449			page: 'all'
9450		}, opts );
9451	};
9452	
9453	
9454	var _selector_first = function ( inst )
9455	{
9456		// Reduce the API instance to the first item found
9457		for ( var i=0, ien=inst.length ; i<ien ; i++ ) {
9458			if ( inst[i].length > 0 ) {
9459				// Assign the first element to the first item in the instance
9460				// and truncate the instance and context
9461				inst[0] = inst[i];
9462				inst[0].length = 1;
9463				inst.length = 1;
9464				inst.context = [ inst.context[i] ];
9465	
9466				return inst;
9467			}
9468		}
9469	
9470		// Not found - return an empty instance
9471		inst.length = 0;
9472		return inst;
9473	};
9474	
9475	
9476	var _selector_row_indexes = function ( settings, opts )
9477	{
9478		var
9479			i, ien, tmp, a=[],
9480			displayFiltered = settings.aiDisplay,
9481			displayMaster = settings.aiDisplayMaster;
9482	
9483		var
9484			search = opts.search,  // none, applied, removed
9485			order  = opts.order,   // applied, current, index (original - compatibility with 1.9)
9486			page   = opts.page;    // all, current
9487	
9488		if ( _fnDataSource( settings ) == 'ssp' ) {
9489			// In server-side processing mode, most options are irrelevant since
9490			// rows not shown don't exist and the index order is the applied order
9491			// Removed is a special case - for consistency just return an empty
9492			// array
9493			return search === 'removed' ?
9494				[] :
9495				_range( 0, displayMaster.length );
9496		}
9497		else if ( page == 'current' ) {
9498			// Current page implies that order=current and fitler=applied, since it is
9499			// fairly senseless otherwise, regardless of what order and search actually
9500			// are
9501			for ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i<ien ; i++ ) {
9502				a.push( displayFiltered[i] );
9503			}
9504		}
9505		else if ( order == 'current' || order == 'applied' ) {
9506			if ( search == 'none') {
9507				a = displayMaster.slice();
9508			}
9509			else if ( search == 'applied' ) {
9510				a = displayFiltered.slice();
9511			}
9512			else if ( search == 'removed' ) {
9513				// O(n+m) solution by creating a hash map
9514				var displayFilteredMap = {};
9515	
9516				for ( var i=0, ien=displayFiltered.length ; i<ien ; i++ ) {
9517					displayFilteredMap[displayFiltered[i]] = null;
9518				}
9519	
9520				a = $.map( displayMaster, function (el) {
9521					return ! displayFilteredMap.hasOwnProperty(el) ?
9522						el :
9523						null;
9524				} );
9525			}
9526		}
9527		else if ( order == 'index' || order == 'original' ) {
9528			for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
9529				if ( search == 'none' ) {
9530					a.push( i );
9531				}
9532				else { // applied | removed
9533					tmp = $.inArray( i, displayFiltered );
9534	
9535					if ((tmp === -1 && search == 'removed') ||
9536						(tmp >= 0   && search == 'applied') )
9537					{
9538						a.push( i );
9539					}
9540				}
9541			}
9542		}
9543	
9544		return a;
9545	};
9546	
9547	
9548	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
9549	 * Rows
9550	 *
9551	 * {}          - no selector - use all available rows
9552	 * {integer}   - row aoData index
9553	 * {node}      - TR node
9554	 * {string}    - jQuery selector to apply to the TR elements
9555	 * {array}     - jQuery array of nodes, or simply an array of TR nodes
9556	 *
9557	 */
9558	var __row_selector = function ( settings, selector, opts )
9559	{
9560		var rows;
9561		var run = function ( sel ) {
9562			var selInt = _intVal( sel );
9563			var i, ien;
9564			var aoData = settings.aoData;
9565	
9566			// Short cut - selector is a number and no options provided (default is
9567			// all records, so no need to check if the index is in there, since it
9568			// must be - dev error if the index doesn't exist).
9569			if ( selInt !== null && ! opts ) {
9570				return [ selInt ];
9571			}
9572	
9573			if ( ! rows ) {
9574				rows = _selector_row_indexes( settings, opts );
9575			}
9576	
9577			if ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) {
9578				// Selector - integer
9579				return [ selInt ];
9580			}
9581			else if ( sel === null || sel === undefined || sel === '' ) {
9582				// Selector - none
9583				return rows;
9584			}
9585	
9586			// Selector - function
9587			if ( typeof sel === 'function' ) {
9588				return $.map( rows, function (idx) {
9589					var row = aoData[ idx ];
9590					return sel( idx, row._aData, row.nTr ) ? idx : null;
9591				} );
9592			}
9593	
9594			// Selector - node
9595			if ( sel.nodeName ) {
9596				var rowIdx = sel._DT_RowIndex;  // Property added by DT for fast lookup
9597				var cellIdx = sel._DT_CellIndex;
9598	
9599				if ( rowIdx !== undefined ) {
9600					// Make sure that the row is actually still present in the table
9601					return aoData[ rowIdx ] && aoData[ rowIdx ].nTr === sel ?
9602						[ rowIdx ] :
9603						[];
9604				}
9605				else if ( cellIdx ) {
9606					return aoData[ cellIdx.row ] && aoData[ cellIdx.row ].nTr === sel.parentNode ?
9607						[ cellIdx.row ] :
9608						[];
9609				}
9610				else {
9611					var host = $(sel).closest('*[data-dt-row]');
9612					return host.length ?
9613						[ host.data('dt-row') ] :
9614						[];
9615				}
9616			}
9617	
9618			// ID selector. Want to always be able to select rows by id, regardless
9619			// of if the tr element has been created or not, so can't rely upon
9620			// jQuery here - hence a custom implementation. This does not match
9621			// Sizzle's fast selector or HTML4 - in HTML5 the ID can be anything,
9622			// but to select it using a CSS selector engine (like Sizzle or
9623			// querySelect) it would need to need to be escaped for some characters.
9624			// DataTables simplifies this for row selectors since you can select
9625			// only a row. A # indicates an id any anything that follows is the id -
9626			// unescaped.
9627			if ( typeof sel === 'string' && sel.charAt(0) === '#' ) {
9628				// get row index from id
9629				var rowObj = settings.aIds[ sel.replace( /^#/, '' ) ];
9630				if ( rowObj !== undefined ) {
9631					return [ rowObj.idx ];
9632				}
9633	
9634				// need to fall through to jQuery in case there is DOM id that
9635				// matches
9636			}
9637			
9638			// Get nodes in the order from the `rows` array with null values removed
9639			var nodes = _removeEmpty(
9640				_pluck_order( settings.aoData, rows, 'nTr' )
9641			);
9642	
9643			// Selector - jQuery selector string, array of nodes or jQuery object/
9644			// As jQuery's .filter() allows jQuery objects to be passed in filter,
9645			// it also allows arrays, so this will cope with all three options
9646			return $(nodes)
9647				.filter( sel )
9648				.map( function () {
9649					return this._DT_RowIndex;
9650				} )
9651				.toArray();
9652		};
9653	
9654		return _selector_run( 'row', selector, run, settings, opts );
9655	};
9656	
9657	
9658	_api_register( 'rows()', function ( selector, opts ) {
9659		// argument shifting
9660		if ( selector === undefined ) {
9661			selector = '';
9662		}
9663		else if ( $.isPlainObject( selector ) ) {
9664			opts = selector;
9665			selector = '';
9666		}
9667	
9668		opts = _selector_opts( opts );
9669	
9670		var inst = this.iterator( 'table', function ( settings ) {
9671			return __row_selector( settings, selector, opts );
9672		}, 1 );
9673	
9674		// Want argument shifting here and in __row_selector?
9675		inst.selector.rows = selector;
9676		inst.selector.opts = opts;
9677	
9678		return inst;
9679	} );
9680	
9681	_api_register( 'rows().nodes()', function () {
9682		return this.iterator( 'row', function ( settings, row ) {
9683			return settings.aoData[ row ].nTr || undefined;
9684		}, 1 );
9685	} );
9686	
9687	_api_register( 'rows().data()', function () {
9688		return this.iterator( true, 'rows', function ( settings, rows ) {
9689			return _pluck_order( settings.aoData, rows, '_aData' );
9690		}, 1 );
9691	} );
9692	
9693	_api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) {
9694		return this.iterator( 'row', function ( settings, row ) {
9695			var r = settings.aoData[ row ];
9696			return type === 'search' ? r._aFilterData : r._aSortData;
9697		}, 1 );
9698	} );
9699	
9700	_api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) {
9701		return this.iterator( 'row', function ( settings, row ) {
9702			_fnInvalidate( settings, row, src );
9703		} );
9704	} );
9705	
9706	_api_registerPlural( 'rows().indexes()', 'row().index()', function () {
9707		return this.iterator( 'row', function ( settings, row ) {
9708			return row;
9709		}, 1 );
9710	} );
9711	
9712	_api_registerPlural( 'rows().ids()', 'row().id()', function ( hash ) {
9713		var a = [];
9714		var context = this.context;
9715	
9716		// `iterator` will drop undefined values, but in this case we want them
9717		for ( var i=0, ien=context.length ; i<ien ; i++ ) {
9718			for ( var j=0, jen=this[i].length ; j<jen ; j++ ) {
9719				var id = context[i].rowIdFn( context[i].aoData[ this[i][j] ]._aData );
9720				a.push( (hash === true ? '#' : '' )+ id );
9721			}
9722		}
9723	
9724		return new _Api( context, a );
9725	} );
9726	
9727	_api_registerPlural( 'rows().remove()', 'row().remove()', function () {
9728		var that = this;
9729	
9730		this.iterator( 'row', function ( settings, row, thatIdx ) {
9731			var data = settings.aoData;
9732			var rowData = data[ row ];
9733			var i, ien, j, jen;
9734			var loopRow, loopCells;
9735	
9736			data.splice( row, 1 );
9737	
9738			// Update the cached indexes
9739			for ( i=0, ien=data.length ; i<ien ; i++ ) {
9740				loopRow = data[i];
9741				loopCells = loopRow.anCells;
9742	
9743				// Rows
9744				if ( loopRow.nTr !== null ) {
9745					loopRow.nTr._DT_RowIndex = i;
9746				}
9747	
9748				// Cells
9749				if ( loopCells !== null ) {
9750					for ( j=0, jen=loopCells.length ; j<jen ; j++ ) {
9751						loopCells[j]._DT_CellIndex.row = i;
9752					}
9753				}
9754			}
9755	
9756			// Delete from the display arrays
9757			_fnDeleteIndex( settings.aiDisplayMaster, row );
9758			_fnDeleteIndex( settings.aiDisplay, row );
9759			_fnDeleteIndex( that[ thatIdx ], row, false ); // maintain local indexes
9760	
9761			// For server-side processing tables - subtract the deleted row from the count
9762			if ( settings._iRecordsDisplay > 0 ) {
9763				settings._iRecordsDisplay--;
9764			}
9765	
9766			// Check for an 'overflow' they case for displaying the table
9767			_fnLengthOverflow( settings );
9768	
9769			// Remove the row's ID reference if there is one
9770			var id = settings.rowIdFn( rowData._aData );
9771			if ( id !== undefined ) {
9772				delete settings.aIds[ id ];
9773			}
9774		} );
9775	
9776		this.iterator( 'table', function ( settings ) {
9777			for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
9778				settings.aoData[i].idx = i;
9779			}
9780		} );
9781	
9782		return this;
9783	} );
9784	
9785	
9786	_api_register( 'rows.add()', function ( rows ) {
9787		var newRows = this.iterator( 'table', function ( settings ) {
9788				var row, i, ien;
9789				var out = [];
9790	
9791				for ( i=0, ien=rows.length ; i<ien ; i++ ) {
9792					row = rows[i];
9793	
9794					if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
9795						out.push( _fnAddTr( settings, row )[0] );
9796					}
9797					else {
9798						out.push( _fnAddData( settings, row ) );
9799					}
9800				}
9801	
9802				return out;
9803			}, 1 );
9804	
9805		// Return an Api.rows() extended instance, so rows().nodes() etc can be used
9806		var modRows = this.rows( -1 );
9807		modRows.pop();
9808		$.merge( modRows, newRows );
9809	
9810		return modRows;
9811	} );
9812	
9813	
9814	
9815	
9816	
9817	/**
9818	 *
9819	 */
9820	_api_register( 'row()', function ( selector, opts ) {
9821		return _selector_first( this.rows( selector, opts ) );
9822	} );
9823	
9824	
9825	_api_register( 'row().data()', function ( data ) {
9826		var ctx = this.context;
9827	
9828		if ( data === undefined ) {
9829			// Get
9830			return ctx.length && this.length ?
9831				ctx[0].aoData[ this[0] ]._aData :
9832				undefined;
9833		}
9834	
9835		// Set
9836		var row = ctx[0].aoData[ this[0] ];
9837		row._aData = data;
9838	
9839		// If the DOM has an id, and the data source is an array
9840		if ( Array.isArray( data ) && row.nTr && row.nTr.id ) {
9841			_fnSetObjectDataFn( ctx[0].rowId )( data, row.nTr.id );
9842		}
9843	
9844		// Automatically invalidate
9845		_fnInvalidate( ctx[0], this[0], 'data' );
9846	
9847		return this;
9848	} );
9849	
9850	
9851	_api_register( 'row().node()', function () {
9852		var ctx = this.context;
9853	
9854		return ctx.length && this.length ?
9855			ctx[0].aoData[ this[0] ].nTr || null :
9856			null;
9857	} );
9858	
9859	
9860	_api_register( 'row.add()', function ( row ) {
9861		// Allow a jQuery object to be passed in - only a single row is added from
9862		// it though - the first element in the set
9863		if ( row instanceof $ && row.length ) {
9864			row = row[0];
9865		}
9866	
9867		var rows = this.iterator( 'table', function ( settings ) {
9868			if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
9869				return _fnAddTr( settings, row )[0];
9870			}
9871			return _fnAddData( settings, row );
9872		} );
9873	
9874		// Return an Api.rows() extended instance, with the newly added row selected
9875		return this.row( rows[0] );
9876	} );
9877	
9878	
9879	
9880	var __details_add = function ( ctx, row, data, klass )
9881	{
9882		// Convert to array of TR elements
9883		var rows = [];
9884		var addRow = function ( r, k ) {
9885			// Recursion to allow for arrays of jQuery objects
9886			if ( Array.isArray( r ) || r instanceof $ ) {
9887				for ( var i=0, ien=r.length ; i<ien ; i++ ) {
9888					addRow( r[i], k );
9889				}
9890				return;
9891			}
9892	
9893			// If we get a TR element, then just add it directly - up to the dev
9894			// to add the correct number of columns etc
9895			if ( r.nodeName && r.nodeName.toLowerCase() === 'tr' ) {
9896				rows.push( r );
9897			}
9898			else {
9899				// Otherwise create a row with a wrapper
9900				var created = $('<tr><td></td></tr>').addClass( k );
9901				$('td', created)
9902					.addClass( k )
9903					.html( r )
9904					[0].colSpan = _fnVisbleColumns( ctx );
9905	
9906				rows.push( created[0] );
9907			}
9908		};
9909	
9910		addRow( data, klass );
9911	
9912		if ( row._details ) {
9913			row._details.detach();
9914		}
9915	
9916		row._details = $(rows);
9917	
9918		// If the children were already shown, that state should be retained
9919		if ( row._detailsShow ) {
9920			row._details.insertAfter( row.nTr );
9921		}
9922	};
9923	
9924	
9925	var __details_remove = function ( api, idx )
9926	{
9927		var ctx = api.context;
9928	
9929		if ( ctx.length ) {
9930			var row = ctx[0].aoData[ idx !== undefined ? idx : api[0] ];
9931	
9932			if ( row && row._details ) {
9933				row._details.remove();
9934	
9935				row._detailsShow = undefined;
9936				row._details = undefined;
9937			}
9938		}
9939	};
9940	
9941	
9942	var __details_display = function ( api, show ) {
9943		var ctx = api.context;
9944	
9945		if ( ctx.length && api.length ) {
9946			var row = ctx[0].aoData[ api[0] ];
9947	
9948			if ( row._details ) {
9949				row._detailsShow = show;
9950	
9951				if ( show ) {
9952					row._details.insertAfter( row.nTr );
9953				}
9954				else {
9955					row._details.detach();
9956				}
9957	
9958				__details_events( ctx[0] );
9959			}
9960		}
9961	};
9962	
9963	
9964	var __details_events = function ( settings )
9965	{
9966		var api = new _Api( settings );
9967		var namespace = '.dt.DT_details';
9968		var drawEvent = 'draw'+namespace;
9969		var colvisEvent = 'column-visibility'+namespace;
9970		var destroyEvent = 'destroy'+namespace;
9971		var data = settings.aoData;
9972	
9973		api.off( drawEvent +' '+ colvisEvent +' '+ destroyEvent );
9974	
9975		if ( _pluck( data, '_details' ).length > 0 ) {
9976			// On each draw, insert the required elements into the document
9977			api.on( drawEvent, function ( e, ctx ) {
9978				if ( settings !== ctx ) {
9979					return;
9980				}
9981	
9982				api.rows( {page:'current'} ).eq(0).each( function (idx) {
9983					// Internal data grab
9984					var row = data[ idx ];
9985	
9986					if ( row._detailsShow ) {
9987						row._details.insertAfter( row.nTr );
9988					}
9989				} );
9990			} );
9991	
9992			// Column visibility change - update the colspan
9993			api.on( colvisEvent, function ( e, ctx, idx, vis ) {
9994				if ( settings !== ctx ) {
9995					return;
9996				}
9997	
9998				// Update the colspan for the details rows (note, only if it already has
9999				// a colspan)
10000				var row, visible = _fnVisbleColumns( ctx );
10001	
10002				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
10003					row = data[i];
10004	
10005					if ( row._details ) {
10006						row._details.children('td[colspan]').attr('colspan', visible );
10007					}
10008				}
10009			} );
10010	
10011			// Table destroyed - nuke any child rows
10012			api.on( destroyEvent, function ( e, ctx ) {
10013				if ( settings !== ctx ) {
10014					return;
10015				}
10016	
10017				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
10018					if ( data[i]._details ) {
10019						__details_remove( api, i );
10020					}
10021				}
10022			} );
10023		}
10024	};
10025	
10026	// Strings for the method names to help minification
10027	var _emp = '';
10028	var _child_obj = _emp+'row().child';
10029	var _child_mth = _child_obj+'()';
10030	
10031	// data can be:
10032	//  tr
10033	//  string
10034	//  jQuery or array of any of the above
10035	_api_register( _child_mth, function ( data, klass ) {
10036		var ctx = this.context;
10037	
10038		if ( data === undefined ) {
10039			// get
10040			return ctx.length && this.length ?
10041				ctx[0].aoData[ this[0] ]._details :
10042				undefined;
10043		}
10044		else if ( data === true ) {
10045			// show
10046			this.child.show();
10047		}
10048		else if ( data === false ) {
10049			// remove
10050			__details_remove( this );
10051		}
10052		else if ( ctx.length && this.length ) {
10053			// set
10054			__details_add( ctx[0], ctx[0].aoData[ this[0] ], data, klass );
10055		}
10056	
10057		return this;
10058	} );
10059	
10060	
10061	_api_register( [
10062		_child_obj+'.show()',
10063		_child_mth+'.show()' // only when `child()` was called with parameters (without
10064	], function ( show ) {   // it returns an object and this method is not executed)
10065		__details_display( this, true );
10066		return this;
10067	} );
10068	
10069	
10070	_api_register( [
10071		_child_obj+'.hide()',
10072		_child_mth+'.hide()' // only when `child()` was called with parameters (without
10073	], function () {         // it returns an object and this method is not executed)
10074		__details_display( this, false );
10075		return this;
10076	} );
10077	
10078	
10079	_api_register( [
10080		_child_obj+'.remove()',
10081		_child_mth+'.remove()' // only when `child()` was called with parameters (without
10082	], function () {           // it returns an object and this method is not executed)
10083		__details_remove( this );
10084		return this;
10085	} );
10086	
10087	
10088	_api_register( _child_obj+'.isShown()', function () {
10089		var ctx = this.context;
10090	
10091		if ( ctx.length && this.length ) {
10092			// _detailsShown as false or undefined will fall through to return false
10093			return ctx[0].aoData[ this[0] ]._detailsShow || false;
10094		}
10095		return false;
10096	} );
10097	
10098	
10099	
10100	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
10101	 * Columns
10102	 *
10103	 * {integer}           - column index (>=0 count from left, <0 count from right)
10104	 * "{integer}:visIdx"  - visible column index (i.e. translate to column index)  (>=0 count from left, <0 count from right)
10105	 * "{integer}:visible" - alias for {integer}:visIdx  (>=0 count from left, <0 count from right)
10106	 * "{string}:name"     - column name
10107	 * "{string}"          - jQuery selector on column header nodes
10108	 *
10109	 */
10110	
10111	// can be an array of these items, comma separated list, or an array of comma
10112	// separated lists
10113	
10114	var __re_column_selector = /^([^:]+):(name|visIdx|visible)$/;
10115	
10116	
10117	// r1 and r2 are redundant - but it means that the parameters match for the
10118	// iterator callback in columns().data()
10119	var __columnData = function ( settings, column, r1, r2, rows ) {
10120		var a = [];
10121		for ( var row=0, ien=rows.length ; row<ien ; row++ ) {
10122			a.push( _fnGetCellData( settings, rows[row], column ) );
10123		}
10124		return a;
10125	};
10126	
10127	
10128	var __column_selector = function ( settings, selector, opts )
10129	{
10130		var
10131			columns = settings.aoColumns,
10132			names = _pluck( columns, 'sName' ),
10133			nodes = _pluck( columns, 'nTh' );
10134	
10135		var run = function ( s ) {
10136			var selInt = _intVal( s );
10137	
10138			// Selector - all
10139			if ( s === '' ) {
10140				return _range( columns.length );
10141			}
10142	
10143			// Selector - index
10144			if ( selInt !== null ) {
10145				return [ selInt >= 0 ?
10146					selInt : // Count from left
10147					columns.length + selInt // Count from right (+ because its a negative value)
10148				];
10149			}
10150	
10151			// Selector = function
10152			if ( typeof s === 'function' ) {
10153				var rows = _selector_row_indexes( settings, opts );
10154	
10155				return $.map( columns, function (col, idx) {
10156					return s(
10157							idx,
10158							__columnData( settings, idx, 0, 0, rows ),
10159							nodes[ idx ]
10160						) ? idx : null;
10161				} );
10162			}
10163	
10164			// jQuery or string selector
10165			var match = typeof s === 'string' ?
10166				s.match( __re_column_selector ) :
10167				'';
10168	
10169			if ( match ) {
10170				switch( match[2] ) {
10171					case 'visIdx':
10172					case 'visible':
10173						var idx = parseInt( match[1], 10 );
10174						// Visible index given, convert to column index
10175						if ( idx < 0 ) {
10176							// Counting from the right
10177							var visColumns = $.map( columns, function (col,i) {
10178								return col.bVisible ? i : null;
10179							} );
10180							return [ visColumns[ visColumns.length + idx ] ];
10181						}
10182						// Counting from the left
10183						return [ _fnVisibleToColumnIndex( settings, idx ) ];
10184	
10185					case 'name':
10186						// match by name. `names` is column index complete and in order
10187						return $.map( names, function (name, i) {
10188							return name === match[1] ? i : null;
10189						} );
10190	
10191					default:
10192						return [];
10193				}
10194			}
10195	
10196			// Cell in the table body
10197			if ( s.nodeName && s._DT_CellIndex ) {
10198				return [ s._DT_CellIndex.column ];
10199			}
10200	
10201			// jQuery selector on the TH elements for the columns
10202			var jqResult = $( nodes )
10203				.filter( s )
10204				.map( function () {
10205					return $.inArray( this, nodes ); // `nodes` is column index complete and in order
10206				} )
10207				.toArray();
10208	
10209			if ( jqResult.length || ! s.nodeName ) {
10210				return jqResult;
10211			}
10212	
10213			// Otherwise a node which might have a `dt-column` data attribute, or be
10214			// a child or such an element
10215			var host = $(s).closest('*[data-dt-column]');
10216			return host.length ?
10217				[ host.data('dt-column') ] :
10218				[];
10219		};
10220	
10221		return _selector_run( 'column', selector, run, settings, opts );
10222	};
10223	
10224	
10225	var __setColumnVis = function ( settings, column, vis ) {
10226		var
10227			cols = settings.aoColumns,
10228			col  = cols[ column ],
10229			data = settings.aoData,
10230			row, cells, i, ien, tr;
10231	
10232		// Get
10233		if ( vis === undefined ) {
10234			return col.bVisible;
10235		}
10236	
10237		// Set
10238		// No change
10239		if ( col.bVisible === vis ) {
10240			return;
10241		}
10242	
10243		if ( vis ) {
10244			// Insert column
10245			// Need to decide if we should use appendChild or insertBefore
10246			var insertBefore = $.inArray( true, _pluck(cols, 'bVisible'), column+1 );
10247	
10248			for ( i=0, ien=data.length ; i<ien ; i++ ) {
10249				tr = data[i].nTr;
10250				cells = data[i].anCells;
10251	
10252				if ( tr ) {
10253					// insertBefore can act like appendChild if 2nd arg is null
10254					tr.insertBefore( cells[ column ], cells[ insertBefore ] || null );
10255				}
10256			}
10257		}
10258		else {
10259			// Remove column
10260			$( _pluck( settings.aoData, 'anCells', column ) ).detach();
10261		}
10262	
10263		// Common actions
10264		col.bVisible = vis;
10265	};
10266	
10267	
10268	_api_register( 'columns()', function ( selector, opts ) {
10269		// argument shifting
10270		if ( selector === undefined ) {
10271			selector = '';
10272		}
10273		else if ( $.isPlainObject( selector ) ) {
10274			opts = selector;
10275			selector = '';
10276		}
10277	
10278		opts = _selector_opts( opts );
10279	
10280		var inst = this.iterator( 'table', function ( settings ) {
10281			return __column_selector( settings, selector, opts );
10282		}, 1 );
10283	
10284		// Want argument shifting here and in _row_selector?
10285		inst.selector.cols = selector;
10286		inst.selector.opts = opts;
10287	
10288		return inst;
10289	} );
10290	
10291	_api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) {
10292		return this.iterator( 'column', function ( settings, column ) {
10293			return settings.aoColumns[column].nTh;
10294		}, 1 );
10295	} );
10296	
10297	_api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) {
10298		return this.iterator( 'column', function ( settings, column ) {
10299			return settings.aoColumns[column].nTf;
10300		}, 1 );
10301	} );
10302	
10303	_api_registerPlural( 'columns().data()', 'column().data()', function () {
10304		return this.iterator( 'column-rows', __columnData, 1 );
10305	} );
10306	
10307	_api_registerPlural( 'columns().dataSrc()', 'column().dataSrc()', function () {
10308		return this.iterator( 'column', function ( settings, column ) {
10309			return settings.aoColumns[column].mData;
10310		}, 1 );
10311	} );
10312	
10313	_api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) {
10314		return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
10315			return _pluck_order( settings.aoData, rows,
10316				type === 'search' ? '_aFilterData' : '_aSortData', column
10317			);
10318		}, 1 );
10319	} );
10320	
10321	_api_registerPlural( 'columns().nodes()', 'column().nodes()', function () {
10322		return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
10323			return _pluck_order( settings.aoData, rows, 'anCells', column ) ;
10324		}, 1 );
10325	} );
10326	
10327	_api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis, calc ) {
10328		var that = this;
10329		var ret = this.iterator( 'column', function ( settings, column ) {
10330			if ( vis === undefined ) {
10331				return settings.aoColumns[ column ].bVisible;
10332			} // else
10333			__setColumnVis( settings, column, vis );
10334		} );
10335	
10336		// Group the column visibility changes
10337		if ( vis !== undefined ) {
10338			this.iterator( 'table', function ( settings ) {
10339				// Redraw the header after changes
10340				_fnDrawHead( settings, settings.aoHeader );
10341				_fnDrawHead( settings, settings.aoFooter );
10342		
10343				// Update colspan for no records display. Child rows and extensions will use their own
10344				// listeners to do this - only need to update the empty table item here
10345				if ( ! settings.aiDisplay.length ) {
10346					$(settings.nTBody).find('td[colspan]').attr('colspan', _fnVisbleColumns(settings));
10347				}
10348		
10349				_fnSaveState( settings );
10350	
10351				// Second loop once the first is done for events
10352				that.iterator( 'column', function ( settings, column ) {
10353					_fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis, calc] );
10354				} );
10355	
10356				if ( calc === undefined || calc ) {
10357					that.columns.adjust();
10358				}
10359			});
10360		}
10361	
10362		return ret;
10363	} );
10364	
10365	_api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) {
10366		return this.iterator( 'column', function ( settings, column ) {
10367			return type === 'visible' ?
10368				_fnColumnIndexToVisible( settings, column ) :
10369				column;
10370		}, 1 );
10371	} );
10372	
10373	_api_register( 'columns.adjust()', function () {
10374		return this.iterator( 'table', function ( settings ) {
10375			_fnAdjustColumnSizing( settings );
10376		}, 1 );
10377	} );
10378	
10379	_api_register( 'column.index()', function ( type, idx ) {
10380		if ( this.context.length !== 0 ) {
10381			var ctx = this.context[0];
10382	
10383			if ( type === 'fromVisible' || type === 'toData' ) {
10384				return _fnVisibleToColumnIndex( ctx, idx );
10385			}
10386			else if ( type === 'fromData' || type === 'toVisible' ) {
10387				return _fnColumnIndexToVisible( ctx, idx );
10388			}
10389		}
10390	} );
10391	
10392	_api_register( 'column()', function ( selector, opts ) {
10393		return _selector_first( this.columns( selector, opts ) );
10394	} );
10395	
10396	var __cell_selector = function ( settings, selector, opts )
10397	{
10398		var data = settings.aoData;
10399		var rows = _selector_row_indexes( settings, opts );
10400		var cells = _removeEmpty( _pluck_order( data, rows, 'anCells' ) );
10401		var allCells = $(_flatten( [], cells ));
10402		var row;
10403		var columns = settings.aoColumns.length;
10404		var a, i, ien, j, o, host;
10405	
10406		var run = function ( s ) {
10407			var fnSelector = typeof s === 'function';
10408	
10409			if ( s === null || s === undefined || fnSelector ) {
10410				// All cells and function selectors
10411				a = [];
10412	
10413				for ( i=0, ien=rows.length ; i<ien ; i++ ) {
10414					row = rows[i];
10415	
10416					for ( j=0 ; j<columns ; j++ ) {
10417						o = {
10418							row: row,
10419							column: j
10420						};
10421	
10422						if ( fnSelector ) {
10423							// Selector - function
10424							host = data[ row ];
10425	
10426							if ( s( o, _fnGetCellData(settings, row, j), host.anCells ? host.anCells[j] : null ) ) {
10427								a.push( o );
10428							}
10429						}
10430						else {
10431							// Selector - all
10432							a.push( o );
10433						}
10434					}
10435				}
10436	
10437				return a;
10438			}
10439			
10440			// Selector - index
10441			if ( $.isPlainObject( s ) ) {
10442				// Valid cell index and its in the array of selectable rows
10443				return s.column !== undefined && s.row !== undefined && $.inArray( s.row, rows ) !== -1 ?
10444					[s] :
10445					[];
10446			}
10447	
10448			// Selector - jQuery filtered cells
10449			var jqResult = allCells
10450				.filter( s )
10451				.map( function (i, el) {
10452					return { // use a new object, in case someone changes the values
10453						row:    el._DT_CellIndex.row,
10454						column: el._DT_CellIndex.column
10455	 				};
10456				} )
10457				.toArray();
10458	
10459			if ( jqResult.length || ! s.nodeName ) {
10460				return jqResult;
10461			}
10462	
10463			// Otherwise the selector is a node, and there is one last option - the
10464			// element might be a child of an element which has dt-row and dt-column
10465			// data attributes
10466			host = $(s).closest('*[data-dt-row]');
10467			return host.length ?
10468				[ {
10469					row: host.data('dt-row'),
10470					column: host.data('dt-column')
10471				} ] :
10472				[];
10473		};
10474	
10475		return _selector_run( 'cell', selector, run, settings, opts );
10476	};
10477	
10478	
10479	
10480	
10481	_api_register( 'cells()', function ( rowSelector, columnSelector, opts ) {
10482		// Argument shifting
10483		if ( $.isPlainObject( rowSelector ) ) {
10484			// Indexes
10485			if ( rowSelector.row === undefined ) {
10486				// Selector options in first parameter
10487				opts = rowSelector;
10488				rowSelector = null;
10489			}
10490			else {
10491				// Cell index objects in first parameter
10492				opts = columnSelector;
10493				columnSelector = null;
10494			}
10495		}
10496		if ( $.isPlainObject( columnSelector ) ) {
10497			opts = columnSelector;
10498			columnSelector = null;
10499		}
10500	
10501		// Cell selector
10502		if ( columnSelector === null || columnSelector === undefined ) {
10503			return this.iterator( 'table', function ( settings ) {
10504				return __cell_selector( settings, rowSelector, _selector_opts( opts ) );
10505			} );
10506		}
10507	
10508		// The default built in options need to apply to row and columns
10509		var internalOpts = opts ? {
10510			page: opts.page,
10511			order: opts.order,
10512			search: opts.search
10513		} : {};
10514	
10515		// Row + column selector
10516		var columns = this.columns( columnSelector, internalOpts );
10517		var rows = this.rows( rowSelector, internalOpts );
10518		var i, ien, j, jen;
10519	
10520		var cellsNoOpts = this.iterator( 'table', function ( settings, idx ) {
10521			var a = [];
10522	
10523			for ( i=0, ien=rows[idx].length ; i<ien ; i++ ) {
10524				for ( j=0, jen=columns[idx].length ; j<jen ; j++ ) {
10525					a.push( {
10526						row:    rows[idx][i],
10527						column: columns[idx][j]
10528					} );
10529				}
10530			}
10531	
10532			return a;
10533		}, 1 );
10534	
10535		// There is currently only one extension which uses a cell selector extension
10536		// It is a _major_ performance drag to run this if it isn't needed, so this is
10537		// an extension specific check at the moment
10538		var cells = opts && opts.selected ?
10539			this.cells( cellsNoOpts, opts ) :
10540			cellsNoOpts;
10541	
10542		$.extend( cells.selector, {
10543			cols: columnSelector,
10544			rows: rowSelector,
10545			opts: opts
10546		} );
10547	
10548		return cells;
10549	} );
10550	
10551	
10552	_api_registerPlural( 'cells().nodes()', 'cell().node()', function () {
10553		return this.iterator( 'cell', function ( settings, row, column ) {
10554			var data = settings.aoData[ row ];
10555	
10556			return data && data.anCells ?
10557				data.anCells[ column ] :
10558				undefined;
10559		}, 1 );
10560	} );
10561	
10562	
10563	_api_register( 'cells().data()', function () {
10564		return this.iterator( 'cell', function ( settings, row, column ) {
10565			return _fnGetCellData( settings, row, column );
10566		}, 1 );
10567	} );
10568	
10569	
10570	_api_registerPlural( 'cells().cache()', 'cell().cache()', function ( type ) {
10571		type = type === 'search' ? '_aFilterData' : '_aSortData';
10572	
10573		return this.iterator( 'cell', function ( settings, row, column ) {
10574			return settings.aoData[ row ][ type ][ column ];
10575		}, 1 );
10576	} );
10577	
10578	
10579	_api_registerPlural( 'cells().render()', 'cell().render()', function ( type ) {
10580		return this.iterator( 'cell', function ( settings, row, column ) {
10581			return _fnGetCellData( settings, row, column, type );
10582		}, 1 );
10583	} );
10584	
10585	
10586	_api_registerPlural( 'cells().indexes()', 'cell().index()', function () {
10587		return this.iterator( 'cell', function ( settings, row, column ) {
10588			return {
10589				row: row,
10590				column: column,
10591				columnVisible: _fnColumnIndexToVisible( settings, column )
10592			};
10593		}, 1 );
10594	} );
10595	
10596	
10597	_api_registerPlural( 'cells().invalidate()', 'cell().invalidate()', function ( src ) {
10598		return this.iterator( 'cell', function ( settings, row, column ) {
10599			_fnInvalidate( settings, row, src, column );
10600		} );
10601	} );
10602	
10603	
10604	
10605	_api_register( 'cell()', function ( rowSelector, columnSelector, opts ) {
10606		return _selector_first( this.cells( rowSelector, columnSelector, opts ) );
10607	} );
10608	
10609	
10610	_api_register( 'cell().data()', function ( data ) {
10611		var ctx = this.context;
10612		var cell = this[0];
10613	
10614		if ( data === undefined ) {
10615			// Get
10616			return ctx.length && cell.length ?
10617				_fnGetCellData( ctx[0], cell[0].row, cell[0].column ) :
10618				undefined;
10619		}
10620	
10621		// Set
10622		_fnSetCellData( ctx[0], cell[0].row, cell[0].column, data );
10623		_fnInvalidate( ctx[0], cell[0].row, 'data', cell[0].column );
10624	
10625		return this;
10626	} );
10627	
10628	
10629	
10630	/**
10631	 * Get current ordering (sorting) that has been applied to the table.
10632	 *
10633	 * @returns {array} 2D array containing the sorting information for the first
10634	 *   table in the current context. Each element in the parent array represents
10635	 *   a column being sorted upon (i.e. multi-sorting with two columns would have
10636	 *   2 inner arrays). The inner arrays may have 2 or 3 elements. The first is
10637	 *   the column index that the sorting condition applies to, the second is the
10638	 *   direction of the sort (`desc` or `asc`) and, optionally, the third is the
10639	 *   index of the sorting order from the `column.sorting` initialisation array.
10640	 *//**
10641	 * Set the ordering for the table.
10642	 *
10643	 * @param {integer} order Column index to sort upon.
10644	 * @param {string} direction Direction of the sort to be applied (`asc` or `desc`)
10645	 * @returns {DataTables.Api} this
10646	 *//**
10647	 * Set the ordering for the table.
10648	 *
10649	 * @param {array} order 1D array of sorting information to be applied.
10650	 * @param {array} [...] Optional additional sorting conditions
10651	 * @returns {DataTables.Api} this
10652	 *//**
10653	 * Set the ordering for the table.
10654	 *
10655	 * @param {array} order 2D array of sorting information to be applied.
10656	 * @returns {DataTables.Api} this
10657	 */
10658	_api_register( 'order()', function ( order, dir ) {
10659		var ctx = this.context;
10660	
10661		if ( order === undefined ) {
10662			// get
10663			return ctx.length !== 0 ?
10664				ctx[0].aaSorting :
10665				undefined;
10666		}
10667	
10668		// set
10669		if ( typeof order === 'number' ) {
10670			// Simple column / direction passed in
10671			order = [ [ order, dir ] ];
10672		}
10673		else if ( order.length && ! Array.isArray( order[0] ) ) {
10674			// Arguments passed in (list of 1D arrays)
10675			order = Array.prototype.slice.call( arguments );
10676		}
10677		// otherwise a 2D array was passed in
10678	
10679		return this.iterator( 'table', function ( settings ) {
10680			settings.aaSorting = order.slice();
10681		} );
10682	} );
10683	
10684	
10685	/**
10686	 * Attach a sort listener to an element for a given column
10687	 *
10688	 * @param {node|jQuery|string} node Identifier for the element(s) to attach the
10689	 *   listener to. This can take the form of a single DOM node, a jQuery
10690	 *   collection of nodes or a jQuery selector which will identify the node(s).
10691	 * @param {integer} column the column that a click on this node will sort on
10692	 * @param {function} [callback] callback function when sort is run
10693	 * @returns {DataTables.Api} this
10694	 */
10695	_api_register( 'order.listener()', function ( node, column, callback ) {
10696		return this.iterator( 'table', function ( settings ) {
10697			_fnSortAttachListener( settings, node, column, callback );
10698		} );
10699	} );
10700	
10701	
10702	_api_register( 'order.fixed()', function ( set ) {
10703		if ( ! set ) {
10704			var ctx = this.context;
10705			var fixed = ctx.length ?
10706				ctx[0].aaSortingFixed :
10707				undefined;
10708	
10709			return Array.isArray( fixed ) ?
10710				{ pre: fixed } :
10711				fixed;
10712		}
10713	
10714		return this.iterator( 'table', function ( settings ) {
10715			settings.aaSortingFixed = $.extend( true, {}, set );
10716		} );
10717	} );
10718	
10719	
10720	// Order by the selected column(s)
10721	_api_register( [
10722		'columns().order()',
10723		'column().order()'
10724	], function ( dir ) {
10725		var that = this;
10726	
10727		return this.iterator( 'table', function ( settings, i ) {
10728			var sort = [];
10729	
10730			$.each( that[i], function (j, col) {
10731				sort.push( [ col, dir ] );
10732			} );
10733	
10734			settings.aaSorting = sort;
10735		} );
10736	} );
10737	
10738	
10739	
10740	_api_register( 'search()', function ( input, regex, smart, caseInsen ) {
10741		var ctx = this.context;
10742	
10743		if ( input === undefined ) {
10744			// get
10745			return ctx.length !== 0 ?
10746				ctx[0].oPreviousSearch.sSearch :
10747				undefined;
10748		}
10749	
10750		// set
10751		return this.iterator( 'table', function ( settings ) {
10752			if ( ! settings.oFeatures.bFilter ) {
10753				return;
10754			}
10755	
10756			_fnFilterComplete( settings, $.extend( {}, settings.oPreviousSearch, {
10757				"sSearch": input+"",
10758				"bRegex":  regex === null ? false : regex,
10759				"bSmart":  smart === null ? true  : smart,
10760				"bCaseInsensitive": caseInsen === null ? true : caseInsen
10761			} ), 1 );
10762		} );
10763	} );
10764	
10765	
10766	_api_registerPlural(
10767		'columns().search()',
10768		'column().search()',
10769		function ( input, regex, smart, caseInsen ) {
10770			return this.iterator( 'column', function ( settings, column ) {
10771				var preSearch = settings.aoPreSearchCols;
10772	
10773				if ( input === undefined ) {
10774					// get
10775					return preSearch[ column ].sSearch;
10776				}
10777	
10778				// set
10779				if ( ! settings.oFeatures.bFilter ) {
10780					return;
10781				}
10782	
10783				$.extend( preSearch[ column ], {
10784					"sSearch": input+"",
10785					"bRegex":  regex === null ? false : regex,
10786					"bSmart":  smart === null ? true  : smart,
10787					"bCaseInsensitive": caseInsen === null ? true : caseInsen
10788				} );
10789	
10790				_fnFilterComplete( settings, settings.oPreviousSearch, 1 );
10791			} );
10792		}
10793	);
10794	
10795	/*
10796	 * State API methods
10797	 */
10798	
10799	_api_register( 'state()', function () {
10800		return this.context.length ?
10801			this.context[0].oSavedState :
10802			null;
10803	} );
10804	
10805	
10806	_api_register( 'state.clear()', function () {
10807		return this.iterator( 'table', function ( settings ) {
10808			// Save an empty object
10809			settings.fnStateSaveCallback.call( settings.oInstance, settings, {} );
10810		} );
10811	} );
10812	
10813	
10814	_api_register( 'state.loaded()', function () {
10815		return this.context.length ?
10816			this.context[0].oLoadedState :
10817			null;
10818	} );
10819	
10820	
10821	_api_register( 'state.save()', function () {
10822		return this.iterator( 'table', function ( settings ) {
10823			_fnSaveState( settings );
10824		} );
10825	} );
10826	
10827	
10828	
10829	/**
10830	 * Provide a common method for plug-ins to check the version of DataTables being
10831	 * used, in order to ensure compatibility.
10832	 *
10833	 *  @param {string} version Version string to check for, in the format "X.Y.Z".
10834	 *    Note that the formats "X" and "X.Y" are also acceptable.
10835	 *  @returns {boolean} true if this version of DataTables is greater or equal to
10836	 *    the required version, or false if this version of DataTales is not
10837	 *    suitable
10838	 *  @static
10839	 *  @dtopt API-Static
10840	 *
10841	 *  @example
10842	 *    alert( $.fn.dataTable.versionCheck( '1.9.0' ) );
10843	 */
10844	DataTable.versionCheck = DataTable.fnVersionCheck = function( version )
10845	{
10846		var aThis = DataTable.version.split('.');
10847		var aThat = version.split('.');
10848		var iThis, iThat;
10849	
10850		for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) {
10851			iThis = parseInt( aThis[i], 10 ) || 0;
10852			iThat = parseInt( aThat[i], 10 ) || 0;
10853	
10854			// Parts are the same, keep comparing
10855			if (iThis === iThat) {
10856				continue;
10857			}
10858	
10859			// Parts are different, return immediately
10860			return iThis > iThat;
10861		}
10862	
10863		return true;
10864	};
10865	
10866	
10867	/**
10868	 * Check if a `<table>` node is a DataTable table already or not.
10869	 *
10870	 *  @param {node|jquery|string} table Table node, jQuery object or jQuery
10871	 *      selector for the table to test. Note that if more than more than one
10872	 *      table is passed on, only the first will be checked
10873	 *  @returns {boolean} true the table given is a DataTable, or false otherwise
10874	 *  @static
10875	 *  @dtopt API-Static
10876	 *
10877	 *  @example
10878	 *    if ( ! $.fn.DataTable.isDataTable( '#example' ) ) {
10879	 *      $('#example').dataTable();
10880	 *    }
10881	 */
10882	DataTable.isDataTable = DataTable.fnIsDataTable = function ( table )
10883	{
10884		var t = $(table).get(0);
10885		var is = false;
10886	
10887		if ( table instanceof DataTable.Api ) {
10888			return true;
10889		}
10890	
10891		$.each( DataTable.settings, function (i, o) {
10892			var head = o.nScrollHead ? $('table', o.nScrollHead)[0] : null;
10893			var foot = o.nScrollFoot ? $('table', o.nScrollFoot)[0] : null;
10894	
10895			if ( o.nTable === t || head === t || foot === t ) {
10896				is = true;
10897			}
10898		} );
10899	
10900		return is;
10901	};
10902	
10903	
10904	/**
10905	 * Get all DataTable tables that have been initialised - optionally you can
10906	 * select to get only currently visible tables.
10907	 *
10908	 *  @param {boolean} [visible=false] Flag to indicate if you want all (default)
10909	 *    or visible tables only.
10910	 *  @returns {array} Array of `table` nodes (not DataTable instances) which are
10911	 *    DataTables
10912	 *  @static
10913	 *  @dtopt API-Static
10914	 *
10915	 *  @example
10916	 *    $.each( $.fn.dataTable.tables(true), function () {
10917	 *      $(table).DataTable().columns.adjust();
10918	 *    } );
10919	 */
10920	DataTable.tables = DataTable.fnTables = function ( visible )
10921	{
10922		var api = false;
10923	
10924		if ( $.isPlainObject( visible ) ) {
10925			api = visible.api;
10926			visible = visible.visible;
10927		}
10928	
10929		var a = $.map( DataTable.settings, function (o) {
10930			if ( !visible || (visible && $(o.nTable).is(':visible')) ) {
10931				return o.nTable;
10932			}
10933		} );
10934	
10935		return api ?
10936			new _Api( a ) :
10937			a;
10938	};
10939	
10940	
10941	/**
10942	 * Convert from camel case parameters to Hungarian notation. This is made public
10943	 * for the extensions to provide the same ability as DataTables core to accept
10944	 * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase
10945	 * parameters.
10946	 *
10947	 *  @param {object} src The model object which holds all parameters that can be
10948	 *    mapped.
10949	 *  @param {object} user The object to convert from camel case to Hungarian.
10950	 *  @param {boolean} force When set to `true`, properties which already have a
10951	 *    Hungarian value in the `user` object will be overwritten. Otherwise they
10952	 *    won't be.
10953	 */
10954	DataTable.camelToHungarian = _fnCamelToHungarian;
10955	
10956	
10957	
10958	/**
10959	 *
10960	 */
10961	_api_register( '$()', function ( selector, opts ) {
10962		var
10963			rows   = this.rows( opts ).nodes(), // Get all rows
10964			jqRows = $(rows);
10965	
10966		return $( [].concat(
10967			jqRows.filter( selector ).toArray(),
10968			jqRows.find( selector ).toArray()
10969		) );
10970	} );
10971	
10972	
10973	// jQuery functions to operate on the tables
10974	$.each( [ 'on', 'one', 'off' ], function (i, key) {
10975		_api_register( key+'()', function ( /* event, handler */ ) {
10976			var args = Array.prototype.slice.call(arguments);
10977	
10978			// Add the `dt` namespace automatically if it isn't already present
10979			args[0] = $.map( args[0].split( /\s/ ), function ( e ) {
10980				return ! e.match(/\.dt\b/) ?
10981					e+'.dt' :
10982					e;
10983				} ).join( ' ' );
10984	
10985			var inst = $( this.tables().nodes() );
10986			inst[key].apply( inst, args );
10987			return this;
10988		} );
10989	} );
10990	
10991	
10992	_api_register( 'clear()', function () {
10993		return this.iterator( 'table', function ( settings ) {
10994			_fnClearTable( settings );
10995		} );
10996	} );
10997	
10998	
10999	_api_register( 'settings()', function () {
11000		return new _Api( this.context, this.context );
11001	} );
11002	
11003	
11004	_api_register( 'init()', function () {
11005		var ctx = this.context;
11006		return ctx.length ? ctx[0].oInit : null;
11007	} );
11008	
11009	
11010	_api_register( 'data()', function () {
11011		return this.iterator( 'table', function ( settings ) {
11012			return _pluck( settings.aoData, '_aData' );
11013		} ).flatten();
11014	} );
11015	
11016	
11017	_api_register( 'destroy()', function ( remove ) {
11018		remove = remove || false;
11019	
11020		return this.iterator( 'table', function ( settings ) {
11021			var orig      = settings.nTableWrapper.parentNode;
11022			var classes   = settings.oClasses;
11023			var table     = settings.nTable;
11024			var tbody     = settings.nTBody;
11025			var thead     = settings.nTHead;
11026			var tfoot     = settings.nTFoot;
11027			var jqTable   = $(table);
11028			var jqTbody   = $(tbody);
11029			var jqWrapper = $(settings.nTableWrapper);
11030			var rows      = $.map( settings.aoData, function (r) { return r.nTr; } );
11031			var i, ien;
11032	
11033			// Flag to note that the table is currently being destroyed - no action
11034			// should be taken
11035			settings.bDestroying = true;
11036	
11037			// Fire off the destroy callbacks for plug-ins etc
11038			_fnCallbackFire( settings, "aoDestroyCallback", "destroy", [settings] );
11039	
11040			// If not being removed from the document, make all columns visible
11041			if ( ! remove ) {
11042				new _Api( settings ).columns().visible( true );
11043			}
11044	
11045			// Blitz all `DT` namespaced events (these are internal events, the
11046			// lowercase, `dt` events are user subscribed and they are responsible
11047			// for removing them
11048			jqWrapper.off('.DT').find(':not(tbody *)').off('.DT');
11049			$(window).off('.DT-'+settings.sInstance);
11050	
11051			// When scrolling we had to break the table up - restore it
11052			if ( table != thead.parentNode ) {
11053				jqTable.children('thead').detach();
11054				jqTable.append( thead );
11055			}
11056	
11057			if ( tfoot && table != tfoot.parentNode ) {
11058				jqTable.children('tfoot').detach();
11059				jqTable.append( tfoot );
11060			}
11061	
11062			settings.aaSorting = [];
11063			settings.aaSortingFixed = [];
11064			_fnSortingClasses( settings );
11065	
11066			$( rows ).removeClass( settings.asStripeClasses.join(' ') );
11067	
11068			$('th, td', thead).removeClass( classes.sSortable+' '+
11069				classes.sSortableAsc+' '+classes.sSortableDesc+' '+classes.sSortableNone
11070			);
11071	
11072			// Add the TR elements back into the table in their original order
11073			jqTbody.children().detach();
11074			jqTbody.append( rows );
11075	
11076			// Remove the DataTables generated nodes, events and classes
11077			var removedMethod = remove ? 'remove' : 'detach';
11078			jqTable[ removedMethod ]();
11079			jqWrapper[ removedMethod ]();
11080	
11081			// If we need to reattach the table to the document
11082			if ( ! remove && orig ) {
11083				// insertBefore acts like appendChild if !arg[1]
11084				orig.insertBefore( table, settings.nTableReinsertBefore );
11085	
11086				// Restore the width of the original table - was read from the style property,
11087				// so we can restore directly to that
11088				jqTable
11089					.css( 'width', settings.sDestroyWidth )
11090					.removeClass( classes.sTable );
11091	
11092				// If the were originally stripe classes - then we add them back here.
11093				// Note this is not fool proof (for example if not all rows had stripe
11094				// classes - but it's a good effort without getting carried away
11095				ien = settings.asDestroyStripes.length;
11096	
11097				if ( ien ) {
11098					jqTbody.children().each( function (i) {
11099						$(this).addClass( settings.asDestroyStripes[i % ien] );
11100					} );
11101				}
11102			}
11103	
11104			/* Remove the settings object from the settings array */
11105			var idx = $.inArray( settings, DataTable.settings );
11106			if ( idx !== -1 ) {
11107				DataTable.settings.splice( idx, 1 );
11108			}
11109		} );
11110	} );
11111	
11112	
11113	// Add the `every()` method for rows, columns and cells in a compact form
11114	$.each( [ 'column', 'row', 'cell' ], function ( i, type ) {
11115		_api_register( type+'s().every()', function ( fn ) {
11116			var opts = this.selector.opts;
11117			var api = this;
11118	
11119			return this.iterator( type, function ( settings, arg1, arg2, arg3, arg4 ) {
11120				// Rows and columns:
11121				//  arg1 - index
11122				//  arg2 - table counter
11123				//  arg3 - loop counter
11124				//  arg4 - undefined
11125				// Cells:
11126				//  arg1 - row index
11127				//  arg2 - column index
11128				//  arg3 - table counter
11129				//  arg4 - loop counter
11130				fn.call(
11131					api[ type ](
11132						arg1,
11133						type==='cell' ? arg2 : opts,
11134						type==='cell' ? opts : undefined
11135					),
11136					arg1, arg2, arg3, arg4
11137				);
11138			} );
11139		} );
11140	} );
11141	
11142	
11143	// i18n method for extensions to be able to use the language object from the
11144	// DataTable
11145	_api_register( 'i18n()', function ( token, def, plural ) {
11146		var ctx = this.context[0];
11147		var resolved = _fnGetObjectDataFn( token )( ctx.oLanguage );
11148	
11149		if ( resolved === undefined ) {
11150			resolved = def;
11151		}
11152	
11153		if ( plural !== undefined && $.isPlainObject( resolved ) ) {
11154			resolved = resolved[ plural ] !== undefined ?
11155				resolved[ plural ] :
11156				resolved._;
11157		}
11158	
11159		return resolved.replace( '%d', plural ); // nb: plural might be undefined,
11160	} );
11161	/**
11162	 * Version string for plug-ins to check compatibility. Allowed format is
11163	 * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used
11164	 * only for non-release builds. See http://semver.org/ for more information.
11165	 *  @member
11166	 *  @type string
11167	 *  @default Version number
11168	 */
11169	DataTable.version = "1.10.24";
11170
11171	/**
11172	 * Private data store, containing all of the settings objects that are
11173	 * created for the tables on a given page.
11174	 *
11175	 * Note that the `DataTable.settings` object is aliased to
11176	 * `jQuery.fn.dataTableExt` through which it may be accessed and
11177	 * manipulated, or `jQuery.fn.dataTable.settings`.
11178	 *  @member
11179	 *  @type array
11180	 *  @default []
11181	 *  @private
11182	 */
11183	DataTable.settings = [];
11184
11185	/**
11186	 * Object models container, for the various models that DataTables has
11187	 * available to it. These models define the objects that are used to hold
11188	 * the active state and configuration of the table.
11189	 *  @namespace
11190	 */
11191	DataTable.models = {};
11192	
11193	
11194	
11195	/**
11196	 * Template object for the way in which DataTables holds information about
11197	 * search information for the global filter and individual column filters.
11198	 *  @namespace
11199	 */
11200	DataTable.models.oSearch = {
11201		/**
11202		 * Flag to indicate if the filtering should be case insensitive or not
11203		 *  @type boolean
11204		 *  @default true
11205		 */
11206		"bCaseInsensitive": true,
11207	
11208		/**
11209		 * Applied search term
11210		 *  @type string
11211		 *  @default <i>Empty string</i>
11212		 */
11213		"sSearch": "",
11214	
11215		/**
11216		 * Flag to indicate if the search term should be interpreted as a
11217		 * regular expression (true) or not (false) and therefore and special
11218		 * regex characters escaped.
11219		 *  @type boolean
11220		 *  @default false
11221		 */
11222		"bRegex": false,
11223	
11224		/**
11225		 * Flag to indicate if DataTables is to use its smart filtering or not.
11226		 *  @type boolean
11227		 *  @default true
11228		 */
11229		"bSmart": true
11230	};
11231	
11232	
11233	
11234	
11235	/**
11236	 * Template object for the way in which DataTables holds information about
11237	 * each individual row. This is the object format used for the settings
11238	 * aoData array.
11239	 *  @namespace
11240	 */
11241	DataTable.models.oRow = {
11242		/**
11243		 * TR element for the row
11244		 *  @type node
11245		 *  @default null
11246		 */
11247		"nTr": null,
11248	
11249		/**
11250		 * Array of TD elements for each row. This is null until the row has been
11251		 * created.
11252		 *  @type array nodes
11253		 *  @default []
11254		 */
11255		"anCells": null,
11256	
11257		/**
11258		 * Data object from the original data source for the row. This is either
11259		 * an array if using the traditional form of DataTables, or an object if
11260		 * using mData options. The exact type will depend on the passed in
11261		 * data from the data source, or will be an array if using DOM a data
11262		 * source.
11263		 *  @type array|object
11264		 *  @default []
11265		 */
11266		"_aData": [],
11267	
11268		/**
11269		 * Sorting data cache - this array is ostensibly the same length as the
11270		 * number of columns (although each index is generated only as it is
11271		 * needed), and holds the data that is used for sorting each column in the
11272		 * row. We do this cache generation at the start of the sort in order that
11273		 * the formatting of the sort data need be done only once for each cell
11274		 * per sort. This array should not be read from or written to by anything
11275		 * other than the master sorting methods.
11276		 *  @type array
11277		 *  @default null
11278		 *  @private
11279		 */
11280		"_aSortData": null,
11281	
11282		/**
11283		 * Per cell filtering data cache. As per the sort data cache, used to
11284		 * increase the performance of the filtering in DataTables
11285		 *  @type array
11286		 *  @default null
11287		 *  @private
11288		 */
11289		"_aFilterData": null,
11290	
11291		/**
11292		 * Filtering data cache. This is the same as the cell filtering cache, but
11293		 * in this case a string rather than an array. This is easily computed with
11294		 * a join on `_aFilterData`, but is provided as a cache so the join isn't
11295		 * needed on every search (memory traded for performance)
11296		 *  @type array
11297		 *  @default null
11298		 *  @private
11299		 */
11300		"_sFilterRow": null,
11301	
11302		/**
11303		 * Cache of the class name that DataTables has applied to the row, so we
11304		 * can quickly look at this variable rather than needing to do a DOM check
11305		 * on className for the nTr property.
11306		 *  @type string
11307		 *  @default <i>Empty string</i>
11308		 *  @private
11309		 */
11310		"_sRowStripe": "",
11311	
11312		/**
11313		 * Denote if the original data source was from the DOM, or the data source
11314		 * object. This is used for invalidating data, so DataTables can
11315		 * automatically read data from the original source, unless uninstructed
11316		 * otherwise.
11317		 *  @type string
11318		 *  @default null
11319		 *  @private
11320		 */
11321		"src": null,
11322	
11323		/**
11324		 * Index in the aoData array. This saves an indexOf lookup when we have the
11325		 * object, but want to know the index
11326		 *  @type integer
11327		 *  @default -1
11328		 *  @private
11329		 */
11330		"idx": -1
11331	};
11332	
11333	
11334	/**
11335	 * Template object for the column information object in DataTables. This object
11336	 * is held in the settings aoColumns array and contains all the information that
11337	 * DataTables needs about each individual column.
11338	 *
11339	 * Note that this object is related to {@link DataTable.defaults.column}
11340	 * but this one is the internal data store for DataTables's cache of columns.
11341	 * It should NOT be manipulated outside of DataTables. Any configuration should
11342	 * be done through the initialisation options.
11343	 *  @namespace
11344	 */
11345	DataTable.models.oColumn = {
11346		/**
11347		 * Column index. This could be worked out on-the-fly with $.inArray, but it
11348		 * is faster to just hold it as a variable
11349		 *  @type integer
11350		 *  @default null
11351		 */
11352		"idx": null,
11353	
11354		/**
11355		 * A list of the columns that sorting should occur on when this column
11356		 * is sorted. That this property is an array allows multi-column sorting
11357		 * to be defined for a column (for example first name / last name columns
11358		 * would benefit from this). The values are integers pointing to the
11359		 * columns to be sorted on (typically it will be a single integer pointing
11360		 * at itself, but that doesn't need to be the case).
11361		 *  @type array
11362		 */
11363		"aDataSort": null,
11364	
11365		/**
11366		 * Define the sorting directions that are applied to the column, in sequence
11367		 * as the column is repeatedly sorted upon - i.e. the first value is used
11368		 * as the sorting direction when the column if first sorted (clicked on).
11369		 * Sort it again (click again) and it will move on to the next index.
11370		 * Repeat until loop.
11371		 *  @type array
11372		 */
11373		"asSorting": null,
11374	
11375		/**
11376		 * Flag to indicate if the column is searchable, and thus should be included
11377		 * in the filtering or not.
11378		 *  @type boolean
11379		 */
11380		"bSearchable": null,
11381	
11382		/**
11383		 * Flag to indicate if the column is sortable or not.
11384		 *  @type boolean
11385		 */
11386		"bSortable": null,
11387	
11388		/**
11389		 * Flag to indicate if the column is currently visible in the table or not
11390		 *  @type boolean
11391		 */
11392		"bVisible": null,
11393	
11394		/**
11395		 * Store for manual type assignment using the `column.type` option. This
11396		 * is held in store so we can manipulate the column's `sType` property.
11397		 *  @type string
11398		 *  @default null
11399		 *  @private
11400		 */
11401		"_sManualType": null,
11402	
11403		/**
11404		 * Flag to indicate if HTML5 data attributes should be used as the data
11405		 * source for filtering or sorting. True is either are.
11406		 *  @type boolean
11407		 *  @default false
11408		 *  @private
11409		 */
11410		"_bAttrSrc": false,
11411	
11412		/**
11413		 * Developer definable function that is called whenever a cell is created (Ajax source,
11414		 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
11415		 * allowing you to modify the DOM element (add background colour for example) when the
11416		 * element is available.
11417		 *  @type function
11418		 *  @param {element} nTd The TD node that has been created
11419		 *  @param {*} sData The Data for the cell
11420		 *  @param {array|object} oData The data for the whole row
11421		 *  @param {int} iRow The row index for the aoData data store
11422		 *  @default null
11423		 */
11424		"fnCreatedCell": null,
11425	
11426		/**
11427		 * Function to get data from a cell in a column. You should <b>never</b>
11428		 * access data directly through _aData internally in DataTables - always use
11429		 * the method attached to this property. It allows mData to function as
11430		 * required. This function is automatically assigned by the column
11431		 * initialisation method
11432		 *  @type function
11433		 *  @param {array|object} oData The data array/object for the array
11434		 *    (i.e. aoData[]._aData)
11435		 *  @param {string} sSpecific The specific data type you want to get -
11436		 *    'display', 'type' 'filter' 'sort'
11437		 *  @returns {*} The data for the cell from the given row's data
11438		 *  @default null
11439		 */
11440		"fnGetData": null,
11441	
11442		/**
11443		 * Function to set data for a cell in the column. You should <b>never</b>
11444		 * set the data directly to _aData internally in DataTables - always use
11445		 * this method. It allows mData to function as required. This function
11446		 * is automatically assigned by the column initialisation method
11447		 *  @type function
11448		 *  @param {array|object} oData The data array/object for the array
11449		 *    (i.e. aoData[]._aData)
11450		 *  @param {*} sValue Value to set
11451		 *  @default null
11452		 */
11453		"fnSetData": null,
11454	
11455		/**
11456		 * Property to read the value for the cells in the column from the data
11457		 * source array / object. If null, then the default content is used, if a
11458		 * function is given then the return from the function is used.
11459		 *  @type function|int|string|null
11460		 *  @default null
11461		 */
11462		"mData": null,
11463	
11464		/**
11465		 * Partner property to mData which is used (only when defined) to get
11466		 * the data - i.e. it is basically the same as mData, but without the
11467		 * 'set' option, and also the data fed to it is the result from mData.
11468		 * This is the rendering method to match the data method of mData.
11469		 *  @type function|int|string|null
11470		 *  @default null
11471		 */
11472		"mRender": null,
11473	
11474		/**
11475		 * Unique header TH/TD element for this column - this is what the sorting
11476		 * listener is attached to (if sorting is enabled.)
11477		 *  @type node
11478		 *  @default null
11479		 */
11480		"nTh": null,
11481	
11482		/**
11483		 * Unique footer TH/TD element for this column (if there is one). Not used
11484		 * in DataTables as such, but can be used for plug-ins to reference the
11485		 * footer for each column.
11486		 *  @type node
11487		 *  @default null
11488		 */
11489		"nTf": null,
11490	
11491		/**
11492		 * The class to apply to all TD elements in the table's TBODY for the column
11493		 *  @type string
11494		 *  @default null
11495		 */
11496		"sClass": null,
11497	
11498		/**
11499		 * When DataTables calculates the column widths to assign to each column,
11500		 * it finds the longest string in each column and then constructs a
11501		 * temporary table and reads the widths from that. The problem with this
11502		 * is that "mmm" is much wider then "iiii", but the latter is a longer
11503		 * string - thus the calculation can go wrong (doing it properly and putting
11504		 * it into an DOM object and measuring that is horribly(!) slow). Thus as
11505		 * a "work around" we provide this option. It will append its value to the
11506		 * text that is found to be the longest string for the column - i.e. padding.
11507		 *  @type string
11508		 */
11509		"sContentPadding": null,
11510	
11511		/**
11512		 * Allows a default value to be given for a column's data, and will be used
11513		 * whenever a null data source is encountered (this can be because mData
11514		 * is set to null, or because the data source itself is null).
11515		 *  @type string
11516		 *  @default null
11517		 */
11518		"sDefaultContent": null,
11519	
11520		/**
11521		 * Name for the column, allowing reference to the column by name as well as
11522		 * by index (needs a lookup to work by name).
11523		 *  @type string
11524		 */
11525		"sName": null,
11526	
11527		/**
11528		 * Custom sorting data type - defines which of the available plug-ins in
11529		 * afnSortData the custom sorting will use - if any is defined.
11530		 *  @type string
11531		 *  @default std
11532		 */
11533		"sSortDataType": 'std',
11534	
11535		/**
11536		 * Class to be applied to the header element when sorting on this column
11537		 *  @type string
11538		 *  @default null
11539		 */
11540		"sSortingClass": null,
11541	
11542		/**
11543		 * Class to be applied to the header element when sorting on this column -
11544		 * when jQuery UI theming is used.
11545		 *  @type string
11546		 *  @default null
11547		 */
11548		"sSortingClassJUI": null,
11549	
11550		/**
11551		 * Title of the column - what is seen in the TH element (nTh).
11552		 *  @type string
11553		 */
11554		"sTitle": null,
11555	
11556		/**
11557		 * Column sorting and filtering type
11558		 *  @type string
11559		 *  @default null
11560		 */
11561		"sType": null,
11562	
11563		/**
11564		 * Width of the column
11565		 *  @type string
11566		 *  @default null
11567		 */
11568		"sWidth": null,
11569	
11570		/**
11571		 * Width of the column when it was first "encountered"
11572		 *  @type string
11573		 *  @default null
11574		 */
11575		"sWidthOrig": null
11576	};
11577	
11578	
11579	/*
11580	 * Developer note: The properties of the object below are given in Hungarian
11581	 * notation, that was used as the interface for DataTables prior to v1.10, however
11582	 * from v1.10 onwards the primary interface is camel case. In order to avoid
11583	 * breaking backwards compatibility utterly with this change, the Hungarian
11584	 * version is still, internally the primary interface, but is is not documented
11585	 * - hence the @name tags in each doc comment. This allows a Javascript function
11586	 * to create a map from Hungarian notation to camel case (going the other direction
11587	 * would require each property to be listed, which would add around 3K to the size
11588	 * of DataTables, while this method is about a 0.5K hit).
11589	 *
11590	 * Ultimately this does pave the way for Hungarian notation to be dropped
11591	 * completely, but that is a massive amount of work and will break current
11592	 * installs (therefore is on-hold until v2).
11593	 */
11594	
11595	/**
11596	 * Initialisation options that can be given to DataTables at initialisation
11597	 * time.
11598	 *  @namespace
11599	 */
11600	DataTable.defaults = {
11601		/**
11602		 * An array of data to use for the table, passed in at initialisation which
11603		 * will be used in preference to any data which is already in the DOM. This is
11604		 * particularly useful for constructing tables purely in Javascript, for
11605		 * example with a custom Ajax call.
11606		 *  @type array
11607		 *  @default null
11608		 *
11609		 *  @dtopt Option
11610		 *  @name DataTable.defaults.data
11611		 *
11612		 *  @example
11613		 *    // Using a 2D array data source
11614		 *    $(document).ready( function () {
11615		 *      $('#example').dataTable( {
11616		 *        "data": [
11617		 *          ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
11618		 *          ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
11619		 *        ],
11620		 *        "columns": [
11621		 *          { "title": "Engine" },
11622		 *          { "title": "Browser" },
11623		 *          { "title": "Platform" },
11624		 *          { "title": "Version" },
11625		 *          { "title": "Grade" }
11626		 *        ]
11627		 *      } );
11628		 *    } );
11629		 *
11630		 *  @example
11631		 *    // Using an array of objects as a data source (`data`)
11632		 *    $(document).ready( function () {
11633		 *      $('#example').dataTable( {
11634		 *        "data": [
11635		 *          {
11636		 *            "engine":   "Trident",
11637		 *            "browser":  "Internet Explorer 4.0",
11638		 *            "platform": "Win 95+",
11639		 *            "version":  4,
11640		 *            "grade":    "X"
11641		 *          },
11642		 *          {
11643		 *            "engine":   "Trident",
11644		 *            "browser":  "Internet Explorer 5.0",
11645		 *            "platform": "Win 95+",
11646		 *            "version":  5,
11647		 *            "grade":    "C"
11648		 *          }
11649		 *        ],
11650		 *        "columns": [
11651		 *          { "title": "Engine",   "data": "engine" },
11652		 *          { "title": "Browser",  "data": "browser" },
11653		 *          { "title": "Platform", "data": "platform" },
11654		 *          { "title": "Version",  "data": "version" },
11655		 *          { "title": "Grade",    "data": "grade" }
11656		 *        ]
11657		 *      } );
11658		 *    } );
11659		 */
11660		"aaData": null,
11661	
11662	
11663		/**
11664		 * If ordering is enabled, then DataTables will perform a first pass sort on
11665		 * initialisation. You can define which column(s) the sort is performed
11666		 * upon, and the sorting direction, with this variable. The `sorting` array
11667		 * should contain an array for each column to be sorted initially containing
11668		 * the column's index and a direction string ('asc' or 'desc').
11669		 *  @type array
11670		 *  @default [[0,'asc']]
11671		 *
11672		 *  @dtopt Option
11673		 *  @name DataTable.defaults.order
11674		 *
11675		 *  @example
11676		 *    // Sort by 3rd column first, and then 4th column
11677		 *    $(document).ready( function() {
11678		 *      $('#example').dataTable( {
11679		 *        "order": [[2,'asc'], [3,'desc']]
11680		 *      } );
11681		 *    } );
11682		 *
11683		 *    // No initial sorting
11684		 *    $(document).ready( function() {
11685		 *      $('#example').dataTable( {
11686		 *        "order": []
11687		 *      } );
11688		 *    } );
11689		 */
11690		"aaSorting": [[0,'asc']],
11691	
11692	
11693		/**
11694		 * This parameter is basically identical to the `sorting` parameter, but
11695		 * cannot be overridden by user interaction with the table. What this means
11696		 * is that you could have a column (visible or hidden) which the sorting
11697		 * will always be forced on first - any sorting after that (from the user)
11698		 * will then be performed as required. This can be useful for grouping rows
11699		 * together.
11700		 *  @type array
11701		 *  @default null
11702		 *
11703		 *  @dtopt Option
11704		 *  @name DataTable.defaults.orderFixed
11705		 *
11706		 *  @example
11707		 *    $(document).ready( function() {
11708		 *      $('#example').dataTable( {
11709		 *        "orderFixed": [[0,'asc']]
11710		 *      } );
11711		 *    } )
11712		 */
11713		"aaSortingFixed": [],
11714	
11715	
11716		/**
11717		 * DataTables can be instructed to load data to display in the table from a
11718		 * Ajax source. This option defines how that Ajax call is made and where to.
11719		 *
11720		 * The `ajax` property has three different modes of operation, depending on
11721		 * how it is defined. These are:
11722		 *
11723		 * * `string` - Set the URL from where the data should be loaded from.
11724		 * * `object` - Define properties for `jQuery.ajax`.
11725		 * * `function` - Custom data get function
11726		 *
11727		 * `string`
11728		 * --------
11729		 *
11730		 * As a string, the `ajax` property simply defines the URL from which
11731		 * DataTables will load data.
11732		 *
11733		 * `object`
11734		 * --------
11735		 *
11736		 * As an object, the parameters in the object are passed to
11737		 * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control
11738		 * of the Ajax request. DataTables has a number of default parameters which
11739		 * you can override using this option. Please refer to the jQuery
11740		 * documentation for a full description of the options available, although
11741		 * the following parameters provide additional options in DataTables or
11742		 * require special consideration:
11743		 *
11744		 * * `data` - As with jQuery, `data` can be provided as an object, but it
11745		 *   can also be used as a function to manipulate the data DataTables sends
11746		 *   to the server. The function takes a single parameter, an object of
11747		 *   parameters with the values that DataTables has readied for sending. An
11748		 *   object may be returned which will be merged into the DataTables
11749		 *   defaults, or you can add the items to the object that was passed in and
11750		 *   not return anything from the function. This supersedes `fnServerParams`
11751		 *   from DataTables 1.9-.
11752		 *
11753		 * * `dataSrc` - By default DataTables will look for the property `data` (or
11754		 *   `aaData` for compatibility with DataTables 1.9-) when obtaining data
11755		 *   from an Ajax source or for server-side processing - this parameter
11756		 *   allows that property to be changed. You can use Javascript dotted
11757		 *   object notation to get a data source for multiple levels of nesting, or
11758		 *   it my be used as a function. As a function it takes a single parameter,
11759		 *   the JSON returned from the server, which can be manipulated as
11760		 *   required, with the returned value being that used by DataTables as the
11761		 *   data source for the table. This supersedes `sAjaxDataProp` from
11762		 *   DataTables 1.9-.
11763		 *
11764		 * * `success` - Should not be overridden it is used internally in
11765		 *   DataTables. To manipulate / transform the data returned by the server
11766		 *   use `ajax.dataSrc`, or use `ajax` as a function (see below).
11767		 *
11768		 * `function`
11769		 * ----------
11770		 *
11771		 * As a function, making the Ajax call is left up to yourself allowing
11772		 * complete control of the Ajax request. Indeed, if desired, a method other
11773		 * than Ajax could be used to obtain the required data, such as Web storage
11774		 * or an AIR database.
11775		 *
11776		 * The function is given four parameters and no return is required. The
11777		 * parameters are:
11778		 *
11779		 * 1. _object_ - Data to send to the server
11780		 * 2. _function_ - Callback function that must be executed when the required
11781		 *    data has been obtained. That data should be passed into the callback
11782		 *    as the only parameter
11783		 * 3. _object_ - DataTables settings object for the table
11784		 *
11785		 * Note that this supersedes `fnServerData` from DataTables 1.9-.
11786		 *
11787		 *  @type string|object|function
11788		 *  @default null
11789		 *
11790		 *  @dtopt Option
11791		 *  @name DataTable.defaults.ajax
11792		 *  @since 1.10.0
11793		 *
11794		 * @example
11795		 *   // Get JSON data from a file via Ajax.
11796		 *   // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default).
11797		 *   $('#example').dataTable( {
11798		 *     "ajax": "data.json"
11799		 *   } );
11800		 *
11801		 * @example
11802		 *   // Get JSON data from a file via Ajax, using `dataSrc` to change
11803		 *   // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`)
11804		 *   $('#example').dataTable( {
11805		 *     "ajax": {
11806		 *       "url": "data.json",
11807		 *       "dataSrc": "tableData"
11808		 *     }
11809		 *   } );
11810		 *
11811		 * @example
11812		 *   // Get JSON data from a file via Ajax, using `dataSrc` to read data
11813		 *   // from a plain array rather than an array in an object
11814		 *   $('#example').dataTable( {
11815		 *     "ajax": {
11816		 *       "url": "data.json",
11817		 *       "dataSrc": ""
11818		 *     }
11819		 *   } );
11820		 *
11821		 * @example
11822		 *   // Manipulate the data returned from the server - add a link to data
11823		 *   // (note this can, should, be done using `render` for the column - this
11824		 *   // is just a simple example of how the data can be manipulated).
11825		 *   $('#example').dataTable( {
11826		 *     "ajax": {
11827		 *       "url": "data.json",
11828		 *       "dataSrc": function ( json ) {
11829		 *         for ( var i=0, ien=json.length ; i<ien ; i++ ) {
11830		 *           json[i][0] = '<a href="/message/'+json[i][0]+'>View message</a>';
11831		 *         }
11832		 *         return json;
11833		 *       }
11834		 *     }
11835		 *   } );
11836		 *
11837		 * @example
11838		 *   // Add data to the request
11839		 *   $('#example').dataTable( {
11840		 *     "ajax": {
11841		 *       "url": "data.json",
11842		 *       "data": function ( d ) {
11843		 *         return {
11844		 *           "extra_search": $('#extra').val()
11845		 *         };
11846		 *       }
11847		 *     }
11848		 *   } );
11849		 *
11850		 * @example
11851		 *   // Send request as POST
11852		 *   $('#example').dataTable( {
11853		 *     "ajax": {
11854		 *       "url": "data.json",
11855		 *       "type": "POST"
11856		 *     }
11857		 *   } );
11858		 *
11859		 * @example
11860		 *   // Get the data from localStorage (could interface with a form for
11861		 *   // adding, editing and removing rows).
11862		 *   $('#example').dataTable( {
11863		 *     "ajax": function (data, callback, settings) {
11864		 *       callback(
11865		 *         JSON.parse( localStorage.getItem('dataTablesData') )
11866		 *       );
11867		 *     }
11868		 *   } );
11869		 */
11870		"ajax": null,
11871	
11872	
11873		/**
11874		 * This parameter allows you to readily specify the entries in the length drop
11875		 * down menu that DataTables shows when pagination is enabled. It can be
11876		 * either a 1D array of options which will be used for both the displayed
11877		 * option and the value, or a 2D array which will use the array in the first
11878		 * position as the value, and the array in the second position as the
11879		 * displayed options (useful for language strings such as 'All').
11880		 *
11881		 * Note that the `pageLength` property will be automatically set to the
11882		 * first value given in this array, unless `pageLength` is also provided.
11883		 *  @type array
11884		 *  @default [ 10, 25, 50, 100 ]
11885		 *
11886		 *  @dtopt Option
11887		 *  @name DataTable.defaults.lengthMenu
11888		 *
11889		 *  @example
11890		 *    $(document).ready( function() {
11891		 *      $('#example').dataTable( {
11892		 *        "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
11893		 *      } );
11894		 *    } );
11895		 */
11896		"aLengthMenu": [ 10, 25, 50, 100 ],
11897	
11898	
11899		/**
11900		 * The `columns` option in the initialisation parameter allows you to define
11901		 * details about the way individual columns behave. For a full list of
11902		 * column options that can be set, please see
11903		 * {@link DataTable.defaults.column}. Note that if you use `columns` to
11904		 * define your columns, you must have an entry in the array for every single
11905		 * column that you have in your table (these can be null if you don't which
11906		 * to specify any options).
11907		 *  @member
11908		 *
11909		 *  @name DataTable.defaults.column
11910		 */
11911		"aoColumns": null,
11912	
11913		/**
11914		 * Very similar to `columns`, `columnDefs` allows you to target a specific
11915		 * column, multiple columns, or all columns, using the `targets` property of
11916		 * each object in the array. This allows great flexibility when creating
11917		 * tables, as the `columnDefs` arrays can be of any length, targeting the
11918		 * columns you specifically want. `columnDefs` may use any of the column
11919		 * options available: {@link DataTable.defaults.column}, but it _must_
11920		 * have `targets` defined in each object in the array. Values in the `targets`
11921		 * array may be:
11922		 *   <ul>
11923		 *     <li>a string - class name will be matched on the TH for the column</li>
11924		 *     <li>0 or a positive integer - column index counting from the left</li>
11925		 *     <li>a negative integer - column index counting from the right</li>
11926		 *     <li>the string "_all" - all columns (i.e. assign a default)</li>
11927		 *   </ul>
11928		 *  @member
11929		 *
11930		 *  @name DataTable.defaults.columnDefs
11931		 */
11932		"aoColumnDefs": null,
11933	
11934	
11935		/**
11936		 * Basically the same as `search`, this parameter defines the individual column
11937		 * filtering state at initialisation time. The array must be of the same size
11938		 * as the number of columns, and each element be an object with the parameters
11939		 * `search` and `escapeRegex` (the latter is optional). 'null' is also
11940		 * accepted and the default will be used.
11941		 *  @type array
11942		 *  @default []
11943		 *
11944		 *  @dtopt Option
11945		 *  @name DataTable.defaults.searchCols
11946		 *
11947		 *  @example
11948		 *    $(document).ready( function() {
11949		 *      $('#example').dataTable( {
11950		 *        "searchCols": [
11951		 *          null,
11952		 *          { "search": "My filter" },
11953		 *          null,
11954		 *          { "search": "^[0-9]", "escapeRegex": false }
11955		 *        ]
11956		 *      } );
11957		 *    } )
11958		 */
11959		"aoSearchCols": [],
11960	
11961	
11962		/**
11963		 * An array of CSS classes that should be applied to displayed rows. This
11964		 * array may be of any length, and DataTables will apply each class
11965		 * sequentially, looping when required.
11966		 *  @type array
11967		 *  @default null <i>Will take the values determined by the `oClasses.stripe*`
11968		 *    options</i>
11969		 *
11970		 *  @dtopt Option
11971		 *  @name DataTable.defaults.stripeClasses
11972		 *
11973		 *  @example
11974		 *    $(document).ready( function() {
11975		 *      $('#example').dataTable( {
11976		 *        "stripeClasses": [ 'strip1', 'strip2', 'strip3' ]
11977		 *      } );
11978		 *    } )
11979		 */
11980		"asStripeClasses": null,
11981	
11982	
11983		/**
11984		 * Enable or disable automatic column width calculation. This can be disabled
11985		 * as an optimisation (it takes some time to calculate the widths) if the
11986		 * tables widths are passed in using `columns`.
11987		 *  @type boolean
11988		 *  @default true
11989		 *
11990		 *  @dtopt Features
11991		 *  @name DataTable.defaults.autoWidth
11992		 *
11993		 *  @example
11994		 *    $(document).ready( function () {
11995		 *      $('#example').dataTable( {
11996		 *        "autoWidth": false
11997		 *      } );
11998		 *    } );
11999		 */
12000		"bAutoWidth": true,
12001	
12002	
12003		/**
12004		 * Deferred rendering can provide DataTables with a huge speed boost when you
12005		 * are using an Ajax or JS data source for the table. This option, when set to
12006		 * true, will cause DataTables to defer the creation of the table elements for
12007		 * each row until they are needed for a draw - saving a significant amount of
12008		 * time.
12009		 *  @type boolean
12010		 *  @default false
12011		 *
12012		 *  @dtopt Features
12013		 *  @name DataTable.defaults.deferRender
12014		 *
12015		 *  @example
12016		 *    $(document).ready( function() {
12017		 *      $('#example').dataTable( {
12018		 *        "ajax": "sources/arrays.txt",
12019		 *        "deferRender": true
12020		 *      } );
12021		 *    } );
12022		 */
12023		"bDeferRender": false,
12024	
12025	
12026		/**
12027		 * Replace a DataTable which matches the given selector and replace it with
12028		 * one which has the properties of the new initialisation object passed. If no
12029		 * table matches the selector, then the new DataTable will be constructed as
12030		 * per normal.
12031		 *  @type boolean
12032		 *  @default false
12033		 *
12034		 *  @dtopt Options
12035		 *  @name DataTable.defaults.destroy
12036		 *
12037		 *  @example
12038		 *    $(document).ready( function() {
12039		 *      $('#example').dataTable( {
12040		 *        "srollY": "200px",
12041		 *        "paginate": false
12042		 *      } );
12043		 *
12044		 *      // Some time later....
12045		 *      $('#example').dataTable( {
12046		 *        "filter": false,
12047		 *        "destroy": true
12048		 *      } );
12049		 *    } );
12050		 */
12051		"bDestroy": false,
12052	
12053	
12054		/**
12055		 * Enable or disable filtering of data. Filtering in DataTables is "smart" in
12056		 * that it allows the end user to input multiple words (space separated) and
12057		 * will match a row containing those words, even if not in the order that was
12058		 * specified (this allow matching across multiple columns). Note that if you
12059		 * wish to use filtering in DataTables this must remain 'true' - to remove the
12060		 * default filtering input box and retain filtering abilities, please use
12061		 * {@link DataTable.defaults.dom}.
12062		 *  @type boolean
12063		 *  @default true
12064		 *
12065		 *  @dtopt Features
12066		 *  @name DataTable.defaults.searching
12067		 *
12068		 *  @example
12069		 *    $(document).ready( function () {
12070		 *      $('#example').dataTable( {
12071		 *        "searching": false
12072		 *      } );
12073		 *    } );
12074		 */
12075		"bFilter": true,
12076	
12077	
12078		/**
12079		 * Enable or disable the table information display. This shows information
12080		 * about the data that is currently visible on the page, including information
12081		 * about filtered data if that action is being performed.
12082		 *  @type boolean
12083		 *  @default true
12084		 *
12085		 *  @dtopt Features
12086		 *  @name DataTable.defaults.info
12087		 *
12088		 *  @example
12089		 *    $(document).ready( function () {
12090		 *      $('#example').dataTable( {
12091		 *        "info": false
12092		 *      } );
12093		 *    } );
12094		 */
12095		"bInfo": true,
12096	
12097	
12098		/**
12099		 * Allows the end user to select the size of a formatted page from a select
12100		 * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`).
12101		 *  @type boolean
12102		 *  @default true
12103		 *
12104		 *  @dtopt Features
12105		 *  @name DataTable.defaults.lengthChange
12106		 *
12107		 *  @example
12108		 *    $(document).ready( function () {
12109		 *      $('#example').dataTable( {
12110		 *        "lengthChange": false
12111		 *      } );
12112		 *    } );
12113		 */
12114		"bLengthChange": true,
12115	
12116	
12117		/**
12118		 * Enable or disable pagination.
12119		 *  @type boolean
12120		 *  @default true
12121		 *
12122		 *  @dtopt Features
12123		 *  @name DataTable.defaults.paging
12124		 *
12125		 *  @example
12126		 *    $(document).ready( function () {
12127		 *      $('#example').dataTable( {
12128		 *        "paging": false
12129		 *      } );
12130		 *    } );
12131		 */
12132		"bPaginate": true,
12133	
12134	
12135		/**
12136		 * Enable or disable the display of a 'processing' indicator when the table is
12137		 * being processed (e.g. a sort). This is particularly useful for tables with
12138		 * large amounts of data where it can take a noticeable amount of time to sort
12139		 * the entries.
12140		 *  @type boolean
12141		 *  @default false
12142		 *
12143		 *  @dtopt Features
12144		 *  @name DataTable.defaults.processing
12145		 *
12146		 *  @example
12147		 *    $(document).ready( function () {
12148		 *      $('#example').dataTable( {
12149		 *        "processing": true
12150		 *      } );
12151		 *    } );
12152		 */
12153		"bProcessing": false,
12154	
12155	
12156		/**
12157		 * Retrieve the DataTables object for the given selector. Note that if the
12158		 * table has already been initialised, this parameter will cause DataTables
12159		 * to simply return the object that has already been set up - it will not take
12160		 * account of any changes you might have made to the initialisation object
12161		 * passed to DataTables (setting this parameter to true is an acknowledgement
12162		 * that you understand this). `destroy` can be used to reinitialise a table if
12163		 * you need.
12164		 *  @type boolean
12165		 *  @default false
12166		 *
12167		 *  @dtopt Options
12168		 *  @name DataTable.defaults.retrieve
12169		 *
12170		 *  @example
12171		 *    $(document).ready( function() {
12172		 *      initTable();
12173		 *      tableActions();
12174		 *    } );
12175		 *
12176		 *    function initTable ()
12177		 *    {
12178		 *      return $('#example').dataTable( {
12179		 *        "scrollY": "200px",
12180		 *        "paginate": false,
12181		 *        "retrieve": true
12182		 *      } );
12183		 *    }
12184		 *
12185		 *    function tableActions ()
12186		 *    {
12187		 *      var table = initTable();
12188		 *      // perform API operations with oTable
12189		 *    }
12190		 */
12191		"bRetrieve": false,
12192	
12193	
12194		/**
12195		 * When vertical (y) scrolling is enabled, DataTables will force the height of
12196		 * the table's viewport to the given height at all times (useful for layout).
12197		 * However, this can look odd when filtering data down to a small data set,
12198		 * and the footer is left "floating" further down. This parameter (when
12199		 * enabled) will cause DataTables to collapse the table's viewport down when
12200		 * the result set will fit within the given Y height.
12201		 *  @type boolean
12202		 *  @default false
12203		 *
12204		 *  @dtopt Options
12205		 *  @name DataTable.defaults.scrollCollapse
12206		 *
12207		 *  @example
12208		 *    $(document).ready( function() {
12209		 *      $('#example').dataTable( {
12210		 *        "scrollY": "200",
12211		 *        "scrollCollapse": true
12212		 *      } );
12213		 *    } );
12214		 */
12215		"bScrollCollapse": false,
12216	
12217	
12218		/**
12219		 * Configure DataTables to use server-side processing. Note that the
12220		 * `ajax` parameter must also be given in order to give DataTables a
12221		 * source to obtain the required data for each draw.
12222		 *  @type boolean
12223		 *  @default false
12224		 *
12225		 *  @dtopt Features
12226		 *  @dtopt Server-side
12227		 *  @name DataTable.defaults.serverSide
12228		 *
12229		 *  @example
12230		 *    $(document).ready( function () {
12231		 *      $('#example').dataTable( {
12232		 *        "serverSide": true,
12233		 *        "ajax": "xhr.php"
12234		 *      } );
12235		 *    } );
12236		 */
12237		"bServerSide": false,
12238	
12239	
12240		/**
12241		 * Enable or disable sorting of columns. Sorting of individual columns can be
12242		 * disabled by the `sortable` option for each column.
12243		 *  @type boolean
12244		 *  @default true
12245		 *
12246		 *  @dtopt Features
12247		 *  @name DataTable.defaults.ordering
12248		 *
12249		 *  @example
12250		 *    $(document).ready( function () {
12251		 *      $('#example').dataTable( {
12252		 *        "ordering": false
12253		 *      } );
12254		 *    } );
12255		 */
12256		"bSort": true,
12257	
12258	
12259		/**
12260		 * Enable or display DataTables' ability to sort multiple columns at the
12261		 * same time (activated by shift-click by the user).
12262		 *  @type boolean
12263		 *  @default true
12264		 *
12265		 *  @dtopt Options
12266		 *  @name DataTable.defaults.orderMulti
12267		 *
12268		 *  @example
12269		 *    // Disable multiple column sorting ability
12270		 *    $(document).ready( function () {
12271		 *      $('#example').dataTable( {
12272		 *        "orderMulti": false
12273		 *      } );
12274		 *    } );
12275		 */
12276		"bSortMulti": true,
12277	
12278	
12279		/**
12280		 * Allows control over whether DataTables should use the top (true) unique
12281		 * cell that is found for a single column, or the bottom (false - default).
12282		 * This is useful when using complex headers.
12283		 *  @type boolean
12284		 *  @default false
12285		 *
12286		 *  @dtopt Options
12287		 *  @name DataTable.defaults.orderCellsTop
12288		 *
12289		 *  @example
12290		 *    $(document).ready( function() {
12291		 *      $('#example').dataTable( {
12292		 *        "orderCellsTop": true
12293		 *      } );
12294		 *    } );
12295		 */
12296		"bSortCellsTop": false,
12297	
12298	
12299		/**
12300		 * Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and
12301		 * `sorting\_3` to the columns which are currently being sorted on. This is
12302		 * presented as a feature switch as it can increase processing time (while
12303		 * classes are removed and added) so for large data sets you might want to
12304		 * turn this off.
12305		 *  @type boolean
12306		 *  @default true
12307		 *
12308		 *  @dtopt Features
12309		 *  @name DataTable.defaults.orderClasses
12310		 *
12311		 *  @example
12312		 *    $(document).ready( function () {
12313		 *      $('#example').dataTable( {
12314		 *        "orderClasses": false
12315		 *      } );
12316		 *    } );
12317		 */
12318		"bSortClasses": true,
12319	
12320	
12321		/**
12322		 * Enable or disable state saving. When enabled HTML5 `localStorage` will be
12323		 * used to save table display information such as pagination information,
12324		 * display length, filtering and sorting. As such when the end user reloads
12325		 * the page the display display will match what thy had previously set up.
12326		 *
12327		 * Due to the use of `localStorage` the default state saving is not supported
12328		 * in IE6 or 7. If state saving is required in those browsers, use
12329		 * `stateSaveCallback` to provide a storage solution such as cookies.
12330		 *  @type boolean
12331		 *  @default false
12332		 *
12333		 *  @dtopt Features
12334		 *  @name DataTable.defaults.stateSave
12335		 *
12336		 *  @example
12337		 *    $(document).ready( function () {
12338		 *      $('#example').dataTable( {
12339		 *        "stateSave": true
12340		 *      } );
12341		 *    } );
12342		 */
12343		"bStateSave": false,
12344	
12345	
12346		/**
12347		 * This function is called when a TR element is created (and all TD child
12348		 * elements have been inserted), or registered if using a DOM source, allowing
12349		 * manipulation of the TR element (adding classes etc).
12350		 *  @type function
12351		 *  @param {node} row "TR" element for the current row
12352		 *  @param {array} data Raw data array for this row
12353		 *  @param {int} dataIndex The index of this row in the internal aoData array
12354		 *
12355		 *  @dtopt Callbacks
12356		 *  @name DataTable.defaults.createdRow
12357		 *
12358		 *  @example
12359		 *    $(document).ready( function() {
12360		 *      $('#example').dataTable( {
12361		 *        "createdRow": function( row, data, dataIndex ) {
12362		 *          // Bold the grade for all 'A' grade browsers
12363		 *          if ( data[4] == "A" )
12364		 *          {
12365		 *            $('td:eq(4)', row).html( '<b>A</b>' );
12366		 *          }
12367		 *        }
12368		 *      } );
12369		 *    } );
12370		 */
12371		"fnCreatedRow": null,
12372	
12373	
12374		/**
12375		 * This function is called on every 'draw' event, and allows you to
12376		 * dynamically modify any aspect you want about the created DOM.
12377		 *  @type function
12378		 *  @param {object} settings DataTables settings object
12379		 *
12380		 *  @dtopt Callbacks
12381		 *  @name DataTable.defaults.drawCallback
12382		 *
12383		 *  @example
12384		 *    $(document).ready( function() {
12385		 *      $('#example').dataTable( {
12386		 *        "drawCallback": function( settings ) {
12387		 *          alert( 'DataTables has redrawn the table' );
12388		 *        }
12389		 *      } );
12390		 *    } );
12391		 */
12392		"fnDrawCallback": null,
12393	
12394	
12395		/**
12396		 * Identical to fnHeaderCallback() but for the table footer this function
12397		 * allows you to modify the table footer on every 'draw' event.
12398		 *  @type function
12399		 *  @param {node} foot "TR" element for the footer
12400		 *  @param {array} data Full table data (as derived from the original HTML)
12401		 *  @param {int} start Index for the current display starting point in the
12402		 *    display array
12403		 *  @param {int} end Index for the current display ending point in the
12404		 *    display array
12405		 *  @param {array int} display Index array to translate the visual position
12406		 *    to the full data array
12407		 *
12408		 *  @dtopt Callbacks
12409		 *  @name DataTable.defaults.footerCallback
12410		 *
12411		 *  @example
12412		 *    $(document).ready( function() {
12413		 *      $('#example').dataTable( {
12414		 *        "footerCallback": function( tfoot, data, start, end, display ) {
12415		 *          tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start;
12416		 *        }
12417		 *      } );
12418		 *    } )
12419		 */
12420		"fnFooterCallback": null,
12421	
12422	
12423		/**
12424		 * When rendering large numbers in the information element for the table
12425		 * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
12426		 * to have a comma separator for the 'thousands' units (e.g. 1 million is
12427		 * rendered as "1,000,000") to help readability for the end user. This
12428		 * function will override the default method DataTables uses.
12429		 *  @type function
12430		 *  @member
12431		 *  @param {int} toFormat number to be formatted
12432		 *  @returns {string} formatted string for DataTables to show the number
12433		 *
12434		 *  @dtopt Callbacks
12435		 *  @name DataTable.defaults.formatNumber
12436		 *
12437		 *  @example
12438		 *    // Format a number using a single quote for the separator (note that
12439		 *    // this can also be done with the language.thousands option)
12440		 *    $(document).ready( function() {
12441		 *      $('#example').dataTable( {
12442		 *        "formatNumber": function ( toFormat ) {
12443		 *          return toFormat.toString().replace(
12444		 *            /\B(?=(\d{3})+(?!\d))/g, "'"
12445		 *          );
12446		 *        };
12447		 *      } );
12448		 *    } );
12449		 */
12450		"fnFormatNumber": function ( toFormat ) {
12451			return toFormat.toString().replace(
12452				/\B(?=(\d{3})+(?!\d))/g,
12453				this.oLanguage.sThousands
12454			);
12455		},
12456	
12457	
12458		/**
12459		 * This function is called on every 'draw' event, and allows you to
12460		 * dynamically modify the header row. This can be used to calculate and
12461		 * display useful information about the table.
12462		 *  @type function
12463		 *  @param {node} head "TR" element for the header
12464		 *  @param {array} data Full table data (as derived from the original HTML)
12465		 *  @param {int} start Index for the current display starting point in the
12466		 *    display array
12467		 *  @param {int} end Index for the current display ending point in the
12468		 *    display array
12469		 *  @param {array int} display Index array to translate the visual position
12470		 *    to the full data array
12471		 *
12472		 *  @dtopt Callbacks
12473		 *  @name DataTable.defaults.headerCallback
12474		 *
12475		 *  @example
12476		 *    $(document).ready( function() {
12477		 *      $('#example').dataTable( {
12478		 *        "fheaderCallback": function( head, data, start, end, display ) {
12479		 *          head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records";
12480		 *        }
12481		 *      } );
12482		 *    } )
12483		 */
12484		"fnHeaderCallback": null,
12485	
12486	
12487		/**
12488		 * The information element can be used to convey information about the current
12489		 * state of the table. Although the internationalisation options presented by
12490		 * DataTables are quite capable of dealing with most customisations, there may
12491		 * be times where you wish to customise the string further. This callback
12492		 * allows you to do exactly that.
12493		 *  @type function
12494		 *  @param {object} oSettings DataTables settings object
12495		 *  @param {int} start Starting position in data for the draw
12496		 *  @param {int} end End position in data for the draw
12497		 *  @param {int} max Total number of rows in the table (regardless of
12498		 *    filtering)
12499		 *  @param {int} total Total number of rows in the data set, after filtering
12500		 *  @param {string} pre The string that DataTables has formatted using it's
12501		 *    own rules
12502		 *  @returns {string} The string to be displayed in the information element.
12503		 *
12504		 *  @dtopt Callbacks
12505		 *  @name DataTable.defaults.infoCallback
12506		 *
12507		 *  @example
12508		 *    $('#example').dataTable( {
12509		 *      "infoCallback": function( settings, start, end, max, total, pre ) {
12510		 *        return start +" to "+ end;
12511		 *      }
12512		 *    } );
12513		 */
12514		"fnInfoCallback": null,
12515	
12516	
12517		/**
12518		 * Called when the table has been initialised. Normally DataTables will
12519		 * initialise sequentially and there will be no need for this function,
12520		 * however, this does not hold true when using external language information
12521		 * since that is obtained using an async XHR call.
12522		 *  @type function
12523		 *  @param {object} settings DataTables settings object
12524		 *  @param {object} json The JSON object request from the server - only
12525		 *    present if client-side Ajax sourced data is used
12526		 *
12527		 *  @dtopt Callbacks
12528		 *  @name DataTable.defaults.initComplete
12529		 *
12530		 *  @example
12531		 *    $(document).ready( function() {
12532		 *      $('#example').dataTable( {
12533		 *        "initComplete": function(settings, json) {
12534		 *          alert( 'DataTables has finished its initialisation.' );
12535		 *        }
12536		 *      } );
12537		 *    } )
12538		 */
12539		"fnInitComplete": null,
12540	
12541	
12542		/**
12543		 * Called at the very start of each table draw and can be used to cancel the
12544		 * draw by returning false, any other return (including undefined) results in
12545		 * the full draw occurring).
12546		 *  @type function
12547		 *  @param {object} settings DataTables settings object
12548		 *  @returns {boolean} False will cancel the draw, anything else (including no
12549		 *    return) will allow it to complete.
12550		 *
12551		 *  @dtopt Callbacks
12552		 *  @name DataTable.defaults.preDrawCallback
12553		 *
12554		 *  @example
12555		 *    $(document).ready( function() {
12556		 *      $('#example').dataTable( {
12557		 *        "preDrawCallback": function( settings ) {
12558		 *          if ( $('#test').val() == 1 ) {
12559		 *            return false;
12560		 *          }
12561		 *        }
12562		 *      } );
12563		 *    } );
12564		 */
12565		"fnPreDrawCallback": null,
12566	
12567	
12568		/**
12569		 * This function allows you to 'post process' each row after it have been
12570		 * generated for each table draw, but before it is rendered on screen. This
12571		 * function might be used for setting the row class name etc.
12572		 *  @type function
12573		 *  @param {node} row "TR" element for the current row
12574		 *  @param {array} data Raw data array for this row
12575		 *  @param {int} displayIndex The display index for the current table draw
12576		 *  @param {int} displayIndexFull The index of the data in the full list of
12577		 *    rows (after filtering)
12578		 *
12579		 *  @dtopt Callbacks
12580		 *  @name DataTable.defaults.rowCallback
12581		 *
12582		 *  @example
12583		 *    $(document).ready( function() {
12584		 *      $('#example').dataTable( {
12585		 *        "rowCallback": function( row, data, displayIndex, displayIndexFull ) {
12586		 *          // Bold the grade for all 'A' grade browsers
12587		 *          if ( data[4] == "A" ) {
12588		 *            $('td:eq(4)', row).html( '<b>A</b>' );
12589		 *          }
12590		 *        }
12591		 *      } );
12592		 *    } );
12593		 */
12594		"fnRowCallback": null,
12595	
12596	
12597		/**
12598		 * __Deprecated__ The functionality provided by this parameter has now been
12599		 * superseded by that provided through `ajax`, which should be used instead.
12600		 *
12601		 * This parameter allows you to override the default function which obtains
12602		 * the data from the server so something more suitable for your application.
12603		 * For example you could use POST data, or pull information from a Gears or
12604		 * AIR database.
12605		 *  @type function
12606		 *  @member
12607		 *  @param {string} source HTTP source to obtain the data from (`ajax`)
12608		 *  @param {array} data A key/value pair object containing the data to send
12609		 *    to the server
12610		 *  @param {function} callback to be called on completion of the data get
12611		 *    process that will draw the data on the page.
12612		 *  @param {object} settings DataTables settings object
12613		 *
12614		 *  @dtopt Callbacks
12615		 *  @dtopt Server-side
12616		 *  @name DataTable.defaults.serverData
12617		 *
12618		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
12619		 */
12620		"fnServerData": null,
12621	
12622	
12623		/**
12624		 * __Deprecated__ The functionality provided by this parameter has now been
12625		 * superseded by that provided through `ajax`, which should be used instead.
12626		 *
12627		 *  It is often useful to send extra data to the server when making an Ajax
12628		 * request - for example custom filtering information, and this callback
12629		 * function makes it trivial to send extra information to the server. The
12630		 * passed in parameter is the data set that has been constructed by
12631		 * DataTables, and you can add to this or modify it as you require.
12632		 *  @type function
12633		 *  @param {array} data Data array (array of objects which are name/value
12634		 *    pairs) that has been constructed by DataTables and will be sent to the
12635		 *    server. In the case of Ajax sourced data with server-side processing
12636		 *    this will be an empty array, for server-side processing there will be a
12637		 *    significant number of parameters!
12638		 *  @returns {undefined} Ensure that you modify the data array passed in,
12639		 *    as this is passed by reference.
12640		 *
12641		 *  @dtopt Callbacks
12642		 *  @dtopt Server-side
12643		 *  @name DataTable.defaults.serverParams
12644		 *
12645		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
12646		 */
12647		"fnServerParams": null,
12648	
12649	
12650		/**
12651		 * Load the table state. With this function you can define from where, and how, the
12652		 * state of a table is loaded. By default DataTables will load from `localStorage`
12653		 * but you might wish to use a server-side database or cookies.
12654		 *  @type function
12655		 *  @member
12656		 *  @param {object} settings DataTables settings object
12657		 *  @param {object} callback Callback that can be executed when done. It
12658		 *    should be passed the loaded state object.
12659		 *  @return {object} The DataTables state object to be loaded
12660		 *
12661		 *  @dtopt Callbacks
12662		 *  @name DataTable.defaults.stateLoadCallback
12663		 *
12664		 *  @example
12665		 *    $(document).ready( function() {
12666		 *      $('#example').dataTable( {
12667		 *        "stateSave": true,
12668		 *        "stateLoadCallback": function (settings, callback) {
12669		 *          $.ajax( {
12670		 *            "url": "/state_load",
12671		 *            "dataType": "json",
12672		 *            "success": function (json) {
12673		 *              callback( json );
12674		 *            }
12675		 *          } );
12676		 *        }
12677		 *      } );
12678		 *    } );
12679		 */
12680		"fnStateLoadCallback": function ( settings ) {
12681			try {
12682				return JSON.parse(
12683					(settings.iStateDuration === -1 ? sessionStorage : localStorage).getItem(
12684						'DataTables_'+settings.sInstance+'_'+location.pathname
12685					)
12686				);
12687			} catch (e) {
12688				return {};
12689			}
12690		},
12691	
12692	
12693		/**
12694		 * Callback which allows modification of the saved state prior to loading that state.
12695		 * This callback is called when the table is loading state from the stored data, but
12696		 * prior to the settings object being modified by the saved state. Note that for
12697		 * plug-in authors, you should use the `stateLoadParams` event to load parameters for
12698		 * a plug-in.
12699		 *  @type function
12700		 *  @param {object} settings DataTables settings object
12701		 *  @param {object} data The state object that is to be loaded
12702		 *
12703		 *  @dtopt Callbacks
12704		 *  @name DataTable.defaults.stateLoadParams
12705		 *
12706		 *  @example
12707		 *    // Remove a saved filter, so filtering is never loaded
12708		 *    $(document).ready( function() {
12709		 *      $('#example').dataTable( {
12710		 *        "stateSave": true,
12711		 *        "stateLoadParams": function (settings, data) {
12712		 *          data.oSearch.sSearch = "";
12713		 *        }
12714		 *      } );
12715		 *    } );
12716		 *
12717		 *  @example
12718		 *    // Disallow state loading by returning false
12719		 *    $(document).ready( function() {
12720		 *      $('#example').dataTable( {
12721		 *        "stateSave": true,
12722		 *        "stateLoadParams": function (settings, data) {
12723		 *          return false;
12724		 *        }
12725		 *      } );
12726		 *    } );
12727		 */
12728		"fnStateLoadParams": null,
12729	
12730	
12731		/**
12732		 * Callback that is called when the state has been loaded from the state saving method
12733		 * and the DataTables settings object has been modified as a result of the loaded state.
12734		 *  @type function
12735		 *  @param {object} settings DataTables settings object
12736		 *  @param {object} data The state object that was loaded
12737		 *
12738		 *  @dtopt Callbacks
12739		 *  @name DataTable.defaults.stateLoaded
12740		 *
12741		 *  @example
12742		 *    // Show an alert with the filtering value that was saved
12743		 *    $(document).ready( function() {
12744		 *      $('#example').dataTable( {
12745		 *        "stateSave": true,
12746		 *        "stateLoaded": function (settings, data) {
12747		 *          alert( 'Saved filter was: '+data.oSearch.sSearch );
12748		 *        }
12749		 *      } );
12750		 *    } );
12751		 */
12752		"fnStateLoaded": null,
12753	
12754	
12755		/**
12756		 * Save the table state. This function allows you to define where and how the state
12757		 * information for the table is stored By default DataTables will use `localStorage`
12758		 * but you might wish to use a server-side database or cookies.
12759		 *  @type function
12760		 *  @member
12761		 *  @param {object} settings DataTables settings object
12762		 *  @param {object} data The state object to be saved
12763		 *
12764		 *  @dtopt Callbacks
12765		 *  @name DataTable.defaults.stateSaveCallback
12766		 *
12767		 *  @example
12768		 *    $(document).ready( function() {
12769		 *      $('#example').dataTable( {
12770		 *        "stateSave": true,
12771		 *        "stateSaveCallback": function (settings, data) {
12772		 *          // Send an Ajax request to the server with the state object
12773		 *          $.ajax( {
12774		 *            "url": "/state_save",
12775		 *            "data": data,
12776		 *            "dataType": "json",
12777		 *            "method": "POST"
12778		 *            "success": function () {}
12779		 *          } );
12780		 *        }
12781		 *      } );
12782		 *    } );
12783		 */
12784		"fnStateSaveCallback": function ( settings, data ) {
12785			try {
12786				(settings.iStateDuration === -1 ? sessionStorage : localStorage).setItem(
12787					'DataTables_'+settings.sInstance+'_'+location.pathname,
12788					JSON.stringify( data )
12789				);
12790			} catch (e) {}
12791		},
12792	
12793	
12794		/**
12795		 * Callback which allows modification of the state to be saved. Called when the table
12796		 * has changed state a new state save is required. This method allows modification of
12797		 * the state saving object prior to actually doing the save, including addition or
12798		 * other state properties or modification. Note that for plug-in authors, you should
12799		 * use the `stateSaveParams` event to save parameters for a plug-in.
12800		 *  @type function
12801		 *  @param {object} settings DataTables settings object
12802		 *  @param {object} data The state object to be saved
12803		 *
12804		 *  @dtopt Callbacks
12805		 *  @name DataTable.defaults.stateSaveParams
12806		 *
12807		 *  @example
12808		 *    // Remove a saved filter, so filtering is never saved
12809		 *    $(document).ready( function() {
12810		 *      $('#example').dataTable( {
12811		 *        "stateSave": true,
12812		 *        "stateSaveParams": function (settings, data) {
12813		 *          data.oSearch.sSearch = "";
12814		 *        }
12815		 *      } );
12816		 *    } );
12817		 */
12818		"fnStateSaveParams": null,
12819	
12820	
12821		/**
12822		 * Duration for which the saved state information is considered valid. After this period
12823		 * has elapsed the state will be returned to the default.
12824		 * Value is given in seconds.
12825		 *  @type int
12826		 *  @default 7200 <i>(2 hours)</i>
12827		 *
12828		 *  @dtopt Options
12829		 *  @name DataTable.defaults.stateDuration
12830		 *
12831		 *  @example
12832		 *    $(document).ready( function() {
12833		 *      $('#example').dataTable( {
12834		 *        "stateDuration": 60*60*24; // 1 day
12835		 *      } );
12836		 *    } )
12837		 */
12838		"iStateDuration": 7200,
12839	
12840	
12841		/**
12842		 * When enabled DataTables will not make a request to the server for the first
12843		 * page draw - rather it will use the data already on the page (no sorting etc
12844		 * will be applied to it), thus saving on an XHR at load time. `deferLoading`
12845		 * is used to indicate that deferred loading is required, but it is also used
12846		 * to tell DataTables how many records there are in the full table (allowing
12847		 * the information element and pagination to be displayed correctly). In the case
12848		 * where a filtering is applied to the table on initial load, this can be
12849		 * indicated by giving the parameter as an array, where the first element is
12850		 * the number of records available after filtering and the second element is the
12851		 * number of records without filtering (allowing the table information element
12852		 * to be shown correctly).
12853		 *  @type int | array
12854		 *  @default null
12855		 *
12856		 *  @dtopt Options
12857		 *  @name DataTable.defaults.deferLoading
12858		 *
12859		 *  @example
12860		 *    // 57 records available in the table, no filtering applied
12861		 *    $(document).ready( function() {
12862		 *      $('#example').dataTable( {
12863		 *        "serverSide": true,
12864		 *        "ajax": "scripts/server_processing.php",
12865		 *        "deferLoading": 57
12866		 *      } );
12867		 *    } );
12868		 *
12869		 *  @example
12870		 *    // 57 records after filtering, 100 without filtering (an initial filter applied)
12871		 *    $(document).ready( function() {
12872		 *      $('#example').dataTable( {
12873		 *        "serverSide": true,
12874		 *        "ajax": "scripts/server_processing.php",
12875		 *        "deferLoading": [ 57, 100 ],
12876		 *        "search": {
12877		 *          "search": "my_filter"
12878		 *        }
12879		 *      } );
12880		 *    } );
12881		 */
12882		"iDeferLoading": null,
12883	
12884	
12885		/**
12886		 * Number of rows to display on a single page when using pagination. If
12887		 * feature enabled (`lengthChange`) then the end user will be able to override
12888		 * this to a custom setting using a pop-up menu.
12889		 *  @type int
12890		 *  @default 10
12891		 *
12892		 *  @dtopt Options
12893		 *  @name DataTable.defaults.pageLength
12894		 *
12895		 *  @example
12896		 *    $(document).ready( function() {
12897		 *      $('#example').dataTable( {
12898		 *        "pageLength": 50
12899		 *      } );
12900		 *    } )
12901		 */
12902		"iDisplayLength": 10,
12903	
12904	
12905		/**
12906		 * Define the starting point for data display when using DataTables with
12907		 * pagination. Note that this parameter is the number of records, rather than
12908		 * the page number, so if you have 10 records per page and want to start on
12909		 * the third page, it should be "20".
12910		 *  @type int
12911		 *  @default 0
12912		 *
12913		 *  @dtopt Options
12914		 *  @name DataTable.defaults.displayStart
12915		 *
12916		 *  @example
12917		 *    $(document).ready( function() {
12918		 *      $('#example').dataTable( {
12919		 *        "displayStart": 20
12920		 *      } );
12921		 *    } )
12922		 */
12923		"iDisplayStart": 0,
12924	
12925	
12926		/**
12927		 * By default DataTables allows keyboard navigation of the table (sorting, paging,
12928		 * and filtering) by adding a `tabindex` attribute to the required elements. This
12929		 * allows you to tab through the controls and press the enter key to activate them.
12930		 * The tabindex is default 0, meaning that the tab follows the flow of the document.
12931		 * You can overrule this using this parameter if you wish. Use a value of -1 to
12932		 * disable built-in keyboard navigation.
12933		 *  @type int
12934		 *  @default 0
12935		 *
12936		 *  @dtopt Options
12937		 *  @name DataTable.defaults.tabIndex
12938		 *
12939		 *  @example
12940		 *    $(document).ready( function() {
12941		 *      $('#example').dataTable( {
12942		 *        "tabIndex": 1
12943		 *      } );
12944		 *    } );
12945		 */
12946		"iTabIndex": 0,
12947	
12948	
12949		/**
12950		 * Classes that DataTables assigns to the various components and features
12951		 * that it adds to the HTML table. This allows classes to be configured
12952		 * during initialisation in addition to through the static
12953		 * {@link DataTable.ext.oStdClasses} object).
12954		 *  @namespace
12955		 *  @name DataTable.defaults.classes
12956		 */
12957		"oClasses": {},
12958	
12959	
12960		/**
12961		 * All strings that DataTables uses in the user interface that it creates
12962		 * are defined in this object, allowing you to modified them individually or
12963		 * completely replace them all as required.
12964		 *  @namespace
12965		 *  @name DataTable.defaults.language
12966		 */
12967		"oLanguage": {
12968			/**
12969			 * Strings that are used for WAI-ARIA labels and controls only (these are not
12970			 * actually visible on the page, but will be read by screenreaders, and thus
12971			 * must be internationalised as well).
12972			 *  @namespace
12973			 *  @name DataTable.defaults.language.aria
12974			 */
12975			"oAria": {
12976				/**
12977				 * ARIA label that is added to the table headers when the column may be
12978				 * sorted ascending by activing the column (click or return when focused).
12979				 * Note that the column header is prefixed to this string.
12980				 *  @type string
12981				 *  @default : activate to sort column ascending
12982				 *
12983				 *  @dtopt Language
12984				 *  @name DataTable.defaults.language.aria.sortAscending
12985				 *
12986				 *  @example
12987				 *    $(document).ready( function() {
12988				 *      $('#example').dataTable( {
12989				 *        "language": {
12990				 *          "aria": {
12991				 *            "sortAscending": " - click/return to sort ascending"
12992				 *          }
12993				 *        }
12994				 *      } );
12995				 *    } );
12996				 */
12997				"sSortAscending": ": activate to sort column ascending",
12998	
12999				/**
13000				 * ARIA label that is added to the table headers when the column may be
13001				 * sorted descending by activing the column (click or return when focused).
13002				 * Note that the column header is prefixed to this string.
13003				 *  @type string
13004				 *  @default : activate to sort column ascending
13005				 *
13006				 *  @dtopt Language
13007				 *  @name DataTable.defaults.language.aria.sortDescending
13008				 *
13009				 *  @example
13010				 *    $(document).ready( function() {
13011				 *      $('#example').dataTable( {
13012				 *        "language": {
13013				 *          "aria": {
13014				 *            "sortDescending": " - click/return to sort descending"
13015				 *          }
13016				 *        }
13017				 *      } );
13018				 *    } );
13019				 */
13020				"sSortDescending": ": activate to sort column descending"
13021			},
13022	
13023			/**
13024			 * Pagination string used by DataTables for the built-in pagination
13025			 * control types.
13026			 *  @namespace
13027			 *  @name DataTable.defaults.language.paginate
13028			 */
13029			"oPaginate": {
13030				/**
13031				 * Text to use when using the 'full_numbers' type of pagination for the
13032				 * button to take the user to the first page.
13033				 *  @type string
13034				 *  @default First
13035				 *
13036				 *  @dtopt Language
13037				 *  @name DataTable.defaults.language.paginate.first
13038				 *
13039				 *  @example
13040				 *    $(document).ready( function() {
13041				 *      $('#example').dataTable( {
13042				 *        "language": {
13043				 *          "paginate": {
13044				 *            "first": "First page"
13045				 *          }
13046				 *        }
13047				 *      } );
13048				 *    } );
13049				 */
13050				"sFirst": "First",
13051	
13052	
13053				/**
13054				 * Text to use when using the 'full_numbers' type of pagination for the
13055				 * button to take the user to the last page.
13056				 *  @type string
13057				 *  @default Last
13058				 *
13059				 *  @dtopt Language
13060				 *  @name DataTable.defaults.language.paginate.last
13061				 *
13062				 *  @example
13063				 *    $(document).ready( function() {
13064				 *      $('#example').dataTable( {
13065				 *        "language": {
13066				 *          "paginate": {
13067				 *            "last": "Last page"
13068				 *          }
13069				 *        }
13070				 *      } );
13071				 *    } );
13072				 */
13073				"sLast": "Last",
13074	
13075	
13076				/**
13077				 * Text to use for the 'next' pagination button (to take the user to the
13078				 * next page).
13079				 *  @type string
13080				 *  @default Next
13081				 *
13082				 *  @dtopt Language
13083				 *  @name DataTable.defaults.language.paginate.next
13084				 *
13085				 *  @example
13086				 *    $(document).ready( function() {
13087				 *      $('#example').dataTable( {
13088				 *        "language": {
13089				 *          "paginate": {
13090				 *            "next": "Next page"
13091				 *          }
13092				 *        }
13093				 *      } );
13094				 *    } );
13095				 */
13096				"sNext": "Next",
13097	
13098	
13099				/**
13100				 * Text to use for the 'previous' pagination button (to take the user to
13101				 * the previous page).
13102				 *  @type string
13103				 *  @default Previous
13104				 *
13105				 *  @dtopt Language
13106				 *  @name DataTable.defaults.language.paginate.previous
13107				 *
13108				 *  @example
13109				 *    $(document).ready( function() {
13110				 *      $('#example').dataTable( {
13111				 *        "language": {
13112				 *          "paginate": {
13113				 *            "previous": "Previous page"
13114				 *          }
13115				 *        }
13116				 *      } );
13117				 *    } );
13118				 */
13119				"sPrevious": "Previous"
13120			},
13121	
13122			/**
13123			 * This string is shown in preference to `zeroRecords` when the table is
13124			 * empty of data (regardless of filtering). Note that this is an optional
13125			 * parameter - if it is not given, the value of `zeroRecords` will be used
13126			 * instead (either the default or given value).
13127			 *  @type string
13128			 *  @default No data available in table
13129			 *
13130			 *  @dtopt Language
13131			 *  @name DataTable.defaults.language.emptyTable
13132			 *
13133			 *  @example
13134			 *    $(document).ready( function() {
13135			 *      $('#example').dataTable( {
13136			 *        "language": {
13137			 *          "emptyTable": "No data available in table"
13138			 *        }
13139			 *      } );
13140			 *    } );
13141			 */
13142			"sEmptyTable": "No data available in table",
13143	
13144	
13145			/**
13146			 * This string gives information to the end user about the information
13147			 * that is current on display on the page. The following tokens can be
13148			 * used in the string and will be dynamically replaced as the table
13149			 * display updates. This tokens can be placed anywhere in the string, or
13150			 * removed as needed by the language requires:
13151			 *
13152			 * * `\_START\_` - Display index of the first record on the current page
13153			 * * `\_END\_` - Display index of the last record on the current page
13154			 * * `\_TOTAL\_` - Number of records in the table after filtering
13155			 * * `\_MAX\_` - Number of records in the table without filtering
13156			 * * `\_PAGE\_` - Current page number
13157			 * * `\_PAGES\_` - Total number of pages of data in the table
13158			 *
13159			 *  @type string
13160			 *  @default Showing _START_ to _END_ of _TOTAL_ entries
13161			 *
13162			 *  @dtopt Language
13163			 *  @name DataTable.defaults.language.info
13164			 *
13165			 *  @example
13166			 *    $(document).ready( function() {
13167			 *      $('#example').dataTable( {
13168			 *        "language": {
13169			 *          "info": "Showing page _PAGE_ of _PAGES_"
13170			 *        }
13171			 *      } );
13172			 *    } );
13173			 */
13174			"sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
13175	
13176	
13177			/**
13178			 * Display information string for when the table is empty. Typically the
13179			 * format of this string should match `info`.
13180			 *  @type string
13181			 *  @default Showing 0 to 0 of 0 entries
13182			 *
13183			 *  @dtopt Language
13184			 *  @name DataTable.defaults.language.infoEmpty
13185			 *
13186			 *  @example
13187			 *    $(document).ready( function() {
13188			 *      $('#example').dataTable( {
13189			 *        "language": {
13190			 *          "infoEmpty": "No entries to show"
13191			 *        }
13192			 *      } );
13193			 *    } );
13194			 */
13195			"sInfoEmpty": "Showing 0 to 0 of 0 entries",
13196	
13197	
13198			/**
13199			 * When a user filters the information in a table, this string is appended
13200			 * to the information (`info`) to give an idea of how strong the filtering
13201			 * is. The variable _MAX_ is dynamically updated.
13202			 *  @type string
13203			 *  @default (filtered from _MAX_ total entries)
13204			 *
13205			 *  @dtopt Language
13206			 *  @name DataTable.defaults.language.infoFiltered
13207			 *
13208			 *  @example
13209			 *    $(document).ready( function() {
13210			 *      $('#example').dataTable( {
13211			 *        "language": {
13212			 *          "infoFiltered": " - filtering from _MAX_ records"
13213			 *        }
13214			 *      } );
13215			 *    } );
13216			 */
13217			"sInfoFiltered": "(filtered from _MAX_ total entries)",
13218	
13219	
13220			/**
13221			 * If can be useful to append extra information to the info string at times,
13222			 * and this variable does exactly that. This information will be appended to
13223			 * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are
13224			 * being used) at all times.
13225			 *  @type string
13226			 *  @default <i>Empty string</i>
13227			 *
13228			 *  @dtopt Language
13229			 *  @name DataTable.defaults.language.infoPostFix
13230			 *
13231			 *  @example
13232			 *    $(document).ready( function() {
13233			 *      $('#example').dataTable( {
13234			 *        "language": {
13235			 *          "infoPostFix": "All records shown are derived from real information."
13236			 *        }
13237			 *      } );
13238			 *    } );
13239			 */
13240			"sInfoPostFix": "",
13241	
13242	
13243			/**
13244			 * This decimal place operator is a little different from the other
13245			 * language options since DataTables doesn't output floating point
13246			 * numbers, so it won't ever use this for display of a number. Rather,
13247			 * what this parameter does is modify the sort methods of the table so
13248			 * that numbers which are in a format which has a character other than
13249			 * a period (`.`) as a decimal place will be sorted numerically.
13250			 *
13251			 * Note that numbers with different decimal places cannot be shown in
13252			 * the same table and still be sortable, the table must be consistent.
13253			 * However, multiple different tables on the page can use different
13254			 * decimal place characters.
13255			 *  @type string
13256			 *  @default 
13257			 *
13258			 *  @dtopt Language
13259			 *  @name DataTable.defaults.language.decimal
13260			 *
13261			 *  @example
13262			 *    $(document).ready( function() {
13263			 *      $('#example').dataTable( {
13264			 *        "language": {
13265			 *          "decimal": ","
13266			 *          "thousands": "."
13267			 *        }
13268			 *      } );
13269			 *    } );
13270			 */
13271			"sDecimal": "",
13272	
13273	
13274			/**
13275			 * DataTables has a build in number formatter (`formatNumber`) which is
13276			 * used to format large numbers that are used in the table information.
13277			 * By default a comma is used, but this can be trivially changed to any
13278			 * character you wish with this parameter.
13279			 *  @type string
13280			 *  @default ,
13281			 *
13282			 *  @dtopt Language
13283			 *  @name DataTable.defaults.language.thousands
13284			 *
13285			 *  @example
13286			 *    $(document).ready( function() {
13287			 *      $('#example').dataTable( {
13288			 *        "language": {
13289			 *          "thousands": "'"
13290			 *        }
13291			 *      } );
13292			 *    } );
13293			 */
13294			"sThousands": ",",
13295	
13296	
13297			/**
13298			 * Detail the action that will be taken when the drop down menu for the
13299			 * pagination length option is changed. The '_MENU_' variable is replaced
13300			 * with a default select list of 10, 25, 50 and 100, and can be replaced
13301			 * with a custom select box if required.
13302			 *  @type string
13303			 *  @default Show _MENU_ entries
13304			 *
13305			 *  @dtopt Language
13306			 *  @name DataTable.defaults.language.lengthMenu
13307			 *
13308			 *  @example
13309			 *    // Language change only
13310			 *    $(document).ready( function() {
13311			 *      $('#example').dataTable( {
13312			 *        "language": {
13313			 *          "lengthMenu": "Display _MENU_ records"
13314			 *        }
13315			 *      } );
13316			 *    } );
13317			 *
13318			 *  @example
13319			 *    // Language and options change
13320			 *    $(document).ready( function() {
13321			 *      $('#example').dataTable( {
13322			 *        "language": {
13323			 *          "lengthMenu": 'Display <select>'+
13324			 *            '<option value="10">10</option>'+
13325			 *            '<option value="20">20</option>'+
13326			 *            '<option value="30">30</option>'+
13327			 *            '<option value="40">40</option>'+
13328			 *            '<option value="50">50</option>'+
13329			 *            '<option value="-1">All</option>'+
13330			 *            '</select> records'
13331			 *        }
13332			 *      } );
13333			 *    } );
13334			 */
13335			"sLengthMenu": "Show _MENU_ entries",
13336	
13337	
13338			/**
13339			 * When using Ajax sourced data and during the first draw when DataTables is
13340			 * gathering the data, this message is shown in an empty row in the table to
13341			 * indicate to the end user the the data is being loaded. Note that this
13342			 * parameter is not used when loading data by server-side processing, just
13343			 * Ajax sourced data with client-side processing.
13344			 *  @type string
13345			 *  @default Loading...
13346			 *
13347			 *  @dtopt Language
13348			 *  @name DataTable.defaults.language.loadingRecords
13349			 *
13350			 *  @example
13351			 *    $(document).ready( function() {
13352			 *      $('#example').dataTable( {
13353			 *        "language": {
13354			 *          "loadingRecords": "Please wait - loading..."
13355			 *        }
13356			 *      } );
13357			 *    } );
13358			 */
13359			"sLoadingRecords": "Loading...",
13360	
13361	
13362			/**
13363			 * Text which is displayed when the table is processing a user action
13364			 * (usually a sort command or similar).
13365			 *  @type string
13366			 *  @default Processing...
13367			 *
13368			 *  @dtopt Language
13369			 *  @name DataTable.defaults.language.processing
13370			 *
13371			 *  @example
13372			 *    $(document).ready( function() {
13373			 *      $('#example').dataTable( {
13374			 *        "language": {
13375			 *          "processing": "DataTables is currently busy"
13376			 *        }
13377			 *      } );
13378			 *    } );
13379			 */
13380			"sProcessing": "Processing...",
13381	
13382	
13383			/**
13384			 * Details the actions that will be taken when the user types into the
13385			 * filtering input text box. The variable "_INPUT_", if used in the string,
13386			 * is replaced with the HTML text box for the filtering input allowing
13387			 * control over where it appears in the string. If "_INPUT_" is not given
13388			 * then the input box is appended to the string automatically.
13389			 *  @type string
13390			 *  @default Search:
13391			 *
13392			 *  @dtopt Language
13393			 *  @name DataTable.defaults.language.search
13394			 *
13395			 *  @example
13396			 *    // Input text box will be appended at the end automatically
13397			 *    $(document).ready( function() {
13398			 *      $('#example').dataTable( {
13399			 *        "language": {
13400			 *          "search": "Filter records:"
13401			 *        }
13402			 *      } );
13403			 *    } );
13404			 *
13405			 *  @example
13406			 *    // Specify where the filter should appear
13407			 *    $(document).ready( function() {
13408			 *      $('#example').dataTable( {
13409			 *        "language": {
13410			 *          "search": "Apply filter _INPUT_ to table"
13411			 *        }
13412			 *      } );
13413			 *    } );
13414			 */
13415			"sSearch": "Search:",
13416	
13417	
13418			/**
13419			 * Assign a `placeholder` attribute to the search `input` element
13420			 *  @type string
13421			 *  @default 
13422			 *
13423			 *  @dtopt Language
13424			 *  @name DataTable.defaults.language.searchPlaceholder
13425			 */
13426			"sSearchPlaceholder": "",
13427	
13428	
13429			/**
13430			 * All of the language information can be stored in a file on the
13431			 * server-side, which DataTables will look up if this parameter is passed.
13432			 * It must store the URL of the language file, which is in a JSON format,
13433			 * and the object has the same properties as the oLanguage object in the
13434			 * initialiser object (i.e. the above parameters). Please refer to one of
13435			 * the example language files to see how this works in action.
13436			 *  @type string
13437			 *  @default <i>Empty string - i.e. disabled</i>
13438			 *
13439			 *  @dtopt Language
13440			 *  @name DataTable.defaults.language.url
13441			 *
13442			 *  @example
13443			 *    $(document).ready( function() {
13444			 *      $('#example').dataTable( {
13445			 *        "language": {
13446			 *          "url": "http://www.sprymedia.co.uk/dataTables/lang.txt"
13447			 *        }
13448			 *      } );
13449			 *    } );
13450			 */
13451			"sUrl": "",
13452	
13453	
13454			/**
13455			 * Text shown inside the table records when the is no information to be
13456			 * displayed after filtering. `emptyTable` is shown when there is simply no
13457			 * information in the table at all (regardless of filtering).
13458			 *  @type string
13459			 *  @default No matching records found
13460			 *
13461			 *  @dtopt Language
13462			 *  @name DataTable.defaults.language.zeroRecords
13463			 *
13464			 *  @example
13465			 *    $(document).ready( function() {
13466			 *      $('#example').dataTable( {
13467			 *        "language": {
13468			 *          "zeroRecords": "No records to display"
13469			 *        }
13470			 *      } );
13471			 *    } );
13472			 */
13473			"sZeroRecords": "No matching records found"
13474		},
13475	
13476	
13477		/**
13478		 * This parameter allows you to have define the global filtering state at
13479		 * initialisation time. As an object the `search` parameter must be
13480		 * defined, but all other parameters are optional. When `regex` is true,
13481		 * the search string will be treated as a regular expression, when false
13482		 * (default) it will be treated as a straight string. When `smart`
13483		 * DataTables will use it's smart filtering methods (to word match at
13484		 * any point in the data), when false this will not be done.
13485		 *  @namespace
13486		 *  @extends DataTable.models.oSearch
13487		 *
13488		 *  @dtopt Options
13489		 *  @name DataTable.defaults.search
13490		 *
13491		 *  @example
13492		 *    $(document).ready( function() {
13493		 *      $('#example').dataTable( {
13494		 *        "search": {"search": "Initial search"}
13495		 *      } );
13496		 *    } )
13497		 */
13498		"oSearch": $.extend( {}, DataTable.models.oSearch ),
13499	
13500	
13501		/**
13502		 * __Deprecated__ The functionality provided by this parameter has now been
13503		 * superseded by that provided through `ajax`, which should be used instead.
13504		 *
13505		 * By default DataTables will look for the property `data` (or `aaData` for
13506		 * compatibility with DataTables 1.9-) when obtaining data from an Ajax
13507		 * source or for server-side processing - this parameter allows that
13508		 * property to be changed. You can use Javascript dotted object notation to
13509		 * get a data source for multiple levels of nesting.
13510		 *  @type string
13511		 *  @default data
13512		 *
13513		 *  @dtopt Options
13514		 *  @dtopt Server-side
13515		 *  @name DataTable.defaults.ajaxDataProp
13516		 *
13517		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
13518		 */
13519		"sAjaxDataProp": "data",
13520	
13521	
13522		/**
13523		 * __Deprecated__ The functionality provided by this parameter has now been
13524		 * superseded by that provided through `ajax`, which should be used instead.
13525		 *
13526		 * You can instruct DataTables to load data from an external
13527		 * source using this parameter (use aData if you want to pass data in you
13528		 * already have). Simply provide a url a JSON object can be obtained from.
13529		 *  @type string
13530		 *  @default null
13531		 *
13532		 *  @dtopt Options
13533		 *  @dtopt Server-side
13534		 *  @name DataTable.defaults.ajaxSource
13535		 *
13536		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
13537		 */
13538		"sAjaxSource": null,
13539	
13540	
13541		/**
13542		 * This initialisation variable allows you to specify exactly where in the
13543		 * DOM you want DataTables to inject the various controls it adds to the page
13544		 * (for example you might want the pagination controls at the top of the
13545		 * table). DIV elements (with or without a custom class) can also be added to
13546		 * aid styling. The follow syntax is used:
13547		 *   <ul>
13548		 *     <li>The following options are allowed:
13549		 *       <ul>
13550		 *         <li>'l' - Length changing</li>
13551		 *         <li>'f' - Filtering input</li>
13552		 *         <li>'t' - The table!</li>
13553		 *         <li>'i' - Information</li>
13554		 *         <li>'p' - Pagination</li>
13555		 *         <li>'r' - pRocessing</li>
13556		 *       </ul>
13557		 *     </li>
13558		 *     <li>The following constants are allowed:
13559		 *       <ul>
13560		 *         <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>
13561		 *         <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>
13562		 *       </ul>
13563		 *     </li>
13564		 *     <li>The following syntax is expected:
13565		 *       <ul>
13566		 *         <li>'&lt;' and '&gt;' - div elements</li>
13567		 *         <li>'&lt;"class" and '&gt;' - div with a class</li>
13568		 *         <li>'&lt;"#id" and '&gt;' - div with an ID</li>
13569		 *       </ul>
13570		 *     </li>
13571		 *     <li>Examples:
13572		 *       <ul>
13573		 *         <li>'&lt;"wrapper"flipt&gt;'</li>
13574		 *         <li>'&lt;lf&lt;t&gt;ip&gt;'</li>
13575		 *       </ul>
13576		 *     </li>
13577		 *   </ul>
13578		 *  @type string
13579		 *  @default lfrtip <i>(when `jQueryUI` is false)</i> <b>or</b>
13580		 *    <"H"lfr>t<"F"ip> <i>(when `jQueryUI` is true)</i>
13581		 *
13582		 *  @dtopt Options
13583		 *  @name DataTable.defaults.dom
13584		 *
13585		 *  @example
13586		 *    $(document).ready( function() {
13587		 *      $('#example').dataTable( {
13588		 *        "dom": '&lt;"top"i&gt;rt&lt;"bottom"flp&gt;&lt;"clear"&gt;'
13589		 *      } );
13590		 *    } );
13591		 */
13592		"sDom": "lfrtip",
13593	
13594	
13595		/**
13596		 * Search delay option. This will throttle full table searches that use the
13597		 * DataTables provided search input element (it does not effect calls to
13598		 * `dt-api search()`, providing a delay before the search is made.
13599		 *  @type integer
13600		 *  @default 0
13601		 *
13602		 *  @dtopt Options
13603		 *  @name DataTable.defaults.searchDelay
13604		 *
13605		 *  @example
13606		 *    $(document).ready( function() {
13607		 *      $('#example').dataTable( {
13608		 *        "searchDelay": 200
13609		 *      } );
13610		 *    } )
13611		 */
13612		"searchDelay": null,
13613	
13614	
13615		/**
13616		 * DataTables features six different built-in options for the buttons to
13617		 * display for pagination control:
13618		 *
13619		 * * `numbers` - Page number buttons only
13620		 * * `simple` - 'Previous' and 'Next' buttons only
13621		 * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers
13622		 * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons
13623		 * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus page numbers
13624		 * * `first_last_numbers` - 'First' and 'Last' buttons, plus page numbers
13625		 *  
13626		 * Further methods can be added using {@link DataTable.ext.oPagination}.
13627		 *  @type string
13628		 *  @default simple_numbers
13629		 *
13630		 *  @dtopt Options
13631		 *  @name DataTable.defaults.pagingType
13632		 *
13633		 *  @example
13634		 *    $(document).ready( function() {
13635		 *      $('#example').dataTable( {
13636		 *        "pagingType": "full_numbers"
13637		 *      } );
13638		 *    } )
13639		 */
13640		"sPaginationType": "simple_numbers",
13641	
13642	
13643		/**
13644		 * Enable horizontal scrolling. When a table is too wide to fit into a
13645		 * certain layout, or you have a large number of columns in the table, you
13646		 * can enable x-scrolling to show the table in a viewport, which can be
13647		 * scrolled. This property can be `true` which will allow the table to
13648		 * scroll horizontally when needed, or any CSS unit, or a number (in which
13649		 * case it will be treated as a pixel measurement). Setting as simply `true`
13650		 * is recommended.
13651		 *  @type boolean|string
13652		 *  @default <i>blank string - i.e. disabled</i>
13653		 *
13654		 *  @dtopt Features
13655		 *  @name DataTable.defaults.scrollX
13656		 *
13657		 *  @example
13658		 *    $(document).ready( function() {
13659		 *      $('#example').dataTable( {
13660		 *        "scrollX": true,
13661		 *        "scrollCollapse": true
13662		 *      } );
13663		 *    } );
13664		 */
13665		"sScrollX": "",
13666	
13667	
13668		/**
13669		 * This property can be used to force a DataTable to use more width than it
13670		 * might otherwise do when x-scrolling is enabled. For example if you have a
13671		 * table which requires to be well spaced, this parameter is useful for
13672		 * "over-sizing" the table, and thus forcing scrolling. This property can by
13673		 * any CSS unit, or a number (in which case it will be treated as a pixel
13674		 * measurement).
13675		 *  @type string
13676		 *  @default <i>blank string - i.e. disabled</i>
13677		 *
13678		 *  @dtopt Options
13679		 *  @name DataTable.defaults.scrollXInner
13680		 *
13681		 *  @example
13682		 *    $(document).ready( function() {
13683		 *      $('#example').dataTable( {
13684		 *        "scrollX": "100%",
13685		 *        "scrollXInner": "110%"
13686		 *      } );
13687		 *    } );
13688		 */
13689		"sScrollXInner": "",
13690	
13691	
13692		/**
13693		 * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
13694		 * to the given height, and enable scrolling for any data which overflows the
13695		 * current viewport. This can be used as an alternative to paging to display
13696		 * a lot of data in a small area (although paging and scrolling can both be
13697		 * enabled at the same time). This property can be any CSS unit, or a number
13698		 * (in which case it will be treated as a pixel measurement).
13699		 *  @type string
13700		 *  @default <i>blank string - i.e. disabled</i>
13701		 *
13702		 *  @dtopt Features
13703		 *  @name DataTable.defaults.scrollY
13704		 *
13705		 *  @example
13706		 *    $(document).ready( function() {
13707		 *      $('#example').dataTable( {
13708		 *        "scrollY": "200px",
13709		 *        "paginate": false
13710		 *      } );
13711		 *    } );
13712		 */
13713		"sScrollY": "",
13714	
13715	
13716		/**
13717		 * __Deprecated__ The functionality provided by this parameter has now been
13718		 * superseded by that provided through `ajax`, which should be used instead.
13719		 *
13720		 * Set the HTTP method that is used to make the Ajax call for server-side
13721		 * processing or Ajax sourced data.
13722		 *  @type string
13723		 *  @default GET
13724		 *
13725		 *  @dtopt Options
13726		 *  @dtopt Server-side
13727		 *  @name DataTable.defaults.serverMethod
13728		 *
13729		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
13730		 */
13731		"sServerMethod": "GET",
13732	
13733	
13734		/**
13735		 * DataTables makes use of renderers when displaying HTML elements for
13736		 * a table. These renderers can be added or modified by plug-ins to
13737		 * generate suitable mark-up for a site. For example the Bootstrap
13738		 * integration plug-in for DataTables uses a paging button renderer to
13739		 * display pagination buttons in the mark-up required by Bootstrap.
13740		 *
13741		 * For further information about the renderers available see
13742		 * DataTable.ext.renderer
13743		 *  @type string|object
13744		 *  @default null
13745		 *
13746		 *  @name DataTable.defaults.renderer
13747		 *
13748		 */
13749		"renderer": null,
13750	
13751	
13752		/**
13753		 * Set the data property name that DataTables should use to get a row's id
13754		 * to set as the `id` property in the node.
13755		 *  @type string
13756		 *  @default DT_RowId
13757		 *
13758		 *  @name DataTable.defaults.rowId
13759		 */
13760		"rowId": "DT_RowId"
13761	};
13762	
13763	_fnHungarianMap( DataTable.defaults );
13764	
13765	
13766	
13767	/*
13768	 * Developer note - See note in model.defaults.js about the use of Hungarian
13769	 * notation and camel case.
13770	 */
13771	
13772	/**
13773	 * Column options that can be given to DataTables at initialisation time.
13774	 *  @namespace
13775	 */
13776	DataTable.defaults.column = {
13777		/**
13778		 * Define which column(s) an order will occur on for this column. This
13779		 * allows a column's ordering to take multiple columns into account when
13780		 * doing a sort or use the data from a different column. For example first
13781		 * name / last name columns make sense to do a multi-column sort over the
13782		 * two columns.
13783		 *  @type array|int
13784		 *  @default null <i>Takes the value of the column index automatically</i>
13785		 *
13786		 *  @name DataTable.defaults.column.orderData
13787		 *  @dtopt Columns
13788		 *
13789		 *  @example
13790		 *    // Using `columnDefs`
13791		 *    $(document).ready( function() {
13792		 *      $('#example').dataTable( {
13793		 *        "columnDefs": [
13794		 *          { "orderData": [ 0, 1 ], "targets": [ 0 ] },
13795		 *          { "orderData": [ 1, 0 ], "targets": [ 1 ] },
13796		 *          { "orderData": 2, "targets": [ 2 ] }
13797		 *        ]
13798		 *      } );
13799		 *    } );
13800		 *
13801		 *  @example
13802		 *    // Using `columns`
13803		 *    $(document).ready( function() {
13804		 *      $('#example').dataTable( {
13805		 *        "columns": [
13806		 *          { "orderData": [ 0, 1 ] },
13807		 *          { "orderData": [ 1, 0 ] },
13808		 *          { "orderData": 2 },
13809		 *          null,
13810		 *          null
13811		 *        ]
13812		 *      } );
13813		 *    } );
13814		 */
13815		"aDataSort": null,
13816		"iDataSort": -1,
13817	
13818	
13819		/**
13820		 * You can control the default ordering direction, and even alter the
13821		 * behaviour of the sort handler (i.e. only allow ascending ordering etc)
13822		 * using this parameter.
13823		 *  @type array
13824		 *  @default [ 'asc', 'desc' ]
13825		 *
13826		 *  @name DataTable.defaults.column.orderSequence
13827		 *  @dtopt Columns
13828		 *
13829		 *  @example
13830		 *    // Using `columnDefs`
13831		 *    $(document).ready( function() {
13832		 *      $('#example').dataTable( {
13833		 *        "columnDefs": [
13834		 *          { "orderSequence": [ "asc" ], "targets": [ 1 ] },
13835		 *          { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] },
13836		 *          { "orderSequence": [ "desc" ], "targets": [ 3 ] }
13837		 *        ]
13838		 *      } );
13839		 *    } );
13840		 *
13841		 *  @example
13842		 *    // Using `columns`
13843		 *    $(document).ready( function() {
13844		 *      $('#example').dataTable( {
13845		 *        "columns": [
13846		 *          null,
13847		 *          { "orderSequence": [ "asc" ] },
13848		 *          { "orderSequence": [ "desc", "asc", "asc" ] },
13849		 *          { "orderSequence": [ "desc" ] },
13850		 *          null
13851		 *        ]
13852		 *      } );
13853		 *    } );
13854		 */
13855		"asSorting": [ 'asc', 'desc' ],
13856	
13857	
13858		/**
13859		 * Enable or disable filtering on the data in this column.
13860		 *  @type boolean
13861		 *  @default true
13862		 *
13863		 *  @name DataTable.defaults.column.searchable
13864		 *  @dtopt Columns
13865		 *
13866		 *  @example
13867		 *    // Using `columnDefs`
13868		 *    $(document).ready( function() {
13869		 *      $('#example').dataTable( {
13870		 *        "columnDefs": [
13871		 *          { "searchable": false, "targets": [ 0 ] }
13872		 *        ] } );
13873		 *    } );
13874		 *
13875		 *  @example
13876		 *    // Using `columns`
13877		 *    $(document).ready( function() {
13878		 *      $('#example').dataTable( {
13879		 *        "columns": [
13880		 *          { "searchable": false },
13881		 *          null,
13882		 *          null,
13883		 *          null,
13884		 *          null
13885		 *        ] } );
13886		 *    } );
13887		 */
13888		"bSearchable": true,
13889	
13890	
13891		/**
13892		 * Enable or disable ordering on this column.
13893		 *  @type boolean
13894		 *  @default true
13895		 *
13896		 *  @name DataTable.defaults.column.orderable
13897		 *  @dtopt Columns
13898		 *
13899		 *  @example
13900		 *    // Using `columnDefs`
13901		 *    $(document).ready( function() {
13902		 *      $('#example').dataTable( {
13903		 *        "columnDefs": [
13904		 *          { "orderable": false, "targets": [ 0 ] }
13905		 *        ] } );
13906		 *    } );
13907		 *
13908		 *  @example
13909		 *    // Using `columns`
13910		 *    $(document).ready( function() {
13911		 *      $('#example').dataTable( {
13912		 *        "columns": [
13913		 *          { "orderable": false },
13914		 *          null,
13915		 *          null,
13916		 *          null,
13917		 *          null
13918		 *        ] } );
13919		 *    } );
13920		 */
13921		"bSortable": true,
13922	
13923	
13924		/**
13925		 * Enable or disable the display of this column.
13926		 *  @type boolean
13927		 *  @default true
13928		 *
13929		 *  @name DataTable.defaults.column.visible
13930		 *  @dtopt Columns
13931		 *
13932		 *  @example
13933		 *    // Using `columnDefs`
13934		 *    $(document).ready( function() {
13935		 *      $('#example').dataTable( {
13936		 *        "columnDefs": [
13937		 *          { "visible": false, "targets": [ 0 ] }
13938		 *        ] } );
13939		 *    } );
13940		 *
13941		 *  @example
13942		 *    // Using `columns`
13943		 *    $(document).ready( function() {
13944		 *      $('#example').dataTable( {
13945		 *        "columns": [
13946		 *          { "visible": false },
13947		 *          null,
13948		 *          null,
13949		 *          null,
13950		 *          null
13951		 *        ] } );
13952		 *    } );
13953		 */
13954		"bVisible": true,
13955	
13956	
13957		/**
13958		 * Developer definable function that is called whenever a cell is created (Ajax source,
13959		 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
13960		 * allowing you to modify the DOM element (add background colour for example) when the
13961		 * element is available.
13962		 *  @type function
13963		 *  @param {element} td The TD node that has been created
13964		 *  @param {*} cellData The Data for the cell
13965		 *  @param {array|object} rowData The data for the whole row
13966		 *  @param {int} row The row index for the aoData data store
13967		 *  @param {int} col The column index for aoColumns
13968		 *
13969		 *  @name DataTable.defaults.column.createdCell
13970		 *  @dtopt Columns
13971		 *
13972		 *  @example
13973		 *    $(document).ready( function() {
13974		 *      $('#example').dataTable( {
13975		 *        "columnDefs": [ {
13976		 *          "targets": [3],
13977		 *          "createdCell": function (td, cellData, rowData, row, col) {
13978		 *            if ( cellData == "1.7" ) {
13979		 *              $(td).css('color', 'blue')
13980		 *            }
13981		 *          }
13982		 *        } ]
13983		 *      });
13984		 *    } );
13985		 */
13986		"fnCreatedCell": null,
13987	
13988	
13989		/**
13990		 * This parameter has been replaced by `data` in DataTables to ensure naming
13991		 * consistency. `dataProp` can still be used, as there is backwards
13992		 * compatibility in DataTables for this option, but it is strongly
13993		 * recommended that you use `data` in preference to `dataProp`.
13994		 *  @name DataTable.defaults.column.dataProp
13995		 */
13996	
13997	
13998		/**
13999		 * This property can be used to read data from any data source property,
14000		 * including deeply nested objects / properties. `data` can be given in a
14001		 * number of different ways which effect its behaviour:
14002		 *
14003		 * * `integer` - treated as an array index for the data source. This is the
14004		 *   default that DataTables uses (incrementally increased for each column).
14005		 * * `string` - read an object property from the data source. There are
14006		 *   three 'special' options that can be used in the string to alter how
14007		 *   DataTables reads the data from the source object:
14008		 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
14009		 *      Javascript to read from nested objects, so to can the options
14010		 *      specified in `data`. For example: `browser.version` or
14011		 *      `browser.name`. If your object parameter name contains a period, use
14012		 *      `\\` to escape it - i.e. `first\\.name`.
14013		 *    * `[]` - Array notation. DataTables can automatically combine data
14014		 *      from and array source, joining the data with the characters provided
14015		 *      between the two brackets. For example: `name[, ]` would provide a
14016		 *      comma-space separated list from the source array. If no characters
14017		 *      are provided between the brackets, the original array source is
14018		 *      returned.
14019		 *    * `()` - Function notation. Adding `()` to the end of a parameter will
14020		 *      execute a function of the name given. For example: `browser()` for a
14021		 *      simple function on the data source, `browser.version()` for a
14022		 *      function in a nested property or even `browser().version` to get an
14023		 *      object property if the function called returns an object. Note that
14024		 *      function notation is recommended for use in `render` rather than
14025		 *      `data` as it is much simpler to use as a renderer.
14026		 * * `null` - use the original data source for the row rather than plucking
14027		 *   data directly from it. This action has effects on two other
14028		 *   initialisation options:
14029		 *    * `defaultContent` - When null is given as the `data` option and
14030		 *      `defaultContent` is specified for the column, the value defined by
14031		 *      `defaultContent` will be used for the cell.
14032		 *    * `render` - When null is used for the `data` option and the `render`
14033		 *      option is specified for the column, the whole data source for the
14034		 *      row is used for the renderer.
14035		 * * `function` - the function given will be executed whenever DataTables
14036		 *   needs to set or get the data for a cell in the column. The function
14037		 *   takes three parameters:
14038		 *    * Parameters:
14039		 *      * `{array|object}` The data source for the row
14040		 *      * `{string}` The type call data requested - this will be 'set' when
14041		 *        setting data or 'filter', 'display', 'type', 'sort' or undefined
14042		 *        when gathering data. Note that when `undefined` is given for the
14043		 *        type DataTables expects to get the raw data for the object back<
14044		 *      * `{*}` Data to set when the second parameter is 'set'.
14045		 *    * Return:
14046		 *      * The return value from the function is not required when 'set' is
14047		 *        the type of call, but otherwise the return is what will be used
14048		 *        for the data requested.
14049		 *
14050		 * Note that `data` is a getter and setter option. If you just require
14051		 * formatting of data for output, you will likely want to use `render` which
14052		 * is simply a getter and thus simpler to use.
14053		 *
14054		 * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The
14055		 * name change reflects the flexibility of this property and is consistent
14056		 * with the naming of mRender. If 'mDataProp' is given, then it will still
14057		 * be used by DataTables, as it automatically maps the old name to the new
14058		 * if required.
14059		 *
14060		 *  @type string|int|function|null
14061		 *  @default null <i>Use automatically calculated column index</i>
14062		 *
14063		 *  @name DataTable.defaults.column.data
14064		 *  @dtopt Columns
14065		 *
14066		 *  @example
14067		 *    // Read table data from objects
14068		 *    // JSON structure for each row:
14069		 *    //   {
14070		 *    //      "engine": {value},
14071		 *    //      "browser": {value},
14072		 *    //      "platform": {value},
14073		 *    //      "version": {value},
14074		 *    //      "grade": {value}
14075		 *    //   }
14076		 *    $(document).ready( function() {
14077		 *      $('#example').dataTable( {
14078		 *        "ajaxSource": "sources/objects.txt",
14079		 *        "columns": [
14080		 *          { "data": "engine" },
14081		 *          { "data": "browser" },
14082		 *          { "data": "platform" },
14083		 *          { "data": "version" },
14084		 *          { "data": "grade" }
14085		 *        ]
14086		 *      } );
14087		 *    } );
14088		 *
14089		 *  @example
14090		 *    // Read information from deeply nested objects
14091		 *    // JSON structure for each row:
14092		 *    //   {
14093		 *    //      "engine": {value},
14094		 *    //      "browser": {value},
14095		 *    //      "platform": {
14096		 *    //         "inner": {value}
14097		 *    //      },
14098		 *    //      "details": [
14099		 *    //         {value}, {value}
14100		 *    //      ]
14101		 *    //   }
14102		 *    $(document).ready( function() {
14103		 *      $('#example').dataTable( {
14104		 *        "ajaxSource": "sources/deep.txt",
14105		 *        "columns": [
14106		 *          { "data": "engine" },
14107		 *          { "data": "browser" },
14108		 *          { "data": "platform.inner" },
14109		 *          { "data": "details.0" },
14110		 *          { "data": "details.1" }
14111		 *        ]
14112		 *      } );
14113		 *    } );
14114		 *
14115		 *  @example
14116		 *    // Using `data` as a function to provide different information for
14117		 *    // sorting, filtering and display. In this case, currency (price)
14118		 *    $(document).ready( function() {
14119		 *      $('#example').dataTable( {
14120		 *        "columnDefs": [ {
14121		 *          "targets": [ 0 ],
14122		 *          "data": function ( source, type, val ) {
14123		 *            if (type === 'set') {
14124		 *              source.price = val;
14125		 *              // Store the computed dislay and filter values for efficiency
14126		 *              source.price_display = val=="" ? "" : "$"+numberFormat(val);
14127		 *              source.price_filter  = val=="" ? "" : "$"+numberFormat(val)+" "+val;
14128		 *              return;
14129		 *            }
14130		 *            else if (type === 'display') {
14131		 *              return source.price_display;
14132		 *            }
14133		 *            else if (type === 'filter') {
14134		 *              return source.price_filter;
14135		 *            }
14136		 *            // 'sort', 'type' and undefined all just use the integer
14137		 *            return source.price;
14138		 *          }
14139		 *        } ]
14140		 *      } );
14141		 *    } );
14142		 *
14143		 *  @example
14144		 *    // Using default content
14145		 *    $(document).ready( function() {
14146		 *      $('#example').dataTable( {
14147		 *        "columnDefs": [ {
14148		 *          "targets": [ 0 ],
14149		 *          "data": null,
14150		 *          "defaultContent": "Click to edit"
14151		 *        } ]
14152		 *      } );
14153		 *    } );
14154		 *
14155		 *  @example
14156		 *    // Using array notation - outputting a list from an array
14157		 *    $(document).ready( function() {
14158		 *      $('#example').dataTable( {
14159		 *        "columnDefs": [ {
14160		 *          "targets": [ 0 ],
14161		 *          "data": "name[, ]"
14162		 *        } ]
14163		 *      } );
14164		 *    } );
14165		 *
14166		 */
14167		"mData": null,
14168	
14169	
14170		/**
14171		 * This property is the rendering partner to `data` and it is suggested that
14172		 * when you want to manipulate data for display (including filtering,
14173		 * sorting etc) without altering the underlying data for the table, use this
14174		 * property. `render` can be considered to be the the read only companion to
14175		 * `data` which is read / write (then as such more complex). Like `data`
14176		 * this option can be given in a number of different ways to effect its
14177		 * behaviour:
14178		 *
14179		 * * `integer` - treated as an array index for the data source. This is the
14180		 *   default that DataTables uses (incrementally increased for each column).
14181		 * * `string` - read an object property from the data source. There are
14182		 *   three 'special' options that can be used in the string to alter how
14183		 *   DataTables reads the data from the source object:
14184		 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
14185		 *      Javascript to read from nested objects, so to can the options
14186		 *      specified in `data`. For example: `browser.version` or
14187		 *      `browser.name`. If your object parameter name contains a period, use
14188		 *      `\\` to escape it - i.e. `first\\.name`.
14189		 *    * `[]` - Array notation. DataTables can automatically combine data
14190		 *      from and array source, joining the data with the characters provided
14191		 *      between the two brackets. For example: `name[, ]` would provide a
14192		 *      comma-space separated list from the source array. If no characters
14193		 *      are provided between the brackets, the original array source is
14194		 *      returned.
14195		 *    * `()` - Function notation. Adding `()` to the end of a parameter will
14196		 *      execute a function of the name given. For example: `browser()` for a
14197		 *      simple function on the data source, `browser.version()` for a
14198		 *      function in a nested property or even `browser().version` to get an
14199		 *      object property if the function called returns an object.
14200		 * * `object` - use different data for the different data types requested by
14201		 *   DataTables ('filter', 'display', 'type' or 'sort'). The property names
14202		 *   of the object is the data type the property refers to and the value can
14203		 *   defined using an integer, string or function using the same rules as
14204		 *   `render` normally does. Note that an `_` option _must_ be specified.
14205		 *   This is the default value to use if you haven't specified a value for
14206		 *   the data type requested by DataTables.
14207		 * * `function` - the function given will be executed whenever DataTables
14208		 *   needs to set or get the data for a cell in the column. The function
14209		 *   takes three parameters:
14210		 *    * Parameters:
14211		 *      * {array|object} The data source for the row (based on `data`)
14212		 *      * {string} The type call data requested - this will be 'filter',
14213		 *        'display', 'type' or 'sort'.
14214		 *      * {array|object} The full data source for the row (not based on
14215		 *        `data`)
14216		 *    * Return:
14217		 *      * The return value from the function is what will be used for the
14218		 *        data requested.
14219		 *
14220		 *  @type string|int|function|object|null
14221		 *  @default null Use the data source value.
14222		 *
14223		 *  @name DataTable.defaults.column.render
14224		 *  @dtopt Columns
14225		 *
14226		 *  @example
14227		 *    // Create a comma separated list from an array of objects
14228		 *    $(document).ready( function() {
14229		 *      $('#example').dataTable( {
14230		 *        "ajaxSource": "sources/deep.txt",
14231		 *        "columns": [
14232		 *          { "data": "engine" },
14233		 *          { "data": "browser" },
14234		 *          {
14235		 *            "data": "platform",
14236		 *            "render": "[, ].name"
14237		 *          }
14238		 *        ]
14239		 *      } );
14240		 *    } );
14241		 *
14242		 *  @example
14243		 *    // Execute a function to obtain data
14244		 *    $(document).ready( function() {
14245		 *      $('#example').dataTable( {
14246		 *        "columnDefs": [ {
14247		 *          "targets": [ 0 ],
14248		 *          "data": null, // Use the full data source object for the renderer's source
14249		 *          "render": "browserName()"
14250		 *        } ]
14251		 *      } );
14252		 *    } );
14253		 *
14254		 *  @example
14255		 *    // As an object, extracting different data for the different types
14256		 *    // This would be used with a data source such as:
14257		 *    //   { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" }
14258		 *    // Here the `phone` integer is used for sorting and type detection, while `phone_filter`
14259		 *    // (which has both forms) is used for filtering for if a user inputs either format, while
14260		 *    // the formatted phone number is the one that is shown in the table.
14261		 *    $(document).ready( function() {
14262		 *      $('#example').dataTable( {
14263		 *        "columnDefs": [ {
14264		 *          "targets": [ 0 ],
14265		 *          "data": null, // Use the full data source object for the renderer's source
14266		 *          "render": {
14267		 *            "_": "phone",
14268		 *            "filter": "phone_filter",
14269		 *            "display": "phone_display"
14270		 *          }
14271		 *        } ]
14272		 *      } );
14273		 *    } );
14274		 *
14275		 *  @example
14276		 *    // Use as a function to create a link from the data source
14277		 *    $(document).ready( function() {
14278		 *      $('#example').dataTable( {
14279		 *        "columnDefs": [ {
14280		 *          "targets": [ 0 ],
14281		 *          "data": "download_link",
14282		 *          "render": function ( data, type, full ) {
14283		 *            return '<a href="'+data+'">Download</a>';
14284		 *          }
14285		 *        } ]
14286		 *      } );
14287		 *    } );
14288		 */
14289		"mRender": null,
14290	
14291	
14292		/**
14293		 * Change the cell type created for the column - either TD cells or TH cells. This
14294		 * can be useful as TH cells have semantic meaning in the table body, allowing them
14295		 * to act as a header for a row (you may wish to add scope='row' to the TH elements).
14296		 *  @type string
14297		 *  @default td
14298		 *
14299		 *  @name DataTable.defaults.column.cellType
14300		 *  @dtopt Columns
14301		 *
14302		 *  @example
14303		 *    // Make the first column use TH cells
14304		 *    $(document).ready( function() {
14305		 *      $('#example').dataTable( {
14306		 *        "columnDefs": [ {
14307		 *          "targets": [ 0 ],
14308		 *          "cellType": "th"
14309		 *        } ]
14310		 *      } );
14311		 *    } );
14312		 */
14313		"sCellType": "td",
14314	
14315	
14316		/**
14317		 * Class to give to each cell in this column.
14318		 *  @type string
14319		 *  @default <i>Empty string</i>
14320		 *
14321		 *  @name DataTable.defaults.column.class
14322		 *  @dtopt Columns
14323		 *
14324		 *  @example
14325		 *    // Using `columnDefs`
14326		 *    $(document).ready( function() {
14327		 *      $('#example').dataTable( {
14328		 *        "columnDefs": [
14329		 *          { "class": "my_class", "targets": [ 0 ] }
14330		 *        ]
14331		 *      } );
14332		 *    } );
14333		 *
14334		 *  @example
14335		 *    // Using `columns`
14336		 *    $(document).ready( function() {
14337		 *      $('#example').dataTable( {
14338		 *        "columns": [
14339		 *          { "class": "my_class" },
14340		 *          null,
14341		 *          null,
14342		 *          null,
14343		 *          null
14344		 *        ]
14345		 *      } );
14346		 *    } );
14347		 */
14348		"sClass": "",
14349	
14350		/**
14351		 * When DataTables calculates the column widths to assign to each column,
14352		 * it finds the longest string in each column and then constructs a
14353		 * temporary table and reads the widths from that. The problem with this
14354		 * is that "mmm" is much wider then "iiii", but the latter is a longer
14355		 * string - thus the calculation can go wrong (doing it properly and putting
14356		 * it into an DOM object and measuring that is horribly(!) slow). Thus as
14357		 * a "work around" we provide this option. It will append its value to the
14358		 * text that is found to be the longest string for the column - i.e. padding.
14359		 * Generally you shouldn't need this!
14360		 *  @type string
14361		 *  @default <i>Empty string<i>
14362		 *
14363		 *  @name DataTable.defaults.column.contentPadding
14364		 *  @dtopt Columns
14365		 *
14366		 *  @example
14367		 *    // Using `columns`
14368		 *    $(document).ready( function() {
14369		 *      $('#example').dataTable( {
14370		 *        "columns": [
14371		 *          null,
14372		 *          null,
14373		 *          null,
14374		 *          {
14375		 *            "contentPadding": "mmm"
14376		 *          }
14377		 *        ]
14378		 *      } );
14379		 *    } );
14380		 */
14381		"sContentPadding": "",
14382	
14383	
14384		/**
14385		 * Allows a default value to be given for a column's data, and will be used
14386		 * whenever a null data source is encountered (this can be because `data`
14387		 * is set to null, or because the data source itself is null).
14388		 *  @type string
14389		 *  @default null
14390		 *
14391		 *  @name DataTable.defaults.column.defaultContent
14392		 *  @dtopt Columns
14393		 *
14394		 *  @example
14395		 *    // Using `columnDefs`
14396		 *    $(document).ready( function() {
14397		 *      $('#example').dataTable( {
14398		 *        "columnDefs": [
14399		 *          {
14400		 *            "data": null,
14401		 *            "defaultContent": "Edit",
14402		 *            "targets": [ -1 ]
14403		 *          }
14404		 *        ]
14405		 *      } );
14406		 *    } );
14407		 *
14408		 *  @example
14409		 *    // Using `columns`
14410		 *    $(document).ready( function() {
14411		 *      $('#example').dataTable( {
14412		 *        "columns": [
14413		 *          null,
14414		 *          null,
14415		 *          null,
14416		 *          {
14417		 *            "data": null,
14418		 *            "defaultContent": "Edit"
14419		 *          }
14420		 *        ]
14421		 *      } );
14422		 *    } );
14423		 */
14424		"sDefaultContent": null,
14425	
14426	
14427		/**
14428		 * This parameter is only used in DataTables' server-side processing. It can
14429		 * be exceptionally useful to know what columns are being displayed on the
14430		 * client side, and to map these to database fields. When defined, the names
14431		 * also allow DataTables to reorder information from the server if it comes
14432		 * back in an unexpected order (i.e. if you switch your columns around on the
14433		 * client-side, your server-side code does not also need updating).
14434		 *  @type string
14435		 *  @default <i>Empty string</i>
14436		 *
14437		 *  @name DataTable.defaults.column.name
14438		 *  @dtopt Columns
14439		 *
14440		 *  @example
14441		 *    // Using `columnDefs`
14442		 *    $(document).ready( function() {
14443		 *      $('#example').dataTable( {
14444		 *        "columnDefs": [
14445		 *          { "name": "engine", "targets": [ 0 ] },
14446		 *          { "name": "browser", "targets": [ 1 ] },
14447		 *          { "name": "platform", "targets": [ 2 ] },
14448		 *          { "name": "version", "targets": [ 3 ] },
14449		 *          { "name": "grade", "targets": [ 4 ] }
14450		 *        ]
14451		 *      } );
14452		 *    } );
14453		 *
14454		 *  @example
14455		 *    // Using `columns`
14456		 *    $(document).ready( function() {
14457		 *      $('#example').dataTable( {
14458		 *        "columns": [
14459		 *          { "name": "engine" },
14460		 *          { "name": "browser" },
14461		 *          { "name": "platform" },
14462		 *          { "name": "version" },
14463		 *          { "name": "grade" }
14464		 *        ]
14465		 *      } );
14466		 *    } );
14467		 */
14468		"sName": "",
14469	
14470	
14471		/**
14472		 * Defines a data source type for the ordering which can be used to read
14473		 * real-time information from the table (updating the internally cached
14474		 * version) prior to ordering. This allows ordering to occur on user
14475		 * editable elements such as form inputs.
14476		 *  @type string
14477		 *  @default std
14478		 *
14479		 *  @name DataTable.defaults.column.orderDataType
14480		 *  @dtopt Columns
14481		 *
14482		 *  @example
14483		 *    // Using `columnDefs`
14484		 *    $(document).ready( function() {
14485		 *      $('#example').dataTable( {
14486		 *        "columnDefs": [
14487		 *          { "orderDataType": "dom-text", "targets": [ 2, 3 ] },
14488		 *          { "type": "numeric", "targets": [ 3 ] },
14489		 *          { "orderDataType": "dom-select", "targets": [ 4 ] },
14490		 *          { "orderDataType": "dom-checkbox", "targets": [ 5 ] }
14491		 *        ]
14492		 *      } );
14493		 *    } );
14494		 *
14495		 *  @example
14496		 *    // Using `columns`
14497		 *    $(document).ready( function() {
14498		 *      $('#example').dataTable( {
14499		 *        "columns": [
14500		 *          null,
14501		 *          null,
14502		 *          { "orderDataType": "dom-text" },
14503		 *          { "orderDataType": "dom-text", "type": "numeric" },
14504		 *          { "orderDataType": "dom-select" },
14505		 *          { "orderDataType": "dom-checkbox" }
14506		 *        ]
14507		 *      } );
14508		 *    } );
14509		 */
14510		"sSortDataType": "std",
14511	
14512	
14513		/**
14514		 * The title of this column.
14515		 *  @type string
14516		 *  @default null <i>Derived from the 'TH' value for this column in the
14517		 *    original HTML table.</i>
14518		 *
14519		 *  @name DataTable.defaults.column.title
14520		 *  @dtopt Columns
14521		 *
14522		 *  @example
14523		 *    // Using `columnDefs`
14524		 *    $(document).ready( function() {
14525		 *      $('#example').dataTable( {
14526		 *        "columnDefs": [
14527		 *          { "title": "My column title", "targets": [ 0 ] }
14528		 *        ]
14529		 *      } );
14530		 *    } );
14531		 *
14532		 *  @example
14533		 *    // Using `columns`
14534		 *    $(document).ready( function() {
14535		 *      $('#example').dataTable( {
14536		 *        "columns": [
14537		 *          { "title": "My column title" },
14538		 *          null,
14539		 *          null,
14540		 *          null,
14541		 *          null
14542		 *        ]
14543		 *      } );
14544		 *    } );
14545		 */
14546		"sTitle": null,
14547	
14548	
14549		/**
14550		 * The type allows you to specify how the data for this column will be
14551		 * ordered. Four types (string, numeric, date and html (which will strip
14552		 * HTML tags before ordering)) are currently available. Note that only date
14553		 * formats understood by Javascript's Date() object will be accepted as type
14554		 * date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string',
14555		 * 'numeric', 'date' or 'html' (by default). Further types can be adding
14556		 * through plug-ins.
14557		 *  @type string
14558		 *  @default null <i>Auto-detected from raw data</i>
14559		 *
14560		 *  @name DataTable.defaults.column.type
14561		 *  @dtopt Columns
14562		 *
14563		 *  @example
14564		 *    // Using `columnDefs`
14565		 *    $(document).ready( function() {
14566		 *      $('#example').dataTable( {
14567		 *        "columnDefs": [
14568		 *          { "type": "html", "targets": [ 0 ] }
14569		 *        ]
14570		 *      } );
14571		 *    } );
14572		 *
14573		 *  @example
14574		 *    // Using `columns`
14575		 *    $(document).ready( function() {
14576		 *      $('#example').dataTable( {
14577		 *        "columns": [
14578		 *          { "type": "html" },
14579		 *          null,
14580		 *          null,
14581		 *          null,
14582		 *          null
14583		 *        ]
14584		 *      } );
14585		 *    } );
14586		 */
14587		"sType": null,
14588	
14589	
14590		/**
14591		 * Defining the width of the column, this parameter may take any CSS value
14592		 * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not
14593		 * been given a specific width through this interface ensuring that the table
14594		 * remains readable.
14595		 *  @type string
14596		 *  @default null <i>Automatic</i>
14597		 *
14598		 *  @name DataTable.defaults.column.width
14599		 *  @dtopt Columns
14600		 *
14601		 *  @example
14602		 *    // Using `columnDefs`
14603		 *    $(document).ready( function() {
14604		 *      $('#example').dataTable( {
14605		 *        "columnDefs": [
14606		 *          { "width": "20%", "targets": [ 0 ] }
14607		 *        ]
14608		 *      } );
14609		 *    } );
14610		 *
14611		 *  @example
14612		 *    // Using `columns`
14613		 *    $(document).ready( function() {
14614		 *      $('#example').dataTable( {
14615		 *        "columns": [
14616		 *          { "width": "20%" },
14617		 *          null,
14618		 *          null,
14619		 *          null,
14620		 *          null
14621		 *        ]
14622		 *      } );
14623		 *    } );
14624		 */
14625		"sWidth": null
14626	};
14627	
14628	_fnHungarianMap( DataTable.defaults.column );
14629	
14630	
14631	
14632	/**
14633	 * DataTables settings object - this holds all the information needed for a
14634	 * given table, including configuration, data and current application of the
14635	 * table options. DataTables does not have a single instance for each DataTable
14636	 * with the settings attached to that instance, but rather instances of the
14637	 * DataTable "class" are created on-the-fly as needed (typically by a
14638	 * $().dataTable() call) and the settings object is then applied to that
14639	 * instance.
14640	 *
14641	 * Note that this object is related to {@link DataTable.defaults} but this
14642	 * one is the internal data store for DataTables's cache of columns. It should
14643	 * NOT be manipulated outside of DataTables. Any configuration should be done
14644	 * through the initialisation options.
14645	 *  @namespace
14646	 *  @todo Really should attach the settings object to individual instances so we
14647	 *    don't need to create new instances on each $().dataTable() call (if the
14648	 *    table already exists). It would also save passing oSettings around and
14649	 *    into every single function. However, this is a very significant
14650	 *    architecture change for DataTables and will almost certainly break
14651	 *    backwards compatibility with older installations. This is something that
14652	 *    will be done in 2.0.
14653	 */
14654	DataTable.models.oSettings = {
14655		/**
14656		 * Primary features of DataTables and their enablement state.
14657		 *  @namespace
14658		 */
14659		"oFeatures": {
14660	
14661			/**
14662			 * Flag to say if DataTables should automatically try to calculate the
14663			 * optimum table and columns widths (true) or not (false).
14664			 * Note that this parameter will be set by the initialisation routine. To
14665			 * set a default use {@link DataTable.defaults}.
14666			 *  @type boolean
14667			 */
14668			"bAutoWidth": null,
14669	
14670			/**
14671			 * Delay the creation of TR and TD elements until they are actually
14672			 * needed by a driven page draw. This can give a significant speed
14673			 * increase for Ajax source and Javascript source data, but makes no
14674			 * difference at all fro DOM and server-side processing tables.
14675			 * Note that this parameter will be set by the initialisation routine. To
14676			 * set a default use {@link DataTable.defaults}.
14677			 *  @type boolean
14678			 */
14679			"bDeferRender": null,
14680	
14681			/**
14682			 * Enable filtering on the table or not. Note that if this is disabled
14683			 * then there is no filtering at all on the table, including fnFilter.
14684			 * To just remove the filtering input use sDom and remove the 'f' option.
14685			 * Note that this parameter will be set by the initialisation routine. To
14686			 * set a default use {@link DataTable.defaults}.
14687			 *  @type boolean
14688			 */
14689			"bFilter": null,
14690	
14691			/**
14692			 * Table information element (the 'Showing x of y records' div) enable
14693			 * flag.
14694			 * Note that this parameter will be set by the initialisation routine. To
14695			 * set a default use {@link DataTable.defaults}.
14696			 *  @type boolean
14697			 */
14698			"bInfo": null,
14699	
14700			/**
14701			 * Present a user control allowing the end user to change the page size
14702			 * when pagination is enabled.
14703			 * Note that this parameter will be set by the initialisation routine. To
14704			 * set a default use {@link DataTable.defaults}.
14705			 *  @type boolean
14706			 */
14707			"bLengthChange": null,
14708	
14709			/**
14710			 * Pagination enabled or not. Note that if this is disabled then length
14711			 * changing must also be disabled.
14712			 * Note that this parameter will be set by the initialisation routine. To
14713			 * set a default use {@link DataTable.defaults}.
14714			 *  @type boolean
14715			 */
14716			"bPaginate": null,
14717	
14718			/**
14719			 * Processing indicator enable flag whenever DataTables is enacting a
14720			 * user request - typically an Ajax request for server-side processing.
14721			 * Note that this parameter will be set by the initialisation routine. To
14722			 * set a default use {@link DataTable.defaults}.
14723			 *  @type boolean
14724			 */
14725			"bProcessing": null,
14726	
14727			/**
14728			 * Server-side processing enabled flag - when enabled DataTables will
14729			 * get all data from the server for every draw - there is no filtering,
14730			 * sorting or paging done on the client-side.
14731			 * Note that this parameter will be set by the initialisation routine. To
14732			 * set a default use {@link DataTable.defaults}.
14733			 *  @type boolean
14734			 */
14735			"bServerSide": null,
14736	
14737			/**
14738			 * Sorting enablement flag.
14739			 * Note that this parameter will be set by the initialisation routine. To
14740			 * set a default use {@link DataTable.defaults}.
14741			 *  @type boolean
14742			 */
14743			"bSort": null,
14744	
14745			/**
14746			 * Multi-column sorting
14747			 * Note that this parameter will be set by the initialisation routine. To
14748			 * set a default use {@link DataTable.defaults}.
14749			 *  @type boolean
14750			 */
14751			"bSortMulti": null,
14752	
14753			/**
14754			 * Apply a class to the columns which are being sorted to provide a
14755			 * visual highlight or not. This can slow things down when enabled since
14756			 * there is a lot of DOM interaction.
14757			 * Note that this parameter will be set by the initialisation routine. To
14758			 * set a default use {@link DataTable.defaults}.
14759			 *  @type boolean
14760			 */
14761			"bSortClasses": null,
14762	
14763			/**
14764			 * State saving enablement flag.
14765			 * Note that this parameter will be set by the initialisation routine. To
14766			 * set a default use {@link DataTable.defaults}.
14767			 *  @type boolean
14768			 */
14769			"bStateSave": null
14770		},
14771	
14772	
14773		/**
14774		 * Scrolling settings for a table.
14775		 *  @namespace
14776		 */
14777		"oScroll": {
14778			/**
14779			 * When the table is shorter in height than sScrollY, collapse the
14780			 * table container down to the height of the table (when true).
14781			 * Note that this parameter will be set by the initialisation routine. To
14782			 * set a default use {@link DataTable.defaults}.
14783			 *  @type boolean
14784			 */
14785			"bCollapse": null,
14786	
14787			/**
14788			 * Width of the scrollbar for the web-browser's platform. Calculated
14789			 * during table initialisation.
14790			 *  @type int
14791			 *  @default 0
14792			 */
14793			"iBarWidth": 0,
14794	
14795			/**
14796			 * Viewport width for horizontal scrolling. Horizontal scrolling is
14797			 * disabled if an empty string.
14798			 * Note that this parameter will be set by the initialisation routine. To
14799			 * set a default use {@link DataTable.defaults}.
14800			 *  @type string
14801			 */
14802			"sX": null,
14803	
14804			/**
14805			 * Width to expand the table to when using x-scrolling. Typically you
14806			 * should not need to use this.
14807			 * Note that this parameter will be set by the initialisation routine. To
14808			 * set a default use {@link DataTable.defaults}.
14809			 *  @type string
14810			 *  @deprecated
14811			 */
14812			"sXInner": null,
14813	
14814			/**
14815			 * Viewport height for vertical scrolling. Vertical scrolling is disabled
14816			 * if an empty string.
14817			 * Note that this parameter will be set by the initialisation routine. To
14818			 * set a default use {@link DataTable.defaults}.
14819			 *  @type string
14820			 */
14821			"sY": null
14822		},
14823	
14824		/**
14825		 * Language information for the table.
14826		 *  @namespace
14827		 *  @extends DataTable.defaults.oLanguage
14828		 */
14829		"oLanguage": {
14830			/**
14831			 * Information callback function. See
14832			 * {@link DataTable.defaults.fnInfoCallback}
14833			 *  @type function
14834			 *  @default null
14835			 */
14836			"fnInfoCallback": null
14837		},
14838	
14839		/**
14840		 * Browser support parameters
14841		 *  @namespace
14842		 */
14843		"oBrowser": {
14844			/**
14845			 * Indicate if the browser incorrectly calculates width:100% inside a
14846			 * scrolling element (IE6/7)
14847			 *  @type boolean
14848			 *  @default false
14849			 */
14850			"bScrollOversize": false,
14851	
14852			/**
14853			 * Determine if the vertical scrollbar is on the right or left of the
14854			 * scrolling container - needed for rtl language layout, although not
14855			 * all browsers move the scrollbar (Safari).
14856			 *  @type boolean
14857			 *  @default false
14858			 */
14859			"bScrollbarLeft": false,
14860	
14861			/**
14862			 * Flag for if `getBoundingClientRect` is fully supported or not
14863			 *  @type boolean
14864			 *  @default false
14865			 */
14866			"bBounding": false,
14867	
14868			/**
14869			 * Browser scrollbar width
14870			 *  @type integer
14871			 *  @default 0
14872			 */
14873			"barWidth": 0
14874		},
14875	
14876	
14877		"ajax": null,
14878	
14879	
14880		/**
14881		 * Array referencing the nodes which are used for the features. The
14882		 * parameters of this object match what is allowed by sDom - i.e.
14883		 *   <ul>
14884		 *     <li>'l' - Length changing</li>
14885		 *     <li>'f' - Filtering input</li>
14886		 *     <li>'t' - The table!</li>
14887		 *     <li>'i' - Information</li>
14888		 *     <li>'p' - Pagination</li>
14889		 *     <li>'r' - pRocessing</li>
14890		 *   </ul>
14891		 *  @type array
14892		 *  @default []
14893		 */
14894		"aanFeatures": [],
14895	
14896		/**
14897		 * Store data information - see {@link DataTable.models.oRow} for detailed
14898		 * information.
14899		 *  @type array
14900		 *  @default []
14901		 */
14902		"aoData": [],
14903	
14904		/**
14905		 * Array of indexes which are in the current display (after filtering etc)
14906		 *  @type array
14907		 *  @default []
14908		 */
14909		"aiDisplay": [],
14910	
14911		/**
14912		 * Array of indexes for display - no filtering
14913		 *  @type array
14914		 *  @default []
14915		 */
14916		"aiDisplayMaster": [],
14917	
14918		/**
14919		 * Map of row ids to data indexes
14920		 *  @type object
14921		 *  @default {}
14922		 */
14923		"aIds": {},
14924	
14925		/**
14926		 * Store information about each column that is in use
14927		 *  @type array
14928		 *  @default []
14929		 */
14930		"aoColumns": [],
14931	
14932		/**
14933		 * Store information about the table's header
14934		 *  @type array
14935		 *  @default []
14936		 */
14937		"aoHeader": [],
14938	
14939		/**
14940		 * Store information about the table's footer
14941		 *  @type array
14942		 *  @default []
14943		 */
14944		"aoFooter": [],
14945	
14946		/**
14947		 * Store the applied global search information in case we want to force a
14948		 * research or compare the old search to a new one.
14949		 * Note that this parameter will be set by the initialisation routine. To
14950		 * set a default use {@link DataTable.defaults}.
14951		 *  @namespace
14952		 *  @extends DataTable.models.oSearch
14953		 */
14954		"oPreviousSearch": {},
14955	
14956		/**
14957		 * Store the applied search for each column - see
14958		 * {@link DataTable.models.oSearch} for the format that is used for the
14959		 * filtering information for each column.
14960		 *  @type array
14961		 *  @default []
14962		 */
14963		"aoPreSearchCols": [],
14964	
14965		/**
14966		 * Sorting that is applied to the table. Note that the inner arrays are
14967		 * used in the following manner:
14968		 * <ul>
14969		 *   <li>Index 0 - column number</li>
14970		 *   <li>Index 1 - current sorting direction</li>
14971		 * </ul>
14972		 * Note that this parameter will be set by the initialisation routine. To
14973		 * set a default use {@link DataTable.defaults}.
14974		 *  @type array
14975		 *  @todo These inner arrays should really be objects
14976		 */
14977		"aaSorting": null,
14978	
14979		/**
14980		 * Sorting that is always applied to the table (i.e. prefixed in front of
14981		 * aaSorting).
14982		 * Note that this parameter will be set by the initialisation routine. To
14983		 * set a default use {@link DataTable.defaults}.
14984		 *  @type array
14985		 *  @default []
14986		 */
14987		"aaSortingFixed": [],
14988	
14989		/**
14990		 * Classes to use for the striping of a table.
14991		 * Note that this parameter will be set by the initialisation routine. To
14992		 * set a default use {@link DataTable.defaults}.
14993		 *  @type array
14994		 *  @default []
14995		 */
14996		"asStripeClasses": null,
14997	
14998		/**
14999		 * If restoring a table - we should restore its striping classes as well
15000		 *  @type array
15001		 *  @default []
15002		 */
15003		"asDestroyStripes": [],
15004	
15005		/**
15006		 * If restoring a table - we should restore its width
15007		 *  @type int
15008		 *  @default 0
15009		 */
15010		"sDestroyWidth": 0,
15011	
15012		/**
15013		 * Callback functions array for every time a row is inserted (i.e. on a draw).
15014		 *  @type array
15015		 *  @default []
15016		 */
15017		"aoRowCallback": [],
15018	
15019		/**
15020		 * Callback functions for the header on each draw.
15021		 *  @type array
15022		 *  @default []
15023		 */
15024		"aoHeaderCallback": [],
15025	
15026		/**
15027		 * Callback function for the footer on each draw.
15028		 *  @type array
15029		 *  @default []
15030		 */
15031		"aoFooterCallback": [],
15032	
15033		/**
15034		 * Array of callback functions for draw callback functions
15035		 *  @type array
15036		 *  @default []
15037		 */
15038		"aoDrawCallback": [],
15039	
15040		/**
15041		 * Array of callback functions for row created function
15042		 *  @type array
15043		 *  @default []
15044		 */
15045		"aoRowCreatedCallback": [],
15046	
15047		/**
15048		 * Callback functions for just before the table is redrawn. A return of
15049		 * false will be used to cancel the draw.
15050		 *  @type array
15051		 *  @default []
15052		 */
15053		"aoPreDrawCallback": [],
15054	
15055		/**
15056		 * Callback functions for when the table has been initialised.
15057		 *  @type array
15058		 *  @default []
15059		 */
15060		"aoInitComplete": [],
15061	
15062	
15063		/**
15064		 * Callbacks for modifying the settings to be stored for state saving, prior to
15065		 * saving state.
15066		 *  @type array
15067		 *  @default []
15068		 */
15069		"aoStateSaveParams": [],
15070	
15071		/**
15072		 * Callbacks for modifying the settings that have been stored for state saving
15073		 * prior to using the stored values to restore the state.
15074		 *  @type array
15075		 *  @default []
15076		 */
15077		"aoStateLoadParams": [],
15078	
15079		/**
15080		 * Callbacks for operating on the settings object once the saved state has been
15081		 * loaded
15082		 *  @type array
15083		 *  @default []
15084		 */
15085		"aoStateLoaded": [],
15086	
15087		/**
15088		 * Cache the table ID for quick access
15089		 *  @type string
15090		 *  @default <i>Empty string</i>
15091		 */
15092		"sTableId": "",
15093	
15094		/**
15095		 * The TABLE node for the main table
15096		 *  @type node
15097		 *  @default null
15098		 */
15099		"nTable": null,
15100	
15101		/**
15102		 * Permanent ref to the thead element
15103		 *  @type node
15104		 *  @default null
15105		 */
15106		"nTHead": null,
15107	
15108		/**
15109		 * Permanent ref to the tfoot element - if it exists
15110		 *  @type node
15111		 *  @default null
15112		 */
15113		"nTFoot": null,
15114	
15115		/**
15116		 * Permanent ref to the tbody element
15117		 *  @type node
15118		 *  @default null
15119		 */
15120		"nTBody": null,
15121	
15122		/**
15123		 * Cache the wrapper node (contains all DataTables controlled elements)
15124		 *  @type node
15125		 *  @default null
15126		 */
15127		"nTableWrapper": null,
15128	
15129		/**
15130		 * Indicate if when using server-side processing the loading of data
15131		 * should be deferred until the second draw.
15132		 * Note that this parameter will be set by the initialisation routine. To
15133		 * set a default use {@link DataTable.defaults}.
15134		 *  @type boolean
15135		 *  @default false
15136		 */
15137		"bDeferLoading": false,
15138	
15139		/**
15140		 * Indicate if all required information has been read in
15141		 *  @type boolean
15142		 *  @default false
15143		 */
15144		"bInitialised": false,
15145	
15146		/**
15147		 * Information about open rows. Each object in the array has the parameters
15148		 * 'nTr' and 'nParent'
15149		 *  @type array
15150		 *  @default []
15151		 */
15152		"aoOpenRows": [],
15153	
15154		/**
15155		 * Dictate the positioning of DataTables' control elements - see
15156		 * {@link DataTable.model.oInit.sDom}.
15157		 * Note that this parameter will be set by the initialisation routine. To
15158		 * set a default use {@link DataTable.defaults}.
15159		 *  @type string
15160		 *  @default null
15161		 */
15162		"sDom": null,
15163	
15164		/**
15165		 * Search delay (in mS)
15166		 *  @type integer
15167		 *  @default null
15168		 */
15169		"searchDelay": null,
15170	
15171		/**
15172		 * Which type of pagination should be used.
15173		 * Note that this parameter will be set by the initialisation routine. To
15174		 * set a default use {@link DataTable.defaults}.
15175		 *  @type string
15176		 *  @default two_button
15177		 */
15178		"sPaginationType": "two_button",
15179	
15180		/**
15181		 * The state duration (for `stateSave`) in seconds.
15182		 * Note that this parameter will be set by the initialisation routine. To
15183		 * set a default use {@link DataTable.defaults}.
15184		 *  @type int
15185		 *  @default 0
15186		 */
15187		"iStateDuration": 0,
15188	
15189		/**
15190		 * Array of callback functions for state saving. Each array element is an
15191		 * object with the following parameters:
15192		 *   <ul>
15193		 *     <li>function:fn - function to call. Takes two parameters, oSettings
15194		 *       and the JSON string to save that has been thus far created. Returns
15195		 *       a JSON string to be inserted into a json object
15196		 *       (i.e. '"param": [ 0, 1, 2]')</li>
15197		 *     <li>string:sName - name of callback</li>
15198		 *   </ul>
15199		 *  @type array
15200		 *  @default []
15201		 */
15202		"aoStateSave": [],
15203	
15204		/**
15205		 * Array of callback functions for state loading. Each array element is an
15206		 * object with the following parameters:
15207		 *   <ul>
15208		 *     <li>function:fn - function to call. Takes two parameters, oSettings
15209		 *       and the object stored. May return false to cancel state loading</li>
15210		 *     <li>string:sName - name of callback</li>
15211		 *   </ul>
15212		 *  @type array
15213		 *  @default []
15214		 */
15215		"aoStateLoad": [],
15216	
15217		/**
15218		 * State that was saved. Useful for back reference
15219		 *  @type object
15220		 *  @default null
15221		 */
15222		"oSavedState": null,
15223	
15224		/**
15225		 * State that was loaded. Useful for back reference
15226		 *  @type object
15227		 *  @default null
15228		 */
15229		"oLoadedState": null,
15230	
15231		/**
15232		 * Source url for AJAX data for the table.
15233		 * Note that this parameter will be set by the initialisation routine. To
15234		 * set a default use {@link DataTable.defaults}.
15235		 *  @type string
15236		 *  @default null
15237		 */
15238		"sAjaxSource": null,
15239	
15240		/**
15241		 * Property from a given object from which to read the table data from. This
15242		 * can be an empty string (when not server-side processing), in which case
15243		 * it is  assumed an an array is given directly.
15244		 * Note that this parameter will be set by the initialisation routine. To
15245		 * set a default use {@link DataTable.defaults}.
15246		 *  @type string
15247		 */
15248		"sAjaxDataProp": null,
15249	
15250		/**
15251		 * Note if draw should be blocked while getting data
15252		 *  @type boolean
15253		 *  @default true
15254		 */
15255		"bAjaxDataGet": true,
15256	
15257		/**
15258		 * The last jQuery XHR object that was used for server-side data gathering.
15259		 * This can be used for working with the XHR information in one of the
15260		 * callbacks
15261		 *  @type object
15262		 *  @default null
15263		 */
15264		"jqXHR": null,
15265	
15266		/**
15267		 * JSON returned from the server in the last Ajax request
15268		 *  @type object
15269		 *  @default undefined
15270		 */
15271		"json": undefined,
15272	
15273		/**
15274		 * Data submitted as part of the last Ajax request
15275		 *  @type object
15276		 *  @default undefined
15277		 */
15278		"oAjaxData": undefined,
15279	
15280		/**
15281		 * Function to get the server-side data.
15282		 * Note that this parameter will be set by the initialisation routine. To
15283		 * set a default use {@link DataTable.defaults}.
15284		 *  @type function
15285		 */
15286		"fnServerData": null,
15287	
15288		/**
15289		 * Functions which are called prior to sending an Ajax request so extra
15290		 * parameters can easily be sent to the server
15291		 *  @type array
15292		 *  @default []
15293		 */
15294		"aoServerParams": [],
15295	
15296		/**
15297		 * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
15298		 * required).
15299		 * Note that this parameter will be set by the initialisation routine. To
15300		 * set a default use {@link DataTable.defaults}.
15301		 *  @type string
15302		 */
15303		"sServerMethod": null,
15304	
15305		/**
15306		 * Format numbers for display.
15307		 * Note that this parameter will be set by the initialisation routine. To
15308		 * set a default use {@link DataTable.defaults}.
15309		 *  @type function
15310		 */
15311		"fnFormatNumber": null,
15312	
15313		/**
15314		 * List of options that can be used for the user selectable length menu.
15315		 * Note that this parameter will be set by the initialisation routine. To
15316		 * set a default use {@link DataTable.defaults}.
15317		 *  @type array
15318		 *  @default []
15319		 */
15320		"aLengthMenu": null,
15321	
15322		/**
15323		 * Counter for the draws that the table does. Also used as a tracker for
15324		 * server-side processing
15325		 *  @type int
15326		 *  @default 0
15327		 */
15328		"iDraw": 0,
15329	
15330		/**
15331		 * Indicate if a redraw is being done - useful for Ajax
15332		 *  @type boolean
15333		 *  @default false
15334		 */
15335		"bDrawing": false,
15336	
15337		/**
15338		 * Draw index (iDraw) of the last error when parsing the returned data
15339		 *  @type int
15340		 *  @default -1
15341		 */
15342		"iDrawError": -1,
15343	
15344		/**
15345		 * Paging display length
15346		 *  @type int
15347		 *  @default 10
15348		 */
15349		"_iDisplayLength": 10,
15350	
15351		/**
15352		 * Paging start point - aiDisplay index
15353		 *  @type int
15354		 *  @default 0
15355		 */
15356		"_iDisplayStart": 0,
15357	
15358		/**
15359		 * Server-side processing - number of records in the result set
15360		 * (i.e. before filtering), Use fnRecordsTotal rather than
15361		 * this property to get the value of the number of records, regardless of
15362		 * the server-side processing setting.
15363		 *  @type int
15364		 *  @default 0
15365		 *  @private
15366		 */
15367		"_iRecordsTotal": 0,
15368	
15369		/**
15370		 * Server-side processing - number of records in the current display set
15371		 * (i.e. after filtering). Use fnRecordsDisplay rather than
15372		 * this property to get the value of the number of records, regardless of
15373		 * the server-side processing setting.
15374		 *  @type boolean
15375		 *  @default 0
15376		 *  @private
15377		 */
15378		"_iRecordsDisplay": 0,
15379	
15380		/**
15381		 * The classes to use for the table
15382		 *  @type object
15383		 *  @default {}
15384		 */
15385		"oClasses": {},
15386	
15387		/**
15388		 * Flag attached to the settings object so you can check in the draw
15389		 * callback if filtering has been done in the draw. Deprecated in favour of
15390		 * events.
15391		 *  @type boolean
15392		 *  @default false
15393		 *  @deprecated
15394		 */
15395		"bFiltered": false,
15396	
15397		/**
15398		 * Flag attached to the settings object so you can check in the draw
15399		 * callback if sorting has been done in the draw. Deprecated in favour of
15400		 * events.
15401		 *  @type boolean
15402		 *  @default false
15403		 *  @deprecated
15404		 */
15405		"bSorted": false,
15406	
15407		/**
15408		 * Indicate that if multiple rows are in the header and there is more than
15409		 * one unique cell per column, if the top one (true) or bottom one (false)
15410		 * should be used for sorting / title by DataTables.
15411		 * Note that this parameter will be set by the initialisation routine. To
15412		 * set a default use {@link DataTable.defaults}.
15413		 *  @type boolean
15414		 */
15415		"bSortCellsTop": null,
15416	
15417		/**
15418		 * Initialisation object that is used for the table
15419		 *  @type object
15420		 *  @default null
15421		 */
15422		"oInit": null,
15423	
15424		/**
15425		 * Destroy callback functions - for plug-ins to attach themselves to the
15426		 * destroy so they can clean up markup and events.
15427		 *  @type array
15428		 *  @default []
15429		 */
15430		"aoDestroyCallback": [],
15431	
15432	
15433		/**
15434		 * Get the number of records in the current record set, before filtering
15435		 *  @type function
15436		 */
15437		"fnRecordsTotal": function ()
15438		{
15439			return _fnDataSource( this ) == 'ssp' ?
15440				this._iRecordsTotal * 1 :
15441				this.aiDisplayMaster.length;
15442		},
15443	
15444		/**
15445		 * Get the number of records in the current record set, after filtering
15446		 *  @type function
15447		 */
15448		"fnRecordsDisplay": function ()
15449		{
15450			return _fnDataSource( this ) == 'ssp' ?
15451				this._iRecordsDisplay * 1 :
15452				this.aiDisplay.length;
15453		},
15454	
15455		/**
15456		 * Get the display end point - aiDisplay index
15457		 *  @type function
15458		 */
15459		"fnDisplayEnd": function ()
15460		{
15461			var
15462				len      = this._iDisplayLength,
15463				start    = this._iDisplayStart,
15464				calc     = start + len,
15465				records  = this.aiDisplay.length,
15466				features = this.oFeatures,
15467				paginate = features.bPaginate;
15468	
15469			if ( features.bServerSide ) {
15470				return paginate === false || len === -1 ?
15471					start + records :
15472					Math.min( start+len, this._iRecordsDisplay );
15473			}
15474			else {
15475				return ! paginate || calc>records || len===-1 ?
15476					records :
15477					calc;
15478			}
15479		},
15480	
15481		/**
15482		 * The DataTables object for this table
15483		 *  @type object
15484		 *  @default null
15485		 */
15486		"oInstance": null,
15487	
15488		/**
15489		 * Unique identifier for each instance of the DataTables object. If there
15490		 * is an ID on the table node, then it takes that value, otherwise an
15491		 * incrementing internal counter is used.
15492		 *  @type string
15493		 *  @default null
15494		 */
15495		"sInstance": null,
15496	
15497		/**
15498		 * tabindex attribute value that is added to DataTables control elements, allowing
15499		 * keyboard navigation of the table and its controls.
15500		 */
15501		"iTabIndex": 0,
15502	
15503		/**
15504		 * DIV container for the footer scrolling table if scrolling
15505		 */
15506		"nScrollHead": null,
15507	
15508		/**
15509		 * DIV container for the footer scrolling table if scrolling
15510		 */
15511		"nScrollFoot": null,
15512	
15513		/**
15514		 * Last applied sort
15515		 *  @type array
15516		 *  @default []
15517		 */
15518		"aLastSort": [],
15519	
15520		/**
15521		 * Stored plug-in instances
15522		 *  @type object
15523		 *  @default {}
15524		 */
15525		"oPlugins": {},
15526	
15527		/**
15528		 * Function used to get a row's id from the row's data
15529		 *  @type function
15530		 *  @default null
15531		 */
15532		"rowIdFn": null,
15533	
15534		/**
15535		 * Data location where to store a row's id
15536		 *  @type string
15537		 *  @default null
15538		 */
15539		"rowId": null
15540	};
15541
15542	/**
15543	 * Extension object for DataTables that is used to provide all extension
15544	 * options.
15545	 *
15546	 * Note that the `DataTable.ext` object is available through
15547	 * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is
15548	 * also aliased to `jQuery.fn.dataTableExt` for historic reasons.
15549	 *  @namespace
15550	 *  @extends DataTable.models.ext
15551	 */
15552	
15553	
15554	/**
15555	 * DataTables extensions
15556	 * 
15557	 * This namespace acts as a collection area for plug-ins that can be used to
15558	 * extend DataTables capabilities. Indeed many of the build in methods
15559	 * use this method to provide their own capabilities (sorting methods for
15560	 * example).
15561	 *
15562	 * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy
15563	 * reasons
15564	 *
15565	 *  @namespace
15566	 */
15567	DataTable.ext = _ext = {
15568		/**
15569		 * Buttons. For use with the Buttons extension for DataTables. This is
15570		 * defined here so other extensions can define buttons regardless of load
15571		 * order. It is _not_ used by DataTables core.
15572		 *
15573		 *  @type object
15574		 *  @default {}
15575		 */
15576		buttons: {},
15577	
15578	
15579		/**
15580		 * Element class names
15581		 *
15582		 *  @type object
15583		 *  @default {}
15584		 */
15585		classes: {},
15586	
15587	
15588		/**
15589		 * DataTables build type (expanded by the download builder)
15590		 *
15591		 *  @type string
15592		 */
15593		builder: "-source-",
15594	
15595	
15596		/**
15597		 * Error reporting.
15598		 * 
15599		 * How should DataTables report an error. Can take the value 'alert',
15600		 * 'throw', 'none' or a function.
15601		 *
15602		 *  @type string|function
15603		 *  @default alert
15604		 */
15605		errMode: "alert",
15606	
15607	
15608		/**
15609		 * Feature plug-ins.
15610		 * 
15611		 * This is an array of objects which describe the feature plug-ins that are
15612		 * available to DataTables. These feature plug-ins are then available for
15613		 * use through the `dom` initialisation option.
15614		 * 
15615		 * Each feature plug-in is described by an object which must have the
15616		 * following properties:
15617		 * 
15618		 * * `fnInit` - function that is used to initialise the plug-in,
15619		 * * `cFeature` - a character so the feature can be enabled by the `dom`
15620		 *   instillation option. This is case sensitive.
15621		 *
15622		 * The `fnInit` function has the following input parameters:
15623		 *
15624		 * 1. `{object}` DataTables settings object: see
15625		 *    {@link DataTable.models.oSettings}
15626		 *
15627		 * And the following return is expected:
15628		 * 
15629		 * * {node|null} The element which contains your feature. Note that the
15630		 *   return may also be void if your plug-in does not require to inject any
15631		 *   DOM elements into DataTables control (`dom`) - for example this might
15632		 *   be useful when developing a plug-in which allows table control via
15633		 *   keyboard entry
15634		 *
15635		 *  @type array
15636		 *
15637		 *  @example
15638		 *    $.fn.dataTable.ext.features.push( {
15639		 *      "fnInit": function( oSettings ) {
15640		 *        return new TableTools( { "oDTSettings": oSettings } );
15641		 *      },
15642		 *      "cFeature": "T"
15643		 *    } );
15644		 */
15645		feature: [],
15646	
15647	
15648		/**
15649		 * Row searching.
15650		 * 
15651		 * This method of searching is complimentary to the default type based
15652		 * searching, and a lot more comprehensive as it allows you complete control
15653		 * over the searching logic. Each element in this array is a function
15654		 * (parameters described below) that is called for every row in the table,
15655		 * and your logic decides if it should be included in the searching data set
15656		 * or not.
15657		 *
15658		 * Searching functions have the following input parameters:
15659		 *
15660		 * 1. `{object}` DataTables settings object: see
15661		 *    {@link DataTable.models.oSettings}
15662		 * 2. `{array|object}` Data for the row to be processed (same as the
15663		 *    original format that was passed in as the data source, or an array
15664		 *    from a DOM data source
15665		 * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which
15666		 *    can be useful to retrieve the `TR` element if you need DOM interaction.
15667		 *
15668		 * And the following return is expected:
15669		 *
15670		 * * {boolean} Include the row in the searched result set (true) or not
15671		 *   (false)
15672		 *
15673		 * Note that as with the main search ability in DataTables, technically this
15674		 * is "filtering", since it is subtractive. However, for consistency in
15675		 * naming we call it searching here.
15676		 *
15677		 *  @type array
15678		 *  @default []
15679		 *
15680		 *  @example
15681		 *    // The following example shows custom search being applied to the
15682		 *    // fourth column (i.e. the data[3] index) based on two input values
15683		 *    // from the end-user, matching the data in a certain range.
15684		 *    $.fn.dataTable.ext.search.push(
15685		 *      function( settings, data, dataIndex ) {
15686		 *        var min = document.getElementById('min').value * 1;
15687		 *        var max = document.getElementById('max').value * 1;
15688		 *        var version = data[3] == "-" ? 0 : data[3]*1;
15689		 *
15690		 *        if ( min == "" && max == "" ) {
15691		 *          return true;
15692		 *        }
15693		 *        else if ( min == "" && version < max ) {
15694		 *          return true;
15695		 *        }
15696		 *        else if ( min < version && "" == max ) {
15697		 *          return true;
15698		 *        }
15699		 *        else if ( min < version && version < max ) {
15700		 *          return true;
15701		 *        }
15702		 *        return false;
15703		 *      }
15704		 *    );
15705		 */
15706		search: [],
15707	
15708	
15709		/**
15710		 * Selector extensions
15711		 *
15712		 * The `selector` option can be used to extend the options available for the
15713		 * selector modifier options (`selector-modifier` object data type) that
15714		 * each of the three built in selector types offer (row, column and cell +
15715		 * their plural counterparts). For example the Select extension uses this
15716		 * mechanism to provide an option to select only rows, columns and cells
15717		 * that have been marked as selected by the end user (`{selected: true}`),
15718		 * which can be used in conjunction with the existing built in selector
15719		 * options.
15720		 *
15721		 * Each property is an array to which functions can be pushed. The functions
15722		 * take three attributes:
15723		 *
15724		 * * Settings object for the host table
15725		 * * Options object (`selector-modifier` object type)
15726		 * * Array of selected item indexes
15727		 *
15728		 * The return is an array of the resulting item indexes after the custom
15729		 * selector has been applied.
15730		 *
15731		 *  @type object
15732		 */
15733		selector: {
15734			cell: [],
15735			column: [],
15736			row: []
15737		},
15738	
15739	
15740		/**
15741		 * Internal functions, exposed for used in plug-ins.
15742		 * 
15743		 * Please note that you should not need to use the internal methods for
15744		 * anything other than a plug-in (and even then, try to avoid if possible).
15745		 * The internal function may change between releases.
15746		 *
15747		 *  @type object
15748		 *  @default {}
15749		 */
15750		internal: {},
15751	
15752	
15753		/**
15754		 * Legacy configuration options. Enable and disable legacy options that
15755		 * are available in DataTables.
15756		 *
15757		 *  @type object
15758		 */
15759		legacy: {
15760			/**
15761			 * Enable / disable DataTables 1.9 compatible server-side processing
15762			 * requests
15763			 *
15764			 *  @type boolean
15765			 *  @default null
15766			 */
15767			ajax: null
15768		},
15769	
15770	
15771		/**
15772		 * Pagination plug-in methods.
15773		 * 
15774		 * Each entry in this object is a function and defines which buttons should
15775		 * be shown by the pagination rendering method that is used for the table:
15776		 * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the
15777		 * buttons are displayed in the document, while the functions here tell it
15778		 * what buttons to display. This is done by returning an array of button
15779		 * descriptions (what each button will do).
15780		 *
15781		 * Pagination types (the four built in options and any additional plug-in
15782		 * options defined here) can be used through the `paginationType`
15783		 * initialisation parameter.
15784		 *
15785		 * The functions defined take two parameters:
15786		 *
15787		 * 1. `{int} page` The current page index
15788		 * 2. `{int} pages` The number of pages in the table
15789		 *
15790		 * Each function is expected to return an array where each element of the
15791		 * array can be one of:
15792		 *
15793		 * * `first` - Jump to first page when activated
15794		 * * `last` - Jump to last page when activated
15795		 * * `previous` - Show previous page when activated
15796		 * * `next` - Show next page when activated
15797		 * * `{int}` - Show page of the index given
15798		 * * `{array}` - A nested array containing the above elements to add a
15799		 *   containing 'DIV' element (might be useful for styling).
15800		 *
15801		 * Note that DataTables v1.9- used this object slightly differently whereby
15802		 * an object with two functions would be defined for each plug-in. That
15803		 * ability is still supported by DataTables 1.10+ to provide backwards
15804		 * compatibility, but this option of use is now decremented and no longer
15805		 * documented in DataTables 1.10+.
15806		 *
15807		 *  @type object
15808		 *  @default {}
15809		 *
15810		 *  @example
15811		 *    // Show previous, next and current page buttons only
15812		 *    $.fn.dataTableExt.oPagination.current = function ( page, pages ) {
15813		 *      return [ 'previous', page, 'next' ];
15814		 *    };
15815		 */
15816		pager: {},
15817	
15818	
15819		renderer: {
15820			pageButton: {},
15821			header: {}
15822		},
15823	
15824	
15825		/**
15826		 * Ordering plug-ins - custom data source
15827		 * 
15828		 * The extension options for ordering of data available here is complimentary
15829		 * to the default type based ordering that DataTables typically uses. It
15830		 * allows much greater control over the the data that is being used to
15831		 * order a column, but is necessarily therefore more complex.
15832		 * 
15833		 * This type of ordering is useful if you want to do ordering based on data
15834		 * live from the DOM (for example the contents of an 'input' element) rather
15835		 * than just the static string that DataTables knows of.
15836		 * 
15837		 * The way these plug-ins work is that you create an array of the values you
15838		 * wish to be ordering for the column in question and then return that
15839		 * array. The data in the array much be in the index order of the rows in
15840		 * the table (not the currently ordering order!). Which order data gathering
15841		 * function is run here depends on the `dt-init columns.orderDataType`
15842		 * parameter that is used for the column (if any).
15843		 *
15844		 * The functions defined take two parameters:
15845		 *
15846		 * 1. `{object}` DataTables settings object: see
15847		 *    {@link DataTable.models.oSettings}
15848		 * 2. `{int}` Target column index
15849		 *
15850		 * Each function is expected to return an array:
15851		 *
15852		 * * `{array}` Data for the column to be ordering upon
15853		 *
15854		 *  @type array
15855		 *
15856		 *  @example
15857		 *    // Ordering using `input` node values
15858		 *    $.fn.dataTable.ext.order['dom-text'] = function  ( settings, col )
15859		 *    {
15860		 *      return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
15861		 *        return $('input', td).val();
15862		 *      } );
15863		 *    }
15864		 */
15865		order: {},
15866	
15867	
15868		/**
15869		 * Type based plug-ins.
15870		 *
15871		 * Each column in DataTables has a type assigned to it, either by automatic
15872		 * detection or by direct assignment using the `type` option for the column.
15873		 * The type of a column will effect how it is ordering and search (plug-ins
15874		 * can also make use of the column type if required).
15875		 *
15876		 * @namespace
15877		 */
15878		type: {
15879			/**
15880			 * Type detection functions.
15881			 *
15882			 * The functions defined in this object are used to automatically detect
15883			 * a column's type, making initialisation of DataTables super easy, even
15884			 * when complex data is in the table.
15885			 *
15886			 * The functions defined take two parameters:
15887			 *
15888		     *  1. `{*}` Data from the column cell to be analysed
15889		     *  2. `{settings}` DataTables settings object. This can be used to
15890		     *     perform context specific type detection - for example detection
15891		     *     based on language settings such as using a comma for a decimal
15892		     *     place. Generally speaking the options from the settings will not
15893		     *     be required
15894			 *
15895			 * Each function is expected to return:
15896			 *
15897			 * * `{string|null}` Data type detected, or null if unknown (and thus
15898			 *   pass it on to the other type detection functions.
15899			 *
15900			 *  @type array
15901			 *
15902			 *  @example
15903			 *    // Currency type detection plug-in:
15904			 *    $.fn.dataTable.ext.type.detect.push(
15905			 *      function ( data, settings ) {
15906			 *        // Check the numeric part
15907			 *        if ( ! data.substring(1).match(/[0-9]/) ) {
15908			 *          return null;
15909			 *        }
15910			 *
15911			 *        // Check prefixed by currency
15912			 *        if ( data.charAt(0) == '$' || data.charAt(0) == '&pound;' ) {
15913			 *          return 'currency';
15914			 *        }
15915			 *        return null;
15916			 *      }
15917			 *    );
15918			 */
15919			detect: [],
15920	
15921	
15922			/**
15923			 * Type based search formatting.
15924			 *
15925			 * The type based searching functions can be used to pre-format the
15926			 * data to be search on. For example, it can be used to strip HTML
15927			 * tags or to de-format telephone numbers for numeric only searching.
15928			 *
15929			 * Note that is a search is not defined for a column of a given type,
15930			 * no search formatting will be performed.
15931			 * 
15932			 * Pre-processing of searching data plug-ins - When you assign the sType
15933			 * for a column (or have it automatically detected for you by DataTables
15934			 * or a type detection plug-in), you will typically be using this for
15935			 * custom sorting, but it can also be used to provide custom searching
15936			 * by allowing you to pre-processing the data and returning the data in
15937			 * the format that should be searched upon. This is done by adding
15938			 * functions this object with a parameter name which matches the sType
15939			 * for that target column. This is the corollary of <i>afnSortData</i>
15940			 * for searching data.
15941			 *
15942			 * The functions defined take a single parameter:
15943			 *
15944		     *  1. `{*}` Data from the column cell to be prepared for searching
15945			 *
15946			 * Each function is expected to return:
15947			 *
15948			 * * `{string|null}` Formatted string that will be used for the searching.
15949			 *
15950			 *  @type object
15951			 *  @default {}
15952			 *
15953			 *  @example
15954			 *    $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) {
15955			 *      return d.replace(/\n/g," ").replace( /<.*?>/g, "" );
15956			 *    }
15957			 */
15958			search: {},
15959	
15960	
15961			/**
15962			 * Type based ordering.
15963			 *
15964			 * The column type tells DataTables what ordering to apply to the table
15965			 * when a column is sorted upon. The order for each type that is defined,
15966			 * is defined by the functions available in this object.
15967			 *
15968			 * Each ordering option can be described by three properties added to
15969			 * this object:
15970			 *
15971			 * * `{type}-pre` - Pre-formatting function
15972			 * * `{type}-asc` - Ascending order function
15973			 * * `{type}-desc` - Descending order function
15974			 *
15975			 * All three can be used together, only `{type}-pre` or only
15976			 * `{type}-asc` and `{type}-desc` together. It is generally recommended
15977			 * that only `{type}-pre` is used, as this provides the optimal
15978			 * implementation in terms of speed, although the others are provided
15979			 * for compatibility with existing Javascript sort functions.
15980			 *
15981			 * `{type}-pre`: Functions defined take a single parameter:
15982			 *
15983		     *  1. `{*}` Data from the column cell to be prepared for ordering
15984			 *
15985			 * And return:
15986			 *
15987			 * * `{*}` Data to be sorted upon
15988			 *
15989			 * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort
15990			 * functions, taking two parameters:
15991			 *
15992		     *  1. `{*}` Data to compare to the second parameter
15993		     *  2. `{*}` Data to compare to the first parameter
15994			 *
15995			 * And returning:
15996			 *
15997			 * * `{*}` Ordering match: <0 if first parameter should be sorted lower
15998			 *   than the second parameter, ===0 if the two parameters are equal and
15999			 *   >0 if the first parameter should be sorted height than the second
16000			 *   parameter.
16001			 * 
16002			 *  @type object
16003			 *  @default {}
16004			 *
16005			 *  @example
16006			 *    // Numeric ordering of formatted numbers with a pre-formatter
16007			 *    $.extend( $.fn.dataTable.ext.type.order, {
16008			 *      "string-pre": function(x) {
16009			 *        a = (a === "-" || a === "") ? 0 : a.replace( /[^\d\-\.]/g, "" );
16010			 *        return parseFloat( a );
16011			 *      }
16012			 *    } );
16013			 *
16014			 *  @example
16015			 *    // Case-sensitive string ordering, with no pre-formatting method
16016			 *    $.extend( $.fn.dataTable.ext.order, {
16017			 *      "string-case-asc": function(x,y) {
16018			 *        return ((x < y) ? -1 : ((x > y) ? 1 : 0));
16019			 *      },
16020			 *      "string-case-desc": function(x,y) {
16021			 *        return ((x < y) ? 1 : ((x > y) ? -1 : 0));
16022			 *      }
16023			 *    } );
16024			 */
16025			order: {}
16026		},
16027	
16028		/**
16029		 * Unique DataTables instance counter
16030		 *
16031		 * @type int
16032		 * @private
16033		 */
16034		_unique: 0,
16035	
16036	
16037		//
16038		// Depreciated
16039		// The following properties are retained for backwards compatiblity only.
16040		// The should not be used in new projects and will be removed in a future
16041		// version
16042		//
16043	
16044		/**
16045		 * Version check function.
16046		 *  @type function
16047		 *  @depreciated Since 1.10
16048		 */
16049		fnVersionCheck: DataTable.fnVersionCheck,
16050	
16051	
16052		/**
16053		 * Index for what 'this' index API functions should use
16054		 *  @type int
16055		 *  @deprecated Since v1.10
16056		 */
16057		iApiIndex: 0,
16058	
16059	
16060		/**
16061		 * jQuery UI class container
16062		 *  @type object
16063		 *  @deprecated Since v1.10
16064		 */
16065		oJUIClasses: {},
16066	
16067	
16068		/**
16069		 * Software version
16070		 *  @type string
16071		 *  @deprecated Since v1.10
16072		 */
16073		sVersion: DataTable.version
16074	};
16075	
16076	
16077	//
16078	// Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts
16079	//
16080	$.extend( _ext, {
16081		afnFiltering: _ext.search,
16082		aTypes:       _ext.type.detect,
16083		ofnSearch:    _ext.type.search,
16084		oSort:        _ext.type.order,
16085		afnSortData:  _ext.order,
16086		aoFeatures:   _ext.feature,
16087		oApi:         _ext.internal,
16088		oStdClasses:  _ext.classes,
16089		oPagination:  _ext.pager
16090	} );
16091	
16092	
16093	$.extend( DataTable.ext.classes, {
16094		"sTable": "dataTable",
16095		"sNoFooter": "no-footer",
16096	
16097		/* Paging buttons */
16098		"sPageButton": "paginate_button",
16099		"sPageButtonActive": "current",
16100		"sPageButtonDisabled": "disabled",
16101	
16102		/* Striping classes */
16103		"sStripeOdd": "odd",
16104		"sStripeEven": "even",
16105	
16106		/* Empty row */
16107		"sRowEmpty": "dataTables_empty",
16108	
16109		/* Features */
16110		"sWrapper": "dataTables_wrapper",
16111		"sFilter": "dataTables_filter",
16112		"sInfo": "dataTables_info",
16113		"sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
16114		"sLength": "dataTables_length",
16115		"sProcessing": "dataTables_processing",
16116	
16117		/* Sorting */
16118		"sSortAsc": "sorting_asc",
16119		"sSortDesc": "sorting_desc",
16120		"sSortable": "sorting", /* Sortable in both directions */
16121		"sSortableAsc": "sorting_desc_disabled",
16122		"sSortableDesc": "sorting_asc_disabled",
16123		"sSortableNone": "sorting_disabled",
16124		"sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
16125	
16126		/* Filtering */
16127		"sFilterInput": "",
16128	
16129		/* Page length */
16130		"sLengthSelect": "",
16131	
16132		/* Scrolling */
16133		"sScrollWrapper": "dataTables_scroll",
16134		"sScrollHead": "dataTables_scrollHead",
16135		"sScrollHeadInner": "dataTables_scrollHeadInner",
16136		"sScrollBody": "dataTables_scrollBody",
16137		"sScrollFoot": "dataTables_scrollFoot",
16138		"sScrollFootInner": "dataTables_scrollFootInner",
16139	
16140		/* Misc */
16141		"sHeaderTH": "",
16142		"sFooterTH": "",
16143	
16144		// Deprecated
16145		"sSortJUIAsc": "",
16146		"sSortJUIDesc": "",
16147		"sSortJUI": "",
16148		"sSortJUIAscAllowed": "",
16149		"sSortJUIDescAllowed": "",
16150		"sSortJUIWrapper": "",
16151		"sSortIcon": "",
16152		"sJUIHeader": "",
16153		"sJUIFooter": ""
16154	} );
16155	
16156	
16157	var extPagination = DataTable.ext.pager;
16158	
16159	function _numbers ( page, pages ) {
16160		var
16161			numbers = [],
16162			buttons = extPagination.numbers_length,
16163			half = Math.floor( buttons / 2 ),
16164			i = 1;
16165	
16166		if ( pages <= buttons ) {
16167			numbers = _range( 0, pages );
16168		}
16169		else if ( page <= half ) {
16170			numbers = _range( 0, buttons-2 );
16171			numbers.push( 'ellipsis' );
16172			numbers.push( pages-1 );
16173		}
16174		else if ( page >= pages - 1 - half ) {
16175			numbers = _range( pages-(buttons-2), pages );
16176			numbers.splice( 0, 0, 'ellipsis' ); // no unshift in ie6
16177			numbers.splice( 0, 0, 0 );
16178		}
16179		else {
16180			numbers = _range( page-half+2, page+half-1 );
16181			numbers.push( 'ellipsis' );
16182			numbers.push( pages-1 );
16183			numbers.splice( 0, 0, 'ellipsis' );
16184			numbers.splice( 0, 0, 0 );
16185		}
16186	
16187		numbers.DT_el = 'span';
16188		return numbers;
16189	}
16190	
16191	
16192	$.extend( extPagination, {
16193		simple: function ( page, pages ) {
16194			return [ 'previous', 'next' ];
16195		},
16196	
16197		full: function ( page, pages ) {
16198			return [  'first', 'previous', 'next', 'last' ];
16199		},
16200	
16201		numbers: function ( page, pages ) {
16202			return [ _numbers(page, pages) ];
16203		},
16204	
16205		simple_numbers: function ( page, pages ) {
16206			return [ 'previous', _numbers(page, pages), 'next' ];
16207		},
16208	
16209		full_numbers: function ( page, pages ) {
16210			return [ 'first', 'previous', _numbers(page, pages), 'next', 'last' ];
16211		},
16212		
16213		first_last_numbers: function (page, pages) {
16214	 		return ['first', _numbers(page, pages), 'last'];
16215	 	},
16216	
16217		// For testing and plug-ins to use
16218		_numbers: _numbers,
16219	
16220		// Number of number buttons (including ellipsis) to show. _Must be odd!_
16221		numbers_length: 7
16222	} );
16223	
16224	
16225	$.extend( true, DataTable.ext.renderer, {
16226		pageButton: {
16227			_: function ( settings, host, idx, buttons, page, pages ) {
16228				var classes = settings.oClasses;
16229				var lang = settings.oLanguage.oPaginate;
16230				var aria = settings.oLanguage.oAria.paginate || {};
16231				var btnDisplay, btnClass, counter=0;
16232	
16233				var attach = function( container, buttons ) {
16234					var i, ien, node, button, tabIndex;
16235					var disabledClass = classes.sPageButtonDisabled;
16236					var clickHandler = function ( e ) {
16237						_fnPageChange( settings, e.data.action, true );
16238					};
16239	
16240					for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
16241						button = buttons[i];
16242	
16243						if ( Array.isArray( button ) ) {
16244							var inner = $( '<'+(button.DT_el || 'div')+'/>' )
16245								.appendTo( container );
16246							attach( inner, button );
16247						}
16248						else {
16249							btnDisplay = null;
16250							btnClass = button;
16251							tabIndex = settings.iTabIndex;
16252	
16253							switch ( button ) {
16254								case 'ellipsis':
16255									container.append('<span class="ellipsis">&#x2026;</span>');
16256									break;
16257	
16258								case 'first':
16259									btnDisplay = lang.sFirst;
16260	
16261									if ( page === 0 ) {
16262										tabIndex = -1;
16263										btnClass += ' ' + disabledClass;
16264									}
16265									break;
16266	
16267								case 'previous':
16268									btnDisplay = lang.sPrevious;
16269	
16270									if ( page === 0 ) {
16271										tabIndex = -1;
16272										btnClass += ' ' + disabledClass;
16273									}
16274									break;
16275	
16276								case 'next':
16277									btnDisplay = lang.sNext;
16278	
16279									if ( pages === 0 || page === pages-1 ) {
16280										tabIndex = -1;
16281										btnClass += ' ' + disabledClass;
16282									}
16283									break;
16284	
16285								case 'last':
16286									btnDisplay = lang.sLast;
16287	
16288									if ( pages === 0 || page === pages-1 ) {
16289										tabIndex = -1;
16290										btnClass += ' ' + disabledClass;
16291									}
16292									break;
16293	
16294								default:
16295									btnDisplay = settings.fnFormatNumber( button + 1 );
16296									btnClass = page === button ?
16297										classes.sPageButtonActive : '';
16298									break;
16299							}
16300	
16301							if ( btnDisplay !== null ) {
16302								node = $('<a>', {
16303										'class': classes.sPageButton+' '+btnClass,
16304										'aria-controls': settings.sTableId,
16305										'aria-label': aria[ button ],
16306										'data-dt-idx': counter,
16307										'tabindex': tabIndex,
16308										'id': idx === 0 && typeof button === 'string' ?
16309											settings.sTableId +'_'+ button :
16310											null
16311									} )
16312									.html( btnDisplay )
16313									.appendTo( container );
16314	
16315								_fnBindAction(
16316									node, {action: button}, clickHandler
16317								);
16318	
16319								counter++;
16320							}
16321						}
16322					}
16323				};
16324	
16325				// IE9 throws an 'unknown error' if document.activeElement is used
16326				// inside an iframe or frame. Try / catch the error. Not good for
16327				// accessibility, but neither are frames.
16328				var activeEl;
16329	
16330				try {
16331					// Because this approach is destroying and recreating the paging
16332					// elements, focus is lost on the select button which is bad for
16333					// accessibility. So we want to restore focus once the draw has
16334					// completed
16335					activeEl = $(host).find(document.activeElement).data('dt-idx');
16336				}
16337				catch (e) {}
16338	
16339				attach( $(host).empty(), buttons );
16340	
16341				if ( activeEl !== undefined ) {
16342					$(host).find( '[data-dt-idx='+activeEl+']' ).trigger('focus');
16343				}
16344			}
16345		}
16346	} );
16347	
16348	
16349	
16350	// Built in type detection. See model.ext.aTypes for information about
16351	// what is required from this methods.
16352	$.extend( DataTable.ext.type.detect, [
16353		// Plain numbers - first since V8 detects some plain numbers as dates
16354		// e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...).
16355		function ( d, settings )
16356		{
16357			var decimal = settings.oLanguage.sDecimal;
16358			return _isNumber( d, decimal ) ? 'num'+decimal : null;
16359		},
16360	
16361		// Dates (only those recognised by the browser's Date.parse)
16362		function ( d, settings )
16363		{
16364			// V8 tries _very_ hard to make a string passed into `Date.parse()`
16365			// valid, so we need to use a regex to restrict date formats. Use a
16366			// plug-in for anything other than ISO8601 style strings
16367			if ( d && !(d instanceof Date) && ! _re_date.test(d) ) {
16368				return null;
16369			}
16370			var parsed = Date.parse(d);
16371			return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null;
16372		},
16373	
16374		// Formatted numbers
16375		function ( d, settings )
16376		{
16377			var decimal = settings.oLanguage.sDecimal;
16378			return _isNumber( d, decimal, true ) ? 'num-fmt'+decimal : null;
16379		},
16380	
16381		// HTML numeric
16382		function ( d, settings )
16383		{
16384			var decimal = settings.oLanguage.sDecimal;
16385			return _htmlNumeric( d, decimal ) ? 'html-num'+decimal : null;
16386		},
16387	
16388		// HTML numeric, formatted
16389		function ( d, settings )
16390		{
16391			var decimal = settings.oLanguage.sDecimal;
16392			return _htmlNumeric( d, decimal, true ) ? 'html-num-fmt'+decimal : null;
16393		},
16394	
16395		// HTML (this is strict checking - there must be html)
16396		function ( d, settings )
16397		{
16398			return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ?
16399				'html' : null;
16400		}
16401	] );
16402	
16403	
16404	
16405	// Filter formatting functions. See model.ext.ofnSearch for information about
16406	// what is required from these methods.
16407	// 
16408	// Note that additional search methods are added for the html numbers and
16409	// html formatted numbers by `_addNumericSort()` when we know what the decimal
16410	// place is
16411	
16412	
16413	$.extend( DataTable.ext.type.search, {
16414		html: function ( data ) {
16415			return _empty(data) ?
16416				data :
16417				typeof data === 'string' ?
16418					data
16419						.replace( _re_new_lines, " " )
16420						.replace( _re_html, "" ) :
16421					'';
16422		},
16423	
16424		string: function ( data ) {
16425			return _empty(data) ?
16426				data :
16427				typeof data === 'string' ?
16428					data.replace( _re_new_lines, " " ) :
16429					data;
16430		}
16431	} );
16432	
16433	
16434	
16435	var __numericReplace = function ( d, decimalPlace, re1, re2 ) {
16436		if ( d !== 0 && (!d || d === '-') ) {
16437			return -Infinity;
16438		}
16439	
16440		// If a decimal place other than `.` is used, it needs to be given to the
16441		// function so we can detect it and replace with a `.` which is the only
16442		// decimal place Javascript recognises - it is not locale aware.
16443		if ( decimalPlace ) {
16444			d = _numToDecimal( d, decimalPlace );
16445		}
16446	
16447		if ( d.replace ) {
16448			if ( re1 ) {
16449				d = d.replace( re1, '' );
16450			}
16451	
16452			if ( re2 ) {
16453				d = d.replace( re2, '' );
16454			}
16455		}
16456	
16457		return d * 1;
16458	};
16459	
16460	
16461	// Add the numeric 'deformatting' functions for sorting and search. This is done
16462	// in a function to provide an easy ability for the language options to add
16463	// additional methods if a non-period decimal place is used.
16464	function _addNumericSort ( decimalPlace ) {
16465		$.each(
16466			{
16467				// Plain numbers
16468				"num": function ( d ) {
16469					return __numericReplace( d, decimalPlace );
16470				},
16471	
16472				// Formatted numbers
16473				"num-fmt": function ( d ) {
16474					return __numericReplace( d, decimalPlace, _re_formatted_numeric );
16475				},
16476	
16477				// HTML numeric
16478				"html-num": function ( d ) {
16479					return __numericReplace( d, decimalPlace, _re_html );
16480				},
16481	
16482				// HTML numeric, formatted
16483				"html-num-fmt": function ( d ) {
16484					return __numericReplace( d, decimalPlace, _re_html, _re_formatted_numeric );
16485				}
16486			},
16487			function ( key, fn ) {
16488				// Add the ordering method
16489				_ext.type.order[ key+decimalPlace+'-pre' ] = fn;
16490	
16491				// For HTML types add a search formatter that will strip the HTML
16492				if ( key.match(/^html\-/) ) {
16493					_ext.type.search[ key+decimalPlace ] = _ext.type.search.html;
16494				}
16495			}
16496		);
16497	}
16498	
16499	
16500	// Default sort methods
16501	$.extend( _ext.type.order, {
16502		// Dates
16503		"date-pre": function ( d ) {
16504			var ts = Date.parse( d );
16505			return isNaN(ts) ? -Infinity : ts;
16506		},
16507	
16508		// html
16509		"html-pre": function ( a ) {
16510			return _empty(a) ?
16511				'' :
16512				a.replace ?
16513					a.replace( /<.*?>/g, "" ).toLowerCase() :
16514					a+'';
16515		},
16516	
16517		// string
16518		"string-pre": function ( a ) {
16519			// This is a little complex, but faster than always calling toString,
16520			// http://jsperf.com/tostring-v-check
16521			return _empty(a) ?
16522				'' :
16523				typeof a === 'string' ?
16524					a.toLowerCase() :
16525					! a.toString ?
16526						'' :
16527						a.toString();
16528		},
16529	
16530		// string-asc and -desc are retained only for compatibility with the old
16531		// sort methods
16532		"string-asc": function ( x, y ) {
16533			return ((x < y) ? -1 : ((x > y) ? 1 : 0));
16534		},
16535	
16536		"string-desc": function ( x, y ) {
16537			return ((x < y) ? 1 : ((x > y) ? -1 : 0));
16538		}
16539	} );
16540	
16541	
16542	// Numeric sorting types - order doesn't matter here
16543	_addNumericSort( '' );
16544	
16545	
16546	$.extend( true, DataTable.ext.renderer, {
16547		header: {
16548			_: function ( settings, cell, column, classes ) {
16549				// No additional mark-up required
16550				// Attach a sort listener to update on sort - note that using the
16551				// `DT` namespace will allow the event to be removed automatically
16552				// on destroy, while the `dt` namespaced event is the one we are
16553				// listening for
16554				$(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
16555					if ( settings !== ctx ) { // need to check this this is the host
16556						return;               // table, not a nested one
16557					}
16558	
16559					var colIdx = column.idx;
16560	
16561					cell
16562						.removeClass(
16563							classes.sSortAsc +' '+
16564							classes.sSortDesc
16565						)
16566						.addClass( columns[ colIdx ] == 'asc' ?
16567							classes.sSortAsc : columns[ colIdx ] == 'desc' ?
16568								classes.sSortDesc :
16569								column.sSortingClass
16570						);
16571				} );
16572			},
16573	
16574			jqueryui: function ( settings, cell, column, classes ) {
16575				$('<div/>')
16576					.addClass( classes.sSortJUIWrapper )
16577					.append( cell.contents() )
16578					.append( $('<span/>')
16579						.addClass( classes.sSortIcon+' '+column.sSortingClassJUI )
16580					)
16581					.appendTo( cell );
16582	
16583				// Attach a sort listener to update on sort
16584				$(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
16585					if ( settings !== ctx ) {
16586						return;
16587					}
16588	
16589					var colIdx = column.idx;
16590	
16591					cell
16592						.removeClass( classes.sSortAsc +" "+classes.sSortDesc )
16593						.addClass( columns[ colIdx ] == 'asc' ?
16594							classes.sSortAsc : columns[ colIdx ] == 'desc' ?
16595								classes.sSortDesc :
16596								column.sSortingClass
16597						);
16598	
16599					cell
16600						.find( 'span.'+classes.sSortIcon )
16601						.removeClass(
16602							classes.sSortJUIAsc +" "+
16603							classes.sSortJUIDesc +" "+
16604							classes.sSortJUI +" "+
16605							classes.sSortJUIAscAllowed +" "+
16606							classes.sSortJUIDescAllowed
16607						)
16608						.addClass( columns[ colIdx ] == 'asc' ?
16609							classes.sSortJUIAsc : columns[ colIdx ] == 'desc' ?
16610								classes.sSortJUIDesc :
16611								column.sSortingClassJUI
16612						);
16613				} );
16614			}
16615		}
16616	} );
16617	
16618	/*
16619	 * Public helper functions. These aren't used internally by DataTables, or
16620	 * called by any of the options passed into DataTables, but they can be used
16621	 * externally by developers working with DataTables. They are helper functions
16622	 * to make working with DataTables a little bit easier.
16623	 */
16624	
16625	var __htmlEscapeEntities = function ( d ) {
16626		return typeof d === 'string' ?
16627			d
16628				.replace(/&/g, '&amp;')
16629				.replace(/</g, '&lt;')
16630				.replace(/>/g, '&gt;')
16631				.replace(/"/g, '&quot;') :
16632			d;
16633	};
16634	
16635	/**
16636	 * Helpers for `columns.render`.
16637	 *
16638	 * The options defined here can be used with the `columns.render` initialisation
16639	 * option to provide a display renderer. The following functions are defined:
16640	 *
16641	 * * `number` - Will format numeric data (defined by `columns.data`) for
16642	 *   display, retaining the original unformatted data for sorting and filtering.
16643	 *   It takes 5 parameters:
16644	 *   * `string` - Thousands grouping separator
16645	 *   * `string` - Decimal point indicator
16646	 *   * `integer` - Number of decimal points to show
16647	 *   * `string` (optional) - Prefix.
16648	 *   * `string` (optional) - Postfix (/suffix).
16649	 * * `text` - Escape HTML to help prevent XSS attacks. It has no optional
16650	 *   parameters.
16651	 *
16652	 * @example
16653	 *   // Column definition using the number renderer
16654	 *   {
16655	 *     data: "salary",
16656	 *     render: $.fn.dataTable.render.number( '\'', '.', 0, '$' )
16657	 *   }
16658	 *
16659	 * @namespace
16660	 */
16661	DataTable.render = {
16662		number: function ( thousands, decimal, precision, prefix, postfix ) {
16663			return {
16664				display: function ( d ) {
16665					if ( typeof d !== 'number' && typeof d !== 'string' ) {
16666						return d;
16667					}
16668	
16669					var negative = d < 0 ? '-' : '';
16670					var flo = parseFloat( d );
16671	
16672					// If NaN then there isn't much formatting that we can do - just
16673					// return immediately, escaping any HTML (this was supposed to
16674					// be a number after all)
16675					if ( isNaN( flo ) ) {
16676						return __htmlEscapeEntities( d );
16677					}
16678	
16679					flo = flo.toFixed( precision );
16680					d = Math.abs( flo );
16681	
16682					var intPart = parseInt( d, 10 );
16683					var floatPart = precision ?
16684						decimal+(d - intPart).toFixed( precision ).substring( 2 ):
16685						'';
16686	
16687					return negative + (prefix||'') +
16688						intPart.toString().replace(
16689							/\B(?=(\d{3})+(?!\d))/g, thousands
16690						) +
16691						floatPart +
16692						(postfix||'');
16693				}
16694			};
16695		},
16696	
16697		text: function () {
16698			return {
16699				display: __htmlEscapeEntities,
16700				filter: __htmlEscapeEntities
16701			};
16702		}
16703	};
16704	
16705	
16706	/*
16707	 * This is really a good bit rubbish this method of exposing the internal methods
16708	 * publicly... - To be fixed in 2.0 using methods on the prototype
16709	 */
16710	
16711	
16712	/**
16713	 * Create a wrapper function for exporting an internal functions to an external API.
16714	 *  @param {string} fn API function name
16715	 *  @returns {function} wrapped function
16716	 *  @memberof DataTable#internal
16717	 */
16718	function _fnExternApiFunc (fn)
16719	{
16720		return function() {
16721			var args = [_fnSettingsFromNode( this[DataTable.ext.iApiIndex] )].concat(
16722				Array.prototype.slice.call(arguments)
16723			);
16724			return DataTable.ext.internal[fn].apply( this, args );
16725		};
16726	}
16727	
16728	
16729	/**
16730	 * Reference to internal functions for use by plug-in developers. Note that
16731	 * these methods are references to internal functions and are considered to be
16732	 * private. If you use these methods, be aware that they are liable to change
16733	 * between versions.
16734	 *  @namespace
16735	 */
16736	$.extend( DataTable.ext.internal, {
16737		_fnExternApiFunc: _fnExternApiFunc,
16738		_fnBuildAjax: _fnBuildAjax,
16739		_fnAjaxUpdate: _fnAjaxUpdate,
16740		_fnAjaxParameters: _fnAjaxParameters,
16741		_fnAjaxUpdateDraw: _fnAjaxUpdateDraw,
16742		_fnAjaxDataSrc: _fnAjaxDataSrc,
16743		_fnAddColumn: _fnAddColumn,
16744		_fnColumnOptions: _fnColumnOptions,
16745		_fnAdjustColumnSizing: _fnAdjustColumnSizing,
16746		_fnVisibleToColumnIndex: _fnVisibleToColumnIndex,
16747		_fnColumnIndexToVisible: _fnColumnIndexToVisible,
16748		_fnVisbleColumns: _fnVisbleColumns,
16749		_fnGetColumns: _fnGetColumns,
16750		_fnColumnTypes: _fnColumnTypes,
16751		_fnApplyColumnDefs: _fnApplyColumnDefs,
16752		_fnHungarianMap: _fnHungarianMap,
16753		_fnCamelToHungarian: _fnCamelToHungarian,
16754		_fnLanguageCompat: _fnLanguageCompat,
16755		_fnBrowserDetect: _fnBrowserDetect,
16756		_fnAddData: _fnAddData,
16757		_fnAddTr: _fnAddTr,
16758		_fnNodeToDataIndex: _fnNodeToDataIndex,
16759		_fnNodeToColumnIndex: _fnNodeToColumnIndex,
16760		_fnGetCellData: _fnGetCellData,
16761		_fnSetCellData: _fnSetCellData,
16762		_fnSplitObjNotation: _fnSplitObjNotation,
16763		_fnGetObjectDataFn: _fnGetObjectDataFn,
16764		_fnSetObjectDataFn: _fnSetObjectDataFn,
16765		_fnGetDataMaster: _fnGetDataMaster,
16766		_fnClearTable: _fnClearTable,
16767		_fnDeleteIndex: _fnDeleteIndex,
16768		_fnInvalidate: _fnInvalidate,
16769		_fnGetRowElements: _fnGetRowElements,
16770		_fnCreateTr: _fnCreateTr,
16771		_fnBuildHead: _fnBuildHead,
16772		_fnDrawHead: _fnDrawHead,
16773		_fnDraw: _fnDraw,
16774		_fnReDraw: _fnReDraw,
16775		_fnAddOptionsHtml: _fnAddOptionsHtml,
16776		_fnDetectHeader: _fnDetectHeader,
16777		_fnGetUniqueThs: _fnGetUniqueThs,
16778		_fnFeatureHtmlFilter: _fnFeatureHtmlFilter,
16779		_fnFilterComplete: _fnFilterComplete,
16780		_fnFilterCustom: _fnFilterCustom,
16781		_fnFilterColumn: _fnFilterColumn,
16782		_fnFilter: _fnFilter,
16783		_fnFilterCreateSearch: _fnFilterCreateSearch,
16784		_fnEscapeRegex: _fnEscapeRegex,
16785		_fnFilterData: _fnFilterData,
16786		_fnFeatureHtmlInfo: _fnFeatureHtmlInfo,
16787		_fnUpdateInfo: _fnUpdateInfo,
16788		_fnInfoMacros: _fnInfoMacros,
16789		_fnInitialise: _fnInitialise,
16790		_fnInitComplete: _fnInitComplete,
16791		_fnLengthChange: _fnLengthChange,
16792		_fnFeatureHtmlLength: _fnFeatureHtmlLength,
16793		_fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate,
16794		_fnPageChange: _fnPageChange,
16795		_fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing,
16796		_fnProcessingDisplay: _fnProcessingDisplay,
16797		_fnFeatureHtmlTable: _fnFeatureHtmlTable,
16798		_fnScrollDraw: _fnScrollDraw,
16799		_fnApplyToChildren: _fnApplyToChildren,
16800		_fnCalculateColumnWidths: _fnCalculateColumnWidths,
16801		_fnThrottle: _fnThrottle,
16802		_fnConvertToWidth: _fnConvertToWidth,
16803		_fnGetWidestNode: _fnGetWidestNode,
16804		_fnGetMaxLenString: _fnGetMaxLenString,
16805		_fnStringToCss: _fnStringToCss,
16806		_fnSortFlatten: _fnSortFlatten,
16807		_fnSort: _fnSort,
16808		_fnSortAria: _fnSortAria,
16809		_fnSortListener: _fnSortListener,
16810		_fnSortAttachListener: _fnSortAttachListener,
16811		_fnSortingClasses: _fnSortingClasses,
16812		_fnSortData: _fnSortData,
16813		_fnSaveState: _fnSaveState,
16814		_fnLoadState: _fnLoadState,
16815		_fnSettingsFromNode: _fnSettingsFromNode,
16816		_fnLog: _fnLog,
16817		_fnMap: _fnMap,
16818		_fnBindAction: _fnBindAction,
16819		_fnCallbackReg: _fnCallbackReg,
16820		_fnCallbackFire: _fnCallbackFire,
16821		_fnLengthOverflow: _fnLengthOverflow,
16822		_fnRenderer: _fnRenderer,
16823		_fnDataSource: _fnDataSource,
16824		_fnRowAttributes: _fnRowAttributes,
16825		_fnExtend: _fnExtend,
16826		_fnCalculateEnd: function () {} // Used by a lot of plug-ins, but redundant
16827		                                // in 1.10, so this dead-end function is
16828		                                // added to prevent errors
16829	} );
16830	
16831
16832	// jQuery access
16833	$.fn.dataTable = DataTable;
16834
16835	// Provide access to the host jQuery object (circular reference)
16836	DataTable.$ = $;
16837
16838	// Legacy aliases
16839	$.fn.dataTableSettings = DataTable.settings;
16840	$.fn.dataTableExt = DataTable.ext;
16841
16842	// With a capital `D` we return a DataTables API instance rather than a
16843	// jQuery object
16844	$.fn.DataTable = function ( opts ) {
16845		return $(this).dataTable( opts ).api();
16846	};
16847
16848	// All properties that are available to $.fn.dataTable should also be
16849	// available on $.fn.DataTable
16850	$.each( DataTable, function ( prop, val ) {
16851		$.fn.DataTable[ prop ] = val;
16852	} );
16853
16854
16855	// Information about events fired by DataTables - for documentation.
16856	/**
16857	 * Draw event, fired whenever the table is redrawn on the page, at the same
16858	 * point as fnDrawCallback. This may be useful for binding events or
16859	 * performing calculations when the table is altered at all.
16860	 *  @name DataTable#draw.dt
16861	 *  @event
16862	 *  @param {event} e jQuery event object
16863	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
16864	 */
16865
16866	/**
16867	 * Search event, fired when the searching applied to the table (using the
16868	 * built-in global search, or column filters) is altered.
16869	 *  @name DataTable#search.dt
16870	 *  @event
16871	 *  @param {event} e jQuery event object
16872	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
16873	 */
16874
16875	/**
16876	 * Page change event, fired when the paging of the table is altered.
16877	 *  @name DataTable#page.dt
16878	 *  @event
16879	 *  @param {event} e jQuery event object
16880	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
16881	 */
16882
16883	/**
16884	 * Order event, fired when the ordering applied to the table is altered.
16885	 *  @name DataTable#order.dt
16886	 *  @event
16887	 *  @param {event} e jQuery event object
16888	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
16889	 */
16890
16891	/**
16892	 * DataTables initialisation complete event, fired when the table is fully
16893	 * drawn, including Ajax data loaded, if Ajax data is required.
16894	 *  @name DataTable#init.dt
16895	 *  @event
16896	 *  @param {event} e jQuery event object
16897	 *  @param {object} oSettings DataTables settings object
16898	 *  @param {object} json The JSON object request from the server - only
16899	 *    present if client-side Ajax sourced data is used</li></ol>
16900	 */
16901
16902	/**
16903	 * State save event, fired when the table has changed state a new state save
16904	 * is required. This event allows modification of the state saving object
16905	 * prior to actually doing the save, including addition or other state
16906	 * properties (for plug-ins) or modification of a DataTables core property.
16907	 *  @name DataTable#stateSaveParams.dt
16908	 *  @event
16909	 *  @param {event} e jQuery event object
16910	 *  @param {object} oSettings DataTables settings object
16911	 *  @param {object} json The state information to be saved
16912	 */
16913
16914	/**
16915	 * State load event, fired when the table is loading state from the stored
16916	 * data, but prior to the settings object being modified by the saved state
16917	 * - allowing modification of the saved state is required or loading of
16918	 * state for a plug-in.
16919	 *  @name DataTable#stateLoadParams.dt
16920	 *  @event
16921	 *  @param {event} e jQuery event object
16922	 *  @param {object} oSettings DataTables settings object
16923	 *  @param {object} json The saved state information
16924	 */
16925
16926	/**
16927	 * State loaded event, fired when state has been loaded from stored data and
16928	 * the settings object has been modified by the loaded data.
16929	 *  @name DataTable#stateLoaded.dt
16930	 *  @event
16931	 *  @param {event} e jQuery event object
16932	 *  @param {object} oSettings DataTables settings object
16933	 *  @param {object} json The saved state information
16934	 */
16935
16936	/**
16937	 * Processing event, fired when DataTables is doing some kind of processing
16938	 * (be it, order, search or anything else). It can be used to indicate to
16939	 * the end user that there is something happening, or that something has
16940	 * finished.
16941	 *  @name DataTable#processing.dt
16942	 *  @event
16943	 *  @param {event} e jQuery event object
16944	 *  @param {object} oSettings DataTables settings object
16945	 *  @param {boolean} bShow Flag for if DataTables is doing processing or not
16946	 */
16947
16948	/**
16949	 * Ajax (XHR) event, fired whenever an Ajax request is completed from a
16950	 * request to made to the server for new data. This event is called before
16951	 * DataTables processed the returned data, so it can also be used to pre-
16952	 * process the data returned from the server, if needed.
16953	 *
16954	 * Note that this trigger is called in `fnServerData`, if you override
16955	 * `fnServerData` and which to use this event, you need to trigger it in you
16956	 * success function.
16957	 *  @name DataTable#xhr.dt
16958	 *  @event
16959	 *  @param {event} e jQuery event object
16960	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
16961	 *  @param {object} json JSON returned from the server
16962	 *
16963	 *  @example
16964	 *     // Use a custom property returned from the server in another DOM element
16965	 *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
16966	 *       $('#status').html( json.status );
16967	 *     } );
16968	 *
16969	 *  @example
16970	 *     // Pre-process the data returned from the server
16971	 *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
16972	 *       for ( var i=0, ien=json.aaData.length ; i<ien ; i++ ) {
16973	 *         json.aaData[i].sum = json.aaData[i].one + json.aaData[i].two;
16974	 *       }
16975	 *       // Note no return - manipulate the data directly in the JSON object.
16976	 *     } );
16977	 */
16978
16979	/**
16980	 * Destroy event, fired when the DataTable is destroyed by calling fnDestroy
16981	 * or passing the bDestroy:true parameter in the initialisation object. This
16982	 * can be used to remove bound events, added DOM nodes, etc.
16983	 *  @name DataTable#destroy.dt
16984	 *  @event
16985	 *  @param {event} e jQuery event object
16986	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
16987	 */
16988
16989	/**
16990	 * Page length change event, fired when number of records to show on each
16991	 * page (the length) is changed.
16992	 *  @name DataTable#length.dt
16993	 *  @event
16994	 *  @param {event} e jQuery event object
16995	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
16996	 *  @param {integer} len New length
16997	 */
16998
16999	/**
17000	 * Column sizing has changed.
17001	 *  @name DataTable#column-sizing.dt
17002	 *  @event
17003	 *  @param {event} e jQuery event object
17004	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
17005	 */
17006
17007	/**
17008	 * Column visibility has changed.
17009	 *  @name DataTable#column-visibility.dt
17010	 *  @event
17011	 *  @param {event} e jQuery event object
17012	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
17013	 *  @param {int} column Column index
17014	 *  @param {bool} vis `false` if column now hidden, or `true` if visible
17015	 */
17016
17017	return $.fn.dataTable;
17018}));
17019
17020
17021/***/ }),
17022
vendor: 290,128 bytes, lines 17023-27926
17023/***/ "./node_modules/jquery/dist/jquery.js":
17024/*!********************************************!*\
17025  !*** ./node_modules/jquery/dist/jquery.js ***!
17026  \********************************************/
17027/*! no static exports found */
17028/***/ (function(module, exports, __webpack_require__) {
17029
17030var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
17031 * jQuery JavaScript Library v3.6.0
17032 * https://jquery.com/
17033 *
17034 * Includes Sizzle.js
17035 * https://sizzlejs.com/
17036 *
17037 * Copyright OpenJS Foundation and other contributors
17038 * Released under the MIT license
17039 * https://jquery.org/license
17040 *
17041 * Date: 2021-03-02T17:08Z
17042 */
17043( function( global, factory ) {
17044
17045	"use strict";
17046
17047	if (  true && typeof module.exports === "object" ) {
17048
17049		// For CommonJS and CommonJS-like environments where a proper `window`
17050		// is present, execute the factory and get jQuery.
17051		// For environments that do not have a `window` with a `document`
17052		// (such as Node.js), expose a factory as module.exports.
17053		// This accentuates the need for the creation of a real `window`.
17054		// e.g. var jQuery = require("jquery")(window);
17055		// See ticket #14549 for more info.
17056		module.exports = global.document ?
17057			factory( global, true ) :
17058			function( w ) {
17059				if ( !w.document ) {
17060					throw new Error( "jQuery requires a window with a document" );
17061				}
17062				return factory( w );
17063			};
17064	} else {
17065		factory( global );
17066	}
17067
17068// Pass this if window is not defined yet
17069} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
17070
17071// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1
17072// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode
17073// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common
17074// enough that all such attempts are guarded in a try block.
17075"use strict";
17076
17077var arr = [];
17078
17079var getProto = Object.getPrototypeOf;
17080
17081var slice = arr.slice;
17082
17083var flat = arr.flat ? function( array ) {
17084	return arr.flat.call( array );
17085} : function( array ) {
17086	return arr.concat.apply( [], array );
17087};
17088
17089
17090var push = arr.push;
17091
17092var indexOf = arr.indexOf;
17093
17094var class2type = {};
17095
17096var toString = class2type.toString;
17097
17098var hasOwn = class2type.hasOwnProperty;
17099
17100var fnToString = hasOwn.toString;
17101
17102var ObjectFunctionString = fnToString.call( Object );
17103
17104var support = {};
17105
17106var isFunction = function isFunction( obj ) {
17107
17108		// Support: Chrome <=57, Firefox <=52
17109		// In some browsers, typeof returns "function" for HTML <object> elements
17110		// (i.e., `typeof document.createElement( "object" ) === "function"`).
17111		// We don't want to classify *any* DOM node as a function.
17112		// Support: QtWeb <=3.8.5, WebKit <=534.34, wkhtmltopdf tool <=0.12.5
17113		// Plus for old WebKit, typeof returns "function" for HTML collections
17114		// (e.g., `typeof document.getElementsByTagName("div") === "function"`). (gh-4756)
17115		return typeof obj === "function" && typeof obj.nodeType !== "number" &&
17116			typeof obj.item !== "function";
17117	};
17118
17119
17120var isWindow = function isWindow( obj ) {
17121		return obj != null && obj === obj.window;
17122	};
17123
17124
17125var document = window.document;
17126
17127
17128
17129	var preservedScriptAttributes = {
17130		type: true,
17131		src: true,
17132		nonce: true,
17133		noModule: true
17134	};
17135
17136	function DOMEval( code, node, doc ) {
17137		doc = doc || document;
17138
17139		var i, val,
17140			script = doc.createElement( "script" );
17141
17142		script.text = code;
17143		if ( node ) {
17144			for ( i in preservedScriptAttributes ) {
17145
17146				// Support: Firefox 64+, Edge 18+
17147				// Some browsers don't support the "nonce" property on scripts.
17148				// On the other hand, just using `getAttribute` is not enough as
17149				// the `nonce` attribute is reset to an empty string whenever it
17150				// becomes browsing-context connected.
17151				// See https://github.com/whatwg/html/issues/2369
17152				// See https://html.spec.whatwg.org/#nonce-attributes
17153				// The `node.getAttribute` check was added for the sake of
17154				// `jQuery.globalEval` so that it can fake a nonce-containing node
17155				// via an object.
17156				val = node[ i ] || node.getAttribute && node.getAttribute( i );
17157				if ( val ) {
17158					script.setAttribute( i, val );
17159				}
17160			}
17161		}
17162		doc.head.appendChild( script ).parentNode.removeChild( script );
17163	}
17164
17165
17166function toType( obj ) {
17167	if ( obj == null ) {
17168		return obj + "";
17169	}
17170
17171	// Support: Android <=2.3 only (functionish RegExp)
17172	return typeof obj === "object" || typeof obj === "function" ?
17173		class2type[ toString.call( obj ) ] || "object" :
17174		typeof obj;
17175}
17176/* global Symbol */
17177// Defining this global in .eslintrc.json would create a danger of using the global
17178// unguarded in another place, it seems safer to define global only for this module
17179
17180
17181
17182var
17183	version = "3.6.0",
17184
17185	// Define a local copy of jQuery
17186	jQuery = function( selector, context ) {
17187
17188		// The jQuery object is actually just the init constructor 'enhanced'
17189		// Need init if jQuery is called (just allow error to be thrown if not included)
17190		return new jQuery.fn.init( selector, context );
17191	};
17192
17193jQuery.fn = jQuery.prototype = {
17194
17195	// The current version of jQuery being used
17196	jquery: version,
17197
17198	constructor: jQuery,
17199
17200	// The default length of a jQuery object is 0
17201	length: 0,
17202
17203	toArray: function() {
17204		return slice.call( this );
17205	},
17206
17207	// Get the Nth element in the matched element set OR
17208	// Get the whole matched element set as a clean array
17209	get: function( num ) {
17210
17211		// Return all the elements in a clean array
17212		if ( num == null ) {
17213			return slice.call( this );
17214		}
17215
17216		// Return just the one element from the set
17217		return num < 0 ? this[ num + this.length ] : this[ num ];
17218	},
17219
17220	// Take an array of elements and push it onto the stack
17221	// (returning the new matched element set)
17222	pushStack: function( elems ) {
17223
17224		// Build a new jQuery matched element set
17225		var ret = jQuery.merge( this.constructor(), elems );
17226
17227		// Add the old object onto the stack (as a reference)
17228		ret.prevObject = this;
17229
17230		// Return the newly-formed element set
17231		return ret;
17232	},
17233
17234	// Execute a callback for every element in the matched set.
17235	each: function( callback ) {
17236		return jQuery.each( this, callback );
17237	},
17238
17239	map: function( callback ) {
17240		return this.pushStack( jQuery.map( this, function( elem, i ) {
17241			return callback.call( elem, i, elem );
17242		} ) );
17243	},
17244
17245	slice: function() {
17246		return this.pushStack( slice.apply( this, arguments ) );
17247	},
17248
17249	first: function() {
17250		return this.eq( 0 );
17251	},
17252
17253	last: function() {
17254		return this.eq( -1 );
17255	},
17256
17257	even: function() {
17258		return this.pushStack( jQuery.grep( this, function( _elem, i ) {
17259			return ( i + 1 ) % 2;
17260		} ) );
17261	},
17262
17263	odd: function() {
17264		return this.pushStack( jQuery.grep( this, function( _elem, i ) {
17265			return i % 2;
17266		} ) );
17267	},
17268
17269	eq: function( i ) {
17270		var len = this.length,
17271			j = +i + ( i < 0 ? len : 0 );
17272		return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );
17273	},
17274
17275	end: function() {
17276		return this.prevObject || this.constructor();
17277	},
17278
17279	// For internal use only.
17280	// Behaves like an Array's method, not like a jQuery method.
17281	push: push,
17282	sort: arr.sort,
17283	splice: arr.splice
17284};
17285
17286jQuery.extend = jQuery.fn.extend = function() {
17287	var options, name, src, copy, copyIsArray, clone,
17288		target = arguments[ 0 ] || {},
17289		i = 1,
17290		length = arguments.length,
17291		deep = false;
17292
17293	// Handle a deep copy situation
17294	if ( typeof target === "boolean" ) {
17295		deep = target;
17296
17297		// Skip the boolean and the target
17298		target = arguments[ i ] || {};
17299		i++;
17300	}
17301
17302	// Handle case when target is a string or something (possible in deep copy)
17303	if ( typeof target !== "object" && !isFunction( target ) ) {
17304		target = {};
17305	}
17306
17307	// Extend jQuery itself if only one argument is passed
17308	if ( i === length ) {
17309		target = this;
17310		i--;
17311	}
17312
17313	for ( ; i < length; i++ ) {
17314
17315		// Only deal with non-null/undefined values
17316		if ( ( options = arguments[ i ] ) != null ) {
17317
17318			// Extend the base object
17319			for ( name in options ) {
17320				copy = options[ name ];
17321
17322				// Prevent Object.prototype pollution
17323				// Prevent never-ending loop
17324				if ( name === "__proto__" || target === copy ) {
17325					continue;
17326				}
17327
17328				// Recurse if we're merging plain objects or arrays
17329				if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
17330					( copyIsArray = Array.isArray( copy ) ) ) ) {
17331					src = target[ name ];
17332
17333					// Ensure proper type for the source value
17334					if ( copyIsArray && !Array.isArray( src ) ) {
17335						clone = [];
17336					} else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) {
17337						clone = {};
17338					} else {
17339						clone = src;
17340					}
17341					copyIsArray = false;
17342
17343					// Never move original objects, clone them
17344					target[ name ] = jQuery.extend( deep, clone, copy );
17345
17346				// Don't bring in undefined values
17347				} else if ( copy !== undefined ) {
17348					target[ name ] = copy;
17349				}
17350			}
17351		}
17352	}
17353
17354	// Return the modified object
17355	return target;
17356};
17357
17358jQuery.extend( {
17359
17360	// Unique for each copy of jQuery on the page
17361	expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
17362
17363	// Assume jQuery is ready without the ready module
17364	isReady: true,
17365
17366	error: function( msg ) {
17367		throw new Error( msg );
17368	},
17369
17370	noop: function() {},
17371
17372	isPlainObject: function( obj ) {
17373		var proto, Ctor;
17374
17375		// Detect obvious negatives
17376		// Use toString instead of jQuery.type to catch host objects
17377		if ( !obj || toString.call( obj ) !== "[object Object]" ) {
17378			return false;
17379		}
17380
17381		proto = getProto( obj );
17382
17383		// Objects with no prototype (e.g., `Object.create( null )`) are plain
17384		if ( !proto ) {
17385			return true;
17386		}
17387
17388		// Objects with prototype are plain iff they were constructed by a global Object function
17389		Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor;
17390		return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString;
17391	},
17392
17393	isEmptyObject: function( obj ) {
17394		var name;
17395
17396		for ( name in obj ) {
17397			return false;
17398		}
17399		return true;
17400	},
17401
17402	// Evaluates a script in a provided context; falls back to the global one
17403	// if not specified.
17404	globalEval: function( code, options, doc ) {
17405		DOMEval( code, { nonce: options && options.nonce }, doc );
17406	},
17407
17408	each: function( obj, callback ) {
17409		var length, i = 0;
17410
17411		if ( isArrayLike( obj ) ) {
17412			length = obj.length;
17413			for ( ; i < length; i++ ) {
17414				if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
17415					break;
17416				}
17417			}
17418		} else {
17419			for ( i in obj ) {
17420				if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
17421					break;
17422				}
17423			}
17424		}
17425
17426		return obj;
17427	},
17428
17429	// results is for internal usage only
17430	makeArray: function( arr, results ) {
17431		var ret = results || [];
17432
17433		if ( arr != null ) {
17434			if ( isArrayLike( Object( arr ) ) ) {
17435				jQuery.merge( ret,
17436					typeof arr === "string" ?
17437						[ arr ] : arr
17438				);
17439			} else {
17440				push.call( ret, arr );
17441			}
17442		}
17443
17444		return ret;
17445	},
17446
17447	inArray: function( elem, arr, i ) {
17448		return arr == null ? -1 : indexOf.call( arr, elem, i );
17449	},
17450
17451	// Support: Android <=4.0 only, PhantomJS 1 only
17452	// push.apply(_, arraylike) throws on ancient WebKit
17453	merge: function( first, second ) {
17454		var len = +second.length,
17455			j = 0,
17456			i = first.length;
17457
17458		for ( ; j < len; j++ ) {
17459			first[ i++ ] = second[ j ];
17460		}
17461
17462		first.length = i;
17463
17464		return first;
17465	},
17466
17467	grep: function( elems, callback, invert ) {
17468		var callbackInverse,
17469			matches = [],
17470			i = 0,
17471			length = elems.length,
17472			callbackExpect = !invert;
17473
17474		// Go through the array, only saving the items
17475		// that pass the validator function
17476		for ( ; i < length; i++ ) {
17477			callbackInverse = !callback( elems[ i ], i );
17478			if ( callbackInverse !== callbackExpect ) {
17479				matches.push( elems[ i ] );
17480			}
17481		}
17482
17483		return matches;
17484	},
17485
17486	// arg is for internal usage only
17487	map: function( elems, callback, arg ) {
17488		var length, value,
17489			i = 0,
17490			ret = [];
17491
17492		// Go through the array, translating each of the items to their new values
17493		if ( isArrayLike( elems ) ) {
17494			length = elems.length;
17495			for ( ; i < length; i++ ) {
17496				value = callback( elems[ i ], i, arg );
17497
17498				if ( value != null ) {
17499					ret.push( value );
17500				}
17501			}
17502
17503		// Go through every key on the object,
17504		} else {
17505			for ( i in elems ) {
17506				value = callback( elems[ i ], i, arg );
17507
17508				if ( value != null ) {
17509					ret.push( value );
17510				}
17511			}
17512		}
17513
17514		// Flatten any nested arrays
17515		return flat( ret );
17516	},
17517
17518	// A global GUID counter for objects
17519	guid: 1,
17520
17521	// jQuery.support is not used in Core but other projects attach their
17522	// properties to it so it needs to exist.
17523	support: support
17524} );
17525
17526if ( typeof Symbol === "function" ) {
17527	jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ];
17528}
17529
17530// Populate the class2type map
17531jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
17532	function( _i, name ) {
17533		class2type[ "[object " + name + "]" ] = name.toLowerCase();
17534	} );
17535
17536function isArrayLike( obj ) {
17537
17538	// Support: real iOS 8.2 only (not reproducible in simulator)
17539	// `in` check used to prevent JIT error (gh-2145)
17540	// hasOwn isn't used here due to false negatives
17541	// regarding Nodelist length in IE
17542	var length = !!obj && "length" in obj && obj.length,
17543		type = toType( obj );
17544
17545	if ( isFunction( obj ) || isWindow( obj ) ) {
17546		return false;
17547	}
17548
17549	return type === "array" || length === 0 ||
17550		typeof length === "number" && length > 0 && ( length - 1 ) in obj;
17551}
17552var Sizzle =
17553/*!
17554 * Sizzle CSS Selector Engine v2.3.6
17555 * https://sizzlejs.com/
17556 *
17557 * Copyright JS Foundation and other contributors
17558 * Released under the MIT license
17559 * https://js.foundation/
17560 *
17561 * Date: 2021-02-16
17562 */
17563( function( window ) {
17564var i,
17565	support,
17566	Expr,
17567	getText,
17568	isXML,
17569	tokenize,
17570	compile,
17571	select,
17572	outermostContext,
17573	sortInput,
17574	hasDuplicate,
17575
17576	// Local document vars
17577	setDocument,
17578	document,
17579	docElem,
17580	documentIsHTML,
17581	rbuggyQSA,
17582	rbuggyMatches,
17583	matches,
17584	contains,
17585
17586	// Instance-specific data
17587	expando = "sizzle" + 1 * new Date(),
17588	preferredDoc = window.document,
17589	dirruns = 0,
17590	done = 0,
17591	classCache = createCache(),
17592	tokenCache = createCache(),
17593	compilerCache = createCache(),
17594	nonnativeSelectorCache = createCache(),
17595	sortOrder = function( a, b ) {
17596		if ( a === b ) {
17597			hasDuplicate = true;
17598		}
17599		return 0;
17600	},
17601
17602	// Instance methods
17603	hasOwn = ( {} ).hasOwnProperty,
17604	arr = [],
17605	pop = arr.pop,
17606	pushNative = arr.push,
17607	push = arr.push,
17608	slice = arr.slice,
17609
17610	// Use a stripped-down indexOf as it's faster than native
17611	// https://jsperf.com/thor-indexof-vs-for/5
17612	indexOf = function( list, elem ) {
17613		var i = 0,
17614			len = list.length;
17615		for ( ; i < len; i++ ) {
17616			if ( list[ i ] === elem ) {
17617				return i;
17618			}
17619		}
17620		return -1;
17621	},
17622
17623	booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" +
17624		"ismap|loop|multiple|open|readonly|required|scoped",
17625
17626	// Regular expressions
17627
17628	// http://www.w3.org/TR/css3-selectors/#whitespace
17629	whitespace = "[\\x20\\t\\r\\n\\f]",
17630
17631	// https://www.w3.org/TR/css-syntax-3/#ident-token-diagram
17632	identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace +
17633		"?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+",
17634
17635	// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
17636	attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace +
17637
17638		// Operator (capture 2)
17639		"*([*^$|!~]?=)" + whitespace +
17640
17641		// "Attribute values must be CSS identifiers [capture 5]
17642		// or strings [capture 3 or capture 4]"
17643		"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" +
17644		whitespace + "*\\]",
17645
17646	pseudos = ":(" + identifier + ")(?:\\((" +
17647
17648		// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
17649		// 1. quoted (capture 3; capture 4 or capture 5)
17650		"('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
17651
17652		// 2. simple (capture 6)
17653		"((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
17654
17655		// 3. anything else (capture 2)
17656		".*" +
17657		")\\)|)",
17658
17659	// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
17660	rwhitespace = new RegExp( whitespace + "+", "g" ),
17661	rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" +
17662		whitespace + "+$", "g" ),
17663
17664	rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
17665	rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace +
17666		"*" ),
17667	rdescend = new RegExp( whitespace + "|>" ),
17668
17669	rpseudo = new RegExp( pseudos ),
17670	ridentifier = new RegExp( "^" + identifier + "$" ),
17671
17672	matchExpr = {
17673		"ID": new RegExp( "^#(" + identifier + ")" ),
17674		"CLASS": new RegExp( "^\\.(" + identifier + ")" ),
17675		"TAG": new RegExp( "^(" + identifier + "|[*])" ),
17676		"ATTR": new RegExp( "^" + attributes ),
17677		"PSEUDO": new RegExp( "^" + pseudos ),
17678		"CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" +
17679			whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" +
17680			whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
17681		"bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
17682
17683		// For use in libraries implementing .is()
17684		// We use this for POS matching in `select`
17685		"needsContext": new RegExp( "^" + whitespace +
17686			"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace +
17687			"*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
17688	},
17689
17690	rhtml = /HTML$/i,
17691	rinputs = /^(?:input|select|textarea|button)$/i,
17692	rheader = /^h\d$/i,
17693
17694	rnative = /^[^{]+\{\s*\[native \w/,
17695
17696	// Easily-parseable/retrievable ID or TAG or CLASS selectors
17697	rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
17698
17699	rsibling = /[+~]/,
17700
17701	// CSS escapes
17702	// http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
17703	runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ),
17704	funescape = function( escape, nonHex ) {
17705		var high = "0x" + escape.slice( 1 ) - 0x10000;
17706
17707		return nonHex ?
17708
17709			// Strip the backslash prefix from a non-hex escape sequence
17710			nonHex :
17711
17712			// Replace a hexadecimal escape sequence with the encoded Unicode code point
17713			// Support: IE <=11+
17714			// For values outside the Basic Multilingual Plane (BMP), manually construct a
17715			// surrogate pair
17716			high < 0 ?
17717				String.fromCharCode( high + 0x10000 ) :
17718				String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
17719	},
17720
17721	// CSS string/identifier serialization
17722	// https://drafts.csswg.org/cssom/#common-serializing-idioms
17723	rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,
17724	fcssescape = function( ch, asCodePoint ) {
17725		if ( asCodePoint ) {
17726
17727			// U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER
17728			if ( ch === "\0" ) {
17729				return "\uFFFD";
17730			}
17731
17732			// Control characters and (dependent upon position) numbers get escaped as code points
17733			return ch.slice( 0, -1 ) + "\\" +
17734				ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " ";
17735		}
17736
17737		// Other potentially-special ASCII characters get backslash-escaped
17738		return "\\" + ch;
17739	},
17740
17741	// Used for iframes
17742	// See setDocument()
17743	// Removing the function wrapper causes a "Permission Denied"
17744	// error in IE
17745	unloadHandler = function() {
17746		setDocument();
17747	},
17748
17749	inDisabledFieldset = addCombinator(
17750		function( elem ) {
17751			return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset";
17752		},
17753		{ dir: "parentNode", next: "legend" }
17754	);
17755
17756// Optimize for push.apply( _, NodeList )
17757try {
17758	push.apply(
17759		( arr = slice.call( preferredDoc.childNodes ) ),
17760		preferredDoc.childNodes
17761	);
17762
17763	// Support: Android<4.0
17764	// Detect silently failing push.apply
17765	// eslint-disable-next-line no-unused-expressions
17766	arr[ preferredDoc.childNodes.length ].nodeType;
17767} catch ( e ) {
17768	push = { apply: arr.length ?
17769
17770		// Leverage slice if possible
17771		function( target, els ) {
17772			pushNative.apply( target, slice.call( els ) );
17773		} :
17774
17775		// Support: IE<9
17776		// Otherwise append directly
17777		function( target, els ) {
17778			var j = target.length,
17779				i = 0;
17780
17781			// Can't trust NodeList.length
17782			while ( ( target[ j++ ] = els[ i++ ] ) ) {}
17783			target.length = j - 1;
17784		}
17785	};
17786}
17787
17788function Sizzle( selector, context, results, seed ) {
17789	var m, i, elem, nid, match, groups, newSelector,
17790		newContext = context && context.ownerDocument,
17791
17792		// nodeType defaults to 9, since context defaults to document
17793		nodeType = context ? context.nodeType : 9;
17794
17795	results = results || [];
17796
17797	// Return early from calls with invalid selector or context
17798	if ( typeof selector !== "string" || !selector ||
17799		nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
17800
17801		return results;
17802	}
17803
17804	// Try to shortcut find operations (as opposed to filters) in HTML documents
17805	if ( !seed ) {
17806		setDocument( context );
17807		context = context || document;
17808
17809		if ( documentIsHTML ) {
17810
17811			// If the selector is sufficiently simple, try using a "get*By*" DOM method
17812			// (excepting DocumentFragment context, where the methods don't exist)
17813			if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) {
17814
17815				// ID selector
17816				if ( ( m = match[ 1 ] ) ) {
17817
17818					// Document context
17819					if ( nodeType === 9 ) {
17820						if ( ( elem = context.getElementById( m ) ) ) {
17821
17822							// Support: IE, Opera, Webkit
17823							// TODO: identify versions
17824							// getElementById can match elements by name instead of ID
17825							if ( elem.id === m ) {
17826								results.push( elem );
17827								return results;
17828							}
17829						} else {
17830							return results;
17831						}
17832
17833					// Element context
17834					} else {
17835
17836						// Support: IE, Opera, Webkit
17837						// TODO: identify versions
17838						// getElementById can match elements by name instead of ID
17839						if ( newContext && ( elem = newContext.getElementById( m ) ) &&
17840							contains( context, elem ) &&
17841							elem.id === m ) {
17842
17843							results.push( elem );
17844							return results;
17845						}
17846					}
17847
17848				// Type selector
17849				} else if ( match[ 2 ] ) {
17850					push.apply( results, context.getElementsByTagName( selector ) );
17851					return results;
17852
17853				// Class selector
17854				} else if ( ( m = match[ 3 ] ) && support.getElementsByClassName &&
17855					context.getElementsByClassName ) {
17856
17857					push.apply( results, context.getElementsByClassName( m ) );
17858					return results;
17859				}
17860			}
17861
17862			// Take advantage of querySelectorAll
17863			if ( support.qsa &&
17864				!nonnativeSelectorCache[ selector + " " ] &&
17865				( !rbuggyQSA || !rbuggyQSA.test( selector ) ) &&
17866
17867				// Support: IE 8 only
17868				// Exclude object elements
17869				( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) {
17870
17871				newSelector = selector;
17872				newContext = context;
17873
17874				// qSA considers elements outside a scoping root when evaluating child or
17875				// descendant combinators, which is not what we want.
17876				// In such cases, we work around the behavior by prefixing every selector in the
17877				// list with an ID selector referencing the scope context.
17878				// The technique has to be used as well when a leading combinator is used
17879				// as such selectors are not recognized by querySelectorAll.
17880				// Thanks to Andrew Dupont for this technique.
17881				if ( nodeType === 1 &&
17882					( rdescend.test( selector ) || rcombinators.test( selector ) ) ) {
17883
17884					// Expand context for sibling selectors
17885					newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
17886						context;
17887
17888					// We can use :scope instead of the ID hack if the browser
17889					// supports it & if we're not changing the context.
17890					if ( newContext !== context || !support.scope ) {
17891
17892						// Capture the context ID, setting it first if necessary
17893						if ( ( nid = context.getAttribute( "id" ) ) ) {
17894							nid = nid.replace( rcssescape, fcssescape );
17895						} else {
17896							context.setAttribute( "id", ( nid = expando ) );
17897						}
17898					}
17899
17900					// Prefix every selector in the list
17901					groups = tokenize( selector );
17902					i = groups.length;
17903					while ( i-- ) {
17904						groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " +
17905							toSelector( groups[ i ] );
17906					}
17907					newSelector = groups.join( "," );
17908				}
17909
17910				try {
17911					push.apply( results,
17912						newContext.querySelectorAll( newSelector )
17913					);
17914					return results;
17915				} catch ( qsaError ) {
17916					nonnativeSelectorCache( selector, true );
17917				} finally {
17918					if ( nid === expando ) {
17919						context.removeAttribute( "id" );
17920					}
17921				}
17922			}
17923		}
17924	}
17925
17926	// All others
17927	return select( selector.replace( rtrim, "$1" ), context, results, seed );
17928}
17929
17930/**
17931 * Create key-value caches of limited size
17932 * @returns {function(string, object)} Returns the Object data after storing it on itself with
17933 *	property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
17934 *	deleting the oldest entry
17935 */
17936function createCache() {
17937	var keys = [];
17938
17939	function cache( key, value ) {
17940
17941		// Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
17942		if ( keys.push( key + " " ) > Expr.cacheLength ) {
17943
17944			// Only keep the most recent entries
17945			delete cache[ keys.shift() ];
17946		}
17947		return ( cache[ key + " " ] = value );
17948	}
17949	return cache;
17950}
17951
17952/**
17953 * Mark a function for special use by Sizzle
17954 * @param {Function} fn The function to mark
17955 */
17956function markFunction( fn ) {
17957	fn[ expando ] = true;
17958	return fn;
17959}
17960
17961/**
17962 * Support testing using an element
17963 * @param {Function} fn Passed the created element and returns a boolean result
17964 */
17965function assert( fn ) {
17966	var el = document.createElement( "fieldset" );
17967
17968	try {
17969		return !!fn( el );
17970	} catch ( e ) {
17971		return false;
17972	} finally {
17973
17974		// Remove from its parent by default
17975		if ( el.parentNode ) {
17976			el.parentNode.removeChild( el );
17977		}
17978
17979		// release memory in IE
17980		el = null;
17981	}
17982}
17983
17984/**
17985 * Adds the same handler for all of the specified attrs
17986 * @param {String} attrs Pipe-separated list of attributes
17987 * @param {Function} handler The method that will be applied
17988 */
17989function addHandle( attrs, handler ) {
17990	var arr = attrs.split( "|" ),
17991		i = arr.length;
17992
17993	while ( i-- ) {
17994		Expr.attrHandle[ arr[ i ] ] = handler;
17995	}
17996}
17997
17998/**
17999 * Checks document order of two siblings
18000 * @param {Element} a
18001 * @param {Element} b
18002 * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
18003 */
18004function siblingCheck( a, b ) {
18005	var cur = b && a,
18006		diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
18007			a.sourceIndex - b.sourceIndex;
18008
18009	// Use IE sourceIndex if available on both nodes
18010	if ( diff ) {
18011		return diff;
18012	}
18013
18014	// Check if b follows a
18015	if ( cur ) {
18016		while ( ( cur = cur.nextSibling ) ) {
18017			if ( cur === b ) {
18018				return -1;
18019			}
18020		}
18021	}
18022
18023	return a ? 1 : -1;
18024}
18025
18026/**
18027 * Returns a function to use in pseudos for input types
18028 * @param {String} type
18029 */
18030function createInputPseudo( type ) {
18031	return function( elem ) {
18032		var name = elem.nodeName.toLowerCase();
18033		return name === "input" && elem.type === type;
18034	};
18035}
18036
18037/**
18038 * Returns a function to use in pseudos for buttons
18039 * @param {String} type
18040 */
18041function createButtonPseudo( type ) {
18042	return function( elem ) {
18043		var name = elem.nodeName.toLowerCase();
18044		return ( name === "input" || name === "button" ) && elem.type === type;
18045	};
18046}
18047
18048/**
18049 * Returns a function to use in pseudos for :enabled/:disabled
18050 * @param {Boolean} disabled true for :disabled; false for :enabled
18051 */
18052function createDisabledPseudo( disabled ) {
18053
18054	// Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable
18055	return function( elem ) {
18056
18057		// Only certain elements can match :enabled or :disabled
18058		// https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled
18059		// https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled
18060		if ( "form" in elem ) {
18061
18062			// Check for inherited disabledness on relevant non-disabled elements:
18063			// * listed form-associated elements in a disabled fieldset
18064			//   https://html.spec.whatwg.org/multipage/forms.html#category-listed
18065			//   https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled
18066			// * option elements in a disabled optgroup
18067			//   https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled
18068			// All such elements have a "form" property.
18069			if ( elem.parentNode && elem.disabled === false ) {
18070
18071				// Option elements defer to a parent optgroup if present
18072				if ( "label" in elem ) {
18073					if ( "label" in elem.parentNode ) {
18074						return elem.parentNode.disabled === disabled;
18075					} else {
18076						return elem.disabled === disabled;
18077					}
18078				}
18079
18080				// Support: IE 6 - 11
18081				// Use the isDisabled shortcut property to check for disabled fieldset ancestors
18082				return elem.isDisabled === disabled ||
18083
18084					// Where there is no isDisabled, check manually
18085					/* jshint -W018 */
18086					elem.isDisabled !== !disabled &&
18087					inDisabledFieldset( elem ) === disabled;
18088			}
18089
18090			return elem.disabled === disabled;
18091
18092		// Try to winnow out elements that can't be disabled before trusting the disabled property.
18093		// Some victims get caught in our net (label, legend, menu, track), but it shouldn't
18094		// even exist on them, let alone have a boolean value.
18095		} else if ( "label" in elem ) {
18096			return elem.disabled === disabled;
18097		}
18098
18099		// Remaining elements are neither :enabled nor :disabled
18100		return false;
18101	};
18102}
18103
18104/**
18105 * Returns a function to use in pseudos for positionals
18106 * @param {Function} fn
18107 */
18108function createPositionalPseudo( fn ) {
18109	return markFunction( function( argument ) {
18110		argument = +argument;
18111		return markFunction( function( seed, matches ) {
18112			var j,
18113				matchIndexes = fn( [], seed.length, argument ),
18114				i = matchIndexes.length;
18115
18116			// Match elements found at the specified indexes
18117			while ( i-- ) {
18118				if ( seed[ ( j = matchIndexes[ i ] ) ] ) {
18119					seed[ j ] = !( matches[ j ] = seed[ j ] );
18120				}
18121			}
18122		} );
18123	} );
18124}
18125
18126/**
18127 * Checks a node for validity as a Sizzle context
18128 * @param {Element|Object=} context
18129 * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
18130 */
18131function testContext( context ) {
18132	return context && typeof context.getElementsByTagName !== "undefined" && context;
18133}
18134
18135// Expose support vars for convenience
18136support = Sizzle.support = {};
18137
18138/**
18139 * Detects XML nodes
18140 * @param {Element|Object} elem An element or a document
18141 * @returns {Boolean} True iff elem is a non-HTML XML node
18142 */
18143isXML = Sizzle.isXML = function( elem ) {
18144	var namespace = elem && elem.namespaceURI,
18145		docElem = elem && ( elem.ownerDocument || elem ).documentElement;
18146
18147	// Support: IE <=8
18148	// Assume HTML when documentElement doesn't yet exist, such as inside loading iframes
18149	// https://bugs.jquery.com/ticket/4833
18150	return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" );
18151};
18152
18153/**
18154 * Sets document-related variables once based on the current document
18155 * @param {Element|Object} [doc] An element or document object to use to set the document
18156 * @returns {Object} Returns the current document
18157 */
18158setDocument = Sizzle.setDocument = function( node ) {
18159	var hasCompare, subWindow,
18160		doc = node ? node.ownerDocument || node : preferredDoc;
18161
18162	// Return early if doc is invalid or already selected
18163	// Support: IE 11+, Edge 17 - 18+
18164	// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
18165	// two documents; shallow comparisons work.
18166	// eslint-disable-next-line eqeqeq
18167	if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) {
18168		return document;
18169	}
18170
18171	// Update global variables
18172	document = doc;
18173	docElem = document.documentElement;
18174	documentIsHTML = !isXML( document );
18175
18176	// Support: IE 9 - 11+, Edge 12 - 18+
18177	// Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936)
18178	// Support: IE 11+, Edge 17 - 18+
18179	// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
18180	// two documents; shallow comparisons work.
18181	// eslint-disable-next-line eqeqeq
18182	if ( preferredDoc != document &&
18183		( subWindow = document.defaultView ) && subWindow.top !== subWindow ) {
18184
18185		// Support: IE 11, Edge
18186		if ( subWindow.addEventListener ) {
18187			subWindow.addEventListener( "unload", unloadHandler, false );
18188
18189		// Support: IE 9 - 10 only
18190		} else if ( subWindow.attachEvent ) {
18191			subWindow.attachEvent( "onunload", unloadHandler );
18192		}
18193	}
18194
18195	// Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only,
18196	// Safari 4 - 5 only, Opera <=11.6 - 12.x only
18197	// IE/Edge & older browsers don't support the :scope pseudo-class.
18198	// Support: Safari 6.0 only
18199	// Safari 6.0 supports :scope but it's an alias of :root there.
18200	support.scope = assert( function( el ) {
18201		docElem.appendChild( el ).appendChild( document.createElement( "div" ) );
18202		return typeof el.querySelectorAll !== "undefined" &&
18203			!el.querySelectorAll( ":scope fieldset div" ).length;
18204	} );
18205
18206	/* Attributes
18207	---------------------------------------------------------------------- */
18208
18209	// Support: IE<8
18210	// Verify that getAttribute really returns attributes and not properties
18211	// (excepting IE8 booleans)
18212	support.attributes = assert( function( el ) {
18213		el.className = "i";
18214		return !el.getAttribute( "className" );
18215	} );
18216
18217	/* getElement(s)By*
18218	---------------------------------------------------------------------- */
18219
18220	// Check if getElementsByTagName("*") returns only elements
18221	support.getElementsByTagName = assert( function( el ) {
18222		el.appendChild( document.createComment( "" ) );
18223		return !el.getElementsByTagName( "*" ).length;
18224	} );
18225
18226	// Support: IE<9
18227	support.getElementsByClassName = rnative.test( document.getElementsByClassName );
18228
18229	// Support: IE<10
18230	// Check if getElementById returns elements by name
18231	// The broken getElementById methods don't pick up programmatically-set names,
18232	// so use a roundabout getElementsByName test
18233	support.getById = assert( function( el ) {
18234		docElem.appendChild( el ).id = expando;
18235		return !document.getElementsByName || !document.getElementsByName( expando ).length;
18236	} );
18237
18238	// ID filter and find
18239	if ( support.getById ) {
18240		Expr.filter[ "ID" ] = function( id ) {
18241			var attrId = id.replace( runescape, funescape );
18242			return function( elem ) {
18243				return elem.getAttribute( "id" ) === attrId;
18244			};
18245		};
18246		Expr.find[ "ID" ] = function( id, context ) {
18247			if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
18248				var elem = context.getElementById( id );
18249				return elem ? [ elem ] : [];
18250			}
18251		};
18252	} else {
18253		Expr.filter[ "ID" ] =  function( id ) {
18254			var attrId = id.replace( runescape, funescape );
18255			return function( elem ) {
18256				var node = typeof elem.getAttributeNode !== "undefined" &&
18257					elem.getAttributeNode( "id" );
18258				return node && node.value === attrId;
18259			};
18260		};
18261
18262		// Support: IE 6 - 7 only
18263		// getElementById is not reliable as a find shortcut
18264		Expr.find[ "ID" ] = function( id, context ) {
18265			if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
18266				var node, i, elems,
18267					elem = context.getElementById( id );
18268
18269				if ( elem ) {
18270
18271					// Verify the id attribute
18272					node = elem.getAttributeNode( "id" );
18273					if ( node && node.value === id ) {
18274						return [ elem ];
18275					}
18276
18277					// Fall back on getElementsByName
18278					elems = context.getElementsByName( id );
18279					i = 0;
18280					while ( ( elem = elems[ i++ ] ) ) {
18281						node = elem.getAttributeNode( "id" );
18282						if ( node && node.value === id ) {
18283							return [ elem ];
18284						}
18285					}
18286				}
18287
18288				return [];
18289			}
18290		};
18291	}
18292
18293	// Tag
18294	Expr.find[ "TAG" ] = support.getElementsByTagName ?
18295		function( tag, context ) {
18296			if ( typeof context.getElementsByTagName !== "undefined" ) {
18297				return context.getElementsByTagName( tag );
18298
18299			// DocumentFragment nodes don't have gEBTN
18300			} else if ( support.qsa ) {
18301				return context.querySelectorAll( tag );
18302			}
18303		} :
18304
18305		function( tag, context ) {
18306			var elem,
18307				tmp = [],
18308				i = 0,
18309
18310				// By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
18311				results = context.getElementsByTagName( tag );
18312
18313			// Filter out possible comments
18314			if ( tag === "*" ) {
18315				while ( ( elem = results[ i++ ] ) ) {
18316					if ( elem.nodeType === 1 ) {
18317						tmp.push( elem );
18318					}
18319				}
18320
18321				return tmp;
18322			}
18323			return results;
18324		};
18325
18326	// Class
18327	Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) {
18328		if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) {
18329			return context.getElementsByClassName( className );
18330		}
18331	};
18332
18333	/* QSA/matchesSelector
18334	---------------------------------------------------------------------- */
18335
18336	// QSA and matchesSelector support
18337
18338	// matchesSelector(:active) reports false when true (IE9/Opera 11.5)
18339	rbuggyMatches = [];
18340
18341	// qSa(:focus) reports false when true (Chrome 21)
18342	// We allow this because of a bug in IE8/9 that throws an error
18343	// whenever `document.activeElement` is accessed on an iframe
18344	// So, we allow :focus to pass through QSA all the time to avoid the IE error
18345	// See https://bugs.jquery.com/ticket/13378
18346	rbuggyQSA = [];
18347
18348	if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) {
18349
18350		// Build QSA regex
18351		// Regex strategy adopted from Diego Perini
18352		assert( function( el ) {
18353
18354			var input;
18355
18356			// Select is set to empty string on purpose
18357			// This is to test IE's treatment of not explicitly
18358			// setting a boolean content attribute,
18359			// since its presence should be enough
18360			// https://bugs.jquery.com/ticket/12359
18361			docElem.appendChild( el ).innerHTML = "<a id='" + expando + "'></a>" +
18362				"<select id='" + expando + "-\r\\' msallowcapture=''>" +
18363				"<option selected=''></option></select>";
18364
18365			// Support: IE8, Opera 11-12.16
18366			// Nothing should be selected when empty strings follow ^= or $= or *=
18367			// The test attribute must be unknown in Opera but "safe" for WinRT
18368			// https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
18369			if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) {
18370				rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
18371			}
18372
18373			// Support: IE8
18374			// Boolean attributes and "value" are not treated correctly
18375			if ( !el.querySelectorAll( "[selected]" ).length ) {
18376				rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
18377			}
18378
18379			// Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+
18380			if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
18381				rbuggyQSA.push( "~=" );
18382			}
18383
18384			// Support: IE 11+, Edge 15 - 18+
18385			// IE 11/Edge don't find elements on a `[name='']` query in some cases.
18386			// Adding a temporary attribute to the document before the selection works
18387			// around the issue.
18388			// Interestingly, IE 10 & older don't seem to have the issue.
18389			input = document.createElement( "input" );
18390			input.setAttribute( "name", "" );
18391			el.appendChild( input );
18392			if ( !el.querySelectorAll( "[name='']" ).length ) {
18393				rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" +
18394					whitespace + "*(?:''|\"\")" );
18395			}
18396
18397			// Webkit/Opera - :checked should return selected option elements
18398			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
18399			// IE8 throws error here and will not see later tests
18400			if ( !el.querySelectorAll( ":checked" ).length ) {
18401				rbuggyQSA.push( ":checked" );
18402			}
18403
18404			// Support: Safari 8+, iOS 8+
18405			// https://bugs.webkit.org/show_bug.cgi?id=136851
18406			// In-page `selector#id sibling-combinator selector` fails
18407			if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) {
18408				rbuggyQSA.push( ".#.+[+~]" );
18409			}
18410
18411			// Support: Firefox <=3.6 - 5 only
18412			// Old Firefox doesn't throw on a badly-escaped identifier.
18413			el.querySelectorAll( "\\\f" );
18414			rbuggyQSA.push( "[\\r\\n\\f]" );
18415		} );
18416
18417		assert( function( el ) {
18418			el.innerHTML = "<a href='' disabled='disabled'></a>" +
18419				"<select disabled='disabled'><option/></select>";
18420
18421			// Support: Windows 8 Native Apps
18422			// The type and name attributes are restricted during .innerHTML assignment
18423			var input = document.createElement( "input" );
18424			input.setAttribute( "type", "hidden" );
18425			el.appendChild( input ).setAttribute( "name", "D" );
18426
18427			// Support: IE8
18428			// Enforce case-sensitivity of name attribute
18429			if ( el.querySelectorAll( "[name=d]" ).length ) {
18430				rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
18431			}
18432
18433			// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
18434			// IE8 throws error here and will not see later tests
18435			if ( el.querySelectorAll( ":enabled" ).length !== 2 ) {
18436				rbuggyQSA.push( ":enabled", ":disabled" );
18437			}
18438
18439			// Support: IE9-11+
18440			// IE's :disabled selector does not pick up the children of disabled fieldsets
18441			docElem.appendChild( el ).disabled = true;
18442			if ( el.querySelectorAll( ":disabled" ).length !== 2 ) {
18443				rbuggyQSA.push( ":enabled", ":disabled" );
18444			}
18445
18446			// Support: Opera 10 - 11 only
18447			// Opera 10-11 does not throw on post-comma invalid pseudos
18448			el.querySelectorAll( "*,:x" );
18449			rbuggyQSA.push( ",.*:" );
18450		} );
18451	}
18452
18453	if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches ||
18454		docElem.webkitMatchesSelector ||
18455		docElem.mozMatchesSelector ||
18456		docElem.oMatchesSelector ||
18457		docElem.msMatchesSelector ) ) ) ) {
18458
18459		assert( function( el ) {
18460
18461			// Check to see if it's possible to do matchesSelector
18462			// on a disconnected node (IE 9)
18463			support.disconnectedMatch = matches.call( el, "*" );
18464
18465			// This should fail with an exception
18466			// Gecko does not error, returns false instead
18467			matches.call( el, "[s!='']:x" );
18468			rbuggyMatches.push( "!=", pseudos );
18469		} );
18470	}
18471
18472	rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) );
18473	rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) );
18474
18475	/* Contains
18476	---------------------------------------------------------------------- */
18477	hasCompare = rnative.test( docElem.compareDocumentPosition );
18478
18479	// Element contains another
18480	// Purposefully self-exclusive
18481	// As in, an element does not contain itself
18482	contains = hasCompare || rnative.test( docElem.contains ) ?
18483		function( a, b ) {
18484			var adown = a.nodeType === 9 ? a.documentElement : a,
18485				bup = b && b.parentNode;
18486			return a === bup || !!( bup && bup.nodeType === 1 && (
18487				adown.contains ?
18488					adown.contains( bup ) :
18489					a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
18490			) );
18491		} :
18492		function( a, b ) {
18493			if ( b ) {
18494				while ( ( b = b.parentNode ) ) {
18495					if ( b === a ) {
18496						return true;
18497					}
18498				}
18499			}
18500			return false;
18501		};
18502
18503	/* Sorting
18504	---------------------------------------------------------------------- */
18505
18506	// Document order sorting
18507	sortOrder = hasCompare ?
18508	function( a, b ) {
18509
18510		// Flag for duplicate removal
18511		if ( a === b ) {
18512			hasDuplicate = true;
18513			return 0;
18514		}
18515
18516		// Sort on method existence if only one input has compareDocumentPosition
18517		var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
18518		if ( compare ) {
18519			return compare;
18520		}
18521
18522		// Calculate position if both inputs belong to the same document
18523		// Support: IE 11+, Edge 17 - 18+
18524		// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
18525		// two documents; shallow comparisons work.
18526		// eslint-disable-next-line eqeqeq
18527		compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ?
18528			a.compareDocumentPosition( b ) :
18529
18530			// Otherwise we know they are disconnected
18531			1;
18532
18533		// Disconnected nodes
18534		if ( compare & 1 ||
18535			( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) {
18536
18537			// Choose the first element that is related to our preferred document
18538			// Support: IE 11+, Edge 17 - 18+
18539			// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
18540			// two documents; shallow comparisons work.
18541			// eslint-disable-next-line eqeqeq
18542			if ( a == document || a.ownerDocument == preferredDoc &&
18543				contains( preferredDoc, a ) ) {
18544				return -1;
18545			}
18546
18547			// Support: IE 11+, Edge 17 - 18+
18548			// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
18549			// two documents; shallow comparisons work.
18550			// eslint-disable-next-line eqeqeq
18551			if ( b == document || b.ownerDocument == preferredDoc &&
18552				contains( preferredDoc, b ) ) {
18553				return 1;
18554			}
18555
18556			// Maintain original order
18557			return sortInput ?
18558				( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
18559				0;
18560		}
18561
18562		return compare & 4 ? -1 : 1;
18563	} :
18564	function( a, b ) {
18565
18566		// Exit early if the nodes are identical
18567		if ( a === b ) {
18568			hasDuplicate = true;
18569			return 0;
18570		}
18571
18572		var cur,
18573			i = 0,
18574			aup = a.parentNode,
18575			bup = b.parentNode,
18576			ap = [ a ],
18577			bp = [ b ];
18578
18579		// Parentless nodes are either documents or disconnected
18580		if ( !aup || !bup ) {
18581
18582			// Support: IE 11+, Edge 17 - 18+
18583			// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
18584			// two documents; shallow comparisons work.
18585			/* eslint-disable eqeqeq */
18586			return a == document ? -1 :
18587				b == document ? 1 :
18588				/* eslint-enable eqeqeq */
18589				aup ? -1 :
18590				bup ? 1 :
18591				sortInput ?
18592				( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
18593				0;
18594
18595		// If the nodes are siblings, we can do a quick check
18596		} else if ( aup === bup ) {
18597			return siblingCheck( a, b );
18598		}
18599
18600		// Otherwise we need full lists of their ancestors for comparison
18601		cur = a;
18602		while ( ( cur = cur.parentNode ) ) {
18603			ap.unshift( cur );
18604		}
18605		cur = b;
18606		while ( ( cur = cur.parentNode ) ) {
18607			bp.unshift( cur );
18608		}
18609
18610		// Walk down the tree looking for a discrepancy
18611		while ( ap[ i ] === bp[ i ] ) {
18612			i++;
18613		}
18614
18615		return i ?
18616
18617			// Do a sibling check if the nodes have a common ancestor
18618			siblingCheck( ap[ i ], bp[ i ] ) :
18619
18620			// Otherwise nodes in our document sort first
18621			// Support: IE 11+, Edge 17 - 18+
18622			// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
18623			// two documents; shallow comparisons work.
18624			/* eslint-disable eqeqeq */
18625			ap[ i ] == preferredDoc ? -1 :
18626			bp[ i ] == preferredDoc ? 1 :
18627			/* eslint-enable eqeqeq */
18628			0;
18629	};
18630
18631	return document;
18632};
18633
18634Sizzle.matches = function( expr, elements ) {
18635	return Sizzle( expr, null, null, elements );
18636};
18637
18638Sizzle.matchesSelector = function( elem, expr ) {
18639	setDocument( elem );
18640
18641	if ( support.matchesSelector && documentIsHTML &&
18642		!nonnativeSelectorCache[ expr + " " ] &&
18643		( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
18644		( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {
18645
18646		try {
18647			var ret = matches.call( elem, expr );
18648
18649			// IE 9's matchesSelector returns false on disconnected nodes
18650			if ( ret || support.disconnectedMatch ||
18651
18652				// As well, disconnected nodes are said to be in a document
18653				// fragment in IE 9
18654				elem.document && elem.document.nodeType !== 11 ) {
18655				return ret;
18656			}
18657		} catch ( e ) {
18658			nonnativeSelectorCache( expr, true );
18659		}
18660	}
18661
18662	return Sizzle( expr, document, null, [ elem ] ).length > 0;
18663};
18664
18665Sizzle.contains = function( context, elem ) {
18666
18667	// Set document vars if needed
18668	// Support: IE 11+, Edge 17 - 18+
18669	// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
18670	// two documents; shallow comparisons work.
18671	// eslint-disable-next-line eqeqeq
18672	if ( ( context.ownerDocument || context ) != document ) {
18673		setDocument( context );
18674	}
18675	return contains( context, elem );
18676};
18677
18678Sizzle.attr = function( elem, name ) {
18679
18680	// Set document vars if needed
18681	// Support: IE 11+, Edge 17 - 18+
18682	// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
18683	// two documents; shallow comparisons work.
18684	// eslint-disable-next-line eqeqeq
18685	if ( ( elem.ownerDocument || elem ) != document ) {
18686		setDocument( elem );
18687	}
18688
18689	var fn = Expr.attrHandle[ name.toLowerCase() ],
18690
18691		// Don't get fooled by Object.prototype properties (jQuery #13807)
18692		val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
18693			fn( elem, name, !documentIsHTML ) :
18694			undefined;
18695
18696	return val !== undefined ?
18697		val :
18698		support.attributes || !documentIsHTML ?
18699			elem.getAttribute( name ) :
18700			( val = elem.getAttributeNode( name ) ) && val.specified ?
18701				val.value :
18702				null;
18703};
18704
18705Sizzle.escape = function( sel ) {
18706	return ( sel + "" ).replace( rcssescape, fcssescape );
18707};
18708
18709Sizzle.error = function( msg ) {
18710	throw new Error( "Syntax error, unrecognized expression: " + msg );
18711};
18712
18713/**
18714 * Document sorting and removing duplicates
18715 * @param {ArrayLike} results
18716 */
18717Sizzle.uniqueSort = function( results ) {
18718	var elem,
18719		duplicates = [],
18720		j = 0,
18721		i = 0;
18722
18723	// Unless we *know* we can detect duplicates, assume their presence
18724	hasDuplicate = !support.detectDuplicates;
18725	sortInput = !support.sortStable && results.slice( 0 );
18726	results.sort( sortOrder );
18727
18728	if ( hasDuplicate ) {
18729		while ( ( elem = results[ i++ ] ) ) {
18730			if ( elem === results[ i ] ) {
18731				j = duplicates.push( i );
18732			}
18733		}
18734		while ( j-- ) {
18735			results.splice( duplicates[ j ], 1 );
18736		}
18737	}
18738
18739	// Clear input after sorting to release objects
18740	// See https://github.com/jquery/sizzle/pull/225
18741	sortInput = null;
18742
18743	return results;
18744};
18745
18746/**
18747 * Utility function for retrieving the text value of an array of DOM nodes
18748 * @param {Array|Element} elem
18749 */
18750getText = Sizzle.getText = function( elem ) {
18751	var node,
18752		ret = "",
18753		i = 0,
18754		nodeType = elem.nodeType;
18755
18756	if ( !nodeType ) {
18757
18758		// If no nodeType, this is expected to be an array
18759		while ( ( node = elem[ i++ ] ) ) {
18760
18761			// Do not traverse comment nodes
18762			ret += getText( node );
18763		}
18764	} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
18765
18766		// Use textContent for elements
18767		// innerText usage removed for consistency of new lines (jQuery #11153)
18768		if ( typeof elem.textContent === "string" ) {
18769			return elem.textContent;
18770		} else {
18771
18772			// Traverse its children
18773			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
18774				ret += getText( elem );
18775			}
18776		}
18777	} else if ( nodeType === 3 || nodeType === 4 ) {
18778		return elem.nodeValue;
18779	}
18780
18781	// Do not include comment or processing instruction nodes
18782
18783	return ret;
18784};
18785
18786Expr = Sizzle.selectors = {
18787
18788	// Can be adjusted by the user
18789	cacheLength: 50,
18790
18791	createPseudo: markFunction,
18792
18793	match: matchExpr,
18794
18795	attrHandle: {},
18796
18797	find: {},
18798
18799	relative: {
18800		">": { dir: "parentNode", first: true },
18801		" ": { dir: "parentNode" },
18802		"+": { dir: "previousSibling", first: true },
18803		"~": { dir: "previousSibling" }
18804	},
18805
18806	preFilter: {
18807		"ATTR": function( match ) {
18808			match[ 1 ] = match[ 1 ].replace( runescape, funescape );
18809
18810			// Move the given value to match[3] whether quoted or unquoted
18811			match[ 3 ] = ( match[ 3 ] || match[ 4 ] ||
18812				match[ 5 ] || "" ).replace( runescape, funescape );
18813
18814			if ( match[ 2 ] === "~=" ) {
18815				match[ 3 ] = " " + match[ 3 ] + " ";
18816			}
18817
18818			return match.slice( 0, 4 );
18819		},
18820
18821		"CHILD": function( match ) {
18822
18823			/* matches from matchExpr["CHILD"]
18824				1 type (only|nth|...)
18825				2 what (child|of-type)
18826				3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
18827				4 xn-component of xn+y argument ([+-]?\d*n|)
18828				5 sign of xn-component
18829				6 x of xn-component
18830				7 sign of y-component
18831				8 y of y-component
18832			*/
18833			match[ 1 ] = match[ 1 ].toLowerCase();
18834
18835			if ( match[ 1 ].slice( 0, 3 ) === "nth" ) {
18836
18837				// nth-* requires argument
18838				if ( !match[ 3 ] ) {
18839					Sizzle.error( match[ 0 ] );
18840				}
18841
18842				// numeric x and y parameters for Expr.filter.CHILD
18843				// remember that false/true cast respectively to 0/1
18844				match[ 4 ] = +( match[ 4 ] ?
18845					match[ 5 ] + ( match[ 6 ] || 1 ) :
18846					2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) );
18847				match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" );
18848
18849				// other types prohibit arguments
18850			} else if ( match[ 3 ] ) {
18851				Sizzle.error( match[ 0 ] );
18852			}
18853
18854			return match;
18855		},
18856
18857		"PSEUDO": function( match ) {
18858			var excess,
18859				unquoted = !match[ 6 ] && match[ 2 ];
18860
18861			if ( matchExpr[ "CHILD" ].test( match[ 0 ] ) ) {
18862				return null;
18863			}
18864
18865			// Accept quoted arguments as-is
18866			if ( match[ 3 ] ) {
18867				match[ 2 ] = match[ 4 ] || match[ 5 ] || "";
18868
18869			// Strip excess characters from unquoted arguments
18870			} else if ( unquoted && rpseudo.test( unquoted ) &&
18871
18872				// Get excess from tokenize (recursively)
18873				( excess = tokenize( unquoted, true ) ) &&
18874
18875				// advance to the next closing parenthesis
18876				( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) {
18877
18878				// excess is a negative index
18879				match[ 0 ] = match[ 0 ].slice( 0, excess );
18880				match[ 2 ] = unquoted.slice( 0, excess );
18881			}
18882
18883			// Return only captures needed by the pseudo filter method (type and argument)
18884			return match.slice( 0, 3 );
18885		}
18886	},
18887
18888	filter: {
18889
18890		"TAG": function( nodeNameSelector ) {
18891			var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
18892			return nodeNameSelector === "*" ?
18893				function() {
18894					return true;
18895				} :
18896				function( elem ) {
18897					return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
18898				};
18899		},
18900
18901		"CLASS": function( className ) {
18902			var pattern = classCache[ className + " " ];
18903
18904			return pattern ||
18905				( pattern = new RegExp( "(^|" + whitespace +
18906					")" + className + "(" + whitespace + "|$)" ) ) && classCache(
18907						className, function( elem ) {
18908							return pattern.test(
18909								typeof elem.className === "string" && elem.className ||
18910								typeof elem.getAttribute !== "undefined" &&
18911									elem.getAttribute( "class" ) ||
18912								""
18913							);
18914				} );
18915		},
18916
18917		"ATTR": function( name, operator, check ) {
18918			return function( elem ) {
18919				var result = Sizzle.attr( elem, name );
18920
18921				if ( result == null ) {
18922					return operator === "!=";
18923				}
18924				if ( !operator ) {
18925					return true;
18926				}
18927
18928				result += "";
18929
18930				/* eslint-disable max-len */
18931
18932				return operator === "=" ? result === check :
18933					operator === "!=" ? result !== check :
18934					operator === "^=" ? check && result.indexOf( check ) === 0 :
18935					operator === "*=" ? check && result.indexOf( check ) > -1 :
18936					operator === "$=" ? check && result.slice( -check.length ) === check :
18937					operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
18938					operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
18939					false;
18940				/* eslint-enable max-len */
18941
18942			};
18943		},
18944
18945		"CHILD": function( type, what, _argument, first, last ) {
18946			var simple = type.slice( 0, 3 ) !== "nth",
18947				forward = type.slice( -4 ) !== "last",
18948				ofType = what === "of-type";
18949
18950			return first === 1 && last === 0 ?
18951
18952				// Shortcut for :nth-*(n)
18953				function( elem ) {
18954					return !!elem.parentNode;
18955				} :
18956
18957				function( elem, _context, xml ) {
18958					var cache, uniqueCache, outerCache, node, nodeIndex, start,
18959						dir = simple !== forward ? "nextSibling" : "previousSibling",
18960						parent = elem.parentNode,
18961						name = ofType && elem.nodeName.toLowerCase(),
18962						useCache = !xml && !ofType,
18963						diff = false;
18964
18965					if ( parent ) {
18966
18967						// :(first|last|only)-(child|of-type)
18968						if ( simple ) {
18969							while ( dir ) {
18970								node = elem;
18971								while ( ( node = node[ dir ] ) ) {
18972									if ( ofType ?
18973										node.nodeName.toLowerCase() === name :
18974										node.nodeType === 1 ) {
18975
18976										return false;
18977									}
18978								}
18979
18980								// Reverse direction for :only-* (if we haven't yet done so)
18981								start = dir = type === "only" && !start && "nextSibling";
18982							}
18983							return true;
18984						}
18985
18986						start = [ forward ? parent.firstChild : parent.lastChild ];
18987
18988						// non-xml :nth-child(...) stores cache data on `parent`
18989						if ( forward && useCache ) {
18990
18991							// Seek `elem` from a previously-cached index
18992
18993							// ...in a gzip-friendly way
18994							node = parent;
18995							outerCache = node[ expando ] || ( node[ expando ] = {} );
18996
18997							// Support: IE <9 only
18998							// Defend against cloned attroperties (jQuery gh-1709)
18999							uniqueCache = outerCache[ node.uniqueID ] ||
19000								( outerCache[ node.uniqueID ] = {} );
19001
19002							cache = uniqueCache[ type ] || [];
19003							nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
19004							diff = nodeIndex && cache[ 2 ];
19005							node = nodeIndex && parent.childNodes[ nodeIndex ];
19006
19007							while ( ( node = ++nodeIndex && node && node[ dir ] ||
19008
19009								// Fallback to seeking `elem` from the start
19010								( diff = nodeIndex = 0 ) || start.pop() ) ) {
19011
19012								// When found, cache indexes on `parent` and break
19013								if ( node.nodeType === 1 && ++diff && node === elem ) {
19014									uniqueCache[ type ] = [ dirruns, nodeIndex, diff ];
19015									break;
19016								}
19017							}
19018
19019						} else {
19020
19021							// Use previously-cached element index if available
19022							if ( useCache ) {
19023
19024								// ...in a gzip-friendly way
19025								node = elem;
19026								outerCache = node[ expando ] || ( node[ expando ] = {} );
19027
19028								// Support: IE <9 only
19029								// Defend against cloned attroperties (jQuery gh-1709)
19030								uniqueCache = outerCache[ node.uniqueID ] ||
19031									( outerCache[ node.uniqueID ] = {} );
19032
19033								cache = uniqueCache[ type ] || [];
19034								nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
19035								diff = nodeIndex;
19036							}
19037
19038							// xml :nth-child(...)
19039							// or :nth-last-child(...) or :nth(-last)?-of-type(...)
19040							if ( diff === false ) {
19041
19042								// Use the same loop as above to seek `elem` from the start
19043								while ( ( node = ++nodeIndex && node && node[ dir ] ||
19044									( diff = nodeIndex = 0 ) || start.pop() ) ) {
19045
19046									if ( ( ofType ?
19047										node.nodeName.toLowerCase() === name :
19048										node.nodeType === 1 ) &&
19049										++diff ) {
19050
19051										// Cache the index of each encountered element
19052										if ( useCache ) {
19053											outerCache = node[ expando ] ||
19054												( node[ expando ] = {} );
19055
19056											// Support: IE <9 only
19057											// Defend against cloned attroperties (jQuery gh-1709)
19058											uniqueCache = outerCache[ node.uniqueID ] ||
19059												( outerCache[ node.uniqueID ] = {} );
19060
19061											uniqueCache[ type ] = [ dirruns, diff ];
19062										}
19063
19064										if ( node === elem ) {
19065											break;
19066										}
19067									}
19068								}
19069							}
19070						}
19071
19072						// Incorporate the offset, then check against cycle size
19073						diff -= last;
19074						return diff === first || ( diff % first === 0 && diff / first >= 0 );
19075					}
19076				};
19077		},
19078
19079		"PSEUDO": function( pseudo, argument ) {
19080
19081			// pseudo-class names are case-insensitive
19082			// http://www.w3.org/TR/selectors/#pseudo-classes
19083			// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
19084			// Remember that setFilters inherits from pseudos
19085			var args,
19086				fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
19087					Sizzle.error( "unsupported pseudo: " + pseudo );
19088
19089			// The user may use createPseudo to indicate that
19090			// arguments are needed to create the filter function
19091			// just as Sizzle does
19092			if ( fn[ expando ] ) {
19093				return fn( argument );
19094			}
19095
19096			// But maintain support for old signatures
19097			if ( fn.length > 1 ) {
19098				args = [ pseudo, pseudo, "", argument ];
19099				return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
19100					markFunction( function( seed, matches ) {
19101						var idx,
19102							matched = fn( seed, argument ),
19103							i = matched.length;
19104						while ( i-- ) {
19105							idx = indexOf( seed, matched[ i ] );
19106							seed[ idx ] = !( matches[ idx ] = matched[ i ] );
19107						}
19108					} ) :
19109					function( elem ) {
19110						return fn( elem, 0, args );
19111					};
19112			}
19113
19114			return fn;
19115		}
19116	},
19117
19118	pseudos: {
19119
19120		// Potentially complex pseudos
19121		"not": markFunction( function( selector ) {
19122
19123			// Trim the selector passed to compile
19124			// to avoid treating leading and trailing
19125			// spaces as combinators
19126			var input = [],
19127				results = [],
19128				matcher = compile( selector.replace( rtrim, "$1" ) );
19129
19130			return matcher[ expando ] ?
19131				markFunction( function( seed, matches, _context, xml ) {
19132					var elem,
19133						unmatched = matcher( seed, null, xml, [] ),
19134						i = seed.length;
19135
19136					// Match elements unmatched by `matcher`
19137					while ( i-- ) {
19138						if ( ( elem = unmatched[ i ] ) ) {
19139							seed[ i ] = !( matches[ i ] = elem );
19140						}
19141					}
19142				} ) :
19143				function( elem, _context, xml ) {
19144					input[ 0 ] = elem;
19145					matcher( input, null, xml, results );
19146
19147					// Don't keep the element (issue #299)
19148					input[ 0 ] = null;
19149					return !results.pop();
19150				};
19151		} ),
19152
19153		"has": markFunction( function( selector ) {
19154			return function( elem ) {
19155				return Sizzle( selector, elem ).length > 0;
19156			};
19157		} ),
19158
19159		"contains": markFunction( function( text ) {
19160			text = text.replace( runescape, funescape );
19161			return function( elem ) {
19162				return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1;
19163			};
19164		} ),
19165
19166		// "Whether an element is represented by a :lang() selector
19167		// is based solely on the element's language value
19168		// being equal to the identifier C,
19169		// or beginning with the identifier C immediately followed by "-".
19170		// The matching of C against the element's language value is performed case-insensitively.
19171		// The identifier C does not have to be a valid language name."
19172		// http://www.w3.org/TR/selectors/#lang-pseudo
19173		"lang": markFunction( function( lang ) {
19174
19175			// lang value must be a valid identifier
19176			if ( !ridentifier.test( lang || "" ) ) {
19177				Sizzle.error( "unsupported lang: " + lang );
19178			}
19179			lang = lang.replace( runescape, funescape ).toLowerCase();
19180			return function( elem ) {
19181				var elemLang;
19182				do {
19183					if ( ( elemLang = documentIsHTML ?
19184						elem.lang :
19185						elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) {
19186
19187						elemLang = elemLang.toLowerCase();
19188						return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
19189					}
19190				} while ( ( elem = elem.parentNode ) && elem.nodeType === 1 );
19191				return false;
19192			};
19193		} ),
19194
19195		// Miscellaneous
19196		"target": function( elem ) {
19197			var hash = window.location && window.location.hash;
19198			return hash && hash.slice( 1 ) === elem.id;
19199		},
19200
19201		"root": function( elem ) {
19202			return elem === docElem;
19203		},
19204
19205		"focus": function( elem ) {
19206			return elem === document.activeElement &&
19207				( !document.hasFocus || document.hasFocus() ) &&
19208				!!( elem.type || elem.href || ~elem.tabIndex );
19209		},
19210
19211		// Boolean properties
19212		"enabled": createDisabledPseudo( false ),
19213		"disabled": createDisabledPseudo( true ),
19214
19215		"checked": function( elem ) {
19216
19217			// In CSS3, :checked should return both checked and selected elements
19218			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
19219			var nodeName = elem.nodeName.toLowerCase();
19220			return ( nodeName === "input" && !!elem.checked ) ||
19221				( nodeName === "option" && !!elem.selected );
19222		},
19223
19224		"selected": function( elem ) {
19225
19226			// Accessing this property makes selected-by-default
19227			// options in Safari work properly
19228			if ( elem.parentNode ) {
19229				// eslint-disable-next-line no-unused-expressions
19230				elem.parentNode.selectedIndex;
19231			}
19232
19233			return elem.selected === true;
19234		},
19235
19236		// Contents
19237		"empty": function( elem ) {
19238
19239			// http://www.w3.org/TR/selectors/#empty-pseudo
19240			// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
19241			//   but not by others (comment: 8; processing instruction: 7; etc.)
19242			// nodeType < 6 works because attributes (2) do not appear as children
19243			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
19244				if ( elem.nodeType < 6 ) {
19245					return false;
19246				}
19247			}
19248			return true;
19249		},
19250
19251		"parent": function( elem ) {
19252			return !Expr.pseudos[ "empty" ]( elem );
19253		},
19254
19255		// Element/input types
19256		"header": function( elem ) {
19257			return rheader.test( elem.nodeName );
19258		},
19259
19260		"input": function( elem ) {
19261			return rinputs.test( elem.nodeName );
19262		},
19263
19264		"button": function( elem ) {
19265			var name = elem.nodeName.toLowerCase();
19266			return name === "input" && elem.type === "button" || name === "button";
19267		},
19268
19269		"text": function( elem ) {
19270			var attr;
19271			return elem.nodeName.toLowerCase() === "input" &&
19272				elem.type === "text" &&
19273
19274				// Support: IE<8
19275				// New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
19276				( ( attr = elem.getAttribute( "type" ) ) == null ||
19277					attr.toLowerCase() === "text" );
19278		},
19279
19280		// Position-in-collection
19281		"first": createPositionalPseudo( function() {
19282			return [ 0 ];
19283		} ),
19284
19285		"last": createPositionalPseudo( function( _matchIndexes, length ) {
19286			return [ length - 1 ];
19287		} ),
19288
19289		"eq": createPositionalPseudo( function( _matchIndexes, length, argument ) {
19290			return [ argument < 0 ? argument + length : argument ];
19291		} ),
19292
19293		"even": createPositionalPseudo( function( matchIndexes, length ) {
19294			var i = 0;
19295			for ( ; i < length; i += 2 ) {
19296				matchIndexes.push( i );
19297			}
19298			return matchIndexes;
19299		} ),
19300
19301		"odd": createPositionalPseudo( function( matchIndexes, length ) {
19302			var i = 1;
19303			for ( ; i < length; i += 2 ) {
19304				matchIndexes.push( i );
19305			}
19306			return matchIndexes;
19307		} ),
19308
19309		"lt": createPositionalPseudo( function( matchIndexes, length, argument ) {
19310			var i = argument < 0 ?
19311				argument + length :
19312				argument > length ?
19313					length :
19314					argument;
19315			for ( ; --i >= 0; ) {
19316				matchIndexes.push( i );
19317			}
19318			return matchIndexes;
19319		} ),
19320
19321		"gt": createPositionalPseudo( function( matchIndexes, length, argument ) {
19322			var i = argument < 0 ? argument + length : argument;
19323			for ( ; ++i < length; ) {
19324				matchIndexes.push( i );
19325			}
19326			return matchIndexes;
19327		} )
19328	}
19329};
19330
19331Expr.pseudos[ "nth" ] = Expr.pseudos[ "eq" ];
19332
19333// Add button/input type pseudos
19334for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
19335	Expr.pseudos[ i ] = createInputPseudo( i );
19336}
19337for ( i in { submit: true, reset: true } ) {
19338	Expr.pseudos[ i ] = createButtonPseudo( i );
19339}
19340
19341// Easy API for creating new setFilters
19342function setFilters() {}
19343setFilters.prototype = Expr.filters = Expr.pseudos;
19344Expr.setFilters = new setFilters();
19345
19346tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
19347	var matched, match, tokens, type,
19348		soFar, groups, preFilters,
19349		cached = tokenCache[ selector + " " ];
19350
19351	if ( cached ) {
19352		return parseOnly ? 0 : cached.slice( 0 );
19353	}
19354
19355	soFar = selector;
19356	groups = [];
19357	preFilters = Expr.preFilter;
19358
19359	while ( soFar ) {
19360
19361		// Comma and first run
19362		if ( !matched || ( match = rcomma.exec( soFar ) ) ) {
19363			if ( match ) {
19364
19365				// Don't consume trailing commas as valid
19366				soFar = soFar.slice( match[ 0 ].length ) || soFar;
19367			}
19368			groups.push( ( tokens = [] ) );
19369		}
19370
19371		matched = false;
19372
19373		// Combinators
19374		if ( ( match = rcombinators.exec( soFar ) ) ) {
19375			matched = match.shift();
19376			tokens.push( {
19377				value: matched,
19378
19379				// Cast descendant combinators to space
19380				type: match[ 0 ].replace( rtrim, " " )
19381			} );
19382			soFar = soFar.slice( matched.length );
19383		}
19384
19385		// Filters
19386		for ( type in Expr.filter ) {
19387			if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] ||
19388				( match = preFilters[ type ]( match ) ) ) ) {
19389				matched = match.shift();
19390				tokens.push( {
19391					value: matched,
19392					type: type,
19393					matches: match
19394				} );
19395				soFar = soFar.slice( matched.length );
19396			}
19397		}
19398
19399		if ( !matched ) {
19400			break;
19401		}
19402	}
19403
19404	// Return the length of the invalid excess
19405	// if we're just parsing
19406	// Otherwise, throw an error or return tokens
19407	return parseOnly ?
19408		soFar.length :
19409		soFar ?
19410			Sizzle.error( selector ) :
19411
19412			// Cache the tokens
19413			tokenCache( selector, groups ).slice( 0 );
19414};
19415
19416function toSelector( tokens ) {
19417	var i = 0,
19418		len = tokens.length,
19419		selector = "";
19420	for ( ; i < len; i++ ) {
19421		selector += tokens[ i ].value;
19422	}
19423	return selector;
19424}
19425
19426function addCombinator( matcher, combinator, base ) {
19427	var dir = combinator.dir,
19428		skip = combinator.next,
19429		key = skip || dir,
19430		checkNonElements = base && key === "parentNode",
19431		doneName = done++;
19432
19433	return combinator.first ?
19434
19435		// Check against closest ancestor/preceding element
19436		function( elem, context, xml ) {
19437			while ( ( elem = elem[ dir ] ) ) {
19438				if ( elem.nodeType === 1 || checkNonElements ) {
19439					return matcher( elem, context, xml );
19440				}
19441			}
19442			return false;
19443		} :
19444
19445		// Check against all ancestor/preceding elements
19446		function( elem, context, xml ) {
19447			var oldCache, uniqueCache, outerCache,
19448				newCache = [ dirruns, doneName ];
19449
19450			// We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching
19451			if ( xml ) {
19452				while ( ( elem = elem[ dir ] ) ) {
19453					if ( elem.nodeType === 1 || checkNonElements ) {
19454						if ( matcher( elem, context, xml ) ) {
19455							return true;
19456						}
19457					}
19458				}
19459			} else {
19460				while ( ( elem = elem[ dir ] ) ) {
19461					if ( elem.nodeType === 1 || checkNonElements ) {
19462						outerCache = elem[ expando ] || ( elem[ expando ] = {} );
19463
19464						// Support: IE <9 only
19465						// Defend against cloned attroperties (jQuery gh-1709)
19466						uniqueCache = outerCache[ elem.uniqueID ] ||
19467							( outerCache[ elem.uniqueID ] = {} );
19468
19469						if ( skip && skip === elem.nodeName.toLowerCase() ) {
19470							elem = elem[ dir ] || elem;
19471						} else if ( ( oldCache = uniqueCache[ key ] ) &&
19472							oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
19473
19474							// Assign to newCache so results back-propagate to previous elements
19475							return ( newCache[ 2 ] = oldCache[ 2 ] );
19476						} else {
19477
19478							// Reuse newcache so results back-propagate to previous elements
19479							uniqueCache[ key ] = newCache;
19480
19481							// A match means we're done; a fail means we have to keep checking
19482							if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) {
19483								return true;
19484							}
19485						}
19486					}
19487				}
19488			}
19489			return false;
19490		};
19491}
19492
19493function elementMatcher( matchers ) {
19494	return matchers.length > 1 ?
19495		function( elem, context, xml ) {
19496			var i = matchers.length;
19497			while ( i-- ) {
19498				if ( !matchers[ i ]( elem, context, xml ) ) {
19499					return false;
19500				}
19501			}
19502			return true;
19503		} :
19504		matchers[ 0 ];
19505}
19506
19507function multipleContexts( selector, contexts, results ) {
19508	var i = 0,
19509		len = contexts.length;
19510	for ( ; i < len; i++ ) {
19511		Sizzle( selector, contexts[ i ], results );
19512	}
19513	return results;
19514}
19515
19516function condense( unmatched, map, filter, context, xml ) {
19517	var elem,
19518		newUnmatched = [],
19519		i = 0,
19520		len = unmatched.length,
19521		mapped = map != null;
19522
19523	for ( ; i < len; i++ ) {
19524		if ( ( elem = unmatched[ i ] ) ) {
19525			if ( !filter || filter( elem, context, xml ) ) {
19526				newUnmatched.push( elem );
19527				if ( mapped ) {
19528					map.push( i );
19529				}
19530			}
19531		}
19532	}
19533
19534	return newUnmatched;
19535}
19536
19537function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
19538	if ( postFilter && !postFilter[ expando ] ) {
19539		postFilter = setMatcher( postFilter );
19540	}
19541	if ( postFinder && !postFinder[ expando ] ) {
19542		postFinder = setMatcher( postFinder, postSelector );
19543	}
19544	return markFunction( function( seed, results, context, xml ) {
19545		var temp, i, elem,
19546			preMap = [],
19547			postMap = [],
19548			preexisting = results.length,
19549
19550			// Get initial elements from seed or context
19551			elems = seed || multipleContexts(
19552				selector || "*",
19553				context.nodeType ? [ context ] : context,
19554				[]
19555			),
19556
19557			// Prefilter to get matcher input, preserving a map for seed-results synchronization
19558			matcherIn = preFilter && ( seed || !selector ) ?
19559				condense( elems, preMap, preFilter, context, xml ) :
19560				elems,
19561
19562			matcherOut = matcher ?
19563
19564				// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
19565				postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
19566
19567					// ...intermediate processing is necessary
19568					[] :
19569
19570					// ...otherwise use results directly
19571					results :
19572				matcherIn;
19573
19574		// Find primary matches
19575		if ( matcher ) {
19576			matcher( matcherIn, matcherOut, context, xml );
19577		}
19578
19579		// Apply postFilter
19580		if ( postFilter ) {
19581			temp = condense( matcherOut, postMap );
19582			postFilter( temp, [], context, xml );
19583
19584			// Un-match failing elements by moving them back to matcherIn
19585			i = temp.length;
19586			while ( i-- ) {
19587				if ( ( elem = temp[ i ] ) ) {
19588					matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem );
19589				}
19590			}
19591		}
19592
19593		if ( seed ) {
19594			if ( postFinder || preFilter ) {
19595				if ( postFinder ) {
19596
19597					// Get the final matcherOut by condensing this intermediate into postFinder contexts
19598					temp = [];
19599					i = matcherOut.length;
19600					while ( i-- ) {
19601						if ( ( elem = matcherOut[ i ] ) ) {
19602
19603							// Restore matcherIn since elem is not yet a final match
19604							temp.push( ( matcherIn[ i ] = elem ) );
19605						}
19606					}
19607					postFinder( null, ( matcherOut = [] ), temp, xml );
19608				}
19609
19610				// Move matched elements from seed to results to keep them synchronized
19611				i = matcherOut.length;
19612				while ( i-- ) {
19613					if ( ( elem = matcherOut[ i ] ) &&
19614						( temp = postFinder ? indexOf( seed, elem ) : preMap[ i ] ) > -1 ) {
19615
19616						seed[ temp ] = !( results[ temp ] = elem );
19617					}
19618				}
19619			}
19620
19621		// Add elements to results, through postFinder if defined
19622		} else {
19623			matcherOut = condense(
19624				matcherOut === results ?
19625					matcherOut.splice( preexisting, matcherOut.length ) :
19626					matcherOut
19627			);
19628			if ( postFinder ) {
19629				postFinder( null, results, matcherOut, xml );
19630			} else {
19631				push.apply( results, matcherOut );
19632			}
19633		}
19634	} );
19635}
19636
19637function matcherFromTokens( tokens ) {
19638	var checkContext, matcher, j,
19639		len = tokens.length,
19640		leadingRelative = Expr.relative[ tokens[ 0 ].type ],
19641		implicitRelative = leadingRelative || Expr.relative[ " " ],
19642		i = leadingRelative ? 1 : 0,
19643
19644		// The foundational matcher ensures that elements are reachable from top-level context(s)
19645		matchContext = addCombinator( function( elem ) {
19646			return elem === checkContext;
19647		}, implicitRelative, true ),
19648		matchAnyContext = addCombinator( function( elem ) {
19649			return indexOf( checkContext, elem ) > -1;
19650		}, implicitRelative, true ),
19651		matchers = [ function( elem, context, xml ) {
19652			var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
19653				( checkContext = context ).nodeType ?
19654					matchContext( elem, context, xml ) :
19655					matchAnyContext( elem, context, xml ) );
19656
19657			// Avoid hanging onto element (issue #299)
19658			checkContext = null;
19659			return ret;
19660		} ];
19661
19662	for ( ; i < len; i++ ) {
19663		if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) {
19664			matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ];
19665		} else {
19666			matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches );
19667
19668			// Return special upon seeing a positional matcher
19669			if ( matcher[ expando ] ) {
19670
19671				// Find the next relative operator (if any) for proper handling
19672				j = ++i;
19673				for ( ; j < len; j++ ) {
19674					if ( Expr.relative[ tokens[ j ].type ] ) {
19675						break;
19676					}
19677				}
19678				return setMatcher(
19679					i > 1 && elementMatcher( matchers ),
19680					i > 1 && toSelector(
19681
19682					// If the preceding token was a descendant combinator, insert an implicit any-element `*`
19683					tokens
19684						.slice( 0, i - 1 )
19685						.concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } )
19686					).replace( rtrim, "$1" ),
19687					matcher,
19688					i < j && matcherFromTokens( tokens.slice( i, j ) ),
19689					j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ),
19690					j < len && toSelector( tokens )
19691				);
19692			}
19693			matchers.push( matcher );
19694		}
19695	}
19696
19697	return elementMatcher( matchers );
19698}
19699
19700function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
19701	var bySet = setMatchers.length > 0,
19702		byElement = elementMatchers.length > 0,
19703		superMatcher = function( seed, context, xml, results, outermost ) {
19704			var elem, j, matcher,
19705				matchedCount = 0,
19706				i = "0",
19707				unmatched = seed && [],
19708				setMatched = [],
19709				contextBackup = outermostContext,
19710
19711				// We must always have either seed elements or outermost context
19712				elems = seed || byElement && Expr.find[ "TAG" ]( "*", outermost ),
19713
19714				// Use integer dirruns iff this is the outermost matcher
19715				dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ),
19716				len = elems.length;
19717
19718			if ( outermost ) {
19719
19720				// Support: IE 11+, Edge 17 - 18+
19721				// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
19722				// two documents; shallow comparisons work.
19723				// eslint-disable-next-line eqeqeq
19724				outermostContext = context == document || context || outermost;
19725			}
19726
19727			// Add elements passing elementMatchers directly to results
19728			// Support: IE<9, Safari
19729			// Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
19730			for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) {
19731				if ( byElement && elem ) {
19732					j = 0;
19733
19734					// Support: IE 11+, Edge 17 - 18+
19735					// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
19736					// two documents; shallow comparisons work.
19737					// eslint-disable-next-line eqeqeq
19738					if ( !context && elem.ownerDocument != document ) {
19739						setDocument( elem );
19740						xml = !documentIsHTML;
19741					}
19742					while ( ( matcher = elementMatchers[ j++ ] ) ) {
19743						if ( matcher( elem, context || document, xml ) ) {
19744							results.push( elem );
19745							break;
19746						}
19747					}
19748					if ( outermost ) {
19749						dirruns = dirrunsUnique;
19750					}
19751				}
19752
19753				// Track unmatched elements for set filters
19754				if ( bySet ) {
19755
19756					// They will have gone through all possible matchers
19757					if ( ( elem = !matcher && elem ) ) {
19758						matchedCount--;
19759					}
19760
19761					// Lengthen the array for every element, matched or not
19762					if ( seed ) {
19763						unmatched.push( elem );
19764					}
19765				}
19766			}
19767
19768			// `i` is now the count of elements visited above, and adding it to `matchedCount`
19769			// makes the latter nonnegative.
19770			matchedCount += i;
19771
19772			// Apply set filters to unmatched elements
19773			// NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`
19774			// equals `i`), unless we didn't visit _any_ elements in the above loop because we have
19775			// no element matchers and no seed.
19776			// Incrementing an initially-string "0" `i` allows `i` to remain a string only in that
19777			// case, which will result in a "00" `matchedCount` that differs from `i` but is also
19778			// numerically zero.
19779			if ( bySet && i !== matchedCount ) {
19780				j = 0;
19781				while ( ( matcher = setMatchers[ j++ ] ) ) {
19782					matcher( unmatched, setMatched, context, xml );
19783				}
19784
19785				if ( seed ) {
19786
19787					// Reintegrate element matches to eliminate the need for sorting
19788					if ( matchedCount > 0 ) {
19789						while ( i-- ) {
19790							if ( !( unmatched[ i ] || setMatched[ i ] ) ) {
19791								setMatched[ i ] = pop.call( results );
19792							}
19793						}
19794					}
19795
19796					// Discard index placeholder values to get only actual matches
19797					setMatched = condense( setMatched );
19798				}
19799
19800				// Add matches to results
19801				push.apply( results, setMatched );
19802
19803				// Seedless set matches succeeding multiple successful matchers stipulate sorting
19804				if ( outermost && !seed && setMatched.length > 0 &&
19805					( matchedCount + setMatchers.length ) > 1 ) {
19806
19807					Sizzle.uniqueSort( results );
19808				}
19809			}
19810
19811			// Override manipulation of globals by nested matchers
19812			if ( outermost ) {
19813				dirruns = dirrunsUnique;
19814				outermostContext = contextBackup;
19815			}
19816
19817			return unmatched;
19818		};
19819
19820	return bySet ?
19821		markFunction( superMatcher ) :
19822		superMatcher;
19823}
19824
19825compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
19826	var i,
19827		setMatchers = [],
19828		elementMatchers = [],
19829		cached = compilerCache[ selector + " " ];
19830
19831	if ( !cached ) {
19832
19833		// Generate a function of recursive functions that can be used to check each element
19834		if ( !match ) {
19835			match = tokenize( selector );
19836		}
19837		i = match.length;
19838		while ( i-- ) {
19839			cached = matcherFromTokens( match[ i ] );
19840			if ( cached[ expando ] ) {
19841				setMatchers.push( cached );
19842			} else {
19843				elementMatchers.push( cached );
19844			}
19845		}
19846
19847		// Cache the compiled function
19848		cached = compilerCache(
19849			selector,
19850			matcherFromGroupMatchers( elementMatchers, setMatchers )
19851		);
19852
19853		// Save selector and tokenization
19854		cached.selector = selector;
19855	}
19856	return cached;
19857};
19858
19859/**
19860 * A low-level selection function that works with Sizzle's compiled
19861 *  selector functions
19862 * @param {String|Function} selector A selector or a pre-compiled
19863 *  selector function built with Sizzle.compile
19864 * @param {Element} context
19865 * @param {Array} [results]
19866 * @param {Array} [seed] A set of elements to match against
19867 */
19868select = Sizzle.select = function( selector, context, results, seed ) {
19869	var i, tokens, token, type, find,
19870		compiled = typeof selector === "function" && selector,
19871		match = !seed && tokenize( ( selector = compiled.selector || selector ) );
19872
19873	results = results || [];
19874
19875	// Try to minimize operations if there is only one selector in the list and no seed
19876	// (the latter of which guarantees us context)
19877	if ( match.length === 1 ) {
19878
19879		// Reduce context if the leading compound selector is an ID
19880		tokens = match[ 0 ] = match[ 0 ].slice( 0 );
19881		if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" &&
19882			context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) {
19883
19884			context = ( Expr.find[ "ID" ]( token.matches[ 0 ]
19885				.replace( runescape, funescape ), context ) || [] )[ 0 ];
19886			if ( !context ) {
19887				return results;
19888
19889			// Precompiled matchers will still verify ancestry, so step up a level
19890			} else if ( compiled ) {
19891				context = context.parentNode;
19892			}
19893
19894			selector = selector.slice( tokens.shift().value.length );
19895		}
19896
19897		// Fetch a seed set for right-to-left matching
19898		i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length;
19899		while ( i-- ) {
19900			token = tokens[ i ];
19901
19902			// Abort if we hit a combinator
19903			if ( Expr.relative[ ( type = token.type ) ] ) {
19904				break;
19905			}
19906			if ( ( find = Expr.find[ type ] ) ) {
19907
19908				// Search, expanding context for leading sibling combinators
19909				if ( ( seed = find(
19910					token.matches[ 0 ].replace( runescape, funescape ),
19911					rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) ||
19912						context
19913				) ) ) {
19914
19915					// If seed is empty or no tokens remain, we can return early
19916					tokens.splice( i, 1 );
19917					selector = seed.length && toSelector( tokens );
19918					if ( !selector ) {
19919						push.apply( results, seed );
19920						return results;
19921					}
19922
19923					break;
19924				}
19925			}
19926		}
19927	}
19928
19929	// Compile and execute a filtering function if one is not provided
19930	// Provide `match` to avoid retokenization if we modified the selector above
19931	( compiled || compile( selector, match ) )(
19932		seed,
19933		context,
19934		!documentIsHTML,
19935		results,
19936		!context || rsibling.test( selector ) && testContext( context.parentNode ) || context
19937	);
19938	return results;
19939};
19940
19941// One-time assignments
19942
19943// Sort stability
19944support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando;
19945
19946// Support: Chrome 14-35+
19947// Always assume duplicates if they aren't passed to the comparison function
19948support.detectDuplicates = !!hasDuplicate;
19949
19950// Initialize against the default document
19951setDocument();
19952
19953// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
19954// Detached nodes confoundingly follow *each other*
19955support.sortDetached = assert( function( el ) {
19956
19957	// Should return 1, but returns 4 (following)
19958	return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1;
19959} );
19960
19961// Support: IE<8
19962// Prevent attribute/property "interpolation"
19963// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
19964if ( !assert( function( el ) {
19965	el.innerHTML = "<a href='#'></a>";
19966	return el.firstChild.getAttribute( "href" ) === "#";
19967} ) ) {
19968	addHandle( "type|href|height|width", function( elem, name, isXML ) {
19969		if ( !isXML ) {
19970			return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
19971		}
19972	} );
19973}
19974
19975// Support: IE<9
19976// Use defaultValue in place of getAttribute("value")
19977if ( !support.attributes || !assert( function( el ) {
19978	el.innerHTML = "<input/>";
19979	el.firstChild.setAttribute( "value", "" );
19980	return el.firstChild.getAttribute( "value" ) === "";
19981} ) ) {
19982	addHandle( "value", function( elem, _name, isXML ) {
19983		if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
19984			return elem.defaultValue;
19985		}
19986	} );
19987}
19988
19989// Support: IE<9
19990// Use getAttributeNode to fetch booleans when getAttribute lies
19991if ( !assert( function( el ) {
19992	return el.getAttribute( "disabled" ) == null;
19993} ) ) {
19994	addHandle( booleans, function( elem, name, isXML ) {
19995		var val;
19996		if ( !isXML ) {
19997			return elem[ name ] === true ? name.toLowerCase() :
19998				( val = elem.getAttributeNode( name ) ) && val.specified ?
19999					val.value :
20000					null;
20001		}
20002	} );
20003}
20004
20005return Sizzle;
20006
20007} )( window );
20008
20009
20010
20011jQuery.find = Sizzle;
20012jQuery.expr = Sizzle.selectors;
20013
20014// Deprecated
20015jQuery.expr[ ":" ] = jQuery.expr.pseudos;
20016jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort;
20017jQuery.text = Sizzle.getText;
20018jQuery.isXMLDoc = Sizzle.isXML;
20019jQuery.contains = Sizzle.contains;
20020jQuery.escapeSelector = Sizzle.escape;
20021
20022
20023
20024
20025var dir = function( elem, dir, until ) {
20026	var matched = [],
20027		truncate = until !== undefined;
20028
20029	while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) {
20030		if ( elem.nodeType === 1 ) {
20031			if ( truncate && jQuery( elem ).is( until ) ) {
20032				break;
20033			}
20034			matched.push( elem );
20035		}
20036	}
20037	return matched;
20038};
20039
20040
20041var siblings = function( n, elem ) {
20042	var matched = [];
20043
20044	for ( ; n; n = n.nextSibling ) {
20045		if ( n.nodeType === 1 && n !== elem ) {
20046			matched.push( n );
20047		}
20048	}
20049
20050	return matched;
20051};
20052
20053
20054var rneedsContext = jQuery.expr.match.needsContext;
20055
20056
20057
20058function nodeName( elem, name ) {
20059
20060	return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
20061
20062}
20063var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i );
20064
20065
20066
20067// Implement the identical functionality for filter and not
20068function winnow( elements, qualifier, not ) {
20069	if ( isFunction( qualifier ) ) {
20070		return jQuery.grep( elements, function( elem, i ) {
20071			return !!qualifier.call( elem, i, elem ) !== not;
20072		} );
20073	}
20074
20075	// Single element
20076	if ( qualifier.nodeType ) {
20077		return jQuery.grep( elements, function( elem ) {
20078			return ( elem === qualifier ) !== not;
20079		} );
20080	}
20081
20082	// Arraylike of elements (jQuery, arguments, Array)
20083	if ( typeof qualifier !== "string" ) {
20084		return jQuery.grep( elements, function( elem ) {
20085			return ( indexOf.call( qualifier, elem ) > -1 ) !== not;
20086		} );
20087	}
20088
20089	// Filtered directly for both simple and complex selectors
20090	return jQuery.filter( qualifier, elements, not );
20091}
20092
20093jQuery.filter = function( expr, elems, not ) {
20094	var elem = elems[ 0 ];
20095
20096	if ( not ) {
20097		expr = ":not(" + expr + ")";
20098	}
20099
20100	if ( elems.length === 1 && elem.nodeType === 1 ) {
20101		return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [];
20102	}
20103
20104	return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
20105		return elem.nodeType === 1;
20106	} ) );
20107};
20108
20109jQuery.fn.extend( {
20110	find: function( selector ) {
20111		var i, ret,
20112			len = this.length,
20113			self = this;
20114
20115		if ( typeof selector !== "string" ) {
20116			return this.pushStack( jQuery( selector ).filter( function() {
20117				for ( i = 0; i < len; i++ ) {
20118					if ( jQuery.contains( self[ i ], this ) ) {
20119						return true;
20120					}
20121				}
20122			} ) );
20123		}
20124
20125		ret = this.pushStack( [] );
20126
20127		for ( i = 0; i < len; i++ ) {
20128			jQuery.find( selector, self[ i ], ret );
20129		}
20130
20131		return len > 1 ? jQuery.uniqueSort( ret ) : ret;
20132	},
20133	filter: function( selector ) {
20134		return this.pushStack( winnow( this, selector || [], false ) );
20135	},
20136	not: function( selector ) {
20137		return this.pushStack( winnow( this, selector || [], true ) );
20138	},
20139	is: function( selector ) {
20140		return !!winnow(
20141			this,
20142
20143			// If this is a positional/relative selector, check membership in the returned set
20144			// so $("p:first").is("p:last") won't return true for a doc with two "p".
20145			typeof selector === "string" && rneedsContext.test( selector ) ?
20146				jQuery( selector ) :
20147				selector || [],
20148			false
20149		).length;
20150	}
20151} );
20152
20153
20154// Initialize a jQuery object
20155
20156
20157// A central reference to the root jQuery(document)
20158var rootjQuery,
20159
20160	// A simple way to check for HTML strings
20161	// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
20162	// Strict HTML recognition (#11290: must start with <)
20163	// Shortcut simple #id case for speed
20164	rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,
20165
20166	init = jQuery.fn.init = function( selector, context, root ) {
20167		var match, elem;
20168
20169		// HANDLE: $(""), $(null), $(undefined), $(false)
20170		if ( !selector ) {
20171			return this;
20172		}
20173
20174		// Method init() accepts an alternate rootjQuery
20175		// so migrate can support jQuery.sub (gh-2101)
20176		root = root || rootjQuery;
20177
20178		// Handle HTML strings
20179		if ( typeof selector === "string" ) {
20180			if ( selector[ 0 ] === "<" &&
20181				selector[ selector.length - 1 ] === ">" &&
20182				selector.length >= 3 ) {
20183
20184				// Assume that strings that start and end with <> are HTML and skip the regex check
20185				match = [ null, selector, null ];
20186
20187			} else {
20188				match = rquickExpr.exec( selector );
20189			}
20190
20191			// Match html or make sure no context is specified for #id
20192			if ( match && ( match[ 1 ] || !context ) ) {
20193
20194				// HANDLE: $(html) -> $(array)
20195				if ( match[ 1 ] ) {
20196					context = context instanceof jQuery ? context[ 0 ] : context;
20197
20198					// Option to run scripts is true for back-compat
20199					// Intentionally let the error be thrown if parseHTML is not present
20200					jQuery.merge( this, jQuery.parseHTML(
20201						match[ 1 ],
20202						context && context.nodeType ? context.ownerDocument || context : document,
20203						true
20204					) );
20205
20206					// HANDLE: $(html, props)
20207					if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) {
20208						for ( match in context ) {
20209
20210							// Properties of context are called as methods if possible
20211							if ( isFunction( this[ match ] ) ) {
20212								this[ match ]( context[ match ] );
20213
20214							// ...and otherwise set as attributes
20215							} else {
20216								this.attr( match, context[ match ] );
20217							}
20218						}
20219					}
20220
20221					return this;
20222
20223				// HANDLE: $(#id)
20224				} else {
20225					elem = document.getElementById( match[ 2 ] );
20226
20227					if ( elem ) {
20228
20229						// Inject the element directly into the jQuery object
20230						this[ 0 ] = elem;
20231						this.length = 1;
20232					}
20233					return this;
20234				}
20235
20236			// HANDLE: $(expr, $(...))
20237			} else if ( !context || context.jquery ) {
20238				return ( context || root ).find( selector );
20239
20240			// HANDLE: $(expr, context)
20241			// (which is just equivalent to: $(context).find(expr)
20242			} else {
20243				return this.constructor( context ).find( selector );
20244			}
20245
20246		// HANDLE: $(DOMElement)
20247		} else if ( selector.nodeType ) {
20248			this[ 0 ] = selector;
20249			this.length = 1;
20250			return this;
20251
20252		// HANDLE: $(function)
20253		// Shortcut for document ready
20254		} else if ( isFunction( selector ) ) {
20255			return root.ready !== undefined ?
20256				root.ready( selector ) :
20257
20258				// Execute immediately if ready is not present
20259				selector( jQuery );
20260		}
20261
20262		return jQuery.makeArray( selector, this );
20263	};
20264
20265// Give the init function the jQuery prototype for later instantiation
20266init.prototype = jQuery.fn;
20267
20268// Initialize central reference
20269rootjQuery = jQuery( document );
20270
20271
20272var rparentsprev = /^(?:parents|prev(?:Until|All))/,
20273
20274	// Methods guaranteed to produce a unique set when starting from a unique set
20275	guaranteedUnique = {
20276		children: true,
20277		contents: true,
20278		next: true,
20279		prev: true
20280	};
20281
20282jQuery.fn.extend( {
20283	has: function( target ) {
20284		var targets = jQuery( target, this ),
20285			l = targets.length;
20286
20287		return this.filter( function() {
20288			var i = 0;
20289			for ( ; i < l; i++ ) {
20290				if ( jQuery.contains( this, targets[ i ] ) ) {
20291					return true;
20292				}
20293			}
20294		} );
20295	},
20296
20297	closest: function( selectors, context ) {
20298		var cur,
20299			i = 0,
20300			l = this.length,
20301			matched = [],
20302			targets = typeof selectors !== "string" && jQuery( selectors );
20303
20304		// Positional selectors never match, since there's no _selection_ context
20305		if ( !rneedsContext.test( selectors ) ) {
20306			for ( ; i < l; i++ ) {
20307				for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) {
20308
20309					// Always skip document fragments
20310					if ( cur.nodeType < 11 && ( targets ?
20311						targets.index( cur ) > -1 :
20312
20313						// Don't pass non-elements to Sizzle
20314						cur.nodeType === 1 &&
20315							jQuery.find.matchesSelector( cur, selectors ) ) ) {
20316
20317						matched.push( cur );
20318						break;
20319					}
20320				}
20321			}
20322		}
20323
20324		return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched );
20325	},
20326
20327	// Determine the position of an element within the set
20328	index: function( elem ) {
20329
20330		// No argument, return index in parent
20331		if ( !elem ) {
20332			return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
20333		}
20334
20335		// Index in selector
20336		if ( typeof elem === "string" ) {
20337			return indexOf.call( jQuery( elem ), this[ 0 ] );
20338		}
20339
20340		// Locate the position of the desired element
20341		return indexOf.call( this,
20342
20343			// If it receives a jQuery object, the first element is used
20344			elem.jquery ? elem[ 0 ] : elem
20345		);
20346	},
20347
20348	add: function( selector, context ) {
20349		return this.pushStack(
20350			jQuery.uniqueSort(
20351				jQuery.merge( this.get(), jQuery( selector, context ) )
20352			)
20353		);
20354	},
20355
20356	addBack: function( selector ) {
20357		return this.add( selector == null ?
20358			this.prevObject : this.prevObject.filter( selector )
20359		);
20360	}
20361} );
20362
20363function sibling( cur, dir ) {
20364	while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {}
20365	return cur;
20366}
20367
20368jQuery.each( {
20369	parent: function( elem ) {
20370		var parent = elem.parentNode;
20371		return parent && parent.nodeType !== 11 ? parent : null;
20372	},
20373	parents: function( elem ) {
20374		return dir( elem, "parentNode" );
20375	},
20376	parentsUntil: function( elem, _i, until ) {
20377		return dir( elem, "parentNode", until );
20378	},
20379	next: function( elem ) {
20380		return sibling( elem, "nextSibling" );
20381	},
20382	prev: function( elem ) {
20383		return sibling( elem, "previousSibling" );
20384	},
20385	nextAll: function( elem ) {
20386		return dir( elem, "nextSibling" );
20387	},
20388	prevAll: function( elem ) {
20389		return dir( elem, "previousSibling" );
20390	},
20391	nextUntil: function( elem, _i, until ) {
20392		return dir( elem, "nextSibling", until );
20393	},
20394	prevUntil: function( elem, _i, until ) {
20395		return dir( elem, "previousSibling", until );
20396	},
20397	siblings: function( elem ) {
20398		return siblings( ( elem.parentNode || {} ).firstChild, elem );
20399	},
20400	children: function( elem ) {
20401		return siblings( elem.firstChild );
20402	},
20403	contents: function( elem ) {
20404		if ( elem.contentDocument != null &&
20405
20406			// Support: IE 11+
20407			// <object> elements with no `data` attribute has an object
20408			// `contentDocument` with a `null` prototype.
20409			getProto( elem.contentDocument ) ) {
20410
20411			return elem.contentDocument;
20412		}
20413
20414		// Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only
20415		// Treat the template element as a regular one in browsers that
20416		// don't support it.
20417		if ( nodeName( elem, "template" ) ) {
20418			elem = elem.content || elem;
20419		}
20420
20421		return jQuery.merge( [], elem.childNodes );
20422	}
20423}, function( name, fn ) {
20424	jQuery.fn[ name ] = function( until, selector ) {
20425		var matched = jQuery.map( this, fn, until );
20426
20427		if ( name.slice( -5 ) !== "Until" ) {
20428			selector = until;
20429		}
20430
20431		if ( selector && typeof selector === "string" ) {
20432			matched = jQuery.filter( selector, matched );
20433		}
20434
20435		if ( this.length > 1 ) {
20436
20437			// Remove duplicates
20438			if ( !guaranteedUnique[ name ] ) {
20439				jQuery.uniqueSort( matched );
20440			}
20441
20442			// Reverse order for parents* and prev-derivatives
20443			if ( rparentsprev.test( name ) ) {
20444				matched.reverse();
20445			}
20446		}
20447
20448		return this.pushStack( matched );
20449	};
20450} );
20451var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g );
20452
20453
20454
20455// Convert String-formatted options into Object-formatted ones
20456function createOptions( options ) {
20457	var object = {};
20458	jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) {
20459		object[ flag ] = true;
20460	} );
20461	return object;
20462}
20463
20464/*
20465 * Create a callback list using the following parameters:
20466 *
20467 *	options: an optional list of space-separated options that will change how
20468 *			the callback list behaves or a more traditional option object
20469 *
20470 * By default a callback list will act like an event callback list and can be
20471 * "fired" multiple times.
20472 *
20473 * Possible options:
20474 *
20475 *	once:			will ensure the callback list can only be fired once (like a Deferred)
20476 *
20477 *	memory:			will keep track of previous values and will call any callback added
20478 *					after the list has been fired right away with the latest "memorized"
20479 *					values (like a Deferred)
20480 *
20481 *	unique:			will ensure a callback can only be added once (no duplicate in the list)
20482 *
20483 *	stopOnFalse:	interrupt callings when a callback returns false
20484 *
20485 */
20486jQuery.Callbacks = function( options ) {
20487
20488	// Convert options from String-formatted to Object-formatted if needed
20489	// (we check in cache first)
20490	options = typeof options === "string" ?
20491		createOptions( options ) :
20492		jQuery.extend( {}, options );
20493
20494	var // Flag to know if list is currently firing
20495		firing,
20496
20497		// Last fire value for non-forgettable lists
20498		memory,
20499
20500		// Flag to know if list was already fired
20501		fired,
20502
20503		// Flag to prevent firing
20504		locked,
20505
20506		// Actual callback list
20507		list = [],
20508
20509		// Queue of execution data for repeatable lists
20510		queue = [],
20511
20512		// Index of currently firing callback (modified by add/remove as needed)
20513		firingIndex = -1,
20514
20515		// Fire callbacks
20516		fire = function() {
20517
20518			// Enforce single-firing
20519			locked = locked || options.once;
20520
20521			// Execute callbacks for all pending executions,
20522			// respecting firingIndex overrides and runtime changes
20523			fired = firing = true;
20524			for ( ; queue.length; firingIndex = -1 ) {
20525				memory = queue.shift();
20526				while ( ++firingIndex < list.length ) {
20527
20528					// Run callback and check for early termination
20529					if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&
20530						options.stopOnFalse ) {
20531
20532						// Jump to end and forget the data so .add doesn't re-fire
20533						firingIndex = list.length;
20534						memory = false;
20535					}
20536				}
20537			}
20538
20539			// Forget the data if we're done with it
20540			if ( !options.memory ) {
20541				memory = false;
20542			}
20543
20544			firing = false;
20545
20546			// Clean up if we're done firing for good
20547			if ( locked ) {
20548
20549				// Keep an empty list if we have data for future add calls
20550				if ( memory ) {
20551					list = [];
20552
20553				// Otherwise, this object is spent
20554				} else {
20555					list = "";
20556				}
20557			}
20558		},
20559
20560		// Actual Callbacks object
20561		self = {
20562
20563			// Add a callback or a collection of callbacks to the list
20564			add: function() {
20565				if ( list ) {
20566
20567					// If we have memory from a past run, we should fire after adding
20568					if ( memory && !firing ) {
20569						firingIndex = list.length - 1;
20570						queue.push( memory );
20571					}
20572
20573					( function add( args ) {
20574						jQuery.each( args, function( _, arg ) {
20575							if ( isFunction( arg ) ) {
20576								if ( !options.unique || !self.has( arg ) ) {
20577									list.push( arg );
20578								}
20579							} else if ( arg && arg.length && toType( arg ) !== "string" ) {
20580
20581								// Inspect recursively
20582								add( arg );
20583							}
20584						} );
20585					} )( arguments );
20586
20587					if ( memory && !firing ) {
20588						fire();
20589					}
20590				}
20591				return this;
20592			},
20593
20594			// Remove a callback from the list
20595			remove: function() {
20596				jQuery.each( arguments, function( _, arg ) {
20597					var index;
20598					while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
20599						list.splice( index, 1 );
20600
20601						// Handle firing indexes
20602						if ( index <= firingIndex ) {
20603							firingIndex--;
20604						}
20605					}
20606				} );
20607				return this;
20608			},
20609
20610			// Check if a given callback is in the list.
20611			// If no argument is given, return whether or not list has callbacks attached.
20612			has: function( fn ) {
20613				return fn ?
20614					jQuery.inArray( fn, list ) > -1 :
20615					list.length > 0;
20616			},
20617
20618			// Remove all callbacks from the list
20619			empty: function() {
20620				if ( list ) {
20621					list = [];
20622				}
20623				return this;
20624			},
20625
20626			// Disable .fire and .add
20627			// Abort any current/pending executions
20628			// Clear all callbacks and values
20629			disable: function() {
20630				locked = queue = [];
20631				list = memory = "";
20632				return this;
20633			},
20634			disabled: function() {
20635				return !list;
20636			},
20637
20638			// Disable .fire
20639			// Also disable .add unless we have memory (since it would have no effect)
20640			// Abort any pending executions
20641			lock: function() {
20642				locked = queue = [];
20643				if ( !memory && !firing ) {
20644					list = memory = "";
20645				}
20646				return this;
20647			},
20648			locked: function() {
20649				return !!locked;
20650			},
20651
20652			// Call all callbacks with the given context and arguments
20653			fireWith: function( context, args ) {
20654				if ( !locked ) {
20655					args = args || [];
20656					args = [ context, args.slice ? args.slice() : args ];
20657					queue.push( args );
20658					if ( !firing ) {
20659						fire();
20660					}
20661				}
20662				return this;
20663			},
20664
20665			// Call all the callbacks with the given arguments
20666			fire: function() {
20667				self.fireWith( this, arguments );
20668				return this;
20669			},
20670
20671			// To know if the callbacks have already been called at least once
20672			fired: function() {
20673				return !!fired;
20674			}
20675		};
20676
20677	return self;
20678};
20679
20680
20681function Identity( v ) {
20682	return v;
20683}
20684function Thrower( ex ) {
20685	throw ex;
20686}
20687
20688function adoptValue( value, resolve, reject, noValue ) {
20689	var method;
20690
20691	try {
20692
20693		// Check for promise aspect first to privilege synchronous behavior
20694		if ( value && isFunction( ( method = value.promise ) ) ) {
20695			method.call( value ).done( resolve ).fail( reject );
20696
20697		// Other thenables
20698		} else if ( value && isFunction( ( method = value.then ) ) ) {
20699			method.call( value, resolve, reject );
20700
20701		// Other non-thenables
20702		} else {
20703
20704			// Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer:
20705			// * false: [ value ].slice( 0 ) => resolve( value )
20706			// * true: [ value ].slice( 1 ) => resolve()
20707			resolve.apply( undefined, [ value ].slice( noValue ) );
20708		}
20709
20710	// For Promises/A+, convert exceptions into rejections
20711	// Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in
20712	// Deferred#then to conditionally suppress rejection.
20713	} catch ( value ) {
20714
20715		// Support: Android 4.0 only
20716		// Strict mode functions invoked without .call/.apply get global-object context
20717		reject.apply( undefined, [ value ] );
20718	}
20719}
20720
20721jQuery.extend( {
20722
20723	Deferred: function( func ) {
20724		var tuples = [
20725
20726				// action, add listener, callbacks,
20727				// ... .then handlers, argument index, [final state]
20728				[ "notify", "progress", jQuery.Callbacks( "memory" ),
20729					jQuery.Callbacks( "memory" ), 2 ],
20730				[ "resolve", "done", jQuery.Callbacks( "once memory" ),
20731					jQuery.Callbacks( "once memory" ), 0, "resolved" ],
20732				[ "reject", "fail", jQuery.Callbacks( "once memory" ),
20733					jQuery.Callbacks( "once memory" ), 1, "rejected" ]
20734			],
20735			state = "pending",
20736			promise = {
20737				state: function() {
20738					return state;
20739				},
20740				always: function() {
20741					deferred.done( arguments ).fail( arguments );
20742					return this;
20743				},
20744				"catch": function( fn ) {
20745					return promise.then( null, fn );
20746				},
20747
20748				// Keep pipe for back-compat
20749				pipe: function( /* fnDone, fnFail, fnProgress */ ) {
20750					var fns = arguments;
20751
20752					return jQuery.Deferred( function( newDefer ) {
20753						jQuery.each( tuples, function( _i, tuple ) {
20754
20755							// Map tuples (progress, done, fail) to arguments (done, fail, progress)
20756							var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ];
20757
20758							// deferred.progress(function() { bind to newDefer or newDefer.notify })
20759							// deferred.done(function() { bind to newDefer or newDefer.resolve })
20760							// deferred.fail(function() { bind to newDefer or newDefer.reject })
20761							deferred[ tuple[ 1 ] ]( function() {
20762								var returned = fn && fn.apply( this, arguments );
20763								if ( returned && isFunction( returned.promise ) ) {
20764									returned.promise()
20765										.progress( newDefer.notify )
20766										.done( newDefer.resolve )
20767										.fail( newDefer.reject );
20768								} else {
20769									newDefer[ tuple[ 0 ] + "With" ](
20770										this,
20771										fn ? [ returned ] : arguments
20772									);
20773								}
20774							} );
20775						} );
20776						fns = null;
20777					} ).promise();
20778				},
20779				then: function( onFulfilled, onRejected, onProgress ) {
20780					var maxDepth = 0;
20781					function resolve( depth, deferred, handler, special ) {
20782						return function() {
20783							var that = this,
20784								args = arguments,
20785								mightThrow = function() {
20786									var returned, then;
20787
20788									// Support: Promises/A+ section 2.3.3.3.3
20789									// https://promisesaplus.com/#point-59
20790									// Ignore double-resolution attempts
20791									if ( depth < maxDepth ) {
20792										return;
20793									}
20794
20795									returned = handler.apply( that, args );
20796
20797									// Support: Promises/A+ section 2.3.1
20798									// https://promisesaplus.com/#point-48
20799									if ( returned === deferred.promise() ) {
20800										throw new TypeError( "Thenable self-resolution" );
20801									}
20802
20803									// Support: Promises/A+ sections 2.3.3.1, 3.5
20804									// https://promisesaplus.com/#point-54
20805									// https://promisesaplus.com/#point-75
20806									// Retrieve `then` only once
20807									then = returned &&
20808
20809										// Support: Promises/A+ section 2.3.4
20810										// https://promisesaplus.com/#point-64
20811										// Only check objects and functions for thenability
20812										( typeof returned === "object" ||
20813											typeof returned === "function" ) &&
20814										returned.then;
20815
20816									// Handle a returned thenable
20817									if ( isFunction( then ) ) {
20818
20819										// Special processors (notify) just wait for resolution
20820										if ( special ) {
20821											then.call(
20822												returned,
20823												resolve( maxDepth, deferred, Identity, special ),
20824												resolve( maxDepth, deferred, Thrower, special )
20825											);
20826
20827										// Normal processors (resolve) also hook into progress
20828										} else {
20829
20830											// ...and disregard older resolution values
20831											maxDepth++;
20832
20833											then.call(
20834												returned,
20835												resolve( maxDepth, deferred, Identity, special ),
20836												resolve( maxDepth, deferred, Thrower, special ),
20837												resolve( maxDepth, deferred, Identity,
20838													deferred.notifyWith )
20839											);
20840										}
20841
20842									// Handle all other returned values
20843									} else {
20844
20845										// Only substitute handlers pass on context
20846										// and multiple values (non-spec behavior)
20847										if ( handler !== Identity ) {
20848											that = undefined;
20849											args = [ returned ];
20850										}
20851
20852										// Process the value(s)
20853										// Default process is resolve
20854										( special || deferred.resolveWith )( that, args );
20855									}
20856								},
20857
20858								// Only normal processors (resolve) catch and reject exceptions
20859								process = special ?
20860									mightThrow :
20861									function() {
20862										try {
20863											mightThrow();
20864										} catch ( e ) {
20865
20866											if ( jQuery.Deferred.exceptionHook ) {
20867												jQuery.Deferred.exceptionHook( e,
20868													process.stackTrace );
20869											}
20870
20871											// Support: Promises/A+ section 2.3.3.3.4.1
20872											// https://promisesaplus.com/#point-61
20873											// Ignore post-resolution exceptions
20874											if ( depth + 1 >= maxDepth ) {
20875
20876												// Only substitute handlers pass on context
20877												// and multiple values (non-spec behavior)
20878												if ( handler !== Thrower ) {
20879													that = undefined;
20880													args = [ e ];
20881												}
20882
20883												deferred.rejectWith( that, args );
20884											}
20885										}
20886									};
20887
20888							// Support: Promises/A+ section 2.3.3.3.1
20889							// https://promisesaplus.com/#point-57
20890							// Re-resolve promises immediately to dodge false rejection from
20891							// subsequent errors
20892							if ( depth ) {
20893								process();
20894							} else {
20895
20896								// Call an optional hook to record the stack, in case of exception
20897								// since it's otherwise lost when execution goes async
20898								if ( jQuery.Deferred.getStackHook ) {
20899									process.stackTrace = jQuery.Deferred.getStackHook();
20900								}
20901								window.setTimeout( process );
20902							}
20903						};
20904					}
20905
20906					return jQuery.Deferred( function( newDefer ) {
20907
20908						// progress_handlers.add( ... )
20909						tuples[ 0 ][ 3 ].add(
20910							resolve(
20911								0,
20912								newDefer,
20913								isFunction( onProgress ) ?
20914									onProgress :
20915									Identity,
20916								newDefer.notifyWith
20917							)
20918						);
20919
20920						// fulfilled_handlers.add( ... )
20921						tuples[ 1 ][ 3 ].add(
20922							resolve(
20923								0,
20924								newDefer,
20925								isFunction( onFulfilled ) ?
20926									onFulfilled :
20927									Identity
20928							)
20929						);
20930
20931						// rejected_handlers.add( ... )
20932						tuples[ 2 ][ 3 ].add(
20933							resolve(
20934								0,
20935								newDefer,
20936								isFunction( onRejected ) ?
20937									onRejected :
20938									Thrower
20939							)
20940						);
20941					} ).promise();
20942				},
20943
20944				// Get a promise for this deferred
20945				// If obj is provided, the promise aspect is added to the object
20946				promise: function( obj ) {
20947					return obj != null ? jQuery.extend( obj, promise ) : promise;
20948				}
20949			},
20950			deferred = {};
20951
20952		// Add list-specific methods
20953		jQuery.each( tuples, function( i, tuple ) {
20954			var list = tuple[ 2 ],
20955				stateString = tuple[ 5 ];
20956
20957			// promise.progress = list.add
20958			// promise.done = list.add
20959			// promise.fail = list.add
20960			promise[ tuple[ 1 ] ] = list.add;
20961
20962			// Handle state
20963			if ( stateString ) {
20964				list.add(
20965					function() {
20966
20967						// state = "resolved" (i.e., fulfilled)
20968						// state = "rejected"
20969						state = stateString;
20970					},
20971
20972					// rejected_callbacks.disable
20973					// fulfilled_callbacks.disable
20974					tuples[ 3 - i ][ 2 ].disable,
20975
20976					// rejected_handlers.disable
20977					// fulfilled_handlers.disable
20978					tuples[ 3 - i ][ 3 ].disable,
20979
20980					// progress_callbacks.lock
20981					tuples[ 0 ][ 2 ].lock,
20982
20983					// progress_handlers.lock
20984					tuples[ 0 ][ 3 ].lock
20985				);
20986			}
20987
20988			// progress_handlers.fire
20989			// fulfilled_handlers.fire
20990			// rejected_handlers.fire
20991			list.add( tuple[ 3 ].fire );
20992
20993			// deferred.notify = function() { deferred.notifyWith(...) }
20994			// deferred.resolve = function() { deferred.resolveWith(...) }
20995			// deferred.reject = function() { deferred.rejectWith(...) }
20996			deferred[ tuple[ 0 ] ] = function() {
20997				deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments );
20998				return this;
20999			};
21000
21001			// deferred.notifyWith = list.fireWith
21002			// deferred.resolveWith = list.fireWith
21003			// deferred.rejectWith = list.fireWith
21004			deferred[ tuple[ 0 ] + "With" ] = list.fireWith;
21005		} );
21006
21007		// Make the deferred a promise
21008		promise.promise( deferred );
21009
21010		// Call given func if any
21011		if ( func ) {
21012			func.call( deferred, deferred );
21013		}
21014
21015		// All done!
21016		return deferred;
21017	},
21018
21019	// Deferred helper
21020	when: function( singleValue ) {
21021		var
21022
21023			// count of uncompleted subordinates
21024			remaining = arguments.length,
21025
21026			// count of unprocessed arguments
21027			i = remaining,
21028
21029			// subordinate fulfillment data
21030			resolveContexts = Array( i ),
21031			resolveValues = slice.call( arguments ),
21032
21033			// the primary Deferred
21034			primary = jQuery.Deferred(),
21035
21036			// subordinate callback factory
21037			updateFunc = function( i ) {
21038				return function( value ) {
21039					resolveContexts[ i ] = this;
21040					resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
21041					if ( !( --remaining ) ) {
21042						primary.resolveWith( resolveContexts, resolveValues );
21043					}
21044				};
21045			};
21046
21047		// Single- and empty arguments are adopted like Promise.resolve
21048		if ( remaining <= 1 ) {
21049			adoptValue( singleValue, primary.done( updateFunc( i ) ).resolve, primary.reject,
21050				!remaining );
21051
21052			// Use .then() to unwrap secondary thenables (cf. gh-3000)
21053			if ( primary.state() === "pending" ||
21054				isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) {
21055
21056				return primary.then();
21057			}
21058		}
21059
21060		// Multiple arguments are aggregated like Promise.all array elements
21061		while ( i-- ) {
21062			adoptValue( resolveValues[ i ], updateFunc( i ), primary.reject );
21063		}
21064
21065		return primary.promise();
21066	}
21067} );
21068
21069
21070// These usually indicate a programmer mistake during development,
21071// warn about them ASAP rather than swallowing them by default.
21072var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;
21073
21074jQuery.Deferred.exceptionHook = function( error, stack ) {
21075
21076	// Support: IE 8 - 9 only
21077	// Console exists when dev tools are open, which can happen at any time
21078	if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) {
21079		window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack );
21080	}
21081};
21082
21083
21084
21085
21086jQuery.readyException = function( error ) {
21087	window.setTimeout( function() {
21088		throw error;
21089	} );
21090};
21091
21092
21093
21094
21095// The deferred used on DOM ready
21096var readyList = jQuery.Deferred();
21097
21098jQuery.fn.ready = function( fn ) {
21099
21100	readyList
21101		.then( fn )
21102
21103		// Wrap jQuery.readyException in a function so that the lookup
21104		// happens at the time of error handling instead of callback
21105		// registration.
21106		.catch( function( error ) {
21107			jQuery.readyException( error );
21108		} );
21109
21110	return this;
21111};
21112
21113jQuery.extend( {
21114
21115	// Is the DOM ready to be used? Set to true once it occurs.
21116	isReady: false,
21117
21118	// A counter to track how many items to wait for before
21119	// the ready event fires. See #6781
21120	readyWait: 1,
21121
21122	// Handle when the DOM is ready
21123	ready: function( wait ) {
21124
21125		// Abort if there are pending holds or we're already ready
21126		if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
21127			return;
21128		}
21129
21130		// Remember that the DOM is ready
21131		jQuery.isReady = true;
21132
21133		// If a normal DOM Ready event fired, decrement, and wait if need be
21134		if ( wait !== true && --jQuery.readyWait > 0 ) {
21135			return;
21136		}
21137
21138		// If there are functions bound, to execute
21139		readyList.resolveWith( document, [ jQuery ] );
21140	}
21141} );
21142
21143jQuery.ready.then = readyList.then;
21144
21145// The ready event handler and self cleanup method
21146function completed() {
21147	document.removeEventListener( "DOMContentLoaded", completed );
21148	window.removeEventListener( "load", completed );
21149	jQuery.ready();
21150}
21151
21152// Catch cases where $(document).ready() is called
21153// after the browser event has already occurred.
21154// Support: IE <=9 - 10 only
21155// Older IE sometimes signals "interactive" too soon
21156if ( document.readyState === "complete" ||
21157	( document.readyState !== "loading" && !document.documentElement.doScroll ) ) {
21158
21159	// Handle it asynchronously to allow scripts the opportunity to delay ready
21160	window.setTimeout( jQuery.ready );
21161
21162} else {
21163
21164	// Use the handy event callback
21165	document.addEventListener( "DOMContentLoaded", completed );
21166
21167	// A fallback to window.onload, that will always work
21168	window.addEventListener( "load", completed );
21169}
21170
21171
21172
21173
21174// Multifunctional method to get and set values of a collection
21175// The value/s can optionally be executed if it's a function
21176var access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
21177	var i = 0,
21178		len = elems.length,
21179		bulk = key == null;
21180
21181	// Sets many values
21182	if ( toType( key ) === "object" ) {
21183		chainable = true;
21184		for ( i in key ) {
21185			access( elems, fn, i, key[ i ], true, emptyGet, raw );
21186		}
21187
21188	// Sets one value
21189	} else if ( value !== undefined ) {
21190		chainable = true;
21191
21192		if ( !isFunction( value ) ) {
21193			raw = true;
21194		}
21195
21196		if ( bulk ) {
21197
21198			// Bulk operations run against the entire set
21199			if ( raw ) {
21200				fn.call( elems, value );
21201				fn = null;
21202
21203			// ...except when executing function values
21204			} else {
21205				bulk = fn;
21206				fn = function( elem, _key, value ) {
21207					return bulk.call( jQuery( elem ), value );
21208				};
21209			}
21210		}
21211
21212		if ( fn ) {
21213			for ( ; i < len; i++ ) {
21214				fn(
21215					elems[ i ], key, raw ?
21216						value :
21217						value.call( elems[ i ], i, fn( elems[ i ], key ) )
21218				);
21219			}
21220		}
21221	}
21222
21223	if ( chainable ) {
21224		return elems;
21225	}
21226
21227	// Gets
21228	if ( bulk ) {
21229		return fn.call( elems );
21230	}
21231
21232	return len ? fn( elems[ 0 ], key ) : emptyGet;
21233};
21234
21235
21236// Matches dashed string for camelizing
21237var rmsPrefix = /^-ms-/,
21238	rdashAlpha = /-([a-z])/g;
21239
21240// Used by camelCase as callback to replace()
21241function fcamelCase( _all, letter ) {
21242	return letter.toUpperCase();
21243}
21244
21245// Convert dashed to camelCase; used by the css and data modules
21246// Support: IE <=9 - 11, Edge 12 - 15
21247// Microsoft forgot to hump their vendor prefix (#9572)
21248function camelCase( string ) {
21249	return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
21250}
21251var acceptData = function( owner ) {
21252
21253	// Accepts only:
21254	//  - Node
21255	//    - Node.ELEMENT_NODE
21256	//    - Node.DOCUMENT_NODE
21257	//  - Object
21258	//    - Any
21259	return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );
21260};
21261
21262
21263
21264
21265function Data() {
21266	this.expando = jQuery.expando + Data.uid++;
21267}
21268
21269Data.uid = 1;
21270
21271Data.prototype = {
21272
21273	cache: function( owner ) {
21274
21275		// Check if the owner object already has a cache
21276		var value = owner[ this.expando ];
21277
21278		// If not, create one
21279		if ( !value ) {
21280			value = {};
21281
21282			// We can accept data for non-element nodes in modern browsers,
21283			// but we should not, see #8335.
21284			// Always return an empty object.
21285			if ( acceptData( owner ) ) {
21286
21287				// If it is a node unlikely to be stringify-ed or looped over
21288				// use plain assignment
21289				if ( owner.nodeType ) {
21290					owner[ this.expando ] = value;
21291
21292				// Otherwise secure it in a non-enumerable property
21293				// configurable must be true to allow the property to be
21294				// deleted when data is removed
21295				} else {
21296					Object.defineProperty( owner, this.expando, {
21297						value: value,
21298						configurable: true
21299					} );
21300				}
21301			}
21302		}
21303
21304		return value;
21305	},
21306	set: function( owner, data, value ) {
21307		var prop,
21308			cache = this.cache( owner );
21309
21310		// Handle: [ owner, key, value ] args
21311		// Always use camelCase key (gh-2257)
21312		if ( typeof data === "string" ) {
21313			cache[ camelCase( data ) ] = value;
21314
21315		// Handle: [ owner, { properties } ] args
21316		} else {
21317
21318			// Copy the properties one-by-one to the cache object
21319			for ( prop in data ) {
21320				cache[ camelCase( prop ) ] = data[ prop ];
21321			}
21322		}
21323		return cache;
21324	},
21325	get: function( owner, key ) {
21326		return key === undefined ?
21327			this.cache( owner ) :
21328
21329			// Always use camelCase key (gh-2257)
21330			owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ];
21331	},
21332	access: function( owner, key, value ) {
21333
21334		// In cases where either:
21335		//
21336		//   1. No key was specified
21337		//   2. A string key was specified, but no value provided
21338		//
21339		// Take the "read" path and allow the get method to determine
21340		// which value to return, respectively either:
21341		//
21342		//   1. The entire cache object
21343		//   2. The data stored at the key
21344		//
21345		if ( key === undefined ||
21346				( ( key && typeof key === "string" ) && value === undefined ) ) {
21347
21348			return this.get( owner, key );
21349		}
21350
21351		// When the key is not a string, or both a key and value
21352		// are specified, set or extend (existing objects) with either:
21353		//
21354		//   1. An object of properties
21355		//   2. A key and value
21356		//
21357		this.set( owner, key, value );
21358
21359		// Since the "set" path can have two possible entry points
21360		// return the expected data based on which path was taken[*]
21361		return value !== undefined ? value : key;
21362	},
21363	remove: function( owner, key ) {
21364		var i,
21365			cache = owner[ this.expando ];
21366
21367		if ( cache === undefined ) {
21368			return;
21369		}
21370
21371		if ( key !== undefined ) {
21372
21373			// Support array or space separated string of keys
21374			if ( Array.isArray( key ) ) {
21375
21376				// If key is an array of keys...
21377				// We always set camelCase keys, so remove that.
21378				key = key.map( camelCase );
21379			} else {
21380				key = camelCase( key );
21381
21382				// If a key with the spaces exists, use it.
21383				// Otherwise, create an array by matching non-whitespace
21384				key = key in cache ?
21385					[ key ] :
21386					( key.match( rnothtmlwhite ) || [] );
21387			}
21388
21389			i = key.length;
21390
21391			while ( i-- ) {
21392				delete cache[ key[ i ] ];
21393			}
21394		}
21395
21396		// Remove the expando if there's no more data
21397		if ( key === undefined || jQuery.isEmptyObject( cache ) ) {
21398
21399			// Support: Chrome <=35 - 45
21400			// Webkit & Blink performance suffers when deleting properties
21401			// from DOM nodes, so set to undefined instead
21402			// https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted)
21403			if ( owner.nodeType ) {
21404				owner[ this.expando ] = undefined;
21405			} else {
21406				delete owner[ this.expando ];
21407			}
21408		}
21409	},
21410	hasData: function( owner ) {
21411		var cache = owner[ this.expando ];
21412		return cache !== undefined && !jQuery.isEmptyObject( cache );
21413	}
21414};
21415var dataPriv = new Data();
21416
21417var dataUser = new Data();
21418
21419
21420
21421//	Implementation Summary
21422//
21423//	1. Enforce API surface and semantic compatibility with 1.9.x branch
21424//	2. Improve the module's maintainability by reducing the storage
21425//		paths to a single mechanism.
21426//	3. Use the same single mechanism to support "private" and "user" data.
21427//	4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
21428//	5. Avoid exposing implementation details on user objects (eg. expando properties)
21429//	6. Provide a clear path for implementation upgrade to WeakMap in 2014
21430
21431var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
21432	rmultiDash = /[A-Z]/g;
21433
21434function getData( data ) {
21435	if ( data === "true" ) {
21436		return true;
21437	}
21438
21439	if ( data === "false" ) {
21440		return false;
21441	}
21442
21443	if ( data === "null" ) {
21444		return null;
21445	}
21446
21447	// Only convert to a number if it doesn't change the string
21448	if ( data === +data + "" ) {
21449		return +data;
21450	}
21451
21452	if ( rbrace.test( data ) ) {
21453		return JSON.parse( data );
21454	}
21455
21456	return data;
21457}
21458
21459function dataAttr( elem, key, data ) {
21460	var name;
21461
21462	// If nothing was found internally, try to fetch any
21463	// data from the HTML5 data-* attribute
21464	if ( data === undefined && elem.nodeType === 1 ) {
21465		name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase();
21466		data = elem.getAttribute( name );
21467
21468		if ( typeof data === "string" ) {
21469			try {
21470				data = getData( data );
21471			} catch ( e ) {}
21472
21473			// Make sure we set the data so it isn't changed later
21474			dataUser.set( elem, key, data );
21475		} else {
21476			data = undefined;
21477		}
21478	}
21479	return data;
21480}
21481
21482jQuery.extend( {
21483	hasData: function( elem ) {
21484		return dataUser.hasData( elem ) || dataPriv.hasData( elem );
21485	},
21486
21487	data: function( elem, name, data ) {
21488		return dataUser.access( elem, name, data );
21489	},
21490
21491	removeData: function( elem, name ) {
21492		dataUser.remove( elem, name );
21493	},
21494
21495	// TODO: Now that all calls to _data and _removeData have been replaced
21496	// with direct calls to dataPriv methods, these can be deprecated.
21497	_data: function( elem, name, data ) {
21498		return dataPriv.access( elem, name, data );
21499	},
21500
21501	_removeData: function( elem, name ) {
21502		dataPriv.remove( elem, name );
21503	}
21504} );
21505
21506jQuery.fn.extend( {
21507	data: function( key, value ) {
21508		var i, name, data,
21509			elem = this[ 0 ],
21510			attrs = elem && elem.attributes;
21511
21512		// Gets all values
21513		if ( key === undefined ) {
21514			if ( this.length ) {
21515				data = dataUser.get( elem );
21516
21517				if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) {
21518					i = attrs.length;
21519					while ( i-- ) {
21520
21521						// Support: IE 11 only
21522						// The attrs elements can be null (#14894)
21523						if ( attrs[ i ] ) {
21524							name = attrs[ i ].name;
21525							if ( name.indexOf( "data-" ) === 0 ) {
21526								name = camelCase( name.slice( 5 ) );
21527								dataAttr( elem, name, data[ name ] );
21528							}
21529						}
21530					}
21531					dataPriv.set( elem, "hasDataAttrs", true );
21532				}
21533			}
21534
21535			return data;
21536		}
21537
21538		// Sets multiple values
21539		if ( typeof key === "object" ) {
21540			return this.each( function() {
21541				dataUser.set( this, key );
21542			} );
21543		}
21544
21545		return access( this, function( value ) {
21546			var data;
21547
21548			// The calling jQuery object (element matches) is not empty
21549			// (and therefore has an element appears at this[ 0 ]) and the
21550			// `value` parameter was not undefined. An empty jQuery object
21551			// will result in `undefined` for elem = this[ 0 ] which will
21552			// throw an exception if an attempt to read a data cache is made.
21553			if ( elem && value === undefined ) {
21554
21555				// Attempt to get data from the cache
21556				// The key will always be camelCased in Data
21557				data = dataUser.get( elem, key );
21558				if ( data !== undefined ) {
21559					return data;
21560				}
21561
21562				// Attempt to "discover" the data in
21563				// HTML5 custom data-* attrs
21564				data = dataAttr( elem, key );
21565				if ( data !== undefined ) {
21566					return data;
21567				}
21568
21569				// We tried really hard, but the data doesn't exist.
21570				return;
21571			}
21572
21573			// Set the data...
21574			this.each( function() {
21575
21576				// We always store the camelCased key
21577				dataUser.set( this, key, value );
21578			} );
21579		}, null, value, arguments.length > 1, null, true );
21580	},
21581
21582	removeData: function( key ) {
21583		return this.each( function() {
21584			dataUser.remove( this, key );
21585		} );
21586	}
21587} );
21588
21589
21590jQuery.extend( {
21591	queue: function( elem, type, data ) {
21592		var queue;
21593
21594		if ( elem ) {
21595			type = ( type || "fx" ) + "queue";
21596			queue = dataPriv.get( elem, type );
21597
21598			// Speed up dequeue by getting out quickly if this is just a lookup
21599			if ( data ) {
21600				if ( !queue || Array.isArray( data ) ) {
21601					queue = dataPriv.access( elem, type, jQuery.makeArray( data ) );
21602				} else {
21603					queue.push( data );
21604				}
21605			}
21606			return queue || [];
21607		}
21608	},
21609
21610	dequeue: function( elem, type ) {
21611		type = type || "fx";
21612
21613		var queue = jQuery.queue( elem, type ),
21614			startLength = queue.length,
21615			fn = queue.shift(),
21616			hooks = jQuery._queueHooks( elem, type ),
21617			next = function() {
21618				jQuery.dequeue( elem, type );
21619			};
21620
21621		// If the fx queue is dequeued, always remove the progress sentinel
21622		if ( fn === "inprogress" ) {
21623			fn = queue.shift();
21624			startLength--;
21625		}
21626
21627		if ( fn ) {
21628
21629			// Add a progress sentinel to prevent the fx queue from being
21630			// automatically dequeued
21631			if ( type === "fx" ) {
21632				queue.unshift( "inprogress" );
21633			}
21634
21635			// Clear up the last queue stop function
21636			delete hooks.stop;
21637			fn.call( elem, next, hooks );
21638		}
21639
21640		if ( !startLength && hooks ) {
21641			hooks.empty.fire();
21642		}
21643	},
21644
21645	// Not public - generate a queueHooks object, or return the current one
21646	_queueHooks: function( elem, type ) {
21647		var key = type + "queueHooks";
21648		return dataPriv.get( elem, key ) || dataPriv.access( elem, key, {
21649			empty: jQuery.Callbacks( "once memory" ).add( function() {
21650				dataPriv.remove( elem, [ type + "queue", key ] );
21651			} )
21652		} );
21653	}
21654} );
21655
21656jQuery.fn.extend( {
21657	queue: function( type, data ) {
21658		var setter = 2;
21659
21660		if ( typeof type !== "string" ) {
21661			data = type;
21662			type = "fx";
21663			setter--;
21664		}
21665
21666		if ( arguments.length < setter ) {
21667			return jQuery.queue( this[ 0 ], type );
21668		}
21669
21670		return data === undefined ?
21671			this :
21672			this.each( function() {
21673				var queue = jQuery.queue( this, type, data );
21674
21675				// Ensure a hooks for this queue
21676				jQuery._queueHooks( this, type );
21677
21678				if ( type === "fx" && queue[ 0 ] !== "inprogress" ) {
21679					jQuery.dequeue( this, type );
21680				}
21681			} );
21682	},
21683	dequeue: function( type ) {
21684		return this.each( function() {
21685			jQuery.dequeue( this, type );
21686		} );
21687	},
21688	clearQueue: function( type ) {
21689		return this.queue( type || "fx", [] );
21690	},
21691
21692	// Get a promise resolved when queues of a certain type
21693	// are emptied (fx is the type by default)
21694	promise: function( type, obj ) {
21695		var tmp,
21696			count = 1,
21697			defer = jQuery.Deferred(),
21698			elements = this,
21699			i = this.length,
21700			resolve = function() {
21701				if ( !( --count ) ) {
21702					defer.resolveWith( elements, [ elements ] );
21703				}
21704			};
21705
21706		if ( typeof type !== "string" ) {
21707			obj = type;
21708			type = undefined;
21709		}
21710		type = type || "fx";
21711
21712		while ( i-- ) {
21713			tmp = dataPriv.get( elements[ i ], type + "queueHooks" );
21714			if ( tmp && tmp.empty ) {
21715				count++;
21716				tmp.empty.add( resolve );
21717			}
21718		}
21719		resolve();
21720		return defer.promise( obj );
21721	}
21722} );
21723var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source;
21724
21725var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" );
21726
21727
21728var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
21729
21730var documentElement = document.documentElement;
21731
21732
21733
21734	var isAttached = function( elem ) {
21735			return jQuery.contains( elem.ownerDocument, elem );
21736		},
21737		composed = { composed: true };
21738
21739	// Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only
21740	// Check attachment across shadow DOM boundaries when possible (gh-3504)
21741	// Support: iOS 10.0-10.2 only
21742	// Early iOS 10 versions support `attachShadow` but not `getRootNode`,
21743	// leading to errors. We need to check for `getRootNode`.
21744	if ( documentElement.getRootNode ) {
21745		isAttached = function( elem ) {
21746			return jQuery.contains( elem.ownerDocument, elem ) ||
21747				elem.getRootNode( composed ) === elem.ownerDocument;
21748		};
21749	}
21750var isHiddenWithinTree = function( elem, el ) {
21751
21752		// isHiddenWithinTree might be called from jQuery#filter function;
21753		// in that case, element will be second argument
21754		elem = el || elem;
21755
21756		// Inline style trumps all
21757		return elem.style.display === "none" ||
21758			elem.style.display === "" &&
21759
21760			// Otherwise, check computed style
21761			// Support: Firefox <=43 - 45
21762			// Disconnected elements can have computed display: none, so first confirm that elem is
21763			// in the document.
21764			isAttached( elem ) &&
21765
21766			jQuery.css( elem, "display" ) === "none";
21767	};
21768
21769
21770
21771function adjustCSS( elem, prop, valueParts, tween ) {
21772	var adjusted, scale,
21773		maxIterations = 20,
21774		currentValue = tween ?
21775			function() {
21776				return tween.cur();
21777			} :
21778			function() {
21779				return jQuery.css( elem, prop, "" );
21780			},
21781		initial = currentValue(),
21782		unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
21783
21784		// Starting value computation is required for potential unit mismatches
21785		initialInUnit = elem.nodeType &&
21786			( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) &&
21787			rcssNum.exec( jQuery.css( elem, prop ) );
21788
21789	if ( initialInUnit && initialInUnit[ 3 ] !== unit ) {
21790
21791		// Support: Firefox <=54
21792		// Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144)
21793		initial = initial / 2;
21794
21795		// Trust units reported by jQuery.css
21796		unit = unit || initialInUnit[ 3 ];
21797
21798		// Iteratively approximate from a nonzero starting point
21799		initialInUnit = +initial || 1;
21800
21801		while ( maxIterations-- ) {
21802
21803			// Evaluate and update our best guess (doubling guesses that zero out).
21804			// Finish if the scale equals or crosses 1 (making the old*new product non-positive).
21805			jQuery.style( elem, prop, initialInUnit + unit );
21806			if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) {
21807				maxIterations = 0;
21808			}
21809			initialInUnit = initialInUnit / scale;
21810
21811		}
21812
21813		initialInUnit = initialInUnit * 2;
21814		jQuery.style( elem, prop, initialInUnit + unit );
21815
21816		// Make sure we update the tween properties later on
21817		valueParts = valueParts || [];
21818	}
21819
21820	if ( valueParts ) {
21821		initialInUnit = +initialInUnit || +initial || 0;
21822
21823		// Apply relative offset (+=/-=) if specified
21824		adjusted = valueParts[ 1 ] ?
21825			initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] :
21826			+valueParts[ 2 ];
21827		if ( tween ) {
21828			tween.unit = unit;
21829			tween.start = initialInUnit;
21830			tween.end = adjusted;
21831		}
21832	}
21833	return adjusted;
21834}
21835
21836
21837var defaultDisplayMap = {};
21838
21839function getDefaultDisplay( elem ) {
21840	var temp,
21841		doc = elem.ownerDocument,
21842		nodeName = elem.nodeName,
21843		display = defaultDisplayMap[ nodeName ];
21844
21845	if ( display ) {
21846		return display;
21847	}
21848
21849	temp = doc.body.appendChild( doc.createElement( nodeName ) );
21850	display = jQuery.css( temp, "display" );
21851
21852	temp.parentNode.removeChild( temp );
21853
21854	if ( display === "none" ) {
21855		display = "block";
21856	}
21857	defaultDisplayMap[ nodeName ] = display;
21858
21859	return display;
21860}
21861
21862function showHide( elements, show ) {
21863	var display, elem,
21864		values = [],
21865		index = 0,
21866		length = elements.length;
21867
21868	// Determine new display value for elements that need to change
21869	for ( ; index < length; index++ ) {
21870		elem = elements[ index ];
21871		if ( !elem.style ) {
21872			continue;
21873		}
21874
21875		display = elem.style.display;
21876		if ( show ) {
21877
21878			// Since we force visibility upon cascade-hidden elements, an immediate (and slow)
21879			// check is required in this first loop unless we have a nonempty display value (either
21880			// inline or about-to-be-restored)
21881			if ( display === "none" ) {
21882				values[ index ] = dataPriv.get( elem, "display" ) || null;
21883				if ( !values[ index ] ) {
21884					elem.style.display = "";
21885				}
21886			}
21887			if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) {
21888				values[ index ] = getDefaultDisplay( elem );
21889			}
21890		} else {
21891			if ( display !== "none" ) {
21892				values[ index ] = "none";
21893
21894				// Remember what we're overwriting
21895				dataPriv.set( elem, "display", display );
21896			}
21897		}
21898	}
21899
21900	// Set the display of the elements in a second loop to avoid constant reflow
21901	for ( index = 0; index < length; index++ ) {
21902		if ( values[ index ] != null ) {
21903			elements[ index ].style.display = values[ index ];
21904		}
21905	}
21906
21907	return elements;
21908}
21909
21910jQuery.fn.extend( {
21911	show: function() {
21912		return showHide( this, true );
21913	},
21914	hide: function() {
21915		return showHide( this );
21916	},
21917	toggle: function( state ) {
21918		if ( typeof state === "boolean" ) {
21919			return state ? this.show() : this.hide();
21920		}
21921
21922		return this.each( function() {
21923			if ( isHiddenWithinTree( this ) ) {
21924				jQuery( this ).show();
21925			} else {
21926				jQuery( this ).hide();
21927			}
21928		} );
21929	}
21930} );
21931var rcheckableType = ( /^(?:checkbox|radio)$/i );
21932
21933var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i );
21934
21935var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i );
21936
21937
21938
21939( function() {
21940	var fragment = document.createDocumentFragment(),
21941		div = fragment.appendChild( document.createElement( "div" ) ),
21942		input = document.createElement( "input" );
21943
21944	// Support: Android 4.0 - 4.3 only
21945	// Check state lost if the name is set (#11217)
21946	// Support: Windows Web Apps (WWA)
21947	// `name` and `type` must use .setAttribute for WWA (#14901)
21948	input.setAttribute( "type", "radio" );
21949	input.setAttribute( "checked", "checked" );
21950	input.setAttribute( "name", "t" );
21951
21952	div.appendChild( input );
21953
21954	// Support: Android <=4.1 only
21955	// Older WebKit doesn't clone checked state correctly in fragments
21956	support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
21957
21958	// Support: IE <=11 only
21959	// Make sure textarea (and checkbox) defaultValue is properly cloned
21960	div.innerHTML = "<textarea>x</textarea>";
21961	support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
21962
21963	// Support: IE <=9 only
21964	// IE <=9 replaces <option> tags with their contents when inserted outside of
21965	// the select element.
21966	div.innerHTML = "<option></option>";
21967	support.option = !!div.lastChild;
21968} )();
21969
21970
21971// We have to close these tags to support XHTML (#13200)
21972var wrapMap = {
21973
21974	// XHTML parsers do not magically insert elements in the
21975	// same way that tag soup parsers do. So we cannot shorten
21976	// this by omitting <tbody> or other required elements.
21977	thead: [ 1, "<table>", "</table>" ],
21978	col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
21979	tr: [ 2, "<table><tbody>", "</tbody></table>" ],
21980	td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
21981
21982	_default: [ 0, "", "" ]
21983};
21984
21985wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
21986wrapMap.th = wrapMap.td;
21987
21988// Support: IE <=9 only
21989if ( !support.option ) {
21990	wrapMap.optgroup = wrapMap.option = [ 1, "<select multiple='multiple'>", "</select>" ];
21991}
21992
21993
21994function getAll( context, tag ) {
21995
21996	// Support: IE <=9 - 11 only
21997	// Use typeof to avoid zero-argument method invocation on host objects (#15151)
21998	var ret;
21999
22000	if ( typeof context.getElementsByTagName !== "undefined" ) {
22001		ret = context.getElementsByTagName( tag || "*" );
22002
22003	} else if ( typeof context.querySelectorAll !== "undefined" ) {
22004		ret = context.querySelectorAll( tag || "*" );
22005
22006	} else {
22007		ret = [];
22008	}
22009
22010	if ( tag === undefined || tag && nodeName( context, tag ) ) {
22011		return jQuery.merge( [ context ], ret );
22012	}
22013
22014	return ret;
22015}
22016
22017
22018// Mark scripts as having already been evaluated
22019function setGlobalEval( elems, refElements ) {
22020	var i = 0,
22021		l = elems.length;
22022
22023	for ( ; i < l; i++ ) {
22024		dataPriv.set(
22025			elems[ i ],
22026			"globalEval",
22027			!refElements || dataPriv.get( refElements[ i ], "globalEval" )
22028		);
22029	}
22030}
22031
22032
22033var rhtml = /<|&#?\w+;/;
22034
22035function buildFragment( elems, context, scripts, selection, ignored ) {
22036	var elem, tmp, tag, wrap, attached, j,
22037		fragment = context.createDocumentFragment(),
22038		nodes = [],
22039		i = 0,
22040		l = elems.length;
22041
22042	for ( ; i < l; i++ ) {
22043		elem = elems[ i ];
22044
22045		if ( elem || elem === 0 ) {
22046
22047			// Add nodes directly
22048			if ( toType( elem ) === "object" ) {
22049
22050				// Support: Android <=4.0 only, PhantomJS 1 only
22051				// push.apply(_, arraylike) throws on ancient WebKit
22052				jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
22053
22054			// Convert non-html into a text node
22055			} else if ( !rhtml.test( elem ) ) {
22056				nodes.push( context.createTextNode( elem ) );
22057
22058			// Convert html into DOM nodes
22059			} else {
22060				tmp = tmp || fragment.appendChild( context.createElement( "div" ) );
22061
22062				// Deserialize a standard representation
22063				tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
22064				wrap = wrapMap[ tag ] || wrapMap._default;
22065				tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];
22066
22067				// Descend through wrappers to the right content
22068				j = wrap[ 0 ];
22069				while ( j-- ) {
22070					tmp = tmp.lastChild;
22071				}
22072
22073				// Support: Android <=4.0 only, PhantomJS 1 only
22074				// push.apply(_, arraylike) throws on ancient WebKit
22075				jQuery.merge( nodes, tmp.childNodes );
22076
22077				// Remember the top-level container
22078				tmp = fragment.firstChild;
22079
22080				// Ensure the created nodes are orphaned (#12392)
22081				tmp.textContent = "";
22082			}
22083		}
22084	}
22085
22086	// Remove wrapper from fragment
22087	fragment.textContent = "";
22088
22089	i = 0;
22090	while ( ( elem = nodes[ i++ ] ) ) {
22091
22092		// Skip elements already in the context collection (trac-4087)
22093		if ( selection && jQuery.inArray( elem, selection ) > -1 ) {
22094			if ( ignored ) {
22095				ignored.push( elem );
22096			}
22097			continue;
22098		}
22099
22100		attached = isAttached( elem );
22101
22102		// Append to fragment
22103		tmp = getAll( fragment.appendChild( elem ), "script" );
22104
22105		// Preserve script evaluation history
22106		if ( attached ) {
22107			setGlobalEval( tmp );
22108		}
22109
22110		// Capture executables
22111		if ( scripts ) {
22112			j = 0;
22113			while ( ( elem = tmp[ j++ ] ) ) {
22114				if ( rscriptType.test( elem.type || "" ) ) {
22115					scripts.push( elem );
22116				}
22117			}
22118		}
22119	}
22120
22121	return fragment;
22122}
22123
22124
22125var rtypenamespace = /^([^.]*)(?:\.(.+)|)/;
22126
22127function returnTrue() {
22128	return true;
22129}
22130
22131function returnFalse() {
22132	return false;
22133}
22134
22135// Support: IE <=9 - 11+
22136// focus() and blur() are asynchronous, except when they are no-op.
22137// So expect focus to be synchronous when the element is already active,
22138// and blur to be synchronous when the element is not already active.
22139// (focus and blur are always synchronous in other supported browsers,
22140// this just defines when we can count on it).
22141function expectSync( elem, type ) {
22142	return ( elem === safeActiveElement() ) === ( type === "focus" );
22143}
22144
22145// Support: IE <=9 only
22146// Accessing document.activeElement can throw unexpectedly
22147// https://bugs.jquery.com/ticket/13393
22148function safeActiveElement() {
22149	try {
22150		return document.activeElement;
22151	} catch ( err ) { }
22152}
22153
22154function on( elem, types, selector, data, fn, one ) {
22155	var origFn, type;
22156
22157	// Types can be a map of types/handlers
22158	if ( typeof types === "object" ) {
22159
22160		// ( types-Object, selector, data )
22161		if ( typeof selector !== "string" ) {
22162
22163			// ( types-Object, data )
22164			data = data || selector;
22165			selector = undefined;
22166		}
22167		for ( type in types ) {
22168			on( elem, type, selector, data, types[ type ], one );
22169		}
22170		return elem;
22171	}
22172
22173	if ( data == null && fn == null ) {
22174
22175		// ( types, fn )
22176		fn = selector;
22177		data = selector = undefined;
22178	} else if ( fn == null ) {
22179		if ( typeof selector === "string" ) {
22180
22181			// ( types, selector, fn )
22182			fn = data;
22183			data = undefined;
22184		} else {
22185
22186			// ( types, data, fn )
22187			fn = data;
22188			data = selector;
22189			selector = undefined;
22190		}
22191	}
22192	if ( fn === false ) {
22193		fn = returnFalse;
22194	} else if ( !fn ) {
22195		return elem;
22196	}
22197
22198	if ( one === 1 ) {
22199		origFn = fn;
22200		fn = function( event ) {
22201
22202			// Can use an empty set, since event contains the info
22203			jQuery().off( event );
22204			return origFn.apply( this, arguments );
22205		};
22206
22207		// Use same guid so caller can remove using origFn
22208		fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
22209	}
22210	return elem.each( function() {
22211		jQuery.event.add( this, types, fn, data, selector );
22212	} );
22213}
22214
22215/*
22216 * Helper functions for managing events -- not part of the public interface.
22217 * Props to Dean Edwards' addEvent library for many of the ideas.
22218 */
22219jQuery.event = {
22220
22221	global: {},
22222
22223	add: function( elem, types, handler, data, selector ) {
22224
22225		var handleObjIn, eventHandle, tmp,
22226			events, t, handleObj,
22227			special, handlers, type, namespaces, origType,
22228			elemData = dataPriv.get( elem );
22229
22230		// Only attach events to objects that accept data
22231		if ( !acceptData( elem ) ) {
22232			return;
22233		}
22234
22235		// Caller can pass in an object of custom data in lieu of the handler
22236		if ( handler.handler ) {
22237			handleObjIn = handler;
22238			handler = handleObjIn.handler;
22239			selector = handleObjIn.selector;
22240		}
22241
22242		// Ensure that invalid selectors throw exceptions at attach time
22243		// Evaluate against documentElement in case elem is a non-element node (e.g., document)
22244		if ( selector ) {
22245			jQuery.find.matchesSelector( documentElement, selector );
22246		}
22247
22248		// Make sure that the handler has a unique ID, used to find/remove it later
22249		if ( !handler.guid ) {
22250			handler.guid = jQuery.guid++;
22251		}
22252
22253		// Init the element's event structure and main handler, if this is the first
22254		if ( !( events = elemData.events ) ) {
22255			events = elemData.events = Object.create( null );
22256		}
22257		if ( !( eventHandle = elemData.handle ) ) {
22258			eventHandle = elemData.handle = function( e ) {
22259
22260				// Discard the second event of a jQuery.event.trigger() and
22261				// when an event is called after a page has unloaded
22262				return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ?
22263					jQuery.event.dispatch.apply( elem, arguments ) : undefined;
22264			};
22265		}
22266
22267		// Handle multiple events separated by a space
22268		types = ( types || "" ).match( rnothtmlwhite ) || [ "" ];
22269		t = types.length;
22270		while ( t-- ) {
22271			tmp = rtypenamespace.exec( types[ t ] ) || [];
22272			type = origType = tmp[ 1 ];
22273			namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
22274
22275			// There *must* be a type, no attaching namespace-only handlers
22276			if ( !type ) {
22277				continue;
22278			}
22279
22280			// If event changes its type, use the special event handlers for the changed type
22281			special = jQuery.event.special[ type ] || {};
22282
22283			// If selector defined, determine special event api type, otherwise given type
22284			type = ( selector ? special.delegateType : special.bindType ) || type;
22285
22286			// Update special based on newly reset type
22287			special = jQuery.event.special[ type ] || {};
22288
22289			// handleObj is passed to all event handlers
22290			handleObj = jQuery.extend( {
22291				type: type,
22292				origType: origType,
22293				data: data,
22294				handler: handler,
22295				guid: handler.guid,
22296				selector: selector,
22297				needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
22298				namespace: namespaces.join( "." )
22299			}, handleObjIn );
22300
22301			// Init the event handler queue if we're the first
22302			if ( !( handlers = events[ type ] ) ) {
22303				handlers = events[ type ] = [];
22304				handlers.delegateCount = 0;
22305
22306				// Only use addEventListener if the special events handler returns false
22307				if ( !special.setup ||
22308					special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
22309
22310					if ( elem.addEventListener ) {
22311						elem.addEventListener( type, eventHandle );
22312					}
22313				}
22314			}
22315
22316			if ( special.add ) {
22317				special.add.call( elem, handleObj );
22318
22319				if ( !handleObj.handler.guid ) {
22320					handleObj.handler.guid = handler.guid;
22321				}
22322			}
22323
22324			// Add to the element's handler list, delegates in front
22325			if ( selector ) {
22326				handlers.splice( handlers.delegateCount++, 0, handleObj );
22327			} else {
22328				handlers.push( handleObj );
22329			}
22330
22331			// Keep track of which events have ever been used, for event optimization
22332			jQuery.event.global[ type ] = true;
22333		}
22334
22335	},
22336
22337	// Detach an event or set of events from an element
22338	remove: function( elem, types, handler, selector, mappedTypes ) {
22339
22340		var j, origCount, tmp,
22341			events, t, handleObj,
22342			special, handlers, type, namespaces, origType,
22343			elemData = dataPriv.hasData( elem ) && dataPriv.get( elem );
22344
22345		if ( !elemData || !( events = elemData.events ) ) {
22346			return;
22347		}
22348
22349		// Once for each type.namespace in types; type may be omitted
22350		types = ( types || "" ).match( rnothtmlwhite ) || [ "" ];
22351		t = types.length;
22352		while ( t-- ) {
22353			tmp = rtypenamespace.exec( types[ t ] ) || [];
22354			type = origType = tmp[ 1 ];
22355			namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
22356
22357			// Unbind all events (on this namespace, if provided) for the element
22358			if ( !type ) {
22359				for ( type in events ) {
22360					jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
22361				}
22362				continue;
22363			}
22364
22365			special = jQuery.event.special[ type ] || {};
22366			type = ( selector ? special.delegateType : special.bindType ) || type;
22367			handlers = events[ type ] || [];
22368			tmp = tmp[ 2 ] &&
22369				new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" );
22370
22371			// Remove matching events
22372			origCount = j = handlers.length;
22373			while ( j-- ) {
22374				handleObj = handlers[ j ];
22375
22376				if ( ( mappedTypes || origType === handleObj.origType ) &&
22377					( !handler || handler.guid === handleObj.guid ) &&
22378					( !tmp || tmp.test( handleObj.namespace ) ) &&
22379					( !selector || selector === handleObj.selector ||
22380						selector === "**" && handleObj.selector ) ) {
22381					handlers.splice( j, 1 );
22382
22383					if ( handleObj.selector ) {
22384						handlers.delegateCount--;
22385					}
22386					if ( special.remove ) {
22387						special.remove.call( elem, handleObj );
22388					}
22389				}
22390			}
22391
22392			// Remove generic event handler if we removed something and no more handlers exist
22393			// (avoids potential for endless recursion during removal of special event handlers)
22394			if ( origCount && !handlers.length ) {
22395				if ( !special.teardown ||
22396					special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
22397
22398					jQuery.removeEvent( elem, type, elemData.handle );
22399				}
22400
22401				delete events[ type ];
22402			}
22403		}
22404
22405		// Remove data and the expando if it's no longer used
22406		if ( jQuery.isEmptyObject( events ) ) {
22407			dataPriv.remove( elem, "handle events" );
22408		}
22409	},
22410
22411	dispatch: function( nativeEvent ) {
22412
22413		var i, j, ret, matched, handleObj, handlerQueue,
22414			args = new Array( arguments.length ),
22415
22416			// Make a writable jQuery.Event from the native event object
22417			event = jQuery.event.fix( nativeEvent ),
22418
22419			handlers = (
22420				dataPriv.get( this, "events" ) || Object.create( null )
22421			)[ event.type ] || [],
22422			special = jQuery.event.special[ event.type ] || {};
22423
22424		// Use the fix-ed jQuery.Event rather than the (read-only) native event
22425		args[ 0 ] = event;
22426
22427		for ( i = 1; i < arguments.length; i++ ) {
22428			args[ i ] = arguments[ i ];
22429		}
22430
22431		event.delegateTarget = this;
22432
22433		// Call the preDispatch hook for the mapped type, and let it bail if desired
22434		if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
22435			return;
22436		}
22437
22438		// Determine handlers
22439		handlerQueue = jQuery.event.handlers.call( this, event, handlers );
22440
22441		// Run delegates first; they may want to stop propagation beneath us
22442		i = 0;
22443		while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {
22444			event.currentTarget = matched.elem;
22445
22446			j = 0;
22447			while ( ( handleObj = matched.handlers[ j++ ] ) &&
22448				!event.isImmediatePropagationStopped() ) {
22449
22450				// If the event is namespaced, then each handler is only invoked if it is
22451				// specially universal or its namespaces are a superset of the event's.
22452				if ( !event.rnamespace || handleObj.namespace === false ||
22453					event.rnamespace.test( handleObj.namespace ) ) {
22454
22455					event.handleObj = handleObj;
22456					event.data = handleObj.data;
22457
22458					ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||
22459						handleObj.handler ).apply( matched.elem, args );
22460
22461					if ( ret !== undefined ) {
22462						if ( ( event.result = ret ) === false ) {
22463							event.preventDefault();
22464							event.stopPropagation();
22465						}
22466					}
22467				}
22468			}
22469		}
22470
22471		// Call the postDispatch hook for the mapped type
22472		if ( special.postDispatch ) {
22473			special.postDispatch.call( this, event );
22474		}
22475
22476		return event.result;
22477	},
22478
22479	handlers: function( event, handlers ) {
22480		var i, handleObj, sel, matchedHandlers, matchedSelectors,
22481			handlerQueue = [],
22482			delegateCount = handlers.delegateCount,
22483			cur = event.target;
22484
22485		// Find delegate handlers
22486		if ( delegateCount &&
22487
22488			// Support: IE <=9
22489			// Black-hole SVG <use> instance trees (trac-13180)
22490			cur.nodeType &&
22491
22492			// Support: Firefox <=42
22493			// Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861)
22494			// https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click
22495			// Support: IE 11 only
22496			// ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343)
22497			!( event.type === "click" && event.button >= 1 ) ) {
22498
22499			for ( ; cur !== this; cur = cur.parentNode || this ) {
22500
22501				// Don't check non-elements (#13208)
22502				// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
22503				if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) {
22504					matchedHandlers = [];
22505					matchedSelectors = {};
22506					for ( i = 0; i < delegateCount; i++ ) {
22507						handleObj = handlers[ i ];
22508
22509						// Don't conflict with Object.prototype properties (#13203)
22510						sel = handleObj.selector + " ";
22511
22512						if ( matchedSelectors[ sel ] === undefined ) {
22513							matchedSelectors[ sel ] = handleObj.needsContext ?
22514								jQuery( sel, this ).index( cur ) > -1 :
22515								jQuery.find( sel, this, null, [ cur ] ).length;
22516						}
22517						if ( matchedSelectors[ sel ] ) {
22518							matchedHandlers.push( handleObj );
22519						}
22520					}
22521					if ( matchedHandlers.length ) {
22522						handlerQueue.push( { elem: cur, handlers: matchedHandlers } );
22523					}
22524				}
22525			}
22526		}
22527
22528		// Add the remaining (directly-bound) handlers
22529		cur = this;
22530		if ( delegateCount < handlers.length ) {
22531			handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } );
22532		}
22533
22534		return handlerQueue;
22535	},
22536
22537	addProp: function( name, hook ) {
22538		Object.defineProperty( jQuery.Event.prototype, name, {
22539			enumerable: true,
22540			configurable: true,
22541
22542			get: isFunction( hook ) ?
22543				function() {
22544					if ( this.originalEvent ) {
22545						return hook( this.originalEvent );
22546					}
22547				} :
22548				function() {
22549					if ( this.originalEvent ) {
22550						return this.originalEvent[ name ];
22551					}
22552				},
22553
22554			set: function( value ) {
22555				Object.defineProperty( this, name, {
22556					enumerable: true,
22557					configurable: true,
22558					writable: true,
22559					value: value
22560				} );
22561			}
22562		} );
22563	},
22564
22565	fix: function( originalEvent ) {
22566		return originalEvent[ jQuery.expando ] ?
22567			originalEvent :
22568			new jQuery.Event( originalEvent );
22569	},
22570
22571	special: {
22572		load: {
22573
22574			// Prevent triggered image.load events from bubbling to window.load
22575			noBubble: true
22576		},
22577		click: {
22578
22579			// Utilize native event to ensure correct state for checkable inputs
22580			setup: function( data ) {
22581
22582				// For mutual compressibility with _default, replace `this` access with a local var.
22583				// `|| data` is dead code meant only to preserve the variable through minification.
22584				var el = this || data;
22585
22586				// Claim the first handler
22587				if ( rcheckableType.test( el.type ) &&
22588					el.click && nodeName( el, "input" ) ) {
22589
22590					// dataPriv.set( el, "click", ... )
22591					leverageNative( el, "click", returnTrue );
22592				}
22593
22594				// Return false to allow normal processing in the caller
22595				return false;
22596			},
22597			trigger: function( data ) {
22598
22599				// For mutual compressibility with _default, replace `this` access with a local var.
22600				// `|| data` is dead code meant only to preserve the variable through minification.
22601				var el = this || data;
22602
22603				// Force setup before triggering a click
22604				if ( rcheckableType.test( el.type ) &&
22605					el.click && nodeName( el, "input" ) ) {
22606
22607					leverageNative( el, "click" );
22608				}
22609
22610				// Return non-false to allow normal event-path propagation
22611				return true;
22612			},
22613
22614			// For cross-browser consistency, suppress native .click() on links
22615			// Also prevent it if we're currently inside a leveraged native-event stack
22616			_default: function( event ) {
22617				var target = event.target;
22618				return rcheckableType.test( target.type ) &&
22619					target.click && nodeName( target, "input" ) &&
22620					dataPriv.get( target, "click" ) ||
22621					nodeName( target, "a" );
22622			}
22623		},
22624
22625		beforeunload: {
22626			postDispatch: function( event ) {
22627
22628				// Support: Firefox 20+
22629				// Firefox doesn't alert if the returnValue field is not set.
22630				if ( event.result !== undefined && event.originalEvent ) {
22631					event.originalEvent.returnValue = event.result;
22632				}
22633			}
22634		}
22635	}
22636};
22637
22638// Ensure the presence of an event listener that handles manually-triggered
22639// synthetic events by interrupting progress until reinvoked in response to
22640// *native* events that it fires directly, ensuring that state changes have
22641// already occurred before other listeners are invoked.
22642function leverageNative( el, type, expectSync ) {
22643
22644	// Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add
22645	if ( !expectSync ) {
22646		if ( dataPriv.get( el, type ) === undefined ) {
22647			jQuery.event.add( el, type, returnTrue );
22648		}
22649		return;
22650	}
22651
22652	// Register the controller as a special universal handler for all event namespaces
22653	dataPriv.set( el, type, false );
22654	jQuery.event.add( el, type, {
22655		namespace: false,
22656		handler: function( event ) {
22657			var notAsync, result,
22658				saved = dataPriv.get( this, type );
22659
22660			if ( ( event.isTrigger & 1 ) && this[ type ] ) {
22661
22662				// Interrupt processing of the outer synthetic .trigger()ed event
22663				// Saved data should be false in such cases, but might be a leftover capture object
22664				// from an async native handler (gh-4350)
22665				if ( !saved.length ) {
22666
22667					// Store arguments for use when handling the inner native event
22668					// There will always be at least one argument (an event object), so this array
22669					// will not be confused with a leftover capture object.
22670					saved = slice.call( arguments );
22671					dataPriv.set( this, type, saved );
22672
22673					// Trigger the native event and capture its result
22674					// Support: IE <=9 - 11+
22675					// focus() and blur() are asynchronous
22676					notAsync = expectSync( this, type );
22677					this[ type ]();
22678					result = dataPriv.get( this, type );
22679					if ( saved !== result || notAsync ) {
22680						dataPriv.set( this, type, false );
22681					} else {
22682						result = {};
22683					}
22684					if ( saved !== result ) {
22685
22686						// Cancel the outer synthetic event
22687						event.stopImmediatePropagation();
22688						event.preventDefault();
22689
22690						// Support: Chrome 86+
22691						// In Chrome, if an element having a focusout handler is blurred by
22692						// clicking outside of it, it invokes the handler synchronously. If
22693						// that handler calls `.remove()` on the element, the data is cleared,
22694						// leaving `result` undefined. We need to guard against this.
22695						return result && result.value;
22696					}
22697
22698				// If this is an inner synthetic event for an event with a bubbling surrogate
22699				// (focus or blur), assume that the surrogate already propagated from triggering the
22700				// native event and prevent that from happening again here.
22701				// This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the
22702				// bubbling surrogate propagates *after* the non-bubbling base), but that seems
22703				// less bad than duplication.
22704				} else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) {
22705					event.stopPropagation();
22706				}
22707
22708			// If this is a native event triggered above, everything is now in order
22709			// Fire an inner synthetic event with the original arguments
22710			} else if ( saved.length ) {
22711
22712				// ...and capture the result
22713				dataPriv.set( this, type, {
22714					value: jQuery.event.trigger(
22715
22716						// Support: IE <=9 - 11+
22717						// Extend with the prototype to reset the above stopImmediatePropagation()
22718						jQuery.extend( saved[ 0 ], jQuery.Event.prototype ),
22719						saved.slice( 1 ),
22720						this
22721					)
22722				} );
22723
22724				// Abort handling of the native event
22725				event.stopImmediatePropagation();
22726			}
22727		}
22728	} );
22729}
22730
22731jQuery.removeEvent = function( elem, type, handle ) {
22732
22733	// This "if" is needed for plain objects
22734	if ( elem.removeEventListener ) {
22735		elem.removeEventListener( type, handle );
22736	}
22737};
22738
22739jQuery.Event = function( src, props ) {
22740
22741	// Allow instantiation without the 'new' keyword
22742	if ( !( this instanceof jQuery.Event ) ) {
22743		return new jQuery.Event( src, props );
22744	}
22745
22746	// Event object
22747	if ( src && src.type ) {
22748		this.originalEvent = src;
22749		this.type = src.type;
22750
22751		// Events bubbling up the document may have been marked as prevented
22752		// by a handler lower down the tree; reflect the correct value.
22753		this.isDefaultPrevented = src.defaultPrevented ||
22754				src.defaultPrevented === undefined &&
22755
22756				// Support: Android <=2.3 only
22757				src.returnValue === false ?
22758			returnTrue :
22759			returnFalse;
22760
22761		// Create target properties
22762		// Support: Safari <=6 - 7 only
22763		// Target should not be a text node (#504, #13143)
22764		this.target = ( src.target && src.target.nodeType === 3 ) ?
22765			src.target.parentNode :
22766			src.target;
22767
22768		this.currentTarget = src.currentTarget;
22769		this.relatedTarget = src.relatedTarget;
22770
22771	// Event type
22772	} else {
22773		this.type = src;
22774	}
22775
22776	// Put explicitly provided properties onto the event object
22777	if ( props ) {
22778		jQuery.extend( this, props );
22779	}
22780
22781	// Create a timestamp if incoming event doesn't have one
22782	this.timeStamp = src && src.timeStamp || Date.now();
22783
22784	// Mark it as fixed
22785	this[ jQuery.expando ] = true;
22786};
22787
22788// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
22789// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
22790jQuery.Event.prototype = {
22791	constructor: jQuery.Event,
22792	isDefaultPrevented: returnFalse,
22793	isPropagationStopped: returnFalse,
22794	isImmediatePropagationStopped: returnFalse,
22795	isSimulated: false,
22796
22797	preventDefault: function() {
22798		var e = this.originalEvent;
22799
22800		this.isDefaultPrevented = returnTrue;
22801
22802		if ( e && !this.isSimulated ) {
22803			e.preventDefault();
22804		}
22805	},
22806	stopPropagation: function() {
22807		var e = this.originalEvent;
22808
22809		this.isPropagationStopped = returnTrue;
22810
22811		if ( e && !this.isSimulated ) {
22812			e.stopPropagation();
22813		}
22814	},
22815	stopImmediatePropagation: function() {
22816		var e = this.originalEvent;
22817
22818		this.isImmediatePropagationStopped = returnTrue;
22819
22820		if ( e && !this.isSimulated ) {
22821			e.stopImmediatePropagation();
22822		}
22823
22824		this.stopPropagation();
22825	}
22826};
22827
22828// Includes all common event props including KeyEvent and MouseEvent specific props
22829jQuery.each( {
22830	altKey: true,
22831	bubbles: true,
22832	cancelable: true,
22833	changedTouches: true,
22834	ctrlKey: true,
22835	detail: true,
22836	eventPhase: true,
22837	metaKey: true,
22838	pageX: true,
22839	pageY: true,
22840	shiftKey: true,
22841	view: true,
22842	"char": true,
22843	code: true,
22844	charCode: true,
22845	key: true,
22846	keyCode: true,
22847	button: true,
22848	buttons: true,
22849	clientX: true,
22850	clientY: true,
22851	offsetX: true,
22852	offsetY: true,
22853	pointerId: true,
22854	pointerType: true,
22855	screenX: true,
22856	screenY: true,
22857	targetTouches: true,
22858	toElement: true,
22859	touches: true,
22860	which: true
22861}, jQuery.event.addProp );
22862
22863jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) {
22864	jQuery.event.special[ type ] = {
22865
22866		// Utilize native event if possible so blur/focus sequence is correct
22867		setup: function() {
22868
22869			// Claim the first handler
22870			// dataPriv.set( this, "focus", ... )
22871			// dataPriv.set( this, "blur", ... )
22872			leverageNative( this, type, expectSync );
22873
22874			// Return false to allow normal processing in the caller
22875			return false;
22876		},
22877		trigger: function() {
22878
22879			// Force setup before trigger
22880			leverageNative( this, type );
22881
22882			// Return non-false to allow normal event-path propagation
22883			return true;
22884		},
22885
22886		// Suppress native focus or blur as it's already being fired
22887		// in leverageNative.
22888		_default: function() {
22889			return true;
22890		},
22891
22892		delegateType: delegateType
22893	};
22894} );
22895
22896// Create mouseenter/leave events using mouseover/out and event-time checks
22897// so that event delegation works in jQuery.
22898// Do the same for pointerenter/pointerleave and pointerover/pointerout
22899//
22900// Support: Safari 7 only
22901// Safari sends mouseenter too often; see:
22902// https://bugs.chromium.org/p/chromium/issues/detail?id=470258
22903// for the description of the bug (it existed in older Chrome versions as well).
22904jQuery.each( {
22905	mouseenter: "mouseover",
22906	mouseleave: "mouseout",
22907	pointerenter: "pointerover",
22908	pointerleave: "pointerout"
22909}, function( orig, fix ) {
22910	jQuery.event.special[ orig ] = {
22911		delegateType: fix,
22912		bindType: fix,
22913
22914		handle: function( event ) {
22915			var ret,
22916				target = this,
22917				related = event.relatedTarget,
22918				handleObj = event.handleObj;
22919
22920			// For mouseenter/leave call the handler if related is outside the target.
22921			// NB: No relatedTarget if the mouse left/entered the browser window
22922			if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) {
22923				event.type = handleObj.origType;
22924				ret = handleObj.handler.apply( this, arguments );
22925				event.type = fix;
22926			}
22927			return ret;
22928		}
22929	};
22930} );
22931
22932jQuery.fn.extend( {
22933
22934	on: function( types, selector, data, fn ) {
22935		return on( this, types, selector, data, fn );
22936	},
22937	one: function( types, selector, data, fn ) {
22938		return on( this, types, selector, data, fn, 1 );
22939	},
22940	off: function( types, selector, fn ) {
22941		var handleObj, type;
22942		if ( types && types.preventDefault && types.handleObj ) {
22943
22944			// ( event )  dispatched jQuery.Event
22945			handleObj = types.handleObj;
22946			jQuery( types.delegateTarget ).off(
22947				handleObj.namespace ?
22948					handleObj.origType + "." + handleObj.namespace :
22949					handleObj.origType,
22950				handleObj.selector,
22951				handleObj.handler
22952			);
22953			return this;
22954		}
22955		if ( typeof types === "object" ) {
22956
22957			// ( types-object [, selector] )
22958			for ( type in types ) {
22959				this.off( type, selector, types[ type ] );
22960			}
22961			return this;
22962		}
22963		if ( selector === false || typeof selector === "function" ) {
22964
22965			// ( types [, fn] )
22966			fn = selector;
22967			selector = undefined;
22968		}
22969		if ( fn === false ) {
22970			fn = returnFalse;
22971		}
22972		return this.each( function() {
22973			jQuery.event.remove( this, types, fn, selector );
22974		} );
22975	}
22976} );
22977
22978
22979var
22980
22981	// Support: IE <=10 - 11, Edge 12 - 13 only
22982	// In IE/Edge using regex groups here causes severe slowdowns.
22983	// See https://connect.microsoft.com/IE/feedback/details/1736512/
22984	rnoInnerhtml = /<script|<style|<link/i,
22985
22986	// checked="checked" or checked
22987	rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
22988	rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;
22989
22990// Prefer a tbody over its parent table for containing new rows
22991function manipulationTarget( elem, content ) {
22992	if ( nodeName( elem, "table" ) &&
22993		nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) {
22994
22995		return jQuery( elem ).children( "tbody" )[ 0 ] || elem;
22996	}
22997
22998	return elem;
22999}
23000
23001// Replace/restore the type attribute of script elements for safe DOM manipulation
23002function disableScript( elem ) {
23003	elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type;
23004	return elem;
23005}
23006function restoreScript( elem ) {
23007	if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) {
23008		elem.type = elem.type.slice( 5 );
23009	} else {
23010		elem.removeAttribute( "type" );
23011	}
23012
23013	return elem;
23014}
23015
23016function cloneCopyEvent( src, dest ) {
23017	var i, l, type, pdataOld, udataOld, udataCur, events;
23018
23019	if ( dest.nodeType !== 1 ) {
23020		return;
23021	}
23022
23023	// 1. Copy private data: events, handlers, etc.
23024	if ( dataPriv.hasData( src ) ) {
23025		pdataOld = dataPriv.get( src );
23026		events = pdataOld.events;
23027
23028		if ( events ) {
23029			dataPriv.remove( dest, "handle events" );
23030
23031			for ( type in events ) {
23032				for ( i = 0, l = events[ type ].length; i < l; i++ ) {
23033					jQuery.event.add( dest, type, events[ type ][ i ] );
23034				}
23035			}
23036		}
23037	}
23038
23039	// 2. Copy user data
23040	if ( dataUser.hasData( src ) ) {
23041		udataOld = dataUser.access( src );
23042		udataCur = jQuery.extend( {}, udataOld );
23043
23044		dataUser.set( dest, udataCur );
23045	}
23046}
23047
23048// Fix IE bugs, see support tests
23049function fixInput( src, dest ) {
23050	var nodeName = dest.nodeName.toLowerCase();
23051
23052	// Fails to persist the checked state of a cloned checkbox or radio button.
23053	if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
23054		dest.checked = src.checked;
23055
23056	// Fails to return the selected option to the default selected state when cloning options
23057	} else if ( nodeName === "input" || nodeName === "textarea" ) {
23058		dest.defaultValue = src.defaultValue;
23059	}
23060}
23061
23062function domManip( collection, args, callback, ignored ) {
23063
23064	// Flatten any nested arrays
23065	args = flat( args );
23066
23067	var fragment, first, scripts, hasScripts, node, doc,
23068		i = 0,
23069		l = collection.length,
23070		iNoClone = l - 1,
23071		value = args[ 0 ],
23072		valueIsFunction = isFunction( value );
23073
23074	// We can't cloneNode fragments that contain checked, in WebKit
23075	if ( valueIsFunction ||
23076			( l > 1 && typeof value === "string" &&
23077				!support.checkClone && rchecked.test( value ) ) ) {
23078		return collection.each( function( index ) {
23079			var self = collection.eq( index );
23080			if ( valueIsFunction ) {
23081				args[ 0 ] = value.call( this, index, self.html() );
23082			}
23083			domManip( self, args, callback, ignored );
23084		} );
23085	}
23086
23087	if ( l ) {
23088		fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored );
23089		first = fragment.firstChild;
23090
23091		if ( fragment.childNodes.length === 1 ) {
23092			fragment = first;
23093		}
23094
23095		// Require either new content or an interest in ignored elements to invoke the callback
23096		if ( first || ignored ) {
23097			scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
23098			hasScripts = scripts.length;
23099
23100			// Use the original fragment for the last item
23101			// instead of the first because it can end up
23102			// being emptied incorrectly in certain situations (#8070).
23103			for ( ; i < l; i++ ) {
23104				node = fragment;
23105
23106				if ( i !== iNoClone ) {
23107					node = jQuery.clone( node, true, true );
23108
23109					// Keep references to cloned scripts for later restoration
23110					if ( hasScripts ) {
23111
23112						// Support: Android <=4.0 only, PhantomJS 1 only
23113						// push.apply(_, arraylike) throws on ancient WebKit
23114						jQuery.merge( scripts, getAll( node, "script" ) );
23115					}
23116				}
23117
23118				callback.call( collection[ i ], node, i );
23119			}
23120
23121			if ( hasScripts ) {
23122				doc = scripts[ scripts.length - 1 ].ownerDocument;
23123
23124				// Reenable scripts
23125				jQuery.map( scripts, restoreScript );
23126
23127				// Evaluate executable scripts on first document insertion
23128				for ( i = 0; i < hasScripts; i++ ) {
23129					node = scripts[ i ];
23130					if ( rscriptType.test( node.type || "" ) &&
23131						!dataPriv.access( node, "globalEval" ) &&
23132						jQuery.contains( doc, node ) ) {
23133
23134						if ( node.src && ( node.type || "" ).toLowerCase()  !== "module" ) {
23135
23136							// Optional AJAX dependency, but won't run scripts if not present
23137							if ( jQuery._evalUrl && !node.noModule ) {
23138								jQuery._evalUrl( node.src, {
23139									nonce: node.nonce || node.getAttribute( "nonce" )
23140								}, doc );
23141							}
23142						} else {
23143							DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc );
23144						}
23145					}
23146				}
23147			}
23148		}
23149	}
23150
23151	return collection;
23152}
23153
23154function remove( elem, selector, keepData ) {
23155	var node,
23156		nodes = selector ? jQuery.filter( selector, elem ) : elem,
23157		i = 0;
23158
23159	for ( ; ( node = nodes[ i ] ) != null; i++ ) {
23160		if ( !keepData && node.nodeType === 1 ) {
23161			jQuery.cleanData( getAll( node ) );
23162		}
23163
23164		if ( node.parentNode ) {
23165			if ( keepData && isAttached( node ) ) {
23166				setGlobalEval( getAll( node, "script" ) );
23167			}
23168			node.parentNode.removeChild( node );
23169		}
23170	}
23171
23172	return elem;
23173}
23174
23175jQuery.extend( {
23176	htmlPrefilter: function( html ) {
23177		return html;
23178	},
23179
23180	clone: function( elem, dataAndEvents, deepDataAndEvents ) {
23181		var i, l, srcElements, destElements,
23182			clone = elem.cloneNode( true ),
23183			inPage = isAttached( elem );
23184
23185		// Fix IE cloning issues
23186		if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&
23187				!jQuery.isXMLDoc( elem ) ) {
23188
23189			// We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2
23190			destElements = getAll( clone );
23191			srcElements = getAll( elem );
23192
23193			for ( i = 0, l = srcElements.length; i < l; i++ ) {
23194				fixInput( srcElements[ i ], destElements[ i ] );
23195			}
23196		}
23197
23198		// Copy the events from the original to the clone
23199		if ( dataAndEvents ) {
23200			if ( deepDataAndEvents ) {
23201				srcElements = srcElements || getAll( elem );
23202				destElements = destElements || getAll( clone );
23203
23204				for ( i = 0, l = srcElements.length; i < l; i++ ) {
23205					cloneCopyEvent( srcElements[ i ], destElements[ i ] );
23206				}
23207			} else {
23208				cloneCopyEvent( elem, clone );
23209			}
23210		}
23211
23212		// Preserve script evaluation history
23213		destElements = getAll( clone, "script" );
23214		if ( destElements.length > 0 ) {
23215			setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
23216		}
23217
23218		// Return the cloned set
23219		return clone;
23220	},
23221
23222	cleanData: function( elems ) {
23223		var data, elem, type,
23224			special = jQuery.event.special,
23225			i = 0;
23226
23227		for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) {
23228			if ( acceptData( elem ) ) {
23229				if ( ( data = elem[ dataPriv.expando ] ) ) {
23230					if ( data.events ) {
23231						for ( type in data.events ) {
23232							if ( special[ type ] ) {
23233								jQuery.event.remove( elem, type );
23234
23235							// This is a shortcut to avoid jQuery.event.remove's overhead
23236							} else {
23237								jQuery.removeEvent( elem, type, data.handle );
23238							}
23239						}
23240					}
23241
23242					// Support: Chrome <=35 - 45+
23243					// Assign undefined instead of using delete, see Data#remove
23244					elem[ dataPriv.expando ] = undefined;
23245				}
23246				if ( elem[ dataUser.expando ] ) {
23247
23248					// Support: Chrome <=35 - 45+
23249					// Assign undefined instead of using delete, see Data#remove
23250					elem[ dataUser.expando ] = undefined;
23251				}
23252			}
23253		}
23254	}
23255} );
23256
23257jQuery.fn.extend( {
23258	detach: function( selector ) {
23259		return remove( this, selector, true );
23260	},
23261
23262	remove: function( selector ) {
23263		return remove( this, selector );
23264	},
23265
23266	text: function( value ) {
23267		return access( this, function( value ) {
23268			return value === undefined ?
23269				jQuery.text( this ) :
23270				this.empty().each( function() {
23271					if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
23272						this.textContent = value;
23273					}
23274				} );
23275		}, null, value, arguments.length );
23276	},
23277
23278	append: function() {
23279		return domManip( this, arguments, function( elem ) {
23280			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
23281				var target = manipulationTarget( this, elem );
23282				target.appendChild( elem );
23283			}
23284		} );
23285	},
23286
23287	prepend: function() {
23288		return domManip( this, arguments, function( elem ) {
23289			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
23290				var target = manipulationTarget( this, elem );
23291				target.insertBefore( elem, target.firstChild );
23292			}
23293		} );
23294	},
23295
23296	before: function() {
23297		return domManip( this, arguments, function( elem ) {
23298			if ( this.parentNode ) {
23299				this.parentNode.insertBefore( elem, this );
23300			}
23301		} );
23302	},
23303
23304	after: function() {
23305		return domManip( this, arguments, function( elem ) {
23306			if ( this.parentNode ) {
23307				this.parentNode.insertBefore( elem, this.nextSibling );
23308			}
23309		} );
23310	},
23311
23312	empty: function() {
23313		var elem,
23314			i = 0;
23315
23316		for ( ; ( elem = this[ i ] ) != null; i++ ) {
23317			if ( elem.nodeType === 1 ) {
23318
23319				// Prevent memory leaks
23320				jQuery.cleanData( getAll( elem, false ) );
23321
23322				// Remove any remaining nodes
23323				elem.textContent = "";
23324			}
23325		}
23326
23327		return this;
23328	},
23329
23330	clone: function( dataAndEvents, deepDataAndEvents ) {
23331		dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
23332		deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
23333
23334		return this.map( function() {
23335			return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
23336		} );
23337	},
23338
23339	html: function( value ) {
23340		return access( this, function( value ) {
23341			var elem = this[ 0 ] || {},
23342				i = 0,
23343				l = this.length;
23344
23345			if ( value === undefined && elem.nodeType === 1 ) {
23346				return elem.innerHTML;
23347			}
23348
23349			// See if we can take a shortcut and just use innerHTML
23350			if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
23351				!wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {
23352
23353				value = jQuery.htmlPrefilter( value );
23354
23355				try {
23356					for ( ; i < l; i++ ) {
23357						elem = this[ i ] || {};
23358
23359						// Remove element nodes and prevent memory leaks
23360						if ( elem.nodeType === 1 ) {
23361							jQuery.cleanData( getAll( elem, false ) );
23362							elem.innerHTML = value;
23363						}
23364					}
23365
23366					elem = 0;
23367
23368				// If using innerHTML throws an exception, use the fallback method
23369				} catch ( e ) {}
23370			}
23371
23372			if ( elem ) {
23373				this.empty().append( value );
23374			}
23375		}, null, value, arguments.length );
23376	},
23377
23378	replaceWith: function() {
23379		var ignored = [];
23380
23381		// Make the changes, replacing each non-ignored context element with the new content
23382		return domManip( this, arguments, function( elem ) {
23383			var parent = this.parentNode;
23384
23385			if ( jQuery.inArray( this, ignored ) < 0 ) {
23386				jQuery.cleanData( getAll( this ) );
23387				if ( parent ) {
23388					parent.replaceChild( elem, this );
23389				}
23390			}
23391
23392		// Force callback invocation
23393		}, ignored );
23394	}
23395} );
23396
23397jQuery.each( {
23398	appendTo: "append",
23399	prependTo: "prepend",
23400	insertBefore: "before",
23401	insertAfter: "after",
23402	replaceAll: "replaceWith"
23403}, function( name, original ) {
23404	jQuery.fn[ name ] = function( selector ) {
23405		var elems,
23406			ret = [],
23407			insert = jQuery( selector ),
23408			last = insert.length - 1,
23409			i = 0;
23410
23411		for ( ; i <= last; i++ ) {
23412			elems = i === last ? this : this.clone( true );
23413			jQuery( insert[ i ] )[ original ]( elems );
23414
23415			// Support: Android <=4.0 only, PhantomJS 1 only
23416			// .get() because push.apply(_, arraylike) throws on ancient WebKit
23417			push.apply( ret, elems.get() );
23418		}
23419
23420		return this.pushStack( ret );
23421	};
23422} );
23423var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
23424
23425var getStyles = function( elem ) {
23426
23427		// Support: IE <=11 only, Firefox <=30 (#15098, #14150)
23428		// IE throws on elements created in popups
23429		// FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
23430		var view = elem.ownerDocument.defaultView;
23431
23432		if ( !view || !view.opener ) {
23433			view = window;
23434		}
23435
23436		return view.getComputedStyle( elem );
23437	};
23438
23439var swap = function( elem, options, callback ) {
23440	var ret, name,
23441		old = {};
23442
23443	// Remember the old values, and insert the new ones
23444	for ( name in options ) {
23445		old[ name ] = elem.style[ name ];
23446		elem.style[ name ] = options[ name ];
23447	}
23448
23449	ret = callback.call( elem );
23450
23451	// Revert the old values
23452	for ( name in options ) {
23453		elem.style[ name ] = old[ name ];
23454	}
23455
23456	return ret;
23457};
23458
23459
23460var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" );
23461
23462
23463
23464( function() {
23465
23466	// Executing both pixelPosition & boxSizingReliable tests require only one layout
23467	// so they're executed at the same time to save the second computation.
23468	function computeStyleTests() {
23469
23470		// This is a singleton, we need to execute it only once
23471		if ( !div ) {
23472			return;
23473		}
23474
23475		container.style.cssText = "position:absolute;left:-11111px;width:60px;" +
23476			"margin-top:1px;padding:0;border:0";
23477		div.style.cssText =
23478			"position:relative;display:block;box-sizing:border-box;overflow:scroll;" +
23479			"margin:auto;border:1px;padding:1px;" +
23480			"width:60%;top:1%";
23481		documentElement.appendChild( container ).appendChild( div );
23482
23483		var divStyle = window.getComputedStyle( div );
23484		pixelPositionVal = divStyle.top !== "1%";
23485
23486		// Support: Android 4.0 - 4.3 only, Firefox <=3 - 44
23487		reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12;
23488
23489		// Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3
23490		// Some styles come back with percentage values, even though they shouldn't
23491		div.style.right = "60%";
23492		pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36;
23493
23494		// Support: IE 9 - 11 only
23495		// Detect misreporting of content dimensions for box-sizing:border-box elements
23496		boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36;
23497
23498		// Support: IE 9 only
23499		// Detect overflow:scroll screwiness (gh-3699)
23500		// Support: Chrome <=64
23501		// Don't get tricked when zoom affects offsetWidth (gh-4029)
23502		div.style.position = "absolute";
23503		scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12;
23504
23505		documentElement.removeChild( container );
23506
23507		// Nullify the div so it wouldn't be stored in the memory and
23508		// it will also be a sign that checks already performed
23509		div = null;
23510	}
23511
23512	function roundPixelMeasures( measure ) {
23513		return Math.round( parseFloat( measure ) );
23514	}
23515
23516	var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal,
23517		reliableTrDimensionsVal, reliableMarginLeftVal,
23518		container = document.createElement( "div" ),
23519		div = document.createElement( "div" );
23520
23521	// Finish early in limited (non-browser) environments
23522	if ( !div.style ) {
23523		return;
23524	}
23525
23526	// Support: IE <=9 - 11 only
23527	// Style of cloned element affects source element cloned (#8908)
23528	div.style.backgroundClip = "content-box";
23529	div.cloneNode( true ).style.backgroundClip = "";
23530	support.clearCloneStyle = div.style.backgroundClip === "content-box";
23531
23532	jQuery.extend( support, {
23533		boxSizingReliable: function() {
23534			computeStyleTests();
23535			return boxSizingReliableVal;
23536		},
23537		pixelBoxStyles: function() {
23538			computeStyleTests();
23539			return pixelBoxStylesVal;
23540		},
23541		pixelPosition: function() {
23542			computeStyleTests();
23543			return pixelPositionVal;
23544		},
23545		reliableMarginLeft: function() {
23546			computeStyleTests();
23547			return reliableMarginLeftVal;
23548		},
23549		scrollboxSize: function() {
23550			computeStyleTests();
23551			return scrollboxSizeVal;
23552		},
23553
23554		// Support: IE 9 - 11+, Edge 15 - 18+
23555		// IE/Edge misreport `getComputedStyle` of table rows with width/height
23556		// set in CSS while `offset*` properties report correct values.
23557		// Behavior in IE 9 is more subtle than in newer versions & it passes
23558		// some versions of this test; make sure not to make it pass there!
23559		//
23560		// Support: Firefox 70+
23561		// Only Firefox includes border widths
23562		// in computed dimensions. (gh-4529)
23563		reliableTrDimensions: function() {
23564			var table, tr, trChild, trStyle;
23565			if ( reliableTrDimensionsVal == null ) {
23566				table = document.createElement( "table" );
23567				tr = document.createElement( "tr" );
23568				trChild = document.createElement( "div" );
23569
23570				table.style.cssText = "position:absolute;left:-11111px;border-collapse:separate";
23571				tr.style.cssText = "border:1px solid";
23572
23573				// Support: Chrome 86+
23574				// Height set through cssText does not get applied.
23575				// Computed height then comes back as 0.
23576				tr.style.height = "1px";
23577				trChild.style.height = "9px";
23578
23579				// Support: Android 8 Chrome 86+
23580				// In our bodyBackground.html iframe,
23581				// display for all div elements is set to "inline",
23582				// which causes a problem only in Android 8 Chrome 86.
23583				// Ensuring the div is display: block
23584				// gets around this issue.
23585				trChild.style.display = "block";
23586
23587				documentElement
23588					.appendChild( table )
23589					.appendChild( tr )
23590					.appendChild( trChild );
23591
23592				trStyle = window.getComputedStyle( tr );
23593				reliableTrDimensionsVal = ( parseInt( trStyle.height, 10 ) +
23594					parseInt( trStyle.borderTopWidth, 10 ) +
23595					parseInt( trStyle.borderBottomWidth, 10 ) ) === tr.offsetHeight;
23596
23597				documentElement.removeChild( table );
23598			}
23599			return reliableTrDimensionsVal;
23600		}
23601	} );
23602} )();
23603
23604
23605function curCSS( elem, name, computed ) {
23606	var width, minWidth, maxWidth, ret,
23607
23608		// Support: Firefox 51+
23609		// Retrieving style before computed somehow
23610		// fixes an issue with getting wrong values
23611		// on detached elements
23612		style = elem.style;
23613
23614	computed = computed || getStyles( elem );
23615
23616	// getPropertyValue is needed for:
23617	//   .css('filter') (IE 9 only, #12537)
23618	//   .css('--customProperty) (#3144)
23619	if ( computed ) {
23620		ret = computed.getPropertyValue( name ) || computed[ name ];
23621
23622		if ( ret === "" && !isAttached( elem ) ) {
23623			ret = jQuery.style( elem, name );
23624		}
23625
23626		// A tribute to the "awesome hack by Dean Edwards"
23627		// Android Browser returns percentage for some values,
23628		// but width seems to be reliably pixels.
23629		// This is against the CSSOM draft spec:
23630		// https://drafts.csswg.org/cssom/#resolved-values
23631		if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) {
23632
23633			// Remember the original values
23634			width = style.width;
23635			minWidth = style.minWidth;
23636			maxWidth = style.maxWidth;
23637
23638			// Put in the new values to get a computed value out
23639			style.minWidth = style.maxWidth = style.width = ret;
23640			ret = computed.width;
23641
23642			// Revert the changed values
23643			style.width = width;
23644			style.minWidth = minWidth;
23645			style.maxWidth = maxWidth;
23646		}
23647	}
23648
23649	return ret !== undefined ?
23650
23651		// Support: IE <=9 - 11 only
23652		// IE returns zIndex value as an integer.
23653		ret + "" :
23654		ret;
23655}
23656
23657
23658function addGetHookIf( conditionFn, hookFn ) {
23659
23660	// Define the hook, we'll check on the first run if it's really needed.
23661	return {
23662		get: function() {
23663			if ( conditionFn() ) {
23664
23665				// Hook not needed (or it's not possible to use it due
23666				// to missing dependency), remove it.
23667				delete this.get;
23668				return;
23669			}
23670
23671			// Hook needed; redefine it so that the support test is not executed again.
23672			return ( this.get = hookFn ).apply( this, arguments );
23673		}
23674	};
23675}
23676
23677
23678var cssPrefixes = [ "Webkit", "Moz", "ms" ],
23679	emptyStyle = document.createElement( "div" ).style,
23680	vendorProps = {};
23681
23682// Return a vendor-prefixed property or undefined
23683function vendorPropName( name ) {
23684
23685	// Check for vendor prefixed names
23686	var capName = name[ 0 ].toUpperCase() + name.slice( 1 ),
23687		i = cssPrefixes.length;
23688
23689	while ( i-- ) {
23690		name = cssPrefixes[ i ] + capName;
23691		if ( name in emptyStyle ) {
23692			return name;
23693		}
23694	}
23695}
23696
23697// Return a potentially-mapped jQuery.cssProps or vendor prefixed property
23698function finalPropName( name ) {
23699	var final = jQuery.cssProps[ name ] || vendorProps[ name ];
23700
23701	if ( final ) {
23702		return final;
23703	}
23704	if ( name in emptyStyle ) {
23705		return name;
23706	}
23707	return vendorProps[ name ] = vendorPropName( name ) || name;
23708}
23709
23710
23711var
23712
23713	// Swappable if display is none or starts with table
23714	// except "table", "table-cell", or "table-caption"
23715	// See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
23716	rdisplayswap = /^(none|table(?!-c[ea]).+)/,
23717	rcustomProp = /^--/,
23718	cssShow = { position: "absolute", visibility: "hidden", display: "block" },
23719	cssNormalTransform = {
23720		letterSpacing: "0",
23721		fontWeight: "400"
23722	};
23723
23724function setPositiveNumber( _elem, value, subtract ) {
23725
23726	// Any relative (+/-) values have already been
23727	// normalized at this point
23728	var matches = rcssNum.exec( value );
23729	return matches ?
23730
23731		// Guard against undefined "subtract", e.g., when used as in cssHooks
23732		Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) :
23733		value;
23734}
23735
23736function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) {
23737	var i = dimension === "width" ? 1 : 0,
23738		extra = 0,
23739		delta = 0;
23740
23741	// Adjustment may not be necessary
23742	if ( box === ( isBorderBox ? "border" : "content" ) ) {
23743		return 0;
23744	}
23745
23746	for ( ; i < 4; i += 2 ) {
23747
23748		// Both box models exclude margin
23749		if ( box === "margin" ) {
23750			delta += jQuery.css( elem, box + cssExpand[ i ], true, styles );
23751		}
23752
23753		// If we get here with a content-box, we're seeking "padding" or "border" or "margin"
23754		if ( !isBorderBox ) {
23755
23756			// Add padding
23757			delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
23758
23759			// For "border" or "margin", add border
23760			if ( box !== "padding" ) {
23761				delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
23762
23763			// But still keep track of it otherwise
23764			} else {
23765				extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
23766			}
23767
23768		// If we get here with a border-box (content + padding + border), we're seeking "content" or
23769		// "padding" or "margin"
23770		} else {
23771
23772			// For "content", subtract padding
23773			if ( box === "content" ) {
23774				delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
23775			}
23776
23777			// For "content" or "padding", subtract border
23778			if ( box !== "margin" ) {
23779				delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
23780			}
23781		}
23782	}
23783
23784	// Account for positive content-box scroll gutter when requested by providing computedVal
23785	if ( !isBorderBox && computedVal >= 0 ) {
23786
23787		// offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border
23788		// Assuming integer scroll gutter, subtract the rest and round down
23789		delta += Math.max( 0, Math.ceil(
23790			elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] -
23791			computedVal -
23792			delta -
23793			extra -
23794			0.5
23795
23796		// If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter
23797		// Use an explicit zero to avoid NaN (gh-3964)
23798		) ) || 0;
23799	}
23800
23801	return delta;
23802}
23803
23804function getWidthOrHeight( elem, dimension, extra ) {
23805
23806	// Start with computed style
23807	var styles = getStyles( elem ),
23808
23809		// To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322).
23810		// Fake content-box until we know it's needed to know the true value.
23811		boxSizingNeeded = !support.boxSizingReliable() || extra,
23812		isBorderBox = boxSizingNeeded &&
23813			jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
23814		valueIsBorderBox = isBorderBox,
23815
23816		val = curCSS( elem, dimension, styles ),
23817		offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 );
23818
23819	// Support: Firefox <=54
23820	// Return a confounding non-pixel value or feign ignorance, as appropriate.
23821	if ( rnumnonpx.test( val ) ) {
23822		if ( !extra ) {
23823			return val;
23824		}
23825		val = "auto";
23826	}
23827
23828
23829	// Support: IE 9 - 11 only
23830	// Use offsetWidth/offsetHeight for when box sizing is unreliable.
23831	// In those cases, the computed value can be trusted to be border-box.
23832	if ( ( !support.boxSizingReliable() && isBorderBox ||
23833
23834		// Support: IE 10 - 11+, Edge 15 - 18+
23835		// IE/Edge misreport `getComputedStyle` of table rows with width/height
23836		// set in CSS while `offset*` properties report correct values.
23837		// Interestingly, in some cases IE 9 doesn't suffer from this issue.
23838		!support.reliableTrDimensions() && nodeName( elem, "tr" ) ||
23839
23840		// Fall back to offsetWidth/offsetHeight when value is "auto"
23841		// This happens for inline elements with no explicit setting (gh-3571)
23842		val === "auto" ||
23843
23844		// Support: Android <=4.1 - 4.3 only
23845		// Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602)
23846		!parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) &&
23847
23848		// Make sure the element is visible & connected
23849		elem.getClientRects().length ) {
23850
23851		isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
23852
23853		// Where available, offsetWidth/offsetHeight approximate border box dimensions.
23854		// Where not available (e.g., SVG), assume unreliable box-sizing and interpret the
23855		// retrieved value as a content box dimension.
23856		valueIsBorderBox = offsetProp in elem;
23857		if ( valueIsBorderBox ) {
23858			val = elem[ offsetProp ];
23859		}
23860	}
23861
23862	// Normalize "" and auto
23863	val = parseFloat( val ) || 0;
23864
23865	// Adjust for the element's box model
23866	return ( val +
23867		boxModelAdjustment(
23868			elem,
23869			dimension,
23870			extra || ( isBorderBox ? "border" : "content" ),
23871			valueIsBorderBox,
23872			styles,
23873
23874			// Provide the current computed size to request scroll gutter calculation (gh-3589)
23875			val
23876		)
23877	) + "px";
23878}
23879
23880jQuery.extend( {
23881
23882	// Add in style property hooks for overriding the default
23883	// behavior of getting and setting a style property
23884	cssHooks: {
23885		opacity: {
23886			get: function( elem, computed ) {
23887				if ( computed ) {
23888
23889					// We should always get a number back from opacity
23890					var ret = curCSS( elem, "opacity" );
23891					return ret === "" ? "1" : ret;
23892				}
23893			}
23894		}
23895	},
23896
23897	// Don't automatically add "px" to these possibly-unitless properties
23898	cssNumber: {
23899		"animationIterationCount": true,
23900		"columnCount": true,
23901		"fillOpacity": true,
23902		"flexGrow": true,
23903		"flexShrink": true,
23904		"fontWeight": true,
23905		"gridArea": true,
23906		"gridColumn": true,
23907		"gridColumnEnd": true,
23908		"gridColumnStart": true,
23909		"gridRow": true,
23910		"gridRowEnd": true,
23911		"gridRowStart": true,
23912		"lineHeight": true,
23913		"opacity": true,
23914		"order": true,
23915		"orphans": true,
23916		"widows": true,
23917		"zIndex": true,
23918		"zoom": true
23919	},
23920
23921	// Add in properties whose names you wish to fix before
23922	// setting or getting the value
23923	cssProps: {},
23924
23925	// Get and set the style property on a DOM Node
23926	style: function( elem, name, value, extra ) {
23927
23928		// Don't set styles on text and comment nodes
23929		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
23930			return;
23931		}
23932
23933		// Make sure that we're working with the right name
23934		var ret, type, hooks,
23935			origName = camelCase( name ),
23936			isCustomProp = rcustomProp.test( name ),
23937			style = elem.style;
23938
23939		// Make sure that we're working with the right name. We don't
23940		// want to query the value if it is a CSS custom property
23941		// since they are user-defined.
23942		if ( !isCustomProp ) {
23943			name = finalPropName( origName );
23944		}
23945
23946		// Gets hook for the prefixed version, then unprefixed version
23947		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
23948
23949		// Check if we're setting a value
23950		if ( value !== undefined ) {
23951			type = typeof value;
23952
23953			// Convert "+=" or "-=" to relative numbers (#7345)
23954			if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) {
23955				value = adjustCSS( elem, name, ret );
23956
23957				// Fixes bug #9237
23958				type = "number";
23959			}
23960
23961			// Make sure that null and NaN values aren't set (#7116)
23962			if ( value == null || value !== value ) {
23963				return;
23964			}
23965
23966			// If a number was passed in, add the unit (except for certain CSS properties)
23967			// The isCustomProp check can be removed in jQuery 4.0 when we only auto-append
23968			// "px" to a few hardcoded values.
23969			if ( type === "number" && !isCustomProp ) {
23970				value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" );
23971			}
23972
23973			// background-* props affect original clone's values
23974			if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) {
23975				style[ name ] = "inherit";
23976			}
23977
23978			// If a hook was provided, use that value, otherwise just set the specified value
23979			if ( !hooks || !( "set" in hooks ) ||
23980				( value = hooks.set( elem, value, extra ) ) !== undefined ) {
23981
23982				if ( isCustomProp ) {
23983					style.setProperty( name, value );
23984				} else {
23985					style[ name ] = value;
23986				}
23987			}
23988
23989		} else {
23990
23991			// If a hook was provided get the non-computed value from there
23992			if ( hooks && "get" in hooks &&
23993				( ret = hooks.get( elem, false, extra ) ) !== undefined ) {
23994
23995				return ret;
23996			}
23997
23998			// Otherwise just get the value from the style object
23999			return style[ name ];
24000		}
24001	},
24002
24003	css: function( elem, name, extra, styles ) {
24004		var val, num, hooks,
24005			origName = camelCase( name ),
24006			isCustomProp = rcustomProp.test( name );
24007
24008		// Make sure that we're working with the right name. We don't
24009		// want to modify the value if it is a CSS custom property
24010		// since they are user-defined.
24011		if ( !isCustomProp ) {
24012			name = finalPropName( origName );
24013		}
24014
24015		// Try prefixed name followed by the unprefixed name
24016		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
24017
24018		// If a hook was provided get the computed value from there
24019		if ( hooks && "get" in hooks ) {
24020			val = hooks.get( elem, true, extra );
24021		}
24022
24023		// Otherwise, if a way to get the computed value exists, use that
24024		if ( val === undefined ) {
24025			val = curCSS( elem, name, styles );
24026		}
24027
24028		// Convert "normal" to computed value
24029		if ( val === "normal" && name in cssNormalTransform ) {
24030			val = cssNormalTransform[ name ];
24031		}
24032
24033		// Make numeric if forced or a qualifier was provided and val looks numeric
24034		if ( extra === "" || extra ) {
24035			num = parseFloat( val );
24036			return extra === true || isFinite( num ) ? num || 0 : val;
24037		}
24038
24039		return val;
24040	}
24041} );
24042
24043jQuery.each( [ "height", "width" ], function( _i, dimension ) {
24044	jQuery.cssHooks[ dimension ] = {
24045		get: function( elem, computed, extra ) {
24046			if ( computed ) {
24047
24048				// Certain elements can have dimension info if we invisibly show them
24049				// but it must have a current display style that would benefit
24050				return rdisplayswap.test( jQuery.css( elem, "display" ) ) &&
24051
24052					// Support: Safari 8+
24053					// Table columns in Safari have non-zero offsetWidth & zero
24054					// getBoundingClientRect().width unless display is changed.
24055					// Support: IE <=11 only
24056					// Running getBoundingClientRect on a disconnected node
24057					// in IE throws an error.
24058					( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ?
24059					swap( elem, cssShow, function() {
24060						return getWidthOrHeight( elem, dimension, extra );
24061					} ) :
24062					getWidthOrHeight( elem, dimension, extra );
24063			}
24064		},
24065
24066		set: function( elem, value, extra ) {
24067			var matches,
24068				styles = getStyles( elem ),
24069
24070				// Only read styles.position if the test has a chance to fail
24071				// to avoid forcing a reflow.
24072				scrollboxSizeBuggy = !support.scrollboxSize() &&
24073					styles.position === "absolute",
24074
24075				// To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991)
24076				boxSizingNeeded = scrollboxSizeBuggy || extra,
24077				isBorderBox = boxSizingNeeded &&
24078					jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
24079				subtract = extra ?
24080					boxModelAdjustment(
24081						elem,
24082						dimension,
24083						extra,
24084						isBorderBox,
24085						styles
24086					) :
24087					0;
24088
24089			// Account for unreliable border-box dimensions by comparing offset* to computed and
24090			// faking a content-box to get border and padding (gh-3699)
24091			if ( isBorderBox && scrollboxSizeBuggy ) {
24092				subtract -= Math.ceil(
24093					elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] -
24094					parseFloat( styles[ dimension ] ) -
24095					boxModelAdjustment( elem, dimension, "border", false, styles ) -
24096					0.5
24097				);
24098			}
24099
24100			// Convert to pixels if value adjustment is needed
24101			if ( subtract && ( matches = rcssNum.exec( value ) ) &&
24102				( matches[ 3 ] || "px" ) !== "px" ) {
24103
24104				elem.style[ dimension ] = value;
24105				value = jQuery.css( elem, dimension );
24106			}
24107
24108			return setPositiveNumber( elem, value, subtract );
24109		}
24110	};
24111} );
24112
24113jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft,
24114	function( elem, computed ) {
24115		if ( computed ) {
24116			return ( parseFloat( curCSS( elem, "marginLeft" ) ) ||
24117				elem.getBoundingClientRect().left -
24118					swap( elem, { marginLeft: 0 }, function() {
24119						return elem.getBoundingClientRect().left;
24120					} )
24121			) + "px";
24122		}
24123	}
24124);
24125
24126// These hooks are used by animate to expand properties
24127jQuery.each( {
24128	margin: "",
24129	padding: "",
24130	border: "Width"
24131}, function( prefix, suffix ) {
24132	jQuery.cssHooks[ prefix + suffix ] = {
24133		expand: function( value ) {
24134			var i = 0,
24135				expanded = {},
24136
24137				// Assumes a single number if not a string
24138				parts = typeof value === "string" ? value.split( " " ) : [ value ];
24139
24140			for ( ; i < 4; i++ ) {
24141				expanded[ prefix + cssExpand[ i ] + suffix ] =
24142					parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
24143			}
24144
24145			return expanded;
24146		}
24147	};
24148
24149	if ( prefix !== "margin" ) {
24150		jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
24151	}
24152} );
24153
24154jQuery.fn.extend( {
24155	css: function( name, value ) {
24156		return access( this, function( elem, name, value ) {
24157			var styles, len,
24158				map = {},
24159				i = 0;
24160
24161			if ( Array.isArray( name ) ) {
24162				styles = getStyles( elem );
24163				len = name.length;
24164
24165				for ( ; i < len; i++ ) {
24166					map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
24167				}
24168
24169				return map;
24170			}
24171
24172			return value !== undefined ?
24173				jQuery.style( elem, name, value ) :
24174				jQuery.css( elem, name );
24175		}, name, value, arguments.length > 1 );
24176	}
24177} );
24178
24179
24180function Tween( elem, options, prop, end, easing ) {
24181	return new Tween.prototype.init( elem, options, prop, end, easing );
24182}
24183jQuery.Tween = Tween;
24184
24185Tween.prototype = {
24186	constructor: Tween,
24187	init: function( elem, options, prop, end, easing, unit ) {
24188		this.elem = elem;
24189		this.prop = prop;
24190		this.easing = easing || jQuery.easing._default;
24191		this.options = options;
24192		this.start = this.now = this.cur();
24193		this.end = end;
24194		this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
24195	},
24196	cur: function() {
24197		var hooks = Tween.propHooks[ this.prop ];
24198
24199		return hooks && hooks.get ?
24200			hooks.get( this ) :
24201			Tween.propHooks._default.get( this );
24202	},
24203	run: function( percent ) {
24204		var eased,
24205			hooks = Tween.propHooks[ this.prop ];
24206
24207		if ( this.options.duration ) {
24208			this.pos = eased = jQuery.easing[ this.easing ](
24209				percent, this.options.duration * percent, 0, 1, this.options.duration
24210			);
24211		} else {
24212			this.pos = eased = percent;
24213		}
24214		this.now = ( this.end - this.start ) * eased + this.start;
24215
24216		if ( this.options.step ) {
24217			this.options.step.call( this.elem, this.now, this );
24218		}
24219
24220		if ( hooks && hooks.set ) {
24221			hooks.set( this );
24222		} else {
24223			Tween.propHooks._default.set( this );
24224		}
24225		return this;
24226	}
24227};
24228
24229Tween.prototype.init.prototype = Tween.prototype;
24230
24231Tween.propHooks = {
24232	_default: {
24233		get: function( tween ) {
24234			var result;
24235
24236			// Use a property on the element directly when it is not a DOM element,
24237			// or when there is no matching style property that exists.
24238			if ( tween.elem.nodeType !== 1 ||
24239				tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) {
24240				return tween.elem[ tween.prop ];
24241			}
24242
24243			// Passing an empty string as a 3rd parameter to .css will automatically
24244			// attempt a parseFloat and fallback to a string if the parse fails.
24245			// Simple values such as "10px" are parsed to Float;
24246			// complex values such as "rotate(1rad)" are returned as-is.
24247			result = jQuery.css( tween.elem, tween.prop, "" );
24248
24249			// Empty strings, null, undefined and "auto" are converted to 0.
24250			return !result || result === "auto" ? 0 : result;
24251		},
24252		set: function( tween ) {
24253
24254			// Use step hook for back compat.
24255			// Use cssHook if its there.
24256			// Use .style if available and use plain properties where available.
24257			if ( jQuery.fx.step[ tween.prop ] ) {
24258				jQuery.fx.step[ tween.prop ]( tween );
24259			} else if ( tween.elem.nodeType === 1 && (
24260				jQuery.cssHooks[ tween.prop ] ||
24261					tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) {
24262				jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
24263			} else {
24264				tween.elem[ tween.prop ] = tween.now;
24265			}
24266		}
24267	}
24268};
24269
24270// Support: IE <=9 only
24271// Panic based approach to setting things on disconnected nodes
24272Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
24273	set: function( tween ) {
24274		if ( tween.elem.nodeType && tween.elem.parentNode ) {
24275			tween.elem[ tween.prop ] = tween.now;
24276		}
24277	}
24278};
24279
24280jQuery.easing = {
24281	linear: function( p ) {
24282		return p;
24283	},
24284	swing: function( p ) {
24285		return 0.5 - Math.cos( p * Math.PI ) / 2;
24286	},
24287	_default: "swing"
24288};
24289
24290jQuery.fx = Tween.prototype.init;
24291
24292// Back compat <1.8 extension point
24293jQuery.fx.step = {};
24294
24295
24296
24297
24298var
24299	fxNow, inProgress,
24300	rfxtypes = /^(?:toggle|show|hide)$/,
24301	rrun = /queueHooks$/;
24302
24303function schedule() {
24304	if ( inProgress ) {
24305		if ( document.hidden === false && window.requestAnimationFrame ) {
24306			window.requestAnimationFrame( schedule );
24307		} else {
24308			window.setTimeout( schedule, jQuery.fx.interval );
24309		}
24310
24311		jQuery.fx.tick();
24312	}
24313}
24314
24315// Animations created synchronously will run synchronously
24316function createFxNow() {
24317	window.setTimeout( function() {
24318		fxNow = undefined;
24319	} );
24320	return ( fxNow = Date.now() );
24321}
24322
24323// Generate parameters to create a standard animation
24324function genFx( type, includeWidth ) {
24325	var which,
24326		i = 0,
24327		attrs = { height: type };
24328
24329	// If we include width, step value is 1 to do all cssExpand values,
24330	// otherwise step value is 2 to skip over Left and Right
24331	includeWidth = includeWidth ? 1 : 0;
24332	for ( ; i < 4; i += 2 - includeWidth ) {
24333		which = cssExpand[ i ];
24334		attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
24335	}
24336
24337	if ( includeWidth ) {
24338		attrs.opacity = attrs.width = type;
24339	}
24340
24341	return attrs;
24342}
24343
24344function createTween( value, prop, animation ) {
24345	var tween,
24346		collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ),
24347		index = 0,
24348		length = collection.length;
24349	for ( ; index < length; index++ ) {
24350		if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) {
24351
24352			// We're done with this property
24353			return tween;
24354		}
24355	}
24356}
24357
24358function defaultPrefilter( elem, props, opts ) {
24359	var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display,
24360		isBox = "width" in props || "height" in props,
24361		anim = this,
24362		orig = {},
24363		style = elem.style,
24364		hidden = elem.nodeType && isHiddenWithinTree( elem ),
24365		dataShow = dataPriv.get( elem, "fxshow" );
24366
24367	// Queue-skipping animations hijack the fx hooks
24368	if ( !opts.queue ) {
24369		hooks = jQuery._queueHooks( elem, "fx" );
24370		if ( hooks.unqueued == null ) {
24371			hooks.unqueued = 0;
24372			oldfire = hooks.empty.fire;
24373			hooks.empty.fire = function() {
24374				if ( !hooks.unqueued ) {
24375					oldfire();
24376				}
24377			};
24378		}
24379		hooks.unqueued++;
24380
24381		anim.always( function() {
24382
24383			// Ensure the complete handler is called before this completes
24384			anim.always( function() {
24385				hooks.unqueued--;
24386				if ( !jQuery.queue( elem, "fx" ).length ) {
24387					hooks.empty.fire();
24388				}
24389			} );
24390		} );
24391	}
24392
24393	// Detect show/hide animations
24394	for ( prop in props ) {
24395		value = props[ prop ];
24396		if ( rfxtypes.test( value ) ) {
24397			delete props[ prop ];
24398			toggle = toggle || value === "toggle";
24399			if ( value === ( hidden ? "hide" : "show" ) ) {
24400
24401				// Pretend to be hidden if this is a "show" and
24402				// there is still data from a stopped show/hide
24403				if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
24404					hidden = true;
24405
24406				// Ignore all other no-op show/hide data
24407				} else {
24408					continue;
24409				}
24410			}
24411			orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
24412		}
24413	}
24414
24415	// Bail out if this is a no-op like .hide().hide()
24416	propTween = !jQuery.isEmptyObject( props );
24417	if ( !propTween && jQuery.isEmptyObject( orig ) ) {
24418		return;
24419	}
24420
24421	// Restrict "overflow" and "display" styles during box animations
24422	if ( isBox && elem.nodeType === 1 ) {
24423
24424		// Support: IE <=9 - 11, Edge 12 - 15
24425		// Record all 3 overflow attributes because IE does not infer the shorthand
24426		// from identically-valued overflowX and overflowY and Edge just mirrors
24427		// the overflowX value there.
24428		opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
24429
24430		// Identify a display type, preferring old show/hide data over the CSS cascade
24431		restoreDisplay = dataShow && dataShow.display;
24432		if ( restoreDisplay == null ) {
24433			restoreDisplay = dataPriv.get( elem, "display" );
24434		}
24435		display = jQuery.css( elem, "display" );
24436		if ( display === "none" ) {
24437			if ( restoreDisplay ) {
24438				display = restoreDisplay;
24439			} else {
24440
24441				// Get nonempty value(s) by temporarily forcing visibility
24442				showHide( [ elem ], true );
24443				restoreDisplay = elem.style.display || restoreDisplay;
24444				display = jQuery.css( elem, "display" );
24445				showHide( [ elem ] );
24446			}
24447		}
24448
24449		// Animate inline elements as inline-block
24450		if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) {
24451			if ( jQuery.css( elem, "float" ) === "none" ) {
24452
24453				// Restore the original display value at the end of pure show/hide animations
24454				if ( !propTween ) {
24455					anim.done( function() {
24456						style.display = restoreDisplay;
24457					} );
24458					if ( restoreDisplay == null ) {
24459						display = style.display;
24460						restoreDisplay = display === "none" ? "" : display;
24461					}
24462				}
24463				style.display = "inline-block";
24464			}
24465		}
24466	}
24467
24468	if ( opts.overflow ) {
24469		style.overflow = "hidden";
24470		anim.always( function() {
24471			style.overflow = opts.overflow[ 0 ];
24472			style.overflowX = opts.overflow[ 1 ];
24473			style.overflowY = opts.overflow[ 2 ];
24474		} );
24475	}
24476
24477	// Implement show/hide animations
24478	propTween = false;
24479	for ( prop in orig ) {
24480
24481		// General show/hide setup for this element animation
24482		if ( !propTween ) {
24483			if ( dataShow ) {
24484				if ( "hidden" in dataShow ) {
24485					hidden = dataShow.hidden;
24486				}
24487			} else {
24488				dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } );
24489			}
24490
24491			// Store hidden/visible for toggle so `.stop().toggle()` "reverses"
24492			if ( toggle ) {
24493				dataShow.hidden = !hidden;
24494			}
24495
24496			// Show elements before animating them
24497			if ( hidden ) {
24498				showHide( [ elem ], true );
24499			}
24500
24501			/* eslint-disable no-loop-func */
24502
24503			anim.done( function() {
24504
24505				/* eslint-enable no-loop-func */
24506
24507				// The final step of a "hide" animation is actually hiding the element
24508				if ( !hidden ) {
24509					showHide( [ elem ] );
24510				}
24511				dataPriv.remove( elem, "fxshow" );
24512				for ( prop in orig ) {
24513					jQuery.style( elem, prop, orig[ prop ] );
24514				}
24515			} );
24516		}
24517
24518		// Per-property setup
24519		propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
24520		if ( !( prop in dataShow ) ) {
24521			dataShow[ prop ] = propTween.start;
24522			if ( hidden ) {
24523				propTween.end = propTween.start;
24524				propTween.start = 0;
24525			}
24526		}
24527	}
24528}
24529
24530function propFilter( props, specialEasing ) {
24531	var index, name, easing, value, hooks;
24532
24533	// camelCase, specialEasing and expand cssHook pass
24534	for ( index in props ) {
24535		name = camelCase( index );
24536		easing = specialEasing[ name ];
24537		value = props[ index ];
24538		if ( Array.isArray( value ) ) {
24539			easing = value[ 1 ];
24540			value = props[ index ] = value[ 0 ];
24541		}
24542
24543		if ( index !== name ) {
24544			props[ name ] = value;
24545			delete props[ index ];
24546		}
24547
24548		hooks = jQuery.cssHooks[ name ];
24549		if ( hooks && "expand" in hooks ) {
24550			value = hooks.expand( value );
24551			delete props[ name ];
24552
24553			// Not quite $.extend, this won't overwrite existing keys.
24554			// Reusing 'index' because we have the correct "name"
24555			for ( index in value ) {
24556				if ( !( index in props ) ) {
24557					props[ index ] = value[ index ];
24558					specialEasing[ index ] = easing;
24559				}
24560			}
24561		} else {
24562			specialEasing[ name ] = easing;
24563		}
24564	}
24565}
24566
24567function Animation( elem, properties, options ) {
24568	var result,
24569		stopped,
24570		index = 0,
24571		length = Animation.prefilters.length,
24572		deferred = jQuery.Deferred().always( function() {
24573
24574			// Don't match elem in the :animated selector
24575			delete tick.elem;
24576		} ),
24577		tick = function() {
24578			if ( stopped ) {
24579				return false;
24580			}
24581			var currentTime = fxNow || createFxNow(),
24582				remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
24583
24584				// Support: Android 2.3 only
24585				// Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)
24586				temp = remaining / animation.duration || 0,
24587				percent = 1 - temp,
24588				index = 0,
24589				length = animation.tweens.length;
24590
24591			for ( ; index < length; index++ ) {
24592				animation.tweens[ index ].run( percent );
24593			}
24594
24595			deferred.notifyWith( elem, [ animation, percent, remaining ] );
24596
24597			// If there's more to do, yield
24598			if ( percent < 1 && length ) {
24599				return remaining;
24600			}
24601
24602			// If this was an empty animation, synthesize a final progress notification
24603			if ( !length ) {
24604				deferred.notifyWith( elem, [ animation, 1, 0 ] );
24605			}
24606
24607			// Resolve the animation and report its conclusion
24608			deferred.resolveWith( elem, [ animation ] );
24609			return false;
24610		},
24611		animation = deferred.promise( {
24612			elem: elem,
24613			props: jQuery.extend( {}, properties ),
24614			opts: jQuery.extend( true, {
24615				specialEasing: {},
24616				easing: jQuery.easing._default
24617			}, options ),
24618			originalProperties: properties,
24619			originalOptions: options,
24620			startTime: fxNow || createFxNow(),
24621			duration: options.duration,
24622			tweens: [],
24623			createTween: function( prop, end ) {
24624				var tween = jQuery.Tween( elem, animation.opts, prop, end,
24625					animation.opts.specialEasing[ prop ] || animation.opts.easing );
24626				animation.tweens.push( tween );
24627				return tween;
24628			},
24629			stop: function( gotoEnd ) {
24630				var index = 0,
24631
24632					// If we are going to the end, we want to run all the tweens
24633					// otherwise we skip this part
24634					length = gotoEnd ? animation.tweens.length : 0;
24635				if ( stopped ) {
24636					return this;
24637				}
24638				stopped = true;
24639				for ( ; index < length; index++ ) {
24640					animation.tweens[ index ].run( 1 );
24641				}
24642
24643				// Resolve when we played the last frame; otherwise, reject
24644				if ( gotoEnd ) {
24645					deferred.notifyWith( elem, [ animation, 1, 0 ] );
24646					deferred.resolveWith( elem, [ animation, gotoEnd ] );
24647				} else {
24648					deferred.rejectWith( elem, [ animation, gotoEnd ] );
24649				}
24650				return this;
24651			}
24652		} ),
24653		props = animation.props;
24654
24655	propFilter( props, animation.opts.specialEasing );
24656
24657	for ( ; index < length; index++ ) {
24658		result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );
24659		if ( result ) {
24660			if ( isFunction( result.stop ) ) {
24661				jQuery._queueHooks( animation.elem, animation.opts.queue ).stop =
24662					result.stop.bind( result );
24663			}
24664			return result;
24665		}
24666	}
24667
24668	jQuery.map( props, createTween, animation );
24669
24670	if ( isFunction( animation.opts.start ) ) {
24671		animation.opts.start.call( elem, animation );
24672	}
24673
24674	// Attach callbacks from options
24675	animation
24676		.progress( animation.opts.progress )
24677		.done( animation.opts.done, animation.opts.complete )
24678		.fail( animation.opts.fail )
24679		.always( animation.opts.always );
24680
24681	jQuery.fx.timer(
24682		jQuery.extend( tick, {
24683			elem: elem,
24684			anim: animation,
24685			queue: animation.opts.queue
24686		} )
24687	);
24688
24689	return animation;
24690}
24691
24692jQuery.Animation = jQuery.extend( Animation, {
24693
24694	tweeners: {
24695		"*": [ function( prop, value ) {
24696			var tween = this.createTween( prop, value );
24697			adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );
24698			return tween;
24699		} ]
24700	},
24701
24702	tweener: function( props, callback ) {
24703		if ( isFunction( props ) ) {
24704			callback = props;
24705			props = [ "*" ];
24706		} else {
24707			props = props.match( rnothtmlwhite );
24708		}
24709
24710		var prop,
24711			index = 0,
24712			length = props.length;
24713
24714		for ( ; index < length; index++ ) {
24715			prop = props[ index ];
24716			Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || [];
24717			Animation.tweeners[ prop ].unshift( callback );
24718		}
24719	},
24720
24721	prefilters: [ defaultPrefilter ],
24722
24723	prefilter: function( callback, prepend ) {
24724		if ( prepend ) {
24725			Animation.prefilters.unshift( callback );
24726		} else {
24727			Animation.prefilters.push( callback );
24728		}
24729	}
24730} );
24731
24732jQuery.speed = function( speed, easing, fn ) {
24733	var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
24734		complete: fn || !fn && easing ||
24735			isFunction( speed ) && speed,
24736		duration: speed,
24737		easing: fn && easing || easing && !isFunction( easing ) && easing
24738	};
24739
24740	// Go to the end state if fx are off
24741	if ( jQuery.fx.off ) {
24742		opt.duration = 0;
24743
24744	} else {
24745		if ( typeof opt.duration !== "number" ) {
24746			if ( opt.duration in jQuery.fx.speeds ) {
24747				opt.duration = jQuery.fx.speeds[ opt.duration ];
24748
24749			} else {
24750				opt.duration = jQuery.fx.speeds._default;
24751			}
24752		}
24753	}
24754
24755	// Normalize opt.queue - true/undefined/null -> "fx"
24756	if ( opt.queue == null || opt.queue === true ) {
24757		opt.queue = "fx";
24758	}
24759
24760	// Queueing
24761	opt.old = opt.complete;
24762
24763	opt.complete = function() {
24764		if ( isFunction( opt.old ) ) {
24765			opt.old.call( this );
24766		}
24767
24768		if ( opt.queue ) {
24769			jQuery.dequeue( this, opt.queue );
24770		}
24771	};
24772
24773	return opt;
24774};
24775
24776jQuery.fn.extend( {
24777	fadeTo: function( speed, to, easing, callback ) {
24778
24779		// Show any hidden elements after setting opacity to 0
24780		return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show()
24781
24782			// Animate to the value specified
24783			.end().animate( { opacity: to }, speed, easing, callback );
24784	},
24785	animate: function( prop, speed, easing, callback ) {
24786		var empty = jQuery.isEmptyObject( prop ),
24787			optall = jQuery.speed( speed, easing, callback ),
24788			doAnimation = function() {
24789
24790				// Operate on a copy of prop so per-property easing won't be lost
24791				var anim = Animation( this, jQuery.extend( {}, prop ), optall );
24792
24793				// Empty animations, or finishing resolves immediately
24794				if ( empty || dataPriv.get( this, "finish" ) ) {
24795					anim.stop( true );
24796				}
24797			};
24798
24799		doAnimation.finish = doAnimation;
24800
24801		return empty || optall.queue === false ?
24802			this.each( doAnimation ) :
24803			this.queue( optall.queue, doAnimation );
24804	},
24805	stop: function( type, clearQueue, gotoEnd ) {
24806		var stopQueue = function( hooks ) {
24807			var stop = hooks.stop;
24808			delete hooks.stop;
24809			stop( gotoEnd );
24810		};
24811
24812		if ( typeof type !== "string" ) {
24813			gotoEnd = clearQueue;
24814			clearQueue = type;
24815			type = undefined;
24816		}
24817		if ( clearQueue ) {
24818			this.queue( type || "fx", [] );
24819		}
24820
24821		return this.each( function() {
24822			var dequeue = true,
24823				index = type != null && type + "queueHooks",
24824				timers = jQuery.timers,
24825				data = dataPriv.get( this );
24826
24827			if ( index ) {
24828				if ( data[ index ] && data[ index ].stop ) {
24829					stopQueue( data[ index ] );
24830				}
24831			} else {
24832				for ( index in data ) {
24833					if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
24834						stopQueue( data[ index ] );
24835					}
24836				}
24837			}
24838
24839			for ( index = timers.length; index--; ) {
24840				if ( timers[ index ].elem === this &&
24841					( type == null || timers[ index ].queue === type ) ) {
24842
24843					timers[ index ].anim.stop( gotoEnd );
24844					dequeue = false;
24845					timers.splice( index, 1 );
24846				}
24847			}
24848
24849			// Start the next in the queue if the last step wasn't forced.
24850			// Timers currently will call their complete callbacks, which
24851			// will dequeue but only if they were gotoEnd.
24852			if ( dequeue || !gotoEnd ) {
24853				jQuery.dequeue( this, type );
24854			}
24855		} );
24856	},
24857	finish: function( type ) {
24858		if ( type !== false ) {
24859			type = type || "fx";
24860		}
24861		return this.each( function() {
24862			var index,
24863				data = dataPriv.get( this ),
24864				queue = data[ type + "queue" ],
24865				hooks = data[ type + "queueHooks" ],
24866				timers = jQuery.timers,
24867				length = queue ? queue.length : 0;
24868
24869			// Enable finishing flag on private data
24870			data.finish = true;
24871
24872			// Empty the queue first
24873			jQuery.queue( this, type, [] );
24874
24875			if ( hooks && hooks.stop ) {
24876				hooks.stop.call( this, true );
24877			}
24878
24879			// Look for any active animations, and finish them
24880			for ( index = timers.length; index--; ) {
24881				if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
24882					timers[ index ].anim.stop( true );
24883					timers.splice( index, 1 );
24884				}
24885			}
24886
24887			// Look for any animations in the old queue and finish them
24888			for ( index = 0; index < length; index++ ) {
24889				if ( queue[ index ] && queue[ index ].finish ) {
24890					queue[ index ].finish.call( this );
24891				}
24892			}
24893
24894			// Turn off finishing flag
24895			delete data.finish;
24896		} );
24897	}
24898} );
24899
24900jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) {
24901	var cssFn = jQuery.fn[ name ];
24902	jQuery.fn[ name ] = function( speed, easing, callback ) {
24903		return speed == null || typeof speed === "boolean" ?
24904			cssFn.apply( this, arguments ) :
24905			this.animate( genFx( name, true ), speed, easing, callback );
24906	};
24907} );
24908
24909// Generate shortcuts for custom animations
24910jQuery.each( {
24911	slideDown: genFx( "show" ),
24912	slideUp: genFx( "hide" ),
24913	slideToggle: genFx( "toggle" ),
24914	fadeIn: { opacity: "show" },
24915	fadeOut: { opacity: "hide" },
24916	fadeToggle: { opacity: "toggle" }
24917}, function( name, props ) {
24918	jQuery.fn[ name ] = function( speed, easing, callback ) {
24919		return this.animate( props, speed, easing, callback );
24920	};
24921} );
24922
24923jQuery.timers = [];
24924jQuery.fx.tick = function() {
24925	var timer,
24926		i = 0,
24927		timers = jQuery.timers;
24928
24929	fxNow = Date.now();
24930
24931	for ( ; i < timers.length; i++ ) {
24932		timer = timers[ i ];
24933
24934		// Run the timer and safely remove it when done (allowing for external removal)
24935		if ( !timer() && timers[ i ] === timer ) {
24936			timers.splice( i--, 1 );
24937		}
24938	}
24939
24940	if ( !timers.length ) {
24941		jQuery.fx.stop();
24942	}
24943	fxNow = undefined;
24944};
24945
24946jQuery.fx.timer = function( timer ) {
24947	jQuery.timers.push( timer );
24948	jQuery.fx.start();
24949};
24950
24951jQuery.fx.interval = 13;
24952jQuery.fx.start = function() {
24953	if ( inProgress ) {
24954		return;
24955	}
24956
24957	inProgress = true;
24958	schedule();
24959};
24960
24961jQuery.fx.stop = function() {
24962	inProgress = null;
24963};
24964
24965jQuery.fx.speeds = {
24966	slow: 600,
24967	fast: 200,
24968
24969	// Default speed
24970	_default: 400
24971};
24972
24973
24974// Based off of the plugin by Clint Helfers, with permission.
24975// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/
24976jQuery.fn.delay = function( time, type ) {
24977	time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
24978	type = type || "fx";
24979
24980	return this.queue( type, function( next, hooks ) {
24981		var timeout = window.setTimeout( next, time );
24982		hooks.stop = function() {
24983			window.clearTimeout( timeout );
24984		};
24985	} );
24986};
24987
24988
24989( function() {
24990	var input = document.createElement( "input" ),
24991		select = document.createElement( "select" ),
24992		opt = select.appendChild( document.createElement( "option" ) );
24993
24994	input.type = "checkbox";
24995
24996	// Support: Android <=4.3 only
24997	// Default value for a checkbox should be "on"
24998	support.checkOn = input.value !== "";
24999
25000	// Support: IE <=11 only
25001	// Must access selectedIndex to make default options select
25002	support.optSelected = opt.selected;
25003
25004	// Support: IE <=11 only
25005	// An input loses its value after becoming a radio
25006	input = document.createElement( "input" );
25007	input.value = "t";
25008	input.type = "radio";
25009	support.radioValue = input.value === "t";
25010} )();
25011
25012
25013var boolHook,
25014	attrHandle = jQuery.expr.attrHandle;
25015
25016jQuery.fn.extend( {
25017	attr: function( name, value ) {
25018		return access( this, jQuery.attr, name, value, arguments.length > 1 );
25019	},
25020
25021	removeAttr: function( name ) {
25022		return this.each( function() {
25023			jQuery.removeAttr( this, name );
25024		} );
25025	}
25026} );
25027
25028jQuery.extend( {
25029	attr: function( elem, name, value ) {
25030		var ret, hooks,
25031			nType = elem.nodeType;
25032
25033		// Don't get/set attributes on text, comment and attribute nodes
25034		if ( nType === 3 || nType === 8 || nType === 2 ) {
25035			return;
25036		}
25037
25038		// Fallback to prop when attributes are not supported
25039		if ( typeof elem.getAttribute === "undefined" ) {
25040			return jQuery.prop( elem, name, value );
25041		}
25042
25043		// Attribute hooks are determined by the lowercase version
25044		// Grab necessary hook if one is defined
25045		if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
25046			hooks = jQuery.attrHooks[ name.toLowerCase() ] ||
25047				( jQuery.expr.match.bool.test( name ) ? boolHook : undefined );
25048		}
25049
25050		if ( value !== undefined ) {
25051			if ( value === null ) {
25052				jQuery.removeAttr( elem, name );
25053				return;
25054			}
25055
25056			if ( hooks && "set" in hooks &&
25057				( ret = hooks.set( elem, value, name ) ) !== undefined ) {
25058				return ret;
25059			}
25060
25061			elem.setAttribute( name, value + "" );
25062			return value;
25063		}
25064
25065		if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
25066			return ret;
25067		}
25068
25069		ret = jQuery.find.attr( elem, name );
25070
25071		// Non-existent attributes return null, we normalize to undefined
25072		return ret == null ? undefined : ret;
25073	},
25074
25075	attrHooks: {
25076		type: {
25077			set: function( elem, value ) {
25078				if ( !support.radioValue && value === "radio" &&
25079					nodeName( elem, "input" ) ) {
25080					var val = elem.value;
25081					elem.setAttribute( "type", value );
25082					if ( val ) {
25083						elem.value = val;
25084					}
25085					return value;
25086				}
25087			}
25088		}
25089	},
25090
25091	removeAttr: function( elem, value ) {
25092		var name,
25093			i = 0,
25094
25095			// Attribute names can contain non-HTML whitespace characters
25096			// https://html.spec.whatwg.org/multipage/syntax.html#attributes-2
25097			attrNames = value && value.match( rnothtmlwhite );
25098
25099		if ( attrNames && elem.nodeType === 1 ) {
25100			while ( ( name = attrNames[ i++ ] ) ) {
25101				elem.removeAttribute( name );
25102			}
25103		}
25104	}
25105} );
25106
25107// Hooks for boolean attributes
25108boolHook = {
25109	set: function( elem, value, name ) {
25110		if ( value === false ) {
25111
25112			// Remove boolean attributes when set to false
25113			jQuery.removeAttr( elem, name );
25114		} else {
25115			elem.setAttribute( name, name );
25116		}
25117		return name;
25118	}
25119};
25120
25121jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) {
25122	var getter = attrHandle[ name ] || jQuery.find.attr;
25123
25124	attrHandle[ name ] = function( elem, name, isXML ) {
25125		var ret, handle,
25126			lowercaseName = name.toLowerCase();
25127
25128		if ( !isXML ) {
25129
25130			// Avoid an infinite loop by temporarily removing this function from the getter
25131			handle = attrHandle[ lowercaseName ];
25132			attrHandle[ lowercaseName ] = ret;
25133			ret = getter( elem, name, isXML ) != null ?
25134				lowercaseName :
25135				null;
25136			attrHandle[ lowercaseName ] = handle;
25137		}
25138		return ret;
25139	};
25140} );
25141
25142
25143
25144
25145var rfocusable = /^(?:input|select|textarea|button)$/i,
25146	rclickable = /^(?:a|area)$/i;
25147
25148jQuery.fn.extend( {
25149	prop: function( name, value ) {
25150		return access( this, jQuery.prop, name, value, arguments.length > 1 );
25151	},
25152
25153	removeProp: function( name ) {
25154		return this.each( function() {
25155			delete this[ jQuery.propFix[ name ] || name ];
25156		} );
25157	}
25158} );
25159
25160jQuery.extend( {
25161	prop: function( elem, name, value ) {
25162		var ret, hooks,
25163			nType = elem.nodeType;
25164
25165		// Don't get/set properties on text, comment and attribute nodes
25166		if ( nType === 3 || nType === 8 || nType === 2 ) {
25167			return;
25168		}
25169
25170		if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
25171
25172			// Fix name and attach hooks
25173			name = jQuery.propFix[ name ] || name;
25174			hooks = jQuery.propHooks[ name ];
25175		}
25176
25177		if ( value !== undefined ) {
25178			if ( hooks && "set" in hooks &&
25179				( ret = hooks.set( elem, value, name ) ) !== undefined ) {
25180				return ret;
25181			}
25182
25183			return ( elem[ name ] = value );
25184		}
25185
25186		if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
25187			return ret;
25188		}
25189
25190		return elem[ name ];
25191	},
25192
25193	propHooks: {
25194		tabIndex: {
25195			get: function( elem ) {
25196
25197				// Support: IE <=9 - 11 only
25198				// elem.tabIndex doesn't always return the
25199				// correct value when it hasn't been explicitly set
25200				// https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
25201				// Use proper attribute retrieval(#12072)
25202				var tabindex = jQuery.find.attr( elem, "tabindex" );
25203
25204				if ( tabindex ) {
25205					return parseInt( tabindex, 10 );
25206				}
25207
25208				if (
25209					rfocusable.test( elem.nodeName ) ||
25210					rclickable.test( elem.nodeName ) &&
25211					elem.href
25212				) {
25213					return 0;
25214				}
25215
25216				return -1;
25217			}
25218		}
25219	},
25220
25221	propFix: {
25222		"for": "htmlFor",
25223		"class": "className"
25224	}
25225} );
25226
25227// Support: IE <=11 only
25228// Accessing the selectedIndex property
25229// forces the browser to respect setting selected
25230// on the option
25231// The getter ensures a default option is selected
25232// when in an optgroup
25233// eslint rule "no-unused-expressions" is disabled for this code
25234// since it considers such accessions noop
25235if ( !support.optSelected ) {
25236	jQuery.propHooks.selected = {
25237		get: function( elem ) {
25238
25239			/* eslint no-unused-expressions: "off" */
25240
25241			var parent = elem.parentNode;
25242			if ( parent && parent.parentNode ) {
25243				parent.parentNode.selectedIndex;
25244			}
25245			return null;
25246		},
25247		set: function( elem ) {
25248
25249			/* eslint no-unused-expressions: "off" */
25250
25251			var parent = elem.parentNode;
25252			if ( parent ) {
25253				parent.selectedIndex;
25254
25255				if ( parent.parentNode ) {
25256					parent.parentNode.selectedIndex;
25257				}
25258			}
25259		}
25260	};
25261}
25262
25263jQuery.each( [
25264	"tabIndex",
25265	"readOnly",
25266	"maxLength",
25267	"cellSpacing",
25268	"cellPadding",
25269	"rowSpan",
25270	"colSpan",
25271	"useMap",
25272	"frameBorder",
25273	"contentEditable"
25274], function() {
25275	jQuery.propFix[ this.toLowerCase() ] = this;
25276} );
25277
25278
25279
25280
25281	// Strip and collapse whitespace according to HTML spec
25282	// https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace
25283	function stripAndCollapse( value ) {
25284		var tokens = value.match( rnothtmlwhite ) || [];
25285		return tokens.join( " " );
25286	}
25287
25288
25289function getClass( elem ) {
25290	return elem.getAttribute && elem.getAttribute( "class" ) || "";
25291}
25292
25293function classesToArray( value ) {
25294	if ( Array.isArray( value ) ) {
25295		return value;
25296	}
25297	if ( typeof value === "string" ) {
25298		return value.match( rnothtmlwhite ) || [];
25299	}
25300	return [];
25301}
25302
25303jQuery.fn.extend( {
25304	addClass: function( value ) {
25305		var classes, elem, cur, curValue, clazz, j, finalValue,
25306			i = 0;
25307
25308		if ( isFunction( value ) ) {
25309			return this.each( function( j ) {
25310				jQuery( this ).addClass( value.call( this, j, getClass( this ) ) );
25311			} );
25312		}
25313
25314		classes = classesToArray( value );
25315
25316		if ( classes.length ) {
25317			while ( ( elem = this[ i++ ] ) ) {
25318				curValue = getClass( elem );
25319				cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );
25320
25321				if ( cur ) {
25322					j = 0;
25323					while ( ( clazz = classes[ j++ ] ) ) {
25324						if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
25325							cur += clazz + " ";
25326						}
25327					}
25328
25329					// Only assign if different to avoid unneeded rendering.
25330					finalValue = stripAndCollapse( cur );
25331					if ( curValue !== finalValue ) {
25332						elem.setAttribute( "class", finalValue );
25333					}
25334				}
25335			}
25336		}
25337
25338		return this;
25339	},
25340
25341	removeClass: function( value ) {
25342		var classes, elem, cur, curValue, clazz, j, finalValue,
25343			i = 0;
25344
25345		if ( isFunction( value ) ) {
25346			return this.each( function( j ) {
25347				jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) );
25348			} );
25349		}
25350
25351		if ( !arguments.length ) {
25352			return this.attr( "class", "" );
25353		}
25354
25355		classes = classesToArray( value );
25356
25357		if ( classes.length ) {
25358			while ( ( elem = this[ i++ ] ) ) {
25359				curValue = getClass( elem );
25360
25361				// This expression is here for better compressibility (see addClass)
25362				cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );
25363
25364				if ( cur ) {
25365					j = 0;
25366					while ( ( clazz = classes[ j++ ] ) ) {
25367
25368						// Remove *all* instances
25369						while ( cur.indexOf( " " + clazz + " " ) > -1 ) {
25370							cur = cur.replace( " " + clazz + " ", " " );
25371						}
25372					}
25373
25374					// Only assign if different to avoid unneeded rendering.
25375					finalValue = stripAndCollapse( cur );
25376					if ( curValue !== finalValue ) {
25377						elem.setAttribute( "class", finalValue );
25378					}
25379				}
25380			}
25381		}
25382
25383		return this;
25384	},
25385
25386	toggleClass: function( value, stateVal ) {
25387		var type = typeof value,
25388			isValidValue = type === "string" || Array.isArray( value );
25389
25390		if ( typeof stateVal === "boolean" && isValidValue ) {
25391			return stateVal ? this.addClass( value ) : this.removeClass( value );
25392		}
25393
25394		if ( isFunction( value ) ) {
25395			return this.each( function( i ) {
25396				jQuery( this ).toggleClass(
25397					value.call( this, i, getClass( this ), stateVal ),
25398					stateVal
25399				);
25400			} );
25401		}
25402
25403		return this.each( function() {
25404			var className, i, self, classNames;
25405
25406			if ( isValidValue ) {
25407
25408				// Toggle individual class names
25409				i = 0;
25410				self = jQuery( this );
25411				classNames = classesToArray( value );
25412
25413				while ( ( className = classNames[ i++ ] ) ) {
25414
25415					// Check each className given, space separated list
25416					if ( self.hasClass( className ) ) {
25417						self.removeClass( className );
25418					} else {
25419						self.addClass( className );
25420					}
25421				}
25422
25423			// Toggle whole class name
25424			} else if ( value === undefined || type === "boolean" ) {
25425				className = getClass( this );
25426				if ( className ) {
25427
25428					// Store className if set
25429					dataPriv.set( this, "__className__", className );
25430				}
25431
25432				// If the element has a class name or if we're passed `false`,
25433				// then remove the whole classname (if there was one, the above saved it).
25434				// Otherwise bring back whatever was previously saved (if anything),
25435				// falling back to the empty string if nothing was stored.
25436				if ( this.setAttribute ) {
25437					this.setAttribute( "class",
25438						className || value === false ?
25439							"" :
25440							dataPriv.get( this, "__className__" ) || ""
25441					);
25442				}
25443			}
25444		} );
25445	},
25446
25447	hasClass: function( selector ) {
25448		var className, elem,
25449			i = 0;
25450
25451		className = " " + selector + " ";
25452		while ( ( elem = this[ i++ ] ) ) {
25453			if ( elem.nodeType === 1 &&
25454				( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) {
25455				return true;
25456			}
25457		}
25458
25459		return false;
25460	}
25461} );
25462
25463
25464
25465
25466var rreturn = /\r/g;
25467
25468jQuery.fn.extend( {
25469	val: function( value ) {
25470		var hooks, ret, valueIsFunction,
25471			elem = this[ 0 ];
25472
25473		if ( !arguments.length ) {
25474			if ( elem ) {
25475				hooks = jQuery.valHooks[ elem.type ] ||
25476					jQuery.valHooks[ elem.nodeName.toLowerCase() ];
25477
25478				if ( hooks &&
25479					"get" in hooks &&
25480					( ret = hooks.get( elem, "value" ) ) !== undefined
25481				) {
25482					return ret;
25483				}
25484
25485				ret = elem.value;
25486
25487				// Handle most common string cases
25488				if ( typeof ret === "string" ) {
25489					return ret.replace( rreturn, "" );
25490				}
25491
25492				// Handle cases where value is null/undef or number
25493				return ret == null ? "" : ret;
25494			}
25495
25496			return;
25497		}
25498
25499		valueIsFunction = isFunction( value );
25500
25501		return this.each( function( i ) {
25502			var val;
25503
25504			if ( this.nodeType !== 1 ) {
25505				return;
25506			}
25507
25508			if ( valueIsFunction ) {
25509				val = value.call( this, i, jQuery( this ).val() );
25510			} else {
25511				val = value;
25512			}
25513
25514			// Treat null/undefined as ""; convert numbers to string
25515			if ( val == null ) {
25516				val = "";
25517
25518			} else if ( typeof val === "number" ) {
25519				val += "";
25520
25521			} else if ( Array.isArray( val ) ) {
25522				val = jQuery.map( val, function( value ) {
25523					return value == null ? "" : value + "";
25524				} );
25525			}
25526
25527			hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
25528
25529			// If set returns undefined, fall back to normal setting
25530			if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) {
25531				this.value = val;
25532			}
25533		} );
25534	}
25535} );
25536
25537jQuery.extend( {
25538	valHooks: {
25539		option: {
25540			get: function( elem ) {
25541
25542				var val = jQuery.find.attr( elem, "value" );
25543				return val != null ?
25544					val :
25545
25546					// Support: IE <=10 - 11 only
25547					// option.text throws exceptions (#14686, #14858)
25548					// Strip and collapse whitespace
25549					// https://html.spec.whatwg.org/#strip-and-collapse-whitespace
25550					stripAndCollapse( jQuery.text( elem ) );
25551			}
25552		},
25553		select: {
25554			get: function( elem ) {
25555				var value, option, i,
25556					options = elem.options,
25557					index = elem.selectedIndex,
25558					one = elem.type === "select-one",
25559					values = one ? null : [],
25560					max = one ? index + 1 : options.length;
25561
25562				if ( index < 0 ) {
25563					i = max;
25564
25565				} else {
25566					i = one ? index : 0;
25567				}
25568
25569				// Loop through all the selected options
25570				for ( ; i < max; i++ ) {
25571					option = options[ i ];
25572
25573					// Support: IE <=9 only
25574					// IE8-9 doesn't update selected after form reset (#2551)
25575					if ( ( option.selected || i === index ) &&
25576
25577							// Don't return options that are disabled or in a disabled optgroup
25578							!option.disabled &&
25579							( !option.parentNode.disabled ||
25580								!nodeName( option.parentNode, "optgroup" ) ) ) {
25581
25582						// Get the specific value for the option
25583						value = jQuery( option ).val();
25584
25585						// We don't need an array for one selects
25586						if ( one ) {
25587							return value;
25588						}
25589
25590						// Multi-Selects return an array
25591						values.push( value );
25592					}
25593				}
25594
25595				return values;
25596			},
25597
25598			set: function( elem, value ) {
25599				var optionSet, option,
25600					options = elem.options,
25601					values = jQuery.makeArray( value ),
25602					i = options.length;
25603
25604				while ( i-- ) {
25605					option = options[ i ];
25606
25607					/* eslint-disable no-cond-assign */
25608
25609					if ( option.selected =
25610						jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1
25611					) {
25612						optionSet = true;
25613					}
25614
25615					/* eslint-enable no-cond-assign */
25616				}
25617
25618				// Force browsers to behave consistently when non-matching value is set
25619				if ( !optionSet ) {
25620					elem.selectedIndex = -1;
25621				}
25622				return values;
25623			}
25624		}
25625	}
25626} );
25627
25628// Radios and checkboxes getter/setter
25629jQuery.each( [ "radio", "checkbox" ], function() {
25630	jQuery.valHooks[ this ] = {
25631		set: function( elem, value ) {
25632			if ( Array.isArray( value ) ) {
25633				return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 );
25634			}
25635		}
25636	};
25637	if ( !support.checkOn ) {
25638		jQuery.valHooks[ this ].get = function( elem ) {
25639			return elem.getAttribute( "value" ) === null ? "on" : elem.value;
25640		};
25641	}
25642} );
25643
25644
25645
25646
25647// Return jQuery for attributes-only inclusion
25648
25649
25650support.focusin = "onfocusin" in window;
25651
25652
25653var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
25654	stopPropagationCallback = function( e ) {
25655		e.stopPropagation();
25656	};
25657
25658jQuery.extend( jQuery.event, {
25659
25660	trigger: function( event, data, elem, onlyHandlers ) {
25661
25662		var i, cur, tmp, bubbleType, ontype, handle, special, lastElement,
25663			eventPath = [ elem || document ],
25664			type = hasOwn.call( event, "type" ) ? event.type : event,
25665			namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : [];
25666
25667		cur = lastElement = tmp = elem = elem || document;
25668
25669		// Don't do events on text and comment nodes
25670		if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
25671			return;
25672		}
25673
25674		// focus/blur morphs to focusin/out; ensure we're not firing them right now
25675		if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
25676			return;
25677		}
25678
25679		if ( type.indexOf( "." ) > -1 ) {
25680
25681			// Namespaced trigger; create a regexp to match event type in handle()
25682			namespaces = type.split( "." );
25683			type = namespaces.shift();
25684			namespaces.sort();
25685		}
25686		ontype = type.indexOf( ":" ) < 0 && "on" + type;
25687
25688		// Caller can pass in a jQuery.Event object, Object, or just an event type string
25689		event = event[ jQuery.expando ] ?
25690			event :
25691			new jQuery.Event( type, typeof event === "object" && event );
25692
25693		// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
25694		event.isTrigger = onlyHandlers ? 2 : 3;
25695		event.namespace = namespaces.join( "." );
25696		event.rnamespace = event.namespace ?
25697			new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) :
25698			null;
25699
25700		// Clean up the event in case it is being reused
25701		event.result = undefined;
25702		if ( !event.target ) {
25703			event.target = elem;
25704		}
25705
25706		// Clone any incoming data and prepend the event, creating the handler arg list
25707		data = data == null ?
25708			[ event ] :
25709			jQuery.makeArray( data, [ event ] );
25710
25711		// Allow special events to draw outside the lines
25712		special = jQuery.event.special[ type ] || {};
25713		if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
25714			return;
25715		}
25716
25717		// Determine event propagation path in advance, per W3C events spec (#9951)
25718		// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
25719		if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) {
25720
25721			bubbleType = special.delegateType || type;
25722			if ( !rfocusMorph.test( bubbleType + type ) ) {
25723				cur = cur.parentNode;
25724			}
25725			for ( ; cur; cur = cur.parentNode ) {
25726				eventPath.push( cur );
25727				tmp = cur;
25728			}
25729
25730			// Only add window if we got to document (e.g., not plain obj or detached DOM)
25731			if ( tmp === ( elem.ownerDocument || document ) ) {
25732				eventPath.push( tmp.defaultView || tmp.parentWindow || window );
25733			}
25734		}
25735
25736		// Fire handlers on the event path
25737		i = 0;
25738		while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) {
25739			lastElement = cur;
25740			event.type = i > 1 ?
25741				bubbleType :
25742				special.bindType || type;
25743
25744			// jQuery handler
25745			handle = ( dataPriv.get( cur, "events" ) || Object.create( null ) )[ event.type ] &&
25746				dataPriv.get( cur, "handle" );
25747			if ( handle ) {
25748				handle.apply( cur, data );
25749			}
25750
25751			// Native handler
25752			handle = ontype && cur[ ontype ];
25753			if ( handle && handle.apply && acceptData( cur ) ) {
25754				event.result = handle.apply( cur, data );
25755				if ( event.result === false ) {
25756					event.preventDefault();
25757				}
25758			}
25759		}
25760		event.type = type;
25761
25762		// If nobody prevented the default action, do it now
25763		if ( !onlyHandlers && !event.isDefaultPrevented() ) {
25764
25765			if ( ( !special._default ||
25766				special._default.apply( eventPath.pop(), data ) === false ) &&
25767				acceptData( elem ) ) {
25768
25769				// Call a native DOM method on the target with the same name as the event.
25770				// Don't do default actions on window, that's where global variables be (#6170)
25771				if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) {
25772
25773					// Don't re-trigger an onFOO event when we call its FOO() method
25774					tmp = elem[ ontype ];
25775
25776					if ( tmp ) {
25777						elem[ ontype ] = null;
25778					}
25779
25780					// Prevent re-triggering of the same event, since we already bubbled it above
25781					jQuery.event.triggered = type;
25782
25783					if ( event.isPropagationStopped() ) {
25784						lastElement.addEventListener( type, stopPropagationCallback );
25785					}
25786
25787					elem[ type ]();
25788
25789					if ( event.isPropagationStopped() ) {
25790						lastElement.removeEventListener( type, stopPropagationCallback );
25791					}
25792
25793					jQuery.event.triggered = undefined;
25794
25795					if ( tmp ) {
25796						elem[ ontype ] = tmp;
25797					}
25798				}
25799			}
25800		}
25801
25802		return event.result;
25803	},
25804
25805	// Piggyback on a donor event to simulate a different one
25806	// Used only for `focus(in | out)` events
25807	simulate: function( type, elem, event ) {
25808		var e = jQuery.extend(
25809			new jQuery.Event(),
25810			event,
25811			{
25812				type: type,
25813				isSimulated: true
25814			}
25815		);
25816
25817		jQuery.event.trigger( e, null, elem );
25818	}
25819
25820} );
25821
25822jQuery.fn.extend( {
25823
25824	trigger: function( type, data ) {
25825		return this.each( function() {
25826			jQuery.event.trigger( type, data, this );
25827		} );
25828	},
25829	triggerHandler: function( type, data ) {
25830		var elem = this[ 0 ];
25831		if ( elem ) {
25832			return jQuery.event.trigger( type, data, elem, true );
25833		}
25834	}
25835} );
25836
25837
25838// Support: Firefox <=44
25839// Firefox doesn't have focus(in | out) events
25840// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787
25841//
25842// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1
25843// focus(in | out) events fire after focus & blur events,
25844// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order
25845// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857
25846if ( !support.focusin ) {
25847	jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) {
25848
25849		// Attach a single capturing handler on the document while someone wants focusin/focusout
25850		var handler = function( event ) {
25851			jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) );
25852		};
25853
25854		jQuery.event.special[ fix ] = {
25855			setup: function() {
25856
25857				// Handle: regular nodes (via `this.ownerDocument`), window
25858				// (via `this.document`) & document (via `this`).
25859				var doc = this.ownerDocument || this.document || this,
25860					attaches = dataPriv.access( doc, fix );
25861
25862				if ( !attaches ) {
25863					doc.addEventListener( orig, handler, true );
25864				}
25865				dataPriv.access( doc, fix, ( attaches || 0 ) + 1 );
25866			},
25867			teardown: function() {
25868				var doc = this.ownerDocument || this.document || this,
25869					attaches = dataPriv.access( doc, fix ) - 1;
25870
25871				if ( !attaches ) {
25872					doc.removeEventListener( orig, handler, true );
25873					dataPriv.remove( doc, fix );
25874
25875				} else {
25876					dataPriv.access( doc, fix, attaches );
25877				}
25878			}
25879		};
25880	} );
25881}
25882var location = window.location;
25883
25884var nonce = { guid: Date.now() };
25885
25886var rquery = ( /\?/ );
25887
25888
25889
25890// Cross-browser xml parsing
25891jQuery.parseXML = function( data ) {
25892	var xml, parserErrorElem;
25893	if ( !data || typeof data !== "string" ) {
25894		return null;
25895	}
25896
25897	// Support: IE 9 - 11 only
25898	// IE throws on parseFromString with invalid input.
25899	try {
25900		xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" );
25901	} catch ( e ) {}
25902
25903	parserErrorElem = xml && xml.getElementsByTagName( "parsererror" )[ 0 ];
25904	if ( !xml || parserErrorElem ) {
25905		jQuery.error( "Invalid XML: " + (
25906			parserErrorElem ?
25907				jQuery.map( parserErrorElem.childNodes, function( el ) {
25908					return el.textContent;
25909				} ).join( "\n" ) :
25910				data
25911		) );
25912	}
25913	return xml;
25914};
25915
25916
25917var
25918	rbracket = /\[\]$/,
25919	rCRLF = /\r?\n/g,
25920	rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
25921	rsubmittable = /^(?:input|select|textarea|keygen)/i;
25922
25923function buildParams( prefix, obj, traditional, add ) {
25924	var name;
25925
25926	if ( Array.isArray( obj ) ) {
25927
25928		// Serialize array item.
25929		jQuery.each( obj, function( i, v ) {
25930			if ( traditional || rbracket.test( prefix ) ) {
25931
25932				// Treat each array item as a scalar.
25933				add( prefix, v );
25934
25935			} else {
25936
25937				// Item is non-scalar (array or object), encode its numeric index.
25938				buildParams(
25939					prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]",
25940					v,
25941					traditional,
25942					add
25943				);
25944			}
25945		} );
25946
25947	} else if ( !traditional && toType( obj ) === "object" ) {
25948
25949		// Serialize object item.
25950		for ( name in obj ) {
25951			buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
25952		}
25953
25954	} else {
25955
25956		// Serialize scalar item.
25957		add( prefix, obj );
25958	}
25959}
25960
25961// Serialize an array of form elements or a set of
25962// key/values into a query string
25963jQuery.param = function( a, traditional ) {
25964	var prefix,
25965		s = [],
25966		add = function( key, valueOrFunction ) {
25967
25968			// If value is a function, invoke it and use its return value
25969			var value = isFunction( valueOrFunction ) ?
25970				valueOrFunction() :
25971				valueOrFunction;
25972
25973			s[ s.length ] = encodeURIComponent( key ) + "=" +
25974				encodeURIComponent( value == null ? "" : value );
25975		};
25976
25977	if ( a == null ) {
25978		return "";
25979	}
25980
25981	// If an array was passed in, assume that it is an array of form elements.
25982	if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
25983
25984		// Serialize the form elements
25985		jQuery.each( a, function() {
25986			add( this.name, this.value );
25987		} );
25988
25989	} else {
25990
25991		// If traditional, encode the "old" way (the way 1.3.2 or older
25992		// did it), otherwise encode params recursively.
25993		for ( prefix in a ) {
25994			buildParams( prefix, a[ prefix ], traditional, add );
25995		}
25996	}
25997
25998	// Return the resulting serialization
25999	return s.join( "&" );
26000};
26001
26002jQuery.fn.extend( {
26003	serialize: function() {
26004		return jQuery.param( this.serializeArray() );
26005	},
26006	serializeArray: function() {
26007		return this.map( function() {
26008
26009			// Can add propHook for "elements" to filter or add form elements
26010			var elements = jQuery.prop( this, "elements" );
26011			return elements ? jQuery.makeArray( elements ) : this;
26012		} ).filter( function() {
26013			var type = this.type;
26014
26015			// Use .is( ":disabled" ) so that fieldset[disabled] works
26016			return this.name && !jQuery( this ).is( ":disabled" ) &&
26017				rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
26018				( this.checked || !rcheckableType.test( type ) );
26019		} ).map( function( _i, elem ) {
26020			var val = jQuery( this ).val();
26021
26022			if ( val == null ) {
26023				return null;
26024			}
26025
26026			if ( Array.isArray( val ) ) {
26027				return jQuery.map( val, function( val ) {
26028					return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
26029				} );
26030			}
26031
26032			return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
26033		} ).get();
26034	}
26035} );
26036
26037
26038var
26039	r20 = /%20/g,
26040	rhash = /#.*$/,
26041	rantiCache = /([?&])_=[^&]*/,
26042	rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg,
26043
26044	// #7653, #8125, #8152: local protocol detection
26045	rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
26046	rnoContent = /^(?:GET|HEAD)$/,
26047	rprotocol = /^\/\//,
26048
26049	/* Prefilters
26050	 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
26051	 * 2) These are called:
26052	 *    - BEFORE asking for a transport
26053	 *    - AFTER param serialization (s.data is a string if s.processData is true)
26054	 * 3) key is the dataType
26055	 * 4) the catchall symbol "*" can be used
26056	 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
26057	 */
26058	prefilters = {},
26059
26060	/* Transports bindings
26061	 * 1) key is the dataType
26062	 * 2) the catchall symbol "*" can be used
26063	 * 3) selection will start with transport dataType and THEN go to "*" if needed
26064	 */
26065	transports = {},
26066
26067	// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
26068	allTypes = "*/".concat( "*" ),
26069
26070	// Anchor tag for parsing the document origin
26071	originAnchor = document.createElement( "a" );
26072
26073originAnchor.href = location.href;
26074
26075// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
26076function addToPrefiltersOrTransports( structure ) {
26077
26078	// dataTypeExpression is optional and defaults to "*"
26079	return function( dataTypeExpression, func ) {
26080
26081		if ( typeof dataTypeExpression !== "string" ) {
26082			func = dataTypeExpression;
26083			dataTypeExpression = "*";
26084		}
26085
26086		var dataType,
26087			i = 0,
26088			dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || [];
26089
26090		if ( isFunction( func ) ) {
26091
26092			// For each dataType in the dataTypeExpression
26093			while ( ( dataType = dataTypes[ i++ ] ) ) {
26094
26095				// Prepend if requested
26096				if ( dataType[ 0 ] === "+" ) {
26097					dataType = dataType.slice( 1 ) || "*";
26098					( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func );
26099
26100				// Otherwise append
26101				} else {
26102					( structure[ dataType ] = structure[ dataType ] || [] ).push( func );
26103				}
26104			}
26105		}
26106	};
26107}
26108
26109// Base inspection function for prefilters and transports
26110function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
26111
26112	var inspected = {},
26113		seekingTransport = ( structure === transports );
26114
26115	function inspect( dataType ) {
26116		var selected;
26117		inspected[ dataType ] = true;
26118		jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
26119			var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
26120			if ( typeof dataTypeOrTransport === "string" &&
26121				!seekingTransport && !inspected[ dataTypeOrTransport ] ) {
26122
26123				options.dataTypes.unshift( dataTypeOrTransport );
26124				inspect( dataTypeOrTransport );
26125				return false;
26126			} else if ( seekingTransport ) {
26127				return !( selected = dataTypeOrTransport );
26128			}
26129		} );
26130		return selected;
26131	}
26132
26133	return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
26134}
26135
26136// A special extend for ajax options
26137// that takes "flat" options (not to be deep extended)
26138// Fixes #9887
26139function ajaxExtend( target, src ) {
26140	var key, deep,
26141		flatOptions = jQuery.ajaxSettings.flatOptions || {};
26142
26143	for ( key in src ) {
26144		if ( src[ key ] !== undefined ) {
26145			( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
26146		}
26147	}
26148	if ( deep ) {
26149		jQuery.extend( true, target, deep );
26150	}
26151
26152	return target;
26153}
26154
26155/* Handles responses to an ajax request:
26156 * - finds the right dataType (mediates between content-type and expected dataType)
26157 * - returns the corresponding response
26158 */
26159function ajaxHandleResponses( s, jqXHR, responses ) {
26160
26161	var ct, type, finalDataType, firstDataType,
26162		contents = s.contents,
26163		dataTypes = s.dataTypes;
26164
26165	// Remove auto dataType and get content-type in the process
26166	while ( dataTypes[ 0 ] === "*" ) {
26167		dataTypes.shift();
26168		if ( ct === undefined ) {
26169			ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" );
26170		}
26171	}
26172
26173	// Check if we're dealing with a known content-type
26174	if ( ct ) {
26175		for ( type in contents ) {
26176			if ( contents[ type ] && contents[ type ].test( ct ) ) {
26177				dataTypes.unshift( type );
26178				break;
26179			}
26180		}
26181	}
26182
26183	// Check to see if we have a response for the expected dataType
26184	if ( dataTypes[ 0 ] in responses ) {
26185		finalDataType = dataTypes[ 0 ];
26186	} else {
26187
26188		// Try convertible dataTypes
26189		for ( type in responses ) {
26190			if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) {
26191				finalDataType = type;
26192				break;
26193			}
26194			if ( !firstDataType ) {
26195				firstDataType = type;
26196			}
26197		}
26198
26199		// Or just use first one
26200		finalDataType = finalDataType || firstDataType;
26201	}
26202
26203	// If we found a dataType
26204	// We add the dataType to the list if needed
26205	// and return the corresponding response
26206	if ( finalDataType ) {
26207		if ( finalDataType !== dataTypes[ 0 ] ) {
26208			dataTypes.unshift( finalDataType );
26209		}
26210		return responses[ finalDataType ];
26211	}
26212}
26213
26214/* Chain conversions given the request and the original response
26215 * Also sets the responseXXX fields on the jqXHR instance
26216 */
26217function ajaxConvert( s, response, jqXHR, isSuccess ) {
26218	var conv2, current, conv, tmp, prev,
26219		converters = {},
26220
26221		// Work with a copy of dataTypes in case we need to modify it for conversion
26222		dataTypes = s.dataTypes.slice();
26223
26224	// Create converters map with lowercased keys
26225	if ( dataTypes[ 1 ] ) {
26226		for ( conv in s.converters ) {
26227			converters[ conv.toLowerCase() ] = s.converters[ conv ];
26228		}
26229	}
26230
26231	current = dataTypes.shift();
26232
26233	// Convert to each sequential dataType
26234	while ( current ) {
26235
26236		if ( s.responseFields[ current ] ) {
26237			jqXHR[ s.responseFields[ current ] ] = response;
26238		}
26239
26240		// Apply the dataFilter if provided
26241		if ( !prev && isSuccess && s.dataFilter ) {
26242			response = s.dataFilter( response, s.dataType );
26243		}
26244
26245		prev = current;
26246		current = dataTypes.shift();
26247
26248		if ( current ) {
26249
26250			// There's only work to do if current dataType is non-auto
26251			if ( current === "*" ) {
26252
26253				current = prev;
26254
26255			// Convert response if prev dataType is non-auto and differs from current
26256			} else if ( prev !== "*" && prev !== current ) {
26257
26258				// Seek a direct converter
26259				conv = converters[ prev + " " + current ] || converters[ "* " + current ];
26260
26261				// If none found, seek a pair
26262				if ( !conv ) {
26263					for ( conv2 in converters ) {
26264
26265						// If conv2 outputs current
26266						tmp = conv2.split( " " );
26267						if ( tmp[ 1 ] === current ) {
26268
26269							// If prev can be converted to accepted input
26270							conv = converters[ prev + " " + tmp[ 0 ] ] ||
26271								converters[ "* " + tmp[ 0 ] ];
26272							if ( conv ) {
26273
26274								// Condense equivalence converters
26275								if ( conv === true ) {
26276									conv = converters[ conv2 ];
26277
26278								// Otherwise, insert the intermediate dataType
26279								} else if ( converters[ conv2 ] !== true ) {
26280									current = tmp[ 0 ];
26281									dataTypes.unshift( tmp[ 1 ] );
26282								}
26283								break;
26284							}
26285						}
26286					}
26287				}
26288
26289				// Apply converter (if not an equivalence)
26290				if ( conv !== true ) {
26291
26292					// Unless errors are allowed to bubble, catch and return them
26293					if ( conv && s.throws ) {
26294						response = conv( response );
26295					} else {
26296						try {
26297							response = conv( response );
26298						} catch ( e ) {
26299							return {
26300								state: "parsererror",
26301								error: conv ? e : "No conversion from " + prev + " to " + current
26302							};
26303						}
26304					}
26305				}
26306			}
26307		}
26308	}
26309
26310	return { state: "success", data: response };
26311}
26312
26313jQuery.extend( {
26314
26315	// Counter for holding the number of active queries
26316	active: 0,
26317
26318	// Last-Modified header cache for next request
26319	lastModified: {},
26320	etag: {},
26321
26322	ajaxSettings: {
26323		url: location.href,
26324		type: "GET",
26325		isLocal: rlocalProtocol.test( location.protocol ),
26326		global: true,
26327		processData: true,
26328		async: true,
26329		contentType: "application/x-www-form-urlencoded; charset=UTF-8",
26330
26331		/*
26332		timeout: 0,
26333		data: null,
26334		dataType: null,
26335		username: null,
26336		password: null,
26337		cache: null,
26338		throws: false,
26339		traditional: false,
26340		headers: {},
26341		*/
26342
26343		accepts: {
26344			"*": allTypes,
26345			text: "text/plain",
26346			html: "text/html",
26347			xml: "application/xml, text/xml",
26348			json: "application/json, text/javascript"
26349		},
26350
26351		contents: {
26352			xml: /\bxml\b/,
26353			html: /\bhtml/,
26354			json: /\bjson\b/
26355		},
26356
26357		responseFields: {
26358			xml: "responseXML",
26359			text: "responseText",
26360			json: "responseJSON"
26361		},
26362
26363		// Data converters
26364		// Keys separate source (or catchall "*") and destination types with a single space
26365		converters: {
26366
26367			// Convert anything to text
26368			"* text": String,
26369
26370			// Text to html (true = no transformation)
26371			"text html": true,
26372
26373			// Evaluate text as a json expression
26374			"text json": JSON.parse,
26375
26376			// Parse text as xml
26377			"text xml": jQuery.parseXML
26378		},
26379
26380		// For options that shouldn't be deep extended:
26381		// you can add your own custom options here if
26382		// and when you create one that shouldn't be
26383		// deep extended (see ajaxExtend)
26384		flatOptions: {
26385			url: true,
26386			context: true
26387		}
26388	},
26389
26390	// Creates a full fledged settings object into target
26391	// with both ajaxSettings and settings fields.
26392	// If target is omitted, writes into ajaxSettings.
26393	ajaxSetup: function( target, settings ) {
26394		return settings ?
26395
26396			// Building a settings object
26397			ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
26398
26399			// Extending ajaxSettings
26400			ajaxExtend( jQuery.ajaxSettings, target );
26401	},
26402
26403	ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
26404	ajaxTransport: addToPrefiltersOrTransports( transports ),
26405
26406	// Main method
26407	ajax: function( url, options ) {
26408
26409		// If url is an object, simulate pre-1.5 signature
26410		if ( typeof url === "object" ) {
26411			options = url;
26412			url = undefined;
26413		}
26414
26415		// Force options to be an object
26416		options = options || {};
26417
26418		var transport,
26419
26420			// URL without anti-cache param
26421			cacheURL,
26422
26423			// Response headers
26424			responseHeadersString,
26425			responseHeaders,
26426
26427			// timeout handle
26428			timeoutTimer,
26429
26430			// Url cleanup var
26431			urlAnchor,
26432
26433			// Request state (becomes false upon send and true upon completion)
26434			completed,
26435
26436			// To know if global events are to be dispatched
26437			fireGlobals,
26438
26439			// Loop variable
26440			i,
26441
26442			// uncached part of the url
26443			uncached,
26444
26445			// Create the final options object
26446			s = jQuery.ajaxSetup( {}, options ),
26447
26448			// Callbacks context
26449			callbackContext = s.context || s,
26450
26451			// Context for global events is callbackContext if it is a DOM node or jQuery collection
26452			globalEventContext = s.context &&
26453				( callbackContext.nodeType || callbackContext.jquery ) ?
26454				jQuery( callbackContext ) :
26455				jQuery.event,
26456
26457			// Deferreds
26458			deferred = jQuery.Deferred(),
26459			completeDeferred = jQuery.Callbacks( "once memory" ),
26460
26461			// Status-dependent callbacks
26462			statusCode = s.statusCode || {},
26463
26464			// Headers (they are sent all at once)
26465			requestHeaders = {},
26466			requestHeadersNames = {},
26467
26468			// Default abort message
26469			strAbort = "canceled",
26470
26471			// Fake xhr
26472			jqXHR = {
26473				readyState: 0,
26474
26475				// Builds headers hashtable if needed
26476				getResponseHeader: function( key ) {
26477					var match;
26478					if ( completed ) {
26479						if ( !responseHeaders ) {
26480							responseHeaders = {};
26481							while ( ( match = rheaders.exec( responseHeadersString ) ) ) {
26482								responseHeaders[ match[ 1 ].toLowerCase() + " " ] =
26483									( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] )
26484										.concat( match[ 2 ] );
26485							}
26486						}
26487						match = responseHeaders[ key.toLowerCase() + " " ];
26488					}
26489					return match == null ? null : match.join( ", " );
26490				},
26491
26492				// Raw string
26493				getAllResponseHeaders: function() {
26494					return completed ? responseHeadersString : null;
26495				},
26496
26497				// Caches the header
26498				setRequestHeader: function( name, value ) {
26499					if ( completed == null ) {
26500						name = requestHeadersNames[ name.toLowerCase() ] =
26501							requestHeadersNames[ name.toLowerCase() ] || name;
26502						requestHeaders[ name ] = value;
26503					}
26504					return this;
26505				},
26506
26507				// Overrides response content-type header
26508				overrideMimeType: function( type ) {
26509					if ( completed == null ) {
26510						s.mimeType = type;
26511					}
26512					return this;
26513				},
26514
26515				// Status-dependent callbacks
26516				statusCode: function( map ) {
26517					var code;
26518					if ( map ) {
26519						if ( completed ) {
26520
26521							// Execute the appropriate callbacks
26522							jqXHR.always( map[ jqXHR.status ] );
26523						} else {
26524
26525							// Lazy-add the new callbacks in a way that preserves old ones
26526							for ( code in map ) {
26527								statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
26528							}
26529						}
26530					}
26531					return this;
26532				},
26533
26534				// Cancel the request
26535				abort: function( statusText ) {
26536					var finalText = statusText || strAbort;
26537					if ( transport ) {
26538						transport.abort( finalText );
26539					}
26540					done( 0, finalText );
26541					return this;
26542				}
26543			};
26544
26545		// Attach deferreds
26546		deferred.promise( jqXHR );
26547
26548		// Add protocol if not provided (prefilters might expect it)
26549		// Handle falsy url in the settings object (#10093: consistency with old signature)
26550		// We also use the url parameter if available
26551		s.url = ( ( url || s.url || location.href ) + "" )
26552			.replace( rprotocol, location.protocol + "//" );
26553
26554		// Alias method option to type as per ticket #12004
26555		s.type = options.method || options.type || s.method || s.type;
26556
26557		// Extract dataTypes list
26558		s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ];
26559
26560		// A cross-domain request is in order when the origin doesn't match the current origin.
26561		if ( s.crossDomain == null ) {
26562			urlAnchor = document.createElement( "a" );
26563
26564			// Support: IE <=8 - 11, Edge 12 - 15
26565			// IE throws exception on accessing the href property if url is malformed,
26566			// e.g. http://example.com:80x/
26567			try {
26568				urlAnchor.href = s.url;
26569
26570				// Support: IE <=8 - 11 only
26571				// Anchor's host property isn't correctly set when s.url is relative
26572				urlAnchor.href = urlAnchor.href;
26573				s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !==
26574					urlAnchor.protocol + "//" + urlAnchor.host;
26575			} catch ( e ) {
26576
26577				// If there is an error parsing the URL, assume it is crossDomain,
26578				// it can be rejected by the transport if it is invalid
26579				s.crossDomain = true;
26580			}
26581		}
26582
26583		// Convert data if not already a string
26584		if ( s.data && s.processData && typeof s.data !== "string" ) {
26585			s.data = jQuery.param( s.data, s.traditional );
26586		}
26587
26588		// Apply prefilters
26589		inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
26590
26591		// If request was aborted inside a prefilter, stop there
26592		if ( completed ) {
26593			return jqXHR;
26594		}
26595
26596		// We can fire global events as of now if asked to
26597		// Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)
26598		fireGlobals = jQuery.event && s.global;
26599
26600		// Watch for a new set of requests
26601		if ( fireGlobals && jQuery.active++ === 0 ) {
26602			jQuery.event.trigger( "ajaxStart" );
26603		}
26604
26605		// Uppercase the type
26606		s.type = s.type.toUpperCase();
26607
26608		// Determine if request has content
26609		s.hasContent = !rnoContent.test( s.type );
26610
26611		// Save the URL in case we're toying with the If-Modified-Since
26612		// and/or If-None-Match header later on
26613		// Remove hash to simplify url manipulation
26614		cacheURL = s.url.replace( rhash, "" );
26615
26616		// More options handling for requests with no content
26617		if ( !s.hasContent ) {
26618
26619			// Remember the hash so we can put it back
26620			uncached = s.url.slice( cacheURL.length );
26621
26622			// If data is available and should be processed, append data to url
26623			if ( s.data && ( s.processData || typeof s.data === "string" ) ) {
26624				cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data;
26625
26626				// #9682: remove data so that it's not used in an eventual retry
26627				delete s.data;
26628			}
26629
26630			// Add or update anti-cache param if needed
26631			if ( s.cache === false ) {
26632				cacheURL = cacheURL.replace( rantiCache, "$1" );
26633				uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) +
26634					uncached;
26635			}
26636
26637			// Put hash and anti-cache on the URL that will be requested (gh-1732)
26638			s.url = cacheURL + uncached;
26639
26640		// Change '%20' to '+' if this is encoded form body content (gh-2658)
26641		} else if ( s.data && s.processData &&
26642			( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) {
26643			s.data = s.data.replace( r20, "+" );
26644		}
26645
26646		// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
26647		if ( s.ifModified ) {
26648			if ( jQuery.lastModified[ cacheURL ] ) {
26649				jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
26650			}
26651			if ( jQuery.etag[ cacheURL ] ) {
26652				jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
26653			}
26654		}
26655
26656		// Set the correct header, if data is being sent
26657		if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
26658			jqXHR.setRequestHeader( "Content-Type", s.contentType );
26659		}
26660
26661		// Set the Accepts header for the server, depending on the dataType
26662		jqXHR.setRequestHeader(
26663			"Accept",
26664			s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ?
26665				s.accepts[ s.dataTypes[ 0 ] ] +
26666					( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
26667				s.accepts[ "*" ]
26668		);
26669
26670		// Check for headers option
26671		for ( i in s.headers ) {
26672			jqXHR.setRequestHeader( i, s.headers[ i ] );
26673		}
26674
26675		// Allow custom headers/mimetypes and early abort
26676		if ( s.beforeSend &&
26677			( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) {
26678
26679			// Abort if not done already and return
26680			return jqXHR.abort();
26681		}
26682
26683		// Aborting is no longer a cancellation
26684		strAbort = "abort";
26685
26686		// Install callbacks on deferreds
26687		completeDeferred.add( s.complete );
26688		jqXHR.done( s.success );
26689		jqXHR.fail( s.error );
26690
26691		// Get transport
26692		transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
26693
26694		// If no transport, we auto-abort
26695		if ( !transport ) {
26696			done( -1, "No Transport" );
26697		} else {
26698			jqXHR.readyState = 1;
26699
26700			// Send global event
26701			if ( fireGlobals ) {
26702				globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
26703			}
26704
26705			// If request was aborted inside ajaxSend, stop there
26706			if ( completed ) {
26707				return jqXHR;
26708			}
26709
26710			// Timeout
26711			if ( s.async && s.timeout > 0 ) {
26712				timeoutTimer = window.setTimeout( function() {
26713					jqXHR.abort( "timeout" );
26714				}, s.timeout );
26715			}
26716
26717			try {
26718				completed = false;
26719				transport.send( requestHeaders, done );
26720			} catch ( e ) {
26721
26722				// Rethrow post-completion exceptions
26723				if ( completed ) {
26724					throw e;
26725				}
26726
26727				// Propagate others as results
26728				done( -1, e );
26729			}
26730		}
26731
26732		// Callback for when everything is done
26733		function done( status, nativeStatusText, responses, headers ) {
26734			var isSuccess, success, error, response, modified,
26735				statusText = nativeStatusText;
26736
26737			// Ignore repeat invocations
26738			if ( completed ) {
26739				return;
26740			}
26741
26742			completed = true;
26743
26744			// Clear timeout if it exists
26745			if ( timeoutTimer ) {
26746				window.clearTimeout( timeoutTimer );
26747			}
26748
26749			// Dereference transport for early garbage collection
26750			// (no matter how long the jqXHR object will be used)
26751			transport = undefined;
26752
26753			// Cache response headers
26754			responseHeadersString = headers || "";
26755
26756			// Set readyState
26757			jqXHR.readyState = status > 0 ? 4 : 0;
26758
26759			// Determine if successful
26760			isSuccess = status >= 200 && status < 300 || status === 304;
26761
26762			// Get response data
26763			if ( responses ) {
26764				response = ajaxHandleResponses( s, jqXHR, responses );
26765			}
26766
26767			// Use a noop converter for missing script but not if jsonp
26768			if ( !isSuccess &&
26769				jQuery.inArray( "script", s.dataTypes ) > -1 &&
26770				jQuery.inArray( "json", s.dataTypes ) < 0 ) {
26771				s.converters[ "text script" ] = function() {};
26772			}
26773
26774			// Convert no matter what (that way responseXXX fields are always set)
26775			response = ajaxConvert( s, response, jqXHR, isSuccess );
26776
26777			// If successful, handle type chaining
26778			if ( isSuccess ) {
26779
26780				// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
26781				if ( s.ifModified ) {
26782					modified = jqXHR.getResponseHeader( "Last-Modified" );
26783					if ( modified ) {
26784						jQuery.lastModified[ cacheURL ] = modified;
26785					}
26786					modified = jqXHR.getResponseHeader( "etag" );
26787					if ( modified ) {
26788						jQuery.etag[ cacheURL ] = modified;
26789					}
26790				}
26791
26792				// if no content
26793				if ( status === 204 || s.type === "HEAD" ) {
26794					statusText = "nocontent";
26795
26796				// if not modified
26797				} else if ( status === 304 ) {
26798					statusText = "notmodified";
26799
26800				// If we have data, let's convert it
26801				} else {
26802					statusText = response.state;
26803					success = response.data;
26804					error = response.error;
26805					isSuccess = !error;
26806				}
26807			} else {
26808
26809				// Extract error from statusText and normalize for non-aborts
26810				error = statusText;
26811				if ( status || !statusText ) {
26812					statusText = "error";
26813					if ( status < 0 ) {
26814						status = 0;
26815					}
26816				}
26817			}
26818
26819			// Set data for the fake xhr object
26820			jqXHR.status = status;
26821			jqXHR.statusText = ( nativeStatusText || statusText ) + "";
26822
26823			// Success/Error
26824			if ( isSuccess ) {
26825				deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
26826			} else {
26827				deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
26828			}
26829
26830			// Status-dependent callbacks
26831			jqXHR.statusCode( statusCode );
26832			statusCode = undefined;
26833
26834			if ( fireGlobals ) {
26835				globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
26836					[ jqXHR, s, isSuccess ? success : error ] );
26837			}
26838
26839			// Complete
26840			completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
26841
26842			if ( fireGlobals ) {
26843				globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
26844
26845				// Handle the global AJAX counter
26846				if ( !( --jQuery.active ) ) {
26847					jQuery.event.trigger( "ajaxStop" );
26848				}
26849			}
26850		}
26851
26852		return jqXHR;
26853	},
26854
26855	getJSON: function( url, data, callback ) {
26856		return jQuery.get( url, data, callback, "json" );
26857	},
26858
26859	getScript: function( url, callback ) {
26860		return jQuery.get( url, undefined, callback, "script" );
26861	}
26862} );
26863
26864jQuery.each( [ "get", "post" ], function( _i, method ) {
26865	jQuery[ method ] = function( url, data, callback, type ) {
26866
26867		// Shift arguments if data argument was omitted
26868		if ( isFunction( data ) ) {
26869			type = type || callback;
26870			callback = data;
26871			data = undefined;
26872		}
26873
26874		// The url can be an options object (which then must have .url)
26875		return jQuery.ajax( jQuery.extend( {
26876			url: url,
26877			type: method,
26878			dataType: type,
26879			data: data,
26880			success: callback
26881		}, jQuery.isPlainObject( url ) && url ) );
26882	};
26883} );
26884
26885jQuery.ajaxPrefilter( function( s ) {
26886	var i;
26887	for ( i in s.headers ) {
26888		if ( i.toLowerCase() === "content-type" ) {
26889			s.contentType = s.headers[ i ] || "";
26890		}
26891	}
26892} );
26893
26894
26895jQuery._evalUrl = function( url, options, doc ) {
26896	return jQuery.ajax( {
26897		url: url,
26898
26899		// Make this explicit, since user can override this through ajaxSetup (#11264)
26900		type: "GET",
26901		dataType: "script",
26902		cache: true,
26903		async: false,
26904		global: false,
26905
26906		// Only evaluate the response if it is successful (gh-4126)
26907		// dataFilter is not invoked for failure responses, so using it instead
26908		// of the default converter is kludgy but it works.
26909		converters: {
26910			"text script": function() {}
26911		},
26912		dataFilter: function( response ) {
26913			jQuery.globalEval( response, options, doc );
26914		}
26915	} );
26916};
26917
26918
26919jQuery.fn.extend( {
26920	wrapAll: function( html ) {
26921		var wrap;
26922
26923		if ( this[ 0 ] ) {
26924			if ( isFunction( html ) ) {
26925				html = html.call( this[ 0 ] );
26926			}
26927
26928			// The elements to wrap the target around
26929			wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );
26930
26931			if ( this[ 0 ].parentNode ) {
26932				wrap.insertBefore( this[ 0 ] );
26933			}
26934
26935			wrap.map( function() {
26936				var elem = this;
26937
26938				while ( elem.firstElementChild ) {
26939					elem = elem.firstElementChild;
26940				}
26941
26942				return elem;
26943			} ).append( this );
26944		}
26945
26946		return this;
26947	},
26948
26949	wrapInner: function( html ) {
26950		if ( isFunction( html ) ) {
26951			return this.each( function( i ) {
26952				jQuery( this ).wrapInner( html.call( this, i ) );
26953			} );
26954		}
26955
26956		return this.each( function() {
26957			var self = jQuery( this ),
26958				contents = self.contents();
26959
26960			if ( contents.length ) {
26961				contents.wrapAll( html );
26962
26963			} else {
26964				self.append( html );
26965			}
26966		} );
26967	},
26968
26969	wrap: function( html ) {
26970		var htmlIsFunction = isFunction( html );
26971
26972		return this.each( function( i ) {
26973			jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html );
26974		} );
26975	},
26976
26977	unwrap: function( selector ) {
26978		this.parent( selector ).not( "body" ).each( function() {
26979			jQuery( this ).replaceWith( this.childNodes );
26980		} );
26981		return this;
26982	}
26983} );
26984
26985
26986jQuery.expr.pseudos.hidden = function( elem ) {
26987	return !jQuery.expr.pseudos.visible( elem );
26988};
26989jQuery.expr.pseudos.visible = function( elem ) {
26990	return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length );
26991};
26992
26993
26994
26995
26996jQuery.ajaxSettings.xhr = function() {
26997	try {
26998		return new window.XMLHttpRequest();
26999	} catch ( e ) {}
27000};
27001
27002var xhrSuccessStatus = {
27003
27004		// File protocol always yields status code 0, assume 200
27005		0: 200,
27006
27007		// Support: IE <=9 only
27008		// #1450: sometimes IE returns 1223 when it should be 204
27009		1223: 204
27010	},
27011	xhrSupported = jQuery.ajaxSettings.xhr();
27012
27013support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
27014support.ajax = xhrSupported = !!xhrSupported;
27015
27016jQuery.ajaxTransport( function( options ) {
27017	var callback, errorCallback;
27018
27019	// Cross domain only allowed if supported through XMLHttpRequest
27020	if ( support.cors || xhrSupported && !options.crossDomain ) {
27021		return {
27022			send: function( headers, complete ) {
27023				var i,
27024					xhr = options.xhr();
27025
27026				xhr.open(
27027					options.type,
27028					options.url,
27029					options.async,
27030					options.username,
27031					options.password
27032				);
27033
27034				// Apply custom fields if provided
27035				if ( options.xhrFields ) {
27036					for ( i in options.xhrFields ) {
27037						xhr[ i ] = options.xhrFields[ i ];
27038					}
27039				}
27040
27041				// Override mime type if needed
27042				if ( options.mimeType && xhr.overrideMimeType ) {
27043					xhr.overrideMimeType( options.mimeType );
27044				}
27045
27046				// X-Requested-With header
27047				// For cross-domain requests, seeing as conditions for a preflight are
27048				// akin to a jigsaw puzzle, we simply never set it to be sure.
27049				// (it can always be set on a per-request basis or even using ajaxSetup)
27050				// For same-domain requests, won't change header if already provided.
27051				if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) {
27052					headers[ "X-Requested-With" ] = "XMLHttpRequest";
27053				}
27054
27055				// Set headers
27056				for ( i in headers ) {
27057					xhr.setRequestHeader( i, headers[ i ] );
27058				}
27059
27060				// Callback
27061				callback = function( type ) {
27062					return function() {
27063						if ( callback ) {
27064							callback = errorCallback = xhr.onload =
27065								xhr.onerror = xhr.onabort = xhr.ontimeout =
27066									xhr.onreadystatechange = null;
27067
27068							if ( type === "abort" ) {
27069								xhr.abort();
27070							} else if ( type === "error" ) {
27071
27072								// Support: IE <=9 only
27073								// On a manual native abort, IE9 throws
27074								// errors on any property access that is not readyState
27075								if ( typeof xhr.status !== "number" ) {
27076									complete( 0, "error" );
27077								} else {
27078									complete(
27079
27080										// File: protocol always yields status 0; see #8605, #14207
27081										xhr.status,
27082										xhr.statusText
27083									);
27084								}
27085							} else {
27086								complete(
27087									xhrSuccessStatus[ xhr.status ] || xhr.status,
27088									xhr.statusText,
27089
27090									// Support: IE <=9 only
27091									// IE9 has no XHR2 but throws on binary (trac-11426)
27092									// For XHR2 non-text, let the caller handle it (gh-2498)
27093									( xhr.responseType || "text" ) !== "text"  ||
27094									typeof xhr.responseText !== "string" ?
27095										{ binary: xhr.response } :
27096										{ text: xhr.responseText },
27097									xhr.getAllResponseHeaders()
27098								);
27099							}
27100						}
27101					};
27102				};
27103
27104				// Listen to events
27105				xhr.onload = callback();
27106				errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" );
27107
27108				// Support: IE 9 only
27109				// Use onreadystatechange to replace onabort
27110				// to handle uncaught aborts
27111				if ( xhr.onabort !== undefined ) {
27112					xhr.onabort = errorCallback;
27113				} else {
27114					xhr.onreadystatechange = function() {
27115
27116						// Check readyState before timeout as it changes
27117						if ( xhr.readyState === 4 ) {
27118
27119							// Allow onerror to be called first,
27120							// but that will not handle a native abort
27121							// Also, save errorCallback to a variable
27122							// as xhr.onerror cannot be accessed
27123							window.setTimeout( function() {
27124								if ( callback ) {
27125									errorCallback();
27126								}
27127							} );
27128						}
27129					};
27130				}
27131
27132				// Create the abort callback
27133				callback = callback( "abort" );
27134
27135				try {
27136
27137					// Do send the request (this may raise an exception)
27138					xhr.send( options.hasContent && options.data || null );
27139				} catch ( e ) {
27140
27141					// #14683: Only rethrow if this hasn't been notified as an error yet
27142					if ( callback ) {
27143						throw e;
27144					}
27145				}
27146			},
27147
27148			abort: function() {
27149				if ( callback ) {
27150					callback();
27151				}
27152			}
27153		};
27154	}
27155} );
27156
27157
27158
27159
27160// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432)
27161jQuery.ajaxPrefilter( function( s ) {
27162	if ( s.crossDomain ) {
27163		s.contents.script = false;
27164	}
27165} );
27166
27167// Install script dataType
27168jQuery.ajaxSetup( {
27169	accepts: {
27170		script: "text/javascript, application/javascript, " +
27171			"application/ecmascript, application/x-ecmascript"
27172	},
27173	contents: {
27174		script: /\b(?:java|ecma)script\b/
27175	},
27176	converters: {
27177		"text script": function( text ) {
27178			jQuery.globalEval( text );
27179			return text;
27180		}
27181	}
27182} );
27183
27184// Handle cache's special case and crossDomain
27185jQuery.ajaxPrefilter( "script", function( s ) {
27186	if ( s.cache === undefined ) {
27187		s.cache = false;
27188	}
27189	if ( s.crossDomain ) {
27190		s.type = "GET";
27191	}
27192} );
27193
27194// Bind script tag hack transport
27195jQuery.ajaxTransport( "script", function( s ) {
27196
27197	// This transport only deals with cross domain or forced-by-attrs requests
27198	if ( s.crossDomain || s.scriptAttrs ) {
27199		var script, callback;
27200		return {
27201			send: function( _, complete ) {
27202				script = jQuery( "<script>" )
27203					.attr( s.scriptAttrs || {} )
27204					.prop( { charset: s.scriptCharset, src: s.url } )
27205					.on( "load error", callback = function( evt ) {
27206						script.remove();
27207						callback = null;
27208						if ( evt ) {
27209							complete( evt.type === "error" ? 404 : 200, evt.type );
27210						}
27211					} );
27212
27213				// Use native DOM manipulation to avoid our domManip AJAX trickery
27214				document.head.appendChild( script[ 0 ] );
27215			},
27216			abort: function() {
27217				if ( callback ) {
27218					callback();
27219				}
27220			}
27221		};
27222	}
27223} );
27224
27225
27226
27227
27228var oldCallbacks = [],
27229	rjsonp = /(=)\?(?=&|$)|\?\?/;
27230
27231// Default jsonp settings
27232jQuery.ajaxSetup( {
27233	jsonp: "callback",
27234	jsonpCallback: function() {
27235		var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce.guid++ ) );
27236		this[ callback ] = true;
27237		return callback;
27238	}
27239} );
27240
27241// Detect, normalize options and install callbacks for jsonp requests
27242jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
27243
27244	var callbackName, overwritten, responseContainer,
27245		jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
27246			"url" :
27247			typeof s.data === "string" &&
27248				( s.contentType || "" )
27249					.indexOf( "application/x-www-form-urlencoded" ) === 0 &&
27250				rjsonp.test( s.data ) && "data"
27251		);
27252
27253	// Handle iff the expected data type is "jsonp" or we have a parameter to set
27254	if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
27255
27256		// Get callback name, remembering preexisting value associated with it
27257		callbackName = s.jsonpCallback = isFunction( s.jsonpCallback ) ?
27258			s.jsonpCallback() :
27259			s.jsonpCallback;
27260
27261		// Insert callback into url or form data
27262		if ( jsonProp ) {
27263			s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
27264		} else if ( s.jsonp !== false ) {
27265			s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
27266		}
27267
27268		// Use data converter to retrieve json after script execution
27269		s.converters[ "script json" ] = function() {
27270			if ( !responseContainer ) {
27271				jQuery.error( callbackName + " was not called" );
27272			}
27273			return responseContainer[ 0 ];
27274		};
27275
27276		// Force json dataType
27277		s.dataTypes[ 0 ] = "json";
27278
27279		// Install callback
27280		overwritten = window[ callbackName ];
27281		window[ callbackName ] = function() {
27282			responseContainer = arguments;
27283		};
27284
27285		// Clean-up function (fires after converters)
27286		jqXHR.always( function() {
27287
27288			// If previous value didn't exist - remove it
27289			if ( overwritten === undefined ) {
27290				jQuery( window ).removeProp( callbackName );
27291
27292			// Otherwise restore preexisting value
27293			} else {
27294				window[ callbackName ] = overwritten;
27295			}
27296
27297			// Save back as free
27298			if ( s[ callbackName ] ) {
27299
27300				// Make sure that re-using the options doesn't screw things around
27301				s.jsonpCallback = originalSettings.jsonpCallback;
27302
27303				// Save the callback name for future use
27304				oldCallbacks.push( callbackName );
27305			}
27306
27307			// Call if it was a function and we have a response
27308			if ( responseContainer && isFunction( overwritten ) ) {
27309				overwritten( responseContainer[ 0 ] );
27310			}
27311
27312			responseContainer = overwritten = undefined;
27313		} );
27314
27315		// Delegate to script
27316		return "script";
27317	}
27318} );
27319
27320
27321
27322
27323// Support: Safari 8 only
27324// In Safari 8 documents created via document.implementation.createHTMLDocument
27325// collapse sibling forms: the second one becomes a child of the first one.
27326// Because of that, this security measure has to be disabled in Safari 8.
27327// https://bugs.webkit.org/show_bug.cgi?id=137337
27328support.createHTMLDocument = ( function() {
27329	var body = document.implementation.createHTMLDocument( "" ).body;
27330	body.innerHTML = "<form></form><form></form>";
27331	return body.childNodes.length === 2;
27332} )();
27333
27334
27335// Argument "data" should be string of html
27336// context (optional): If specified, the fragment will be created in this context,
27337// defaults to document
27338// keepScripts (optional): If true, will include scripts passed in the html string
27339jQuery.parseHTML = function( data, context, keepScripts ) {
27340	if ( typeof data !== "string" ) {
27341		return [];
27342	}
27343	if ( typeof context === "boolean" ) {
27344		keepScripts = context;
27345		context = false;
27346	}
27347
27348	var base, parsed, scripts;
27349
27350	if ( !context ) {
27351
27352		// Stop scripts or inline event handlers from being executed immediately
27353		// by using document.implementation
27354		if ( support.createHTMLDocument ) {
27355			context = document.implementation.createHTMLDocument( "" );
27356
27357			// Set the base href for the created document
27358			// so any parsed elements with URLs
27359			// are based on the document's URL (gh-2965)
27360			base = context.createElement( "base" );
27361			base.href = document.location.href;
27362			context.head.appendChild( base );
27363		} else {
27364			context = document;
27365		}
27366	}
27367
27368	parsed = rsingleTag.exec( data );
27369	scripts = !keepScripts && [];
27370
27371	// Single tag
27372	if ( parsed ) {
27373		return [ context.createElement( parsed[ 1 ] ) ];
27374	}
27375
27376	parsed = buildFragment( [ data ], context, scripts );
27377
27378	if ( scripts && scripts.length ) {
27379		jQuery( scripts ).remove();
27380	}
27381
27382	return jQuery.merge( [], parsed.childNodes );
27383};
27384
27385
27386/**
27387 * Load a url into a page
27388 */
27389jQuery.fn.load = function( url, params, callback ) {
27390	var selector, type, response,
27391		self = this,
27392		off = url.indexOf( " " );
27393
27394	if ( off > -1 ) {
27395		selector = stripAndCollapse( url.slice( off ) );
27396		url = url.slice( 0, off );
27397	}
27398
27399	// If it's a function
27400	if ( isFunction( params ) ) {
27401
27402		// We assume that it's the callback
27403		callback = params;
27404		params = undefined;
27405
27406	// Otherwise, build a param string
27407	} else if ( params && typeof params === "object" ) {
27408		type = "POST";
27409	}
27410
27411	// If we have elements to modify, make the request
27412	if ( self.length > 0 ) {
27413		jQuery.ajax( {
27414			url: url,
27415
27416			// If "type" variable is undefined, then "GET" method will be used.
27417			// Make value of this field explicit since
27418			// user can override it through ajaxSetup method
27419			type: type || "GET",
27420			dataType: "html",
27421			data: params
27422		} ).done( function( responseText ) {
27423
27424			// Save response for use in complete callback
27425			response = arguments;
27426
27427			self.html( selector ?
27428
27429				// If a selector was specified, locate the right elements in a dummy div
27430				// Exclude scripts to avoid IE 'Permission Denied' errors
27431				jQuery( "<div>" ).append( jQuery.parseHTML( responseText ) ).find( selector ) :
27432
27433				// Otherwise use the full result
27434				responseText );
27435
27436		// If the request succeeds, this function gets "data", "status", "jqXHR"
27437		// but they are ignored because response was set above.
27438		// If it fails, this function gets "jqXHR", "status", "error"
27439		} ).always( callback && function( jqXHR, status ) {
27440			self.each( function() {
27441				callback.apply( this, response || [ jqXHR.responseText, status, jqXHR ] );
27442			} );
27443		} );
27444	}
27445
27446	return this;
27447};
27448
27449
27450
27451
27452jQuery.expr.pseudos.animated = function( elem ) {
27453	return jQuery.grep( jQuery.timers, function( fn ) {
27454		return elem === fn.elem;
27455	} ).length;
27456};
27457
27458
27459
27460
27461jQuery.offset = {
27462	setOffset: function( elem, options, i ) {
27463		var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
27464			position = jQuery.css( elem, "position" ),
27465			curElem = jQuery( elem ),
27466			props = {};
27467
27468		// Set position first, in-case top/left are set even on static elem
27469		if ( position === "static" ) {
27470			elem.style.position = "relative";
27471		}
27472
27473		curOffset = curElem.offset();
27474		curCSSTop = jQuery.css( elem, "top" );
27475		curCSSLeft = jQuery.css( elem, "left" );
27476		calculatePosition = ( position === "absolute" || position === "fixed" ) &&
27477			( curCSSTop + curCSSLeft ).indexOf( "auto" ) > -1;
27478
27479		// Need to be able to calculate position if either
27480		// top or left is auto and position is either absolute or fixed
27481		if ( calculatePosition ) {
27482			curPosition = curElem.position();
27483			curTop = curPosition.top;
27484			curLeft = curPosition.left;
27485
27486		} else {
27487			curTop = parseFloat( curCSSTop ) || 0;
27488			curLeft = parseFloat( curCSSLeft ) || 0;
27489		}
27490
27491		if ( isFunction( options ) ) {
27492
27493			// Use jQuery.extend here to allow modification of coordinates argument (gh-1848)
27494			options = options.call( elem, i, jQuery.extend( {}, curOffset ) );
27495		}
27496
27497		if ( options.top != null ) {
27498			props.top = ( options.top - curOffset.top ) + curTop;
27499		}
27500		if ( options.left != null ) {
27501			props.left = ( options.left - curOffset.left ) + curLeft;
27502		}
27503
27504		if ( "using" in options ) {
27505			options.using.call( elem, props );
27506
27507		} else {
27508			curElem.css( props );
27509		}
27510	}
27511};
27512
27513jQuery.fn.extend( {
27514
27515	// offset() relates an element's border box to the document origin
27516	offset: function( options ) {
27517
27518		// Preserve chaining for setter
27519		if ( arguments.length ) {
27520			return options === undefined ?
27521				this :
27522				this.each( function( i ) {
27523					jQuery.offset.setOffset( this, options, i );
27524				} );
27525		}
27526
27527		var rect, win,
27528			elem = this[ 0 ];
27529
27530		if ( !elem ) {
27531			return;
27532		}
27533
27534		// Return zeros for disconnected and hidden (display: none) elements (gh-2310)
27535		// Support: IE <=11 only
27536		// Running getBoundingClientRect on a
27537		// disconnected node in IE throws an error
27538		if ( !elem.getClientRects().length ) {
27539			return { top: 0, left: 0 };
27540		}
27541
27542		// Get document-relative position by adding viewport scroll to viewport-relative gBCR
27543		rect = elem.getBoundingClientRect();
27544		win = elem.ownerDocument.defaultView;
27545		return {
27546			top: rect.top + win.pageYOffset,
27547			left: rect.left + win.pageXOffset
27548		};
27549	},
27550
27551	// position() relates an element's margin box to its offset parent's padding box
27552	// This corresponds to the behavior of CSS absolute positioning
27553	position: function() {
27554		if ( !this[ 0 ] ) {
27555			return;
27556		}
27557
27558		var offsetParent, offset, doc,
27559			elem = this[ 0 ],
27560			parentOffset = { top: 0, left: 0 };
27561
27562		// position:fixed elements are offset from the viewport, which itself always has zero offset
27563		if ( jQuery.css( elem, "position" ) === "fixed" ) {
27564
27565			// Assume position:fixed implies availability of getBoundingClientRect
27566			offset = elem.getBoundingClientRect();
27567
27568		} else {
27569			offset = this.offset();
27570
27571			// Account for the *real* offset parent, which can be the document or its root element
27572			// when a statically positioned element is identified
27573			doc = elem.ownerDocument;
27574			offsetParent = elem.offsetParent || doc.documentElement;
27575			while ( offsetParent &&
27576				( offsetParent === doc.body || offsetParent === doc.documentElement ) &&
27577				jQuery.css( offsetParent, "position" ) === "static" ) {
27578
27579				offsetParent = offsetParent.parentNode;
27580			}
27581			if ( offsetParent && offsetParent !== elem && offsetParent.nodeType === 1 ) {
27582
27583				// Incorporate borders into its offset, since they are outside its content origin
27584				parentOffset = jQuery( offsetParent ).offset();
27585				parentOffset.top += jQuery.css( offsetParent, "borderTopWidth", true );
27586				parentOffset.left += jQuery.css( offsetParent, "borderLeftWidth", true );
27587			}
27588		}
27589
27590		// Subtract parent offsets and element margins
27591		return {
27592			top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
27593			left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )
27594		};
27595	},
27596
27597	// This method will return documentElement in the following cases:
27598	// 1) For the element inside the iframe without offsetParent, this method will return
27599	//    documentElement of the parent window
27600	// 2) For the hidden or detached element
27601	// 3) For body or html element, i.e. in case of the html node - it will return itself
27602	//
27603	// but those exceptions were never presented as a real life use-cases
27604	// and might be considered as more preferable results.
27605	//
27606	// This logic, however, is not guaranteed and can change at any point in the future
27607	offsetParent: function() {
27608		return this.map( function() {
27609			var offsetParent = this.offsetParent;
27610
27611			while ( offsetParent && jQuery.css( offsetParent, "position" ) === "static" ) {
27612				offsetParent = offsetParent.offsetParent;
27613			}
27614
27615			return offsetParent || documentElement;
27616		} );
27617	}
27618} );
27619
27620// Create scrollLeft and scrollTop methods
27621jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
27622	var top = "pageYOffset" === prop;
27623
27624	jQuery.fn[ method ] = function( val ) {
27625		return access( this, function( elem, method, val ) {
27626
27627			// Coalesce documents and windows
27628			var win;
27629			if ( isWindow( elem ) ) {
27630				win = elem;
27631			} else if ( elem.nodeType === 9 ) {
27632				win = elem.defaultView;
27633			}
27634
27635			if ( val === undefined ) {
27636				return win ? win[ prop ] : elem[ method ];
27637			}
27638
27639			if ( win ) {
27640				win.scrollTo(
27641					!top ? val : win.pageXOffset,
27642					top ? val : win.pageYOffset
27643				);
27644
27645			} else {
27646				elem[ method ] = val;
27647			}
27648		}, method, val, arguments.length );
27649	};
27650} );
27651
27652// Support: Safari <=7 - 9.1, Chrome <=37 - 49
27653// Add the top/left cssHooks using jQuery.fn.position
27654// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
27655// Blink bug: https://bugs.chromium.org/p/chromium/issues/detail?id=589347
27656// getComputedStyle returns percent when specified for top/left/bottom/right;
27657// rather than make the css module depend on the offset module, just check for it here
27658jQuery.each( [ "top", "left" ], function( _i, prop ) {
27659	jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
27660		function( elem, computed ) {
27661			if ( computed ) {
27662				computed = curCSS( elem, prop );
27663
27664				// If curCSS returns percentage, fallback to offset
27665				return rnumnonpx.test( computed ) ?
27666					jQuery( elem ).position()[ prop ] + "px" :
27667					computed;
27668			}
27669		}
27670	);
27671} );
27672
27673
27674// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
27675jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
27676	jQuery.each( {
27677		padding: "inner" + name,
27678		content: type,
27679		"": "outer" + name
27680	}, function( defaultExtra, funcName ) {
27681
27682		// Margin is only for outerHeight, outerWidth
27683		jQuery.fn[ funcName ] = function( margin, value ) {
27684			var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
27685				extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
27686
27687			return access( this, function( elem, type, value ) {
27688				var doc;
27689
27690				if ( isWindow( elem ) ) {
27691
27692					// $( window ).outerWidth/Height return w/h including scrollbars (gh-1729)
27693					return funcName.indexOf( "outer" ) === 0 ?
27694						elem[ "inner" + name ] :
27695						elem.document.documentElement[ "client" + name ];
27696				}
27697
27698				// Get document width or height
27699				if ( elem.nodeType === 9 ) {
27700					doc = elem.documentElement;
27701
27702					// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],
27703					// whichever is greatest
27704					return Math.max(
27705						elem.body[ "scroll" + name ], doc[ "scroll" + name ],
27706						elem.body[ "offset" + name ], doc[ "offset" + name ],
27707						doc[ "client" + name ]
27708					);
27709				}
27710
27711				return value === undefined ?
27712
27713					// Get width or height on the element, requesting but not forcing parseFloat
27714					jQuery.css( elem, type, extra ) :
27715
27716					// Set width or height on the element
27717					jQuery.style( elem, type, value, extra );
27718			}, type, chainable ? margin : undefined, chainable );
27719		};
27720	} );
27721} );
27722
27723
27724jQuery.each( [
27725	"ajaxStart",
27726	"ajaxStop",
27727	"ajaxComplete",
27728	"ajaxError",
27729	"ajaxSuccess",
27730	"ajaxSend"
27731], function( _i, type ) {
27732	jQuery.fn[ type ] = function( fn ) {
27733		return this.on( type, fn );
27734	};
27735} );
27736
27737
27738
27739
27740jQuery.fn.extend( {
27741
27742	bind: function( types, data, fn ) {
27743		return this.on( types, null, data, fn );
27744	},
27745	unbind: function( types, fn ) {
27746		return this.off( types, null, fn );
27747	},
27748
27749	delegate: function( selector, types, data, fn ) {
27750		return this.on( types, selector, data, fn );
27751	},
27752	undelegate: function( selector, types, fn ) {
27753
27754		// ( namespace ) or ( selector, types [, fn] )
27755		return arguments.length === 1 ?
27756			this.off( selector, "**" ) :
27757			this.off( types, selector || "**", fn );
27758	},
27759
27760	hover: function( fnOver, fnOut ) {
27761		return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
27762	}
27763} );
27764
27765jQuery.each(
27766	( "blur focus focusin focusout resize scroll click dblclick " +
27767	"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
27768	"change select submit keydown keypress keyup contextmenu" ).split( " " ),
27769	function( _i, name ) {
27770
27771		// Handle event binding
27772		jQuery.fn[ name ] = function( data, fn ) {
27773			return arguments.length > 0 ?
27774				this.on( name, null, data, fn ) :
27775				this.trigger( name );
27776		};
27777	}
27778);
27779
27780
27781
27782
27783// Support: Android <=4.0 only
27784// Make sure we trim BOM and NBSP
27785var rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;
27786
27787// Bind a function to a context, optionally partially applying any
27788// arguments.
27789// jQuery.proxy is deprecated to promote standards (specifically Function#bind)
27790// However, it is not slated for removal any time soon
27791jQuery.proxy = function( fn, context ) {
27792	var tmp, args, proxy;
27793
27794	if ( typeof context === "string" ) {
27795		tmp = fn[ context ];
27796		context = fn;
27797		fn = tmp;
27798	}
27799
27800	// Quick check to determine if target is callable, in the spec
27801	// this throws a TypeError, but we will just return undefined.
27802	if ( !isFunction( fn ) ) {
27803		return undefined;
27804	}
27805
27806	// Simulated bind
27807	args = slice.call( arguments, 2 );
27808	proxy = function() {
27809		return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
27810	};
27811
27812	// Set the guid of unique handler to the same of original handler, so it can be removed
27813	proxy.guid = fn.guid = fn.guid || jQuery.guid++;
27814
27815	return proxy;
27816};
27817
27818jQuery.holdReady = function( hold ) {
27819	if ( hold ) {
27820		jQuery.readyWait++;
27821	} else {
27822		jQuery.ready( true );
27823	}
27824};
27825jQuery.isArray = Array.isArray;
27826jQuery.parseJSON = JSON.parse;
27827jQuery.nodeName = nodeName;
27828jQuery.isFunction = isFunction;
27829jQuery.isWindow = isWindow;
27830jQuery.camelCase = camelCase;
27831jQuery.type = toType;
27832
27833jQuery.now = Date.now;
27834
27835jQuery.isNumeric = function( obj ) {
27836
27837	// As of jQuery 3.0, isNumeric is limited to
27838	// strings and numbers (primitives or objects)
27839	// that can be coerced to finite numbers (gh-2662)
27840	var type = jQuery.type( obj );
27841	return ( type === "number" || type === "string" ) &&
27842
27843		// parseFloat NaNs numeric-cast false positives ("")
27844		// ...but misinterprets leading-number strings, particularly hex literals ("0x...")
27845		// subtraction forces infinities to NaN
27846		!isNaN( obj - parseFloat( obj ) );
27847};
27848
27849jQuery.trim = function( text ) {
27850	return text == null ?
27851		"" :
27852		( text + "" ).replace( rtrim, "" );
27853};
27854
27855
27856
27857// Register as a named AMD module, since jQuery can be concatenated with other
27858// files that may use define, but not via a proper concatenation script that
27859// understands anonymous AMD modules. A named AMD is safest and most robust
27860// way to register. Lowercase jquery is used because AMD module names are
27861// derived from file names, and jQuery is normally delivered in a lowercase
27862// file name. Do this after creating the global so that if an AMD module wants
27863// to call noConflict to hide this version of jQuery, it will work.
27864
27865// Note that for maximum portability, libraries that are not jQuery should
27866// declare themselves as anonymous modules, and avoid setting a global if an
27867// AMD loader is present. jQuery is a special case. For more information, see
27868// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
27869
27870if ( true ) {
27871	!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = (function() {
27872		return jQuery;
27873	}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
27874				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
27875}
27876
27877
27878
27879
27880var
27881
27882	// Map over jQuery in case of overwrite
27883	_jQuery = window.jQuery,
27884
27885	// Map over the $ in case of overwrite
27886	_$ = window.$;
27887
27888jQuery.noConflict = function( deep ) {
27889	if ( window.$ === jQuery ) {
27890		window.$ = _$;
27891	}
27892
27893	if ( deep && window.jQuery === jQuery ) {
27894		window.jQuery = _jQuery;
27895	}
27896
27897	return jQuery;
27898};
27899
27900// Expose jQuery and $ identifiers, even in AMD
27901// (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
27902// and CommonJS for browser emulators (#13566)
27903if ( typeof noGlobal === "undefined" ) {
27904	window.jQuery = window.$ = jQuery;
27905}
27906
27907
27908
27909
27910return jQuery;
27911} );
27912
27913
27914/***/ }),
27915
27916/***/ "./node_modules/mini-css-extract-plugin/dist/loader.js!./node_modules/css-loader/dist/cjs.js?!./node_modules/postcss-loader/src/index.js?!./node_modules/sass-loader/dist/cjs.js?!./Frontend/SCSS/main.scss":
27917/*!************************************************************************************************************************************************************************************************************************************!*\
27918  !*** ./node_modules/mini-css-extract-plugin/dist/loader.js!./node_modules/css-loader/dist/cjs.js??ref--6-2!./node_modules/postcss-loader/src??ref--6-3!./node_modules/sass-loader/dist/cjs.js??ref--6-4!./Frontend/SCSS/main.scss ***!
27919  \************************************************************************************************************************************************************************************************************************************/
27920/*! no static exports found */
27921/***/ (function(module, exports, __webpack_require__) {
27922
27923// extracted by mini-css-extract-plugin
27924
27925/***/ }),
27926
vendor: 7,080 bytes, lines 27927-28204
27927/***/ "./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js":
27928/*!****************************************************************************!*\
27929  !*** ./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js ***!
27930  \****************************************************************************/
27931/*! no static exports found */
27932/***/ (function(module, exports, __webpack_require__) {
27933
27934"use strict";
27935
27936
27937var isOldIE = function isOldIE() {
27938  var memo;
27939  return function memorize() {
27940    if (typeof memo === 'undefined') {
27941      // Test for IE <= 9 as proposed by Browserhacks
27942      // @see http://browserhacks.com/#hack-e71d8692f65334173fee715c222cb805
27943      // Tests for existence of standard globals is to allow style-loader
27944      // to operate correctly into non-standard environments
27945      // @see https://github.com/webpack-contrib/style-loader/issues/177
27946      memo = Boolean(window && document && document.all && !window.atob);
27947    }
27948
27949    return memo;
27950  };
27951}();
27952
27953var getTarget = function getTarget() {
27954  var memo = {};
27955  return function memorize(target) {
27956    if (typeof memo[target] === 'undefined') {
27957      var styleTarget = document.querySelector(target); // Special case to return head of iframe instead of iframe itself
27958
27959      if (window.HTMLIFrameElement && styleTarget instanceof window.HTMLIFrameElement) {
27960        try {
27961          // This will throw an exception if access to iframe is blocked
27962          // due to cross-origin restrictions
27963          styleTarget = styleTarget.contentDocument.head;
27964        } catch (e) {
27965          // istanbul ignore next
27966          styleTarget = null;
27967        }
27968      }
27969
27970      memo[target] = styleTarget;
27971    }
27972
27973    return memo[target];
27974  };
27975}();
27976
27977var stylesInDom = [];
27978
27979function getIndexByIdentifier(identifier) {
27980  var result = -1;
27981
27982  for (var i = 0; i < stylesInDom.length; i++) {
27983    if (stylesInDom[i].identifier === identifier) {
27984      result = i;
27985      break;
27986    }
27987  }
27988
27989  return result;
27990}
27991
27992function modulesToDom(list, options) {
27993  var idCountMap = {};
27994  var identifiers = [];
27995
27996  for (var i = 0; i < list.length; i++) {
27997    var item = list[i];
27998    var id = options.base ? item[0] + options.base : item[0];
27999    var count = idCountMap[id] || 0;
28000    var identifier = "".concat(id, " ").concat(count);
28001    idCountMap[id] = count + 1;
28002    var index = getIndexByIdentifier(identifier);
28003    var obj = {
28004      css: item[1],
28005      media: item[2],
28006      sourceMap: item[3]
28007    };
28008
28009    if (index !== -1) {
28010      stylesInDom[index].references++;
28011      stylesInDom[index].updater(obj);
28012    } else {
28013      stylesInDom.push({
28014        identifier: identifier,
28015        updater: addStyle(obj, options),
28016        references: 1
28017      });
28018    }
28019
28020    identifiers.push(identifier);
28021  }
28022
28023  return identifiers;
28024}
28025
28026function insertStyleElement(options) {
28027  var style = document.createElement('style');
28028  var attributes = options.attributes || {};
28029
28030  if (typeof attributes.nonce === 'undefined') {
28031    var nonce =  true ? __webpack_require__.nc : undefined;
28032
28033    if (nonce) {
28034      attributes.nonce = nonce;
28035    }
28036  }
28037
28038  Object.keys(attributes).forEach(function (key) {
28039    style.setAttribute(key, attributes[key]);
28040  });
28041
28042  if (typeof options.insert === 'function') {
28043    options.insert(style);
28044  } else {
28045    var target = getTarget(options.insert || 'head');
28046
28047    if (!target) {
28048      throw new Error("Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid.");
28049    }
28050
28051    target.appendChild(style);
28052  }
28053
28054  return style;
28055}
28056
28057function removeStyleElement(style) {
28058  // istanbul ignore if
28059  if (style.parentNode === null) {
28060    return false;
28061  }
28062
28063  style.parentNode.removeChild(style);
28064}
28065/* istanbul ignore next  */
28066
28067
28068var replaceText = function replaceText() {
28069  var textStore = [];
28070  return function replace(index, replacement) {
28071    textStore[index] = replacement;
28072    return textStore.filter(Boolean).join('\n');
28073  };
28074}();
28075
28076function applyToSingletonTag(style, index, remove, obj) {
28077  var css = remove ? '' : obj.media ? "@media ".concat(obj.media, " {").concat(obj.css, "}") : obj.css; // For old IE
28078
28079  /* istanbul ignore if  */
28080
28081  if (style.styleSheet) {
28082    style.styleSheet.cssText = replaceText(index, css);
28083  } else {
28084    var cssNode = document.createTextNode(css);
28085    var childNodes = style.childNodes;
28086
28087    if (childNodes[index]) {
28088      style.removeChild(childNodes[index]);
28089    }
28090
28091    if (childNodes.length) {
28092      style.insertBefore(cssNode, childNodes[index]);
28093    } else {
28094      style.appendChild(cssNode);
28095    }
28096  }
28097}
28098
28099function applyToTag(style, options, obj) {
28100  var css = obj.css;
28101  var media = obj.media;
28102  var sourceMap = obj.sourceMap;
28103
28104  if (media) {
28105    style.setAttribute('media', media);
28106  } else {
28107    style.removeAttribute('media');
28108  }
28109
28110  if (sourceMap && typeof btoa !== 'undefined') {
28111  } // For old IE
28112
28113  /* istanbul ignore if  */
28114
28115
28116  if (style.styleSheet) {
28117    style.styleSheet.cssText = css;
28118  } else {
28119    while (style.firstChild) {
28120      style.removeChild(style.firstChild);
28121    }
28122
28123    style.appendChild(document.createTextNode(css));
28124  }
28125}
28126
28127var singleton = null;
28128var singletonCounter = 0;
28129
28130function addStyle(obj, options) {
28131  var style;
28132  var update;
28133  var remove;
28134
28135  if (options.singleton) {
28136    var styleIndex = singletonCounter++;
28137    style = singleton || (singleton = insertStyleElement(options));
28138    update = applyToSingletonTag.bind(null, style, styleIndex, false);
28139    remove = applyToSingletonTag.bind(null, style, styleIndex, true);
28140  } else {
28141    style = insertStyleElement(options);
28142    update = applyToTag.bind(null, style, options);
28143
28144    remove = function remove() {
28145      removeStyleElement(style);
28146    };
28147  }
28148
28149  update(obj);
28150  return function updateStyle(newObj) {
28151    if (newObj) {
28152      if (newObj.css === obj.css && newObj.media === obj.media && newObj.sourceMap === obj.sourceMap) {
28153        return;
28154      }
28155
28156      update(obj = newObj);
28157    } else {
28158      remove();
28159    }
28160  };
28161}
28162
28163module.exports = function (list, options) {
28164  options = options || {}; // Force single-tag solution on IE6-9, which has a hard limit on the # of <style>
28165  // tags it will allow on a page
28166
28167  if (!options.singleton && typeof options.singleton !== 'boolean') {
28168    options.singleton = isOldIE();
28169  }
28170
28171  list = list || [];
28172  var lastIdentifiers = modulesToDom(list, options);
28173  return function update(newList) {
28174    newList = newList || [];
28175
28176    if (Object.prototype.toString.call(newList) !== '[object Array]') {
28177      return;
28178    }
28179
28180    for (var i = 0; i < lastIdentifiers.length; i++) {
28181      var identifier = lastIdentifiers[i];
28182      var index = getIndexByIdentifier(identifier);
28183      stylesInDom[index].references--;
28184    }
28185
28186    var newLastIdentifiers = modulesToDom(newList, options);
28187
28188    for (var _i = 0; _i < lastIdentifiers.length; _i++) {
28189      var _identifier = lastIdentifiers[_i];
28190
28191      var _index = getIndexByIdentifier(_identifier);
28192
28193      if (stylesInDom[_index].references === 0) {
28194        stylesInDom[_index].updater();
28195
28196        stylesInDom.splice(_index, 1);
28197      }
28198    }
28199
28200    lastIdentifiers = newLastIdentifiers;
28201  };
28202};
28203
28204/***/ })
28204,
28205
28206/***/ 0:
28207/*!********************************************************************************!*\
28208  !*** multi ./Frontend/JavaScript/src/public/main.js ./Frontend/SCSS/main.scss ***!
28209  \********************************************************************************/
28210/*! no static exports found */
28211/***/ (function(module, exports, __webpack_require__) {
28212
28213__webpack_require__(/*! ./Frontend/JavaScript/src/public/main.js */"./Frontend/JavaScript/src/public/main.js");
28214module.exports = __webpack_require__(/*! ./Frontend/SCSS/main.scss */"./Frontend/SCSS/main.scss");
28215
28216
28217/***/ })
28218
28219/******/ });

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.