1/*! DataTables 1.13.5
2 * ©2008-2023 SpryMedia Ltd - datatables.net/license
3 */
4
5/**
6 * @summary     DataTables
7 * @description Paginate, search and order HTML tables
8 * @version     1.13.4
9 * @author      SpryMedia Ltd
10 * @contact     www.datatables.net
11 * @copyright   SpryMedia Ltd.
12 *
13 * This source file is free software, available under the following license:
14 *   MIT license - http://datatables.net/license
15 *
16 * This source file is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
19 *
20 * For details please refer to: http://www.datatables.net
21 */
22
23/*jslint evil: true, undef: true, browser: true */
24/*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*/
25
26(function( factory ) {
27	"use strict";
28
29	if ( typeof define === 'function' && define.amd ) {
30		// AMD
31		define( ['jquery'], function ( $ ) {
32			return factory( $, window, document );
33		} );
34	}
35	else if ( typeof exports === 'object' ) {
36		// CommonJS
37		// jQuery's factory checks for a global window - if it isn't present then it
38		// returns a factory function that expects the window object
39		var jq = require('jquery');
40
41		if (typeof window !== 'undefined') {
42			module.exports = function (root, $) {
43				if ( ! root ) {
44					// CommonJS environments without a window global must pass a
45					// root. This will give an error otherwise
46					root = window;
47				}
48
49				if ( ! $ ) {
50					$ = jq( root );
51				}
52
53				return factory( $, root, root.document );
54			};
55		}
56		else {
57			return factory( jq, window, window.document );
58		}
59	}
60	else {
61		// Browser
62		window.DataTable = factory( jQuery, window, document );
63	}
64}
65(function( $, window, document, undefined ) {
66	"use strict";
67
68
69	var DataTable = function ( selector, options )
70	{
71		// Check if called with a window or jQuery object for DOM less applications
72		// This is for backwards compatibility
73		if (DataTable.factory(selector, options)) {
74			return DataTable;
75		}
76
77		// When creating with `new`, create a new DataTable, returning the API instance
78		if (this instanceof DataTable) {
79			return $(selector).DataTable(options);
80		}
81		else {
82			// Argument switching
83			options = selector;
84		}
85
86		/**
87		 * Perform a jQuery selector action on the table's TR elements (from the tbody) and
88		 * return the resulting jQuery object.
89		 *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
90		 *  @param {object} [oOpts] Optional parameters for modifying the rows to be included
91		 *  @param {string} [oOpts.filter=none] Select TR elements that meet the current filter
92		 *    criterion ("applied") or all TR elements (i.e. no filter).
93		 *  @param {string} [oOpts.order=current] Order of the TR elements in the processed array.
94		 *    Can be either 'current', whereby the current sorting of the table is used, or
95		 *    'original' whereby the original order the data was read into the table is used.
96		 *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
97		 *    ("current") or not ("all"). If 'current' is given, then order is assumed to be
98		 *    'current' and filter is 'applied', regardless of what they might be given as.
99		 *  @returns {object} jQuery object, filtered by the given selector.
100		 *  @dtopt API
101		 *  @deprecated Since v1.10
102		 *
103		 *  @example
104		 *    $(document).ready(function() {
105		 *      var oTable = $('#example').dataTable();
106		 *
107		 *      // Highlight every second row
108		 *      oTable.$('tr:odd').css('backgroundColor', 'blue');
109		 *    } );
110		 *
111		 *  @example
112		 *    $(document).ready(function() {
113		 *      var oTable = $('#example').dataTable();
114		 *
115		 *      // Filter to rows with 'Webkit' in them, add a background colour and then
116		 *      // remove the filter, thus highlighting the 'Webkit' rows only.
117		 *      oTable.fnFilter('Webkit');
118		 *      oTable.$('tr', {"search": "applied"}).css('backgroundColor', 'blue');
119		 *      oTable.fnFilter('');
120		 *    } );
121		 */
122		this.$ = function ( sSelector, oOpts )
123		{
124			return this.api(true).$( sSelector, oOpts );
125		};
126
127
128		/**
129		 * Almost identical to $ in operation, but in this case returns the data for the matched
130		 * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes
131		 * rather than any descendants, so the data can be obtained for the row/cell. If matching
132		 * rows are found, the data returned is the original data array/object that was used to
133		 * create the row (or a generated array if from a DOM source).
134		 *
135		 * This method is often useful in-combination with $ where both functions are given the
136		 * same parameters and the array indexes will match identically.
137		 *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
138		 *  @param {object} [oOpts] Optional parameters for modifying the rows to be included
139		 *  @param {string} [oOpts.filter=none] Select elements that meet the current filter
140		 *    criterion ("applied") or all elements (i.e. no filter).
141		 *  @param {string} [oOpts.order=current] Order of the data in the processed array.
142		 *    Can be either 'current', whereby the current sorting of the table is used, or
143		 *    'original' whereby the original order the data was read into the table is used.
144		 *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
145		 *    ("current") or not ("all"). If 'current' is given, then order is assumed to be
146		 *    'current' and filter is 'applied', regardless of what they might be given as.
147		 *  @returns {array} Data for the matched elements. If any elements, as a result of the
148		 *    selector, were not TR, TD or TH elements in the DataTable, they will have a null
149		 *    entry in the array.
150		 *  @dtopt API
151		 *  @deprecated Since v1.10
152		 *
153		 *  @example
154		 *    $(document).ready(function() {
155		 *      var oTable = $('#example').dataTable();
156		 *
157		 *      // Get the data from the first row in the table
158		 *      var data = oTable._('tr:first');
159		 *
160		 *      // Do something useful with the data
161		 *      alert( "First cell is: "+data[0] );
162		 *    } );
163		 *
164		 *  @example
165		 *    $(document).ready(function() {
166		 *      var oTable = $('#example').dataTable();
167		 *
168		 *      // Filter to 'Webkit' and get all data for
169		 *      oTable.fnFilter('Webkit');
170		 *      var data = oTable._('tr', {"search": "applied"});
171		 *
172		 *      // Do something with the data
173		 *      alert( data.length+" rows matched the search" );
174		 *    } );
175		 */
176		this._ = function ( sSelector, oOpts )
177		{
178			return this.api(true).rows( sSelector, oOpts ).data();
179		};
180
181
182		/**
183		 * Create a DataTables Api instance, with the currently selected tables for
184		 * the Api's context.
185		 * @param {boolean} [traditional=false] Set the API instance's context to be
186		 *   only the table referred to by the `DataTable.ext.iApiIndex` option, as was
187		 *   used in the API presented by DataTables 1.9- (i.e. the traditional mode),
188		 *   or if all tables captured in the jQuery object should be used.
189		 * @return {DataTables.Api}
190		 */
191		this.api = function ( traditional )
192		{
193			return traditional ?
194				new _Api(
195					_fnSettingsFromNode( this[ _ext.iApiIndex ] )
196				) :
197				new _Api( this );
198		};
199
200
201		/**
202		 * Add a single new row or multiple rows of data to the table. Please note
203		 * that this is suitable for client-side processing only - if you are using
204		 * server-side processing (i.e. "bServerSide": true), then to add data, you
205		 * must add it to the data source, i.e. the server-side, through an Ajax call.
206		 *  @param {array|object} data The data to be added to the table. This can be:
207		 *    <ul>
208		 *      <li>1D array of data - add a single row with the data provided</li>
209		 *      <li>2D array of arrays - add multiple rows in a single call</li>
210		 *      <li>object - data object when using <i>mData</i></li>
211		 *      <li>array of objects - multiple data objects when using <i>mData</i></li>
212		 *    </ul>
213		 *  @param {bool} [redraw=true] redraw the table or not
214		 *  @returns {array} An array of integers, representing the list of indexes in
215		 *    <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to
216		 *    the table.
217		 *  @dtopt API
218		 *  @deprecated Since v1.10
219		 *
220		 *  @example
221		 *    // Global var for counter
222		 *    var giCount = 2;
223		 *
224		 *    $(document).ready(function() {
225		 *      $('#example').dataTable();
226		 *    } );
227		 *
228		 *    function fnClickAddRow() {
229		 *      $('#example').dataTable().fnAddData( [
230		 *        giCount+".1",
231		 *        giCount+".2",
232		 *        giCount+".3",
233		 *        giCount+".4" ]
234		 *      );
235		 *
236		 *      giCount++;
237		 *    }
238		 */
239		this.fnAddData = function( data, redraw )
240		{
241			var api = this.api( true );
242
243			/* Check if we want to add multiple rows or not */
244			var rows = Array.isArray(data) && ( Array.isArray(data[0]) || $.isPlainObject(data[0]) ) ?
245				api.rows.add( data ) :
246				api.row.add( data );
247
248			if ( redraw === undefined || redraw ) {
249				api.draw();
250			}
251
252			return rows.flatten().toArray();
253		};
254
255
256		/**
257		 * This function will make DataTables recalculate the column sizes, based on the data
258		 * contained in the table and the sizes applied to the columns (in the DOM, CSS or
259		 * through the sWidth parameter). This can be useful when the width of the table's
260		 * parent element changes (for example a window resize).
261		 *  @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to
262		 *  @dtopt API
263		 *  @deprecated Since v1.10
264		 *
265		 *  @example
266		 *    $(document).ready(function() {
267		 *      var oTable = $('#example').dataTable( {
268		 *        "sScrollY": "200px",
269		 *        "bPaginate": false
270		 *      } );
271		 *
272		 *      $(window).on('resize', function () {
273		 *        oTable.fnAdjustColumnSizing();
274		 *      } );
275		 *    } );
276		 */
277		this.fnAdjustColumnSizing = function ( bRedraw )
278		{
279			var api = this.api( true ).columns.adjust();
280			var settings = api.settings()[0];
281			var scroll = settings.oScroll;
282
283			if ( bRedraw === undefined || bRedraw ) {
284				api.draw( false );
285			}
286			else if ( scroll.sX !== "" || scroll.sY !== "" ) {
287				/* If not redrawing, but scrolling, we want to apply the new column sizes anyway */
288				_fnScrollDraw( settings );
289			}
290		};
291
292
293		/**
294		 * Quickly and simply clear a table
295		 *  @param {bool} [bRedraw=true] redraw the table or not
296		 *  @dtopt API
297		 *  @deprecated Since v1.10
298		 *
299		 *  @example
300		 *    $(document).ready(function() {
301		 *      var oTable = $('#example').dataTable();
302		 *
303		 *      // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...)
304		 *      oTable.fnClearTable();
305		 *    } );
306		 */
307		this.fnClearTable = function( bRedraw )
308		{
309			var api = this.api( true ).clear();
310
311			if ( bRedraw === undefined || bRedraw ) {
312				api.draw();
313			}
314		};
315
316
317		/**
318		 * The exact opposite of 'opening' a row, this function will close any rows which
319		 * are currently 'open'.
320		 *  @param {node} nTr the table row to 'close'
321		 *  @returns {int} 0 on success, or 1 if failed (can't find the row)
322		 *  @dtopt API
323		 *  @deprecated Since v1.10
324		 *
325		 *  @example
326		 *    $(document).ready(function() {
327		 *      var oTable;
328		 *
329		 *      // 'open' an information row when a row is clicked on
330		 *      $('#example tbody tr').click( function () {
331		 *        if ( oTable.fnIsOpen(this) ) {
332		 *          oTable.fnClose( this );
333		 *        } else {
334		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
335		 *        }
336		 *      } );
337		 *
338		 *      oTable = $('#example').dataTable();
339		 *    } );
340		 */
341		this.fnClose = function( nTr )
342		{
343			this.api( true ).row( nTr ).child.hide();
344		};
345
346
347		/**
348		 * Remove a row for the table
349		 *  @param {mixed} target The index of the row from aoData to be deleted, or
350		 *    the TR element you want to delete
351		 *  @param {function|null} [callBack] Callback function
352		 *  @param {bool} [redraw=true] Redraw the table or not
353		 *  @returns {array} The row that was deleted
354		 *  @dtopt API
355		 *  @deprecated Since v1.10
356		 *
357		 *  @example
358		 *    $(document).ready(function() {
359		 *      var oTable = $('#example').dataTable();
360		 *
361		 *      // Immediately remove the first row
362		 *      oTable.fnDeleteRow( 0 );
363		 *    } );
364		 */
365		this.fnDeleteRow = function( target, callback, redraw )
366		{
367			var api = this.api( true );
368			var rows = api.rows( target );
369			var settings = rows.settings()[0];
370			var data = settings.aoData[ rows[0][0] ];
371
372			rows.remove();
373
374			if ( callback ) {
375				callback.call( this, settings, data );
376			}
377
378			if ( redraw === undefined || redraw ) {
379				api.draw();
380			}
381
382			return data;
383		};
384
385
386		/**
387		 * Restore the table to it's original state in the DOM by removing all of DataTables
388		 * enhancements, alterations to the DOM structure of the table and event listeners.
389		 *  @param {boolean} [remove=false] Completely remove the table from the DOM
390		 *  @dtopt API
391		 *  @deprecated Since v1.10
392		 *
393		 *  @example
394		 *    $(document).ready(function() {
395		 *      // This example is fairly pointless in reality, but shows how fnDestroy can be used
396		 *      var oTable = $('#example').dataTable();
397		 *      oTable.fnDestroy();
398		 *    } );
399		 */
400		this.fnDestroy = function ( remove )
401		{
402			this.api( true ).destroy( remove );
403		};
404
405
406		/**
407		 * Redraw the table
408		 *  @param {bool} [complete=true] Re-filter and resort (if enabled) the table before the draw.
409		 *  @dtopt API
410		 *  @deprecated Since v1.10
411		 *
412		 *  @example
413		 *    $(document).ready(function() {
414		 *      var oTable = $('#example').dataTable();
415		 *
416		 *      // Re-draw the table - you wouldn't want to do it here, but it's an example :-)
417		 *      oTable.fnDraw();
418		 *    } );
419		 */
420		this.fnDraw = function( complete )
421		{
422			// Note that this isn't an exact match to the old call to _fnDraw - it takes
423			// into account the new data, but can hold position.
424			this.api( true ).draw( complete );
425		};
426
427
428		/**
429		 * Filter the input based on data
430		 *  @param {string} sInput String to filter the table on
431		 *  @param {int|null} [iColumn] Column to limit filtering to
432		 *  @param {bool} [bRegex=false] Treat as regular expression or not
433		 *  @param {bool} [bSmart=true] Perform smart filtering or not
434		 *  @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es)
435		 *  @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false)
436		 *  @dtopt API
437		 *  @deprecated Since v1.10
438		 *
439		 *  @example
440		 *    $(document).ready(function() {
441		 *      var oTable = $('#example').dataTable();
442		 *
443		 *      // Sometime later - filter...
444		 *      oTable.fnFilter( 'test string' );
445		 *    } );
446		 */
447		this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive )
448		{
449			var api = this.api( true );
450
451			if ( iColumn === null || iColumn === undefined ) {
452				api.search( sInput, bRegex, bSmart, bCaseInsensitive );
453			}
454			else {
455				api.column( iColumn ).search( sInput, bRegex, bSmart, bCaseInsensitive );
456			}
457
458			api.draw();
459		};
460
461
462		/**
463		 * Get the data for the whole table, an individual row or an individual cell based on the
464		 * provided parameters.
465		 *  @param {int|node} [src] A TR row node, TD/TH cell node or an integer. If given as
466		 *    a TR node then the data source for the whole row will be returned. If given as a
467		 *    TD/TH cell node then iCol will be automatically calculated and the data for the
468		 *    cell returned. If given as an integer, then this is treated as the aoData internal
469		 *    data index for the row (see fnGetPosition) and the data for that row used.
470		 *  @param {int} [col] Optional column index that you want the data of.
471		 *  @returns {array|object|string} If mRow is undefined, then the data for all rows is
472		 *    returned. If mRow is defined, just data for that row, and is iCol is
473		 *    defined, only data for the designated cell is returned.
474		 *  @dtopt API
475		 *  @deprecated Since v1.10
476		 *
477		 *  @example
478		 *    // Row data
479		 *    $(document).ready(function() {
480		 *      oTable = $('#example').dataTable();
481		 *
482		 *      oTable.$('tr').click( function () {
483		 *        var data = oTable.fnGetData( this );
484		 *        // ... do something with the array / object of data for the row
485		 *      } );
486		 *    } );
487		 *
488		 *  @example
489		 *    // Individual cell data
490		 *    $(document).ready(function() {
491		 *      oTable = $('#example').dataTable();
492		 *
493		 *      oTable.$('td').click( function () {
494		 *        var sData = oTable.fnGetData( this );
495		 *        alert( 'The cell clicked on had the value of '+sData );
496		 *      } );
497		 *    } );
498		 */
499		this.fnGetData = function( src, col )
500		{
501			var api = this.api( true );
502
503			if ( src !== undefined ) {
504				var type = src.nodeName ? src.nodeName.toLowerCase() : '';
505
506				return col !== undefined || type == 'td' || type == 'th' ?
507					api.cell( src, col ).data() :
508					api.row( src ).data() || null;
509			}
510
511			return api.data().toArray();
512		};
513
514
515		/**
516		 * Get an array of the TR nodes that are used in the table's body. Note that you will
517		 * typically want to use the '$' API method in preference to this as it is more
518		 * flexible.
519		 *  @param {int} [iRow] Optional row index for the TR element you want
520		 *  @returns {array|node} If iRow is undefined, returns an array of all TR elements
521		 *    in the table's body, or iRow is defined, just the TR element requested.
522		 *  @dtopt API
523		 *  @deprecated Since v1.10
524		 *
525		 *  @example
526		 *    $(document).ready(function() {
527		 *      var oTable = $('#example').dataTable();
528		 *
529		 *      // Get the nodes from the table
530		 *      var nNodes = oTable.fnGetNodes( );
531		 *    } );
532		 */
533		this.fnGetNodes = function( iRow )
534		{
535			var api = this.api( true );
536
537			return iRow !== undefined ?
538				api.row( iRow ).node() :
539				api.rows().nodes().flatten().toArray();
540		};
541
542
543		/**
544		 * Get the array indexes of a particular cell from it's DOM element
545		 * and column index including hidden columns
546		 *  @param {node} node this can either be a TR, TD or TH in the table's body
547		 *  @returns {int} If nNode is given as a TR, then a single index is returned, or
548		 *    if given as a cell, an array of [row index, column index (visible),
549		 *    column index (all)] is given.
550		 *  @dtopt API
551		 *  @deprecated Since v1.10
552		 *
553		 *  @example
554		 *    $(document).ready(function() {
555		 *      $('#example tbody td').click( function () {
556		 *        // Get the position of the current data from the node
557		 *        var aPos = oTable.fnGetPosition( this );
558		 *
559		 *        // Get the data array for this row
560		 *        var aData = oTable.fnGetData( aPos[0] );
561		 *
562		 *        // Update the data array and return the value
563		 *        aData[ aPos[1] ] = 'clicked';
564		 *        this.innerHTML = 'clicked';
565		 *      } );
566		 *
567		 *      // Init DataTables
568		 *      oTable = $('#example').dataTable();
569		 *    } );
570		 */
571		this.fnGetPosition = function( node )
572		{
573			var api = this.api( true );
574			var nodeName = node.nodeName.toUpperCase();
575
576			if ( nodeName == 'TR' ) {
577				return api.row( node ).index();
578			}
579			else if ( nodeName == 'TD' || nodeName == 'TH' ) {
580				var cell = api.cell( node ).index();
581
582				return [
583					cell.row,
584					cell.columnVisible,
585					cell.column
586				];
587			}
588			return null;
589		};
590
591
592		/**
593		 * Check to see if a row is 'open' or not.
594		 *  @param {node} nTr the table row to check
595		 *  @returns {boolean} true if the row is currently open, false otherwise
596		 *  @dtopt API
597		 *  @deprecated Since v1.10
598		 *
599		 *  @example
600		 *    $(document).ready(function() {
601		 *      var oTable;
602		 *
603		 *      // 'open' an information row when a row is clicked on
604		 *      $('#example tbody tr').click( function () {
605		 *        if ( oTable.fnIsOpen(this) ) {
606		 *          oTable.fnClose( this );
607		 *        } else {
608		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
609		 *        }
610		 *      } );
611		 *
612		 *      oTable = $('#example').dataTable();
613		 *    } );
614		 */
615		this.fnIsOpen = function( nTr )
616		{
617			return this.api( true ).row( nTr ).child.isShown();
618		};
619
620
621		/**
622		 * This function will place a new row directly after a row which is currently
623		 * on display on the page, with the HTML contents that is passed into the
624		 * function. This can be used, for example, to ask for confirmation that a
625		 * particular record should be deleted.
626		 *  @param {node} nTr The table row to 'open'
627		 *  @param {string|node|jQuery} mHtml The HTML to put into the row
628		 *  @param {string} sClass Class to give the new TD cell
629		 *  @returns {node} The row opened. Note that if the table row passed in as the
630		 *    first parameter, is not found in the table, this method will silently
631		 *    return.
632		 *  @dtopt API
633		 *  @deprecated Since v1.10
634		 *
635		 *  @example
636		 *    $(document).ready(function() {
637		 *      var oTable;
638		 *
639		 *      // 'open' an information row when a row is clicked on
640		 *      $('#example tbody tr').click( function () {
641		 *        if ( oTable.fnIsOpen(this) ) {
642		 *          oTable.fnClose( this );
643		 *        } else {
644		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
645		 *        }
646		 *      } );
647		 *
648		 *      oTable = $('#example').dataTable();
649		 *    } );
650		 */
651		this.fnOpen = function( nTr, mHtml, sClass )
652		{
653			return this.api( true )
654				.row( nTr )
655				.child( mHtml, sClass )
656				.show()
657				.child()[0];
658		};
659
660
661		/**
662		 * Change the pagination - provides the internal logic for pagination in a simple API
663		 * function. With this function you can have a DataTables table go to the next,
664		 * previous, first or last pages.
665		 *  @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
666		 *    or page number to jump to (integer), note that page 0 is the first page.
667		 *  @param {bool} [bRedraw=true] Redraw the table or not
668		 *  @dtopt API
669		 *  @deprecated Since v1.10
670		 *
671		 *  @example
672		 *    $(document).ready(function() {
673		 *      var oTable = $('#example').dataTable();
674		 *      oTable.fnPageChange( 'next' );
675		 *    } );
676		 */
677		this.fnPageChange = function ( mAction, bRedraw )
678		{
679			var api = this.api( true ).page( mAction );
680
681			if ( bRedraw === undefined || bRedraw ) {
682				api.draw(false);
683			}
684		};
685
686
687		/**
688		 * Show a particular column
689		 *  @param {int} iCol The column whose display should be changed
690		 *  @param {bool} bShow Show (true) or hide (false) the column
691		 *  @param {bool} [bRedraw=true] Redraw the table or not
692		 *  @dtopt API
693		 *  @deprecated Since v1.10
694		 *
695		 *  @example
696		 *    $(document).ready(function() {
697		 *      var oTable = $('#example').dataTable();
698		 *
699		 *      // Hide the second column after initialisation
700		 *      oTable.fnSetColumnVis( 1, false );
701		 *    } );
702		 */
703		this.fnSetColumnVis = function ( iCol, bShow, bRedraw )
704		{
705			var api = this.api( true ).column( iCol ).visible( bShow );
706
707			if ( bRedraw === undefined || bRedraw ) {
708				api.columns.adjust().draw();
709			}
710		};
711
712
713		/**
714		 * Get the settings for a particular table for external manipulation
715		 *  @returns {object} DataTables settings object. See
716		 *    {@link DataTable.models.oSettings}
717		 *  @dtopt API
718		 *  @deprecated Since v1.10
719		 *
720		 *  @example
721		 *    $(document).ready(function() {
722		 *      var oTable = $('#example').dataTable();
723		 *      var oSettings = oTable.fnSettings();
724		 *
725		 *      // Show an example parameter from the settings
726		 *      alert( oSettings._iDisplayStart );
727		 *    } );
728		 */
729		this.fnSettings = function()
730		{
731			return _fnSettingsFromNode( this[_ext.iApiIndex] );
732		};
733
734
735		/**
736		 * Sort the table by a particular column
737		 *  @param {int} iCol the data index to sort on. Note that this will not match the
738		 *    'display index' if you have hidden data entries
739		 *  @dtopt API
740		 *  @deprecated Since v1.10
741		 *
742		 *  @example
743		 *    $(document).ready(function() {
744		 *      var oTable = $('#example').dataTable();
745		 *
746		 *      // Sort immediately with columns 0 and 1
747		 *      oTable.fnSort( [ [0,'asc'], [1,'asc'] ] );
748		 *    } );
749		 */
750		this.fnSort = function( aaSort )
751		{
752			this.api( true ).order( aaSort ).draw();
753		};
754
755
756		/**
757		 * Attach a sort listener to an element for a given column
758		 *  @param {node} nNode the element to attach the sort listener to
759		 *  @param {int} iColumn the column that a click on this node will sort on
760		 *  @param {function} [fnCallback] callback function when sort is run
761		 *  @dtopt API
762		 *  @deprecated Since v1.10
763		 *
764		 *  @example
765		 *    $(document).ready(function() {
766		 *      var oTable = $('#example').dataTable();
767		 *
768		 *      // Sort on column 1, when 'sorter' is clicked on
769		 *      oTable.fnSortListener( document.getElementById('sorter'), 1 );
770		 *    } );
771		 */
772		this.fnSortListener = function( nNode, iColumn, fnCallback )
773		{
774			this.api( true ).order.listener( nNode, iColumn, fnCallback );
775		};
776
777
778		/**
779		 * Update a table cell or row - this method will accept either a single value to
780		 * update the cell with, an array of values with one element for each column or
781		 * an object in the same format as the original data source. The function is
782		 * self-referencing in order to make the multi column updates easier.
783		 *  @param {object|array|string} mData Data to update the cell/row with
784		 *  @param {node|int} mRow TR element you want to update or the aoData index
785		 *  @param {int} [iColumn] The column to update, give as null or undefined to
786		 *    update a whole row.
787		 *  @param {bool} [bRedraw=true] Redraw the table or not
788		 *  @param {bool} [bAction=true] Perform pre-draw actions or not
789		 *  @returns {int} 0 on success, 1 on error
790		 *  @dtopt API
791		 *  @deprecated Since v1.10
792		 *
793		 *  @example
794		 *    $(document).ready(function() {
795		 *      var oTable = $('#example').dataTable();
796		 *      oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell
797		 *      oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], $('tbody tr')[0] ); // Row
798		 *    } );
799		 */
800		this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction )
801		{
802			var api = this.api( true );
803
804			if ( iColumn === undefined || iColumn === null ) {
805				api.row( mRow ).data( mData );
806			}
807			else {
808				api.cell( mRow, iColumn ).data( mData );
809			}
810
811			if ( bAction === undefined || bAction ) {
812				api.columns.adjust();
813			}
814
815			if ( bRedraw === undefined || bRedraw ) {
816				api.draw();
817			}
818			return 0;
819		};
820
821
822		/**
823		 * Provide a common method for plug-ins to check the version of DataTables being used, in order
824		 * to ensure compatibility.
825		 *  @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the
826		 *    formats "X" and "X.Y" are also acceptable.
827		 *  @returns {boolean} true if this version of DataTables is greater or equal to the required
828		 *    version, or false if this version of DataTales is not suitable
829		 *  @method
830		 *  @dtopt API
831		 *  @deprecated Since v1.10
832		 *
833		 *  @example
834		 *    $(document).ready(function() {
835		 *      var oTable = $('#example').dataTable();
836		 *      alert( oTable.fnVersionCheck( '1.9.0' ) );
837		 *    } );
838		 */
839		this.fnVersionCheck = _ext.fnVersionCheck;
840
841
842		var _that = this;
843		var emptyInit = options === undefined;
844		var len = this.length;
845
846		if ( emptyInit ) {
847			options = {};
848		}
849
850		this.oApi = this.internal = _ext.internal;
851
852		// Extend with old style plug-in API methods
853		for ( var fn in DataTable.ext.internal ) {
854			if ( fn ) {
855				this[fn] = _fnExternApiFunc(fn);
856			}
857		}
858
859		this.each(function() {
860			// For each initialisation we want to give it a clean initialisation
861			// object that can be bashed around
862			var o = {};
863			var oInit = len > 1 ? // optimisation for single table case
864				_fnExtend( o, options, true ) :
865				options;
866
867			/*global oInit,_that,emptyInit*/
868			var i=0, iLen, j, jLen, k, kLen;
869			var sId = this.getAttribute( 'id' );
870			var bInitHandedOff = false;
871			var defaults = DataTable.defaults;
872			var $this = $(this);
873
874
875			/* Sanity check */
876			if ( this.nodeName.toLowerCase() != 'table' )
877			{
878				_fnLog( null, 0, 'Non-table node initialisation ('+this.nodeName+')', 2 );
879				return;
880			}
881
882			/* Backwards compatibility for the defaults */
883			_fnCompatOpts( defaults );
884			_fnCompatCols( defaults.column );
885
886			/* Convert the camel-case defaults to Hungarian */
887			_fnCamelToHungarian( defaults, defaults, true );
888			_fnCamelToHungarian( defaults.column, defaults.column, true );
889
890			/* Setting up the initialisation object */
891			_fnCamelToHungarian( defaults, $.extend( oInit, $this.data() ), true );
892
893
894
895			/* Check to see if we are re-initialising a table */
896			var allSettings = DataTable.settings;
897			for ( i=0, iLen=allSettings.length ; i<iLen ; i++ )
898			{
899				var s = allSettings[i];
900
901				/* Base check on table node */
902				if (
903					s.nTable == this ||
904					(s.nTHead && s.nTHead.parentNode == this) ||
905					(s.nTFoot && s.nTFoot.parentNode == this)
906				) {
907					var bRetrieve = oInit.bRetrieve !== undefined ? oInit.bRetrieve : defaults.bRetrieve;
908					var bDestroy = oInit.bDestroy !== undefined ? oInit.bDestroy : defaults.bDestroy;
909
910					if ( emptyInit || bRetrieve )
911					{
912						return s.oInstance;
913					}
914					else if ( bDestroy )
915					{
916						s.oInstance.fnDestroy();
917						break;
918					}
919					else
920					{
921						_fnLog( s, 0, 'Cannot reinitialise DataTable', 3 );
922						return;
923					}
924				}
925
926				/* If the element we are initialising has the same ID as a table which was previously
927				 * initialised, but the table nodes don't match (from before) then we destroy the old
928				 * instance by simply deleting it. This is under the assumption that the table has been
929				 * destroyed by other methods. Anyone using non-id selectors will need to do this manually
930				 */
931				if ( s.sTableId == this.id )
932				{
933					allSettings.splice( i, 1 );
934					break;
935				}
936			}
937
938			/* Ensure the table has an ID - required for accessibility */
939			if ( sId === null || sId === "" )
940			{
941				sId = "DataTables_Table_"+(DataTable.ext._unique++);
942				this.id = sId;
943			}
944
945			/* Create the settings object for this table and set some of the default parameters */
946			var oSettings = $.extend( true, {}, DataTable.models.oSettings, {
947				"sDestroyWidth": $this[0].style.width,
948				"sInstance":     sId,
949				"sTableId":      sId
950			} );
951			oSettings.nTable = this;
952			oSettings.oApi   = _that.internal;
953			oSettings.oInit  = oInit;
954
955			allSettings.push( oSettings );
956
957			// Need to add the instance after the instance after the settings object has been added
958			// to the settings array, so we can self reference the table instance if more than one
959			oSettings.oInstance = (_that.length===1) ? _that : $this.dataTable();
960
961			// Backwards compatibility, before we apply all the defaults
962			_fnCompatOpts( oInit );
963			_fnLanguageCompat( oInit.oLanguage );
964
965			// If the length menu is given, but the init display length is not, use the length menu
966			if ( oInit.aLengthMenu && ! oInit.iDisplayLength )
967			{
968				oInit.iDisplayLength = Array.isArray( oInit.aLengthMenu[0] ) ?
969					oInit.aLengthMenu[0][0] : oInit.aLengthMenu[0];
970			}
971
972			// Apply the defaults and init options to make a single init object will all
973			// options defined from defaults and instance options.
974			oInit = _fnExtend( $.extend( true, {}, defaults ), oInit );
975
976
977			// Map the initialisation options onto the settings object
978			_fnMap( oSettings.oFeatures, oInit, [
979				"bPaginate",
980				"bLengthChange",
981				"bFilter",
982				"bSort",
983				"bSortMulti",
984				"bInfo",
985				"bProcessing",
986				"bAutoWidth",
987				"bSortClasses",
988				"bServerSide",
989				"bDeferRender"
990			] );
991			_fnMap( oSettings, oInit, [
992				"asStripeClasses",
993				"ajax",
994				"fnServerData",
995				"fnFormatNumber",
996				"sServerMethod",
997				"aaSorting",
998				"aaSortingFixed",
999				"aLengthMenu",
1000				"sPaginationType",
1001				"sAjaxSource",
1002				"sAjaxDataProp",
1003				"iStateDuration",
1004				"sDom",
1005				"bSortCellsTop",
1006				"iTabIndex",
1007				"fnStateLoadCallback",
1008				"fnStateSaveCallback",
1009				"renderer",
1010				"searchDelay",
1011				"rowId",
1012				[ "iCookieDuration", "iStateDuration" ], // backwards compat
1013				[ "oSearch", "oPreviousSearch" ],
1014				[ "aoSearchCols", "aoPreSearchCols" ],
1015				[ "iDisplayLength", "_iDisplayLength" ]
1016			] );
1017			_fnMap( oSettings.oScroll, oInit, [
1018				[ "sScrollX", "sX" ],
1019				[ "sScrollXInner", "sXInner" ],
1020				[ "sScrollY", "sY" ],
1021				[ "bScrollCollapse", "bCollapse" ]
1022			] );
1023			_fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" );
1024
1025			/* Callback functions which are array driven */
1026			_fnCallbackReg( oSettings, 'aoDrawCallback',       oInit.fnDrawCallback,      'user' );
1027			_fnCallbackReg( oSettings, 'aoServerParams',       oInit.fnServerParams,      'user' );
1028			_fnCallbackReg( oSettings, 'aoStateSaveParams',    oInit.fnStateSaveParams,   'user' );
1029			_fnCallbackReg( oSettings, 'aoStateLoadParams',    oInit.fnStateLoadParams,   'user' );
1030			_fnCallbackReg( oSettings, 'aoStateLoaded',        oInit.fnStateLoaded,       'user' );
1031			_fnCallbackReg( oSettings, 'aoRowCallback',        oInit.fnRowCallback,       'user' );
1032			_fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow,        'user' );
1033			_fnCallbackReg( oSettings, 'aoHeaderCallback',     oInit.fnHeaderCallback,    'user' );
1034			_fnCallbackReg( oSettings, 'aoFooterCallback',     oInit.fnFooterCallback,    'user' );
1035			_fnCallbackReg( oSettings, 'aoInitComplete',       oInit.fnInitComplete,      'user' );
1036			_fnCallbackReg( oSettings, 'aoPreDrawCallback',    oInit.fnPreDrawCallback,   'user' );
1037
1038			oSettings.rowIdFn = _fnGetObjectDataFn( oInit.rowId );
1039
1040			/* Browser support detection */
1041			_fnBrowserDetect( oSettings );
1042
1043			var oClasses = oSettings.oClasses;
1044
1045			$.extend( oClasses, DataTable.ext.classes, oInit.oClasses );
1046			$this.addClass( oClasses.sTable );
1047
1048
1049			if ( oSettings.iInitDisplayStart === undefined )
1050			{
1051				/* Display start point, taking into account the save saving */
1052				oSettings.iInitDisplayStart = oInit.iDisplayStart;
1053				oSettings._iDisplayStart = oInit.iDisplayStart;
1054			}
1055
1056			if ( oInit.iDeferLoading !== null )
1057			{
1058				oSettings.bDeferLoading = true;
1059				var tmp = Array.isArray( oInit.iDeferLoading );
1060				oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading;
1061				oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading;
1062			}
1063
1064			/* Language definitions */
1065			var oLanguage = oSettings.oLanguage;
1066			$.extend( true, oLanguage, oInit.oLanguage );
1067
1068			if ( oLanguage.sUrl )
1069			{
1070				/* Get the language definitions from a file - because this Ajax call makes the language
1071				 * get async to the remainder of this function we use bInitHandedOff to indicate that
1072				 * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor
1073				 */
1074				$.ajax( {
1075					dataType: 'json',
1076					url: oLanguage.sUrl,
1077					success: function ( json ) {
1078						_fnCamelToHungarian( defaults.oLanguage, json );
1079						_fnLanguageCompat( json );
1080						$.extend( true, oLanguage, json, oSettings.oInit.oLanguage );
1081
1082						_fnCallbackFire( oSettings, null, 'i18n', [oSettings]);
1083						_fnInitialise( oSettings );
1084					},
1085					error: function () {
1086						// Error occurred loading language file, continue on as best we can
1087						_fnInitialise( oSettings );
1088					}
1089				} );
1090				bInitHandedOff = true;
1091			}
1092			else {
1093				_fnCallbackFire( oSettings, null, 'i18n', [oSettings]);
1094			}
1095
1096			/*
1097			 * Stripes
1098			 */
1099			if ( oInit.asStripeClasses === null )
1100			{
1101				oSettings.asStripeClasses =[
1102					oClasses.sStripeOdd,
1103					oClasses.sStripeEven
1104				];
1105			}
1106
1107			/* Remove row stripe classes if they are already on the table row */
1108			var stripeClasses = oSettings.asStripeClasses;
1109			var rowOne = $this.children('tbody').find('tr').eq(0);
1110			if ( $.inArray( true, $.map( stripeClasses, function(el, i) {
1111				return rowOne.hasClass(el);
1112			} ) ) !== -1 ) {
1113				$('tbody tr', this).removeClass( stripeClasses.join(' ') );
1114				oSettings.asDestroyStripes = stripeClasses.slice();
1115			}
1116
1117			/*
1118			 * Columns
1119			 * See if we should load columns automatically or use defined ones
1120			 */
1121			var anThs = [];
1122			var aoColumnsInit;
1123			var nThead = this.getElementsByTagName('thead');
1124			if ( nThead.length !== 0 )
1125			{
1126				_fnDetectHeader( oSettings.aoHeader, nThead[0] );
1127				anThs = _fnGetUniqueThs( oSettings );
1128			}
1129
1130			/* If not given a column array, generate one with nulls */
1131			if ( oInit.aoColumns === null )
1132			{
1133				aoColumnsInit = [];
1134				for ( i=0, iLen=anThs.length ; i<iLen ; i++ )
1135				{
1136					aoColumnsInit.push( null );
1137				}
1138			}
1139			else
1140			{
1141				aoColumnsInit = oInit.aoColumns;
1142			}
1143
1144			/* Add the columns */
1145			for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ )
1146			{
1147				_fnAddColumn( oSettings, anThs ? anThs[i] : null );
1148			}
1149
1150			/* Apply the column definitions */
1151			_fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) {
1152				_fnColumnOptions( oSettings, iCol, oDef );
1153			} );
1154
1155			/* HTML5 attribute detection - build an mData object automatically if the
1156			 * attributes are found
1157			 */
1158			if ( rowOne.length ) {
1159				var a = function ( cell, name ) {
1160					return cell.getAttribute( 'data-'+name ) !== null ? name : null;
1161				};
1162
1163				$( rowOne[0] ).children('th, td').each( function (i, cell) {
1164					var col = oSettings.aoColumns[i];
1165
1166					if (! col) {
1167						_fnLog( oSettings, 0, 'Incorrect column count', 18 );
1168					}
1169
1170					if ( col.mData === i ) {
1171						var sort = a( cell, 'sort' ) || a( cell, 'order' );
1172						var filter = a( cell, 'filter' ) || a( cell, 'search' );
1173
1174						if ( sort !== null || filter !== null ) {
1175							col.mData = {
1176								_:      i+'.display',
1177								sort:   sort !== null   ? i+'.@data-'+sort   : undefined,
1178								type:   sort !== null   ? i+'.@data-'+sort   : undefined,
1179								filter: filter !== null ? i+'.@data-'+filter : undefined
1180							};
1181							col._isArrayHost = true;
1182
1183							_fnColumnOptions( oSettings, i );
1184						}
1185					}
1186				} );
1187			}
1188
1189			var features = oSettings.oFeatures;
1190			var loadedInit = function () {
1191				/*
1192				 * Sorting
1193				 * @todo For modularisation (1.11) this needs to do into a sort start up handler
1194				 */
1195
1196				// If aaSorting is not defined, then we use the first indicator in asSorting
1197				// in case that has been altered, so the default sort reflects that option
1198				if ( oInit.aaSorting === undefined ) {
1199					var sorting = oSettings.aaSorting;
1200					for ( i=0, iLen=sorting.length ; i<iLen ; i++ ) {
1201						sorting[i][1] = oSettings.aoColumns[ i ].asSorting[0];
1202					}
1203				}
1204
1205				/* Do a first pass on the sorting classes (allows any size changes to be taken into
1206				 * account, and also will apply sorting disabled classes if disabled
1207				 */
1208				_fnSortingClasses( oSettings );
1209
1210				if ( features.bSort ) {
1211					_fnCallbackReg( oSettings, 'aoDrawCallback', function () {
1212						if ( oSettings.bSorted ) {
1213							var aSort = _fnSortFlatten( oSettings );
1214							var sortedColumns = {};
1215
1216							$.each( aSort, function (i, val) {
1217								sortedColumns[ val.src ] = val.dir;
1218							} );
1219
1220							_fnCallbackFire( oSettings, null, 'order', [oSettings, aSort, sortedColumns] );
1221							_fnSortAria( oSettings );
1222						}
1223					} );
1224				}
1225
1226				_fnCallbackReg( oSettings, 'aoDrawCallback', function () {
1227					if ( oSettings.bSorted || _fnDataSource( oSettings ) === 'ssp' || features.bDeferRender ) {
1228						_fnSortingClasses( oSettings );
1229					}
1230				}, 'sc' );
1231
1232
1233				/*
1234				 * Final init
1235				 * Cache the header, body and footer as required, creating them if needed
1236				 */
1237
1238				// Work around for Webkit bug 83867 - store the caption-side before removing from doc
1239				var captions = $this.children('caption').each( function () {
1240					this._captionSide = $(this).css('caption-side');
1241				} );
1242
1243				var thead = $this.children('thead');
1244				if ( thead.length === 0 ) {
1245					thead = $('<thead/>').appendTo($this);
1246				}
1247				oSettings.nTHead = thead[0];
1248
1249				var tbody = $this.children('tbody');
1250				if ( tbody.length === 0 ) {
1251					tbody = $('<tbody/>').insertAfter(thead);
1252				}
1253				oSettings.nTBody = tbody[0];
1254
1255				var tfoot = $this.children('tfoot');
1256				if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") ) {
1257					// If we are a scrolling table, and no footer has been given, then we need to create
1258					// a tfoot element for the caption element to be appended to
1259					tfoot = $('<tfoot/>').appendTo($this);
1260				}
1261
1262				if ( tfoot.length === 0 || tfoot.children().length === 0 ) {
1263					$this.addClass( oClasses.sNoFooter );
1264				}
1265				else if ( tfoot.length > 0 ) {
1266					oSettings.nTFoot = tfoot[0];
1267					_fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );
1268				}
1269
1270				/* Check if there is data passing into the constructor */
1271				if ( oInit.aaData ) {
1272					for ( i=0 ; i<oInit.aaData.length ; i++ ) {
1273						_fnAddData( oSettings, oInit.aaData[ i ] );
1274					}
1275				}
1276				else if ( oSettings.bDeferLoading || _fnDataSource( oSettings ) == 'dom' ) {
1277					/* Grab the data from the page - only do this when deferred loading or no Ajax
1278					 * source since there is no point in reading the DOM data if we are then going
1279					 * to replace it with Ajax data
1280					 */
1281					_fnAddTr( oSettings, $(oSettings.nTBody).children('tr') );
1282				}
1283
1284				/* Copy the data index array */
1285				oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
1286
1287				/* Initialisation complete - table can be drawn */
1288				oSettings.bInitialised = true;
1289
1290				/* Check if we need to initialise the table (it might not have been handed off to the
1291				 * language processor)
1292				 */
1293				if ( bInitHandedOff === false ) {
1294					_fnInitialise( oSettings );
1295				}
1296			};
1297
1298			/* Must be done after everything which can be overridden by the state saving! */
1299			_fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' );
1300
1301			if ( oInit.bStateSave )
1302			{
1303				features.bStateSave = true;
1304				_fnLoadState( oSettings, oInit, loadedInit );
1305			}
1306			else {
1307				loadedInit();
1308			}
1309
1310		} );
1311		_that = null;
1312		return this;
1313	};
1314
1315
1316	/*
1317	 * It is useful to have variables which are scoped locally so only the
1318	 * DataTables functions can access them and they don't leak into global space.
1319	 * At the same time these functions are often useful over multiple files in the
1320	 * core and API, so we list, or at least document, all variables which are used
1321	 * by DataTables as private variables here. This also ensures that there is no
1322	 * clashing of variable names and that they can easily referenced for reuse.
1323	 */
1324
1325
1326	// Defined else where
1327	//  _selector_run
1328	//  _selector_opts
1329	//  _selector_first
1330	//  _selector_row_indexes
1331
1332	var _ext; // DataTable.ext
1333	var _Api; // DataTable.Api
1334	var _api_register; // DataTable.Api.register
1335	var _api_registerPlural; // DataTable.Api.registerPlural
1336
1337	var _re_dic = {};
1338	var _re_new_lines = /[\r\n\u2028]/g;
1339	var _re_html = /<.*?>/g;
1340
1341	// This is not strict ISO8601 - Date.parse() is quite lax, although
1342	// implementations differ between browsers.
1343	var _re_date = /^\d{2,4}[\.\/\-]\d{1,2}[\.\/\-]\d{1,2}([T ]{1}\d{1,2}[:\.]\d{2}([\.:]\d{2})?)?$/;
1344
1345	// Escape regular expression special characters
1346	var _re_escape_regex = new RegExp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' );
1347
1348	// http://en.wikipedia.org/wiki/Foreign_exchange_market
1349	// - \u20BD - Russian ruble.
1350	// - \u20a9 - South Korean Won
1351	// - \u20BA - Turkish Lira
1352	// - \u20B9 - Indian Rupee
1353	// - R - Brazil (R$) and South Africa
1354	// - fr - Swiss Franc
1355	// - kr - Swedish krona, Norwegian krone and Danish krone
1356	// - \u2009 is thin space and \u202F is narrow no-break space, both used in many
1357	// - Ƀ - Bitcoin
1358	// - Ξ - Ethereum
1359	//   standards as thousands separators.
1360	var _re_formatted_numeric = /['\u00A0,$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfkɃΞ]/gi;
1361
1362
1363	var _empty = function ( d ) {
1364		return !d || d === true || d === '-' ? true : false;
1365	};
1366
1367
1368	var _intVal = function ( s ) {
1369		var integer = parseInt( s, 10 );
1370		return !isNaN(integer) && isFinite(s) ? integer : null;
1371	};
1372
1373	// Convert from a formatted number with characters other than `.` as the
1374	// decimal place, to a Javascript number
1375	var _numToDecimal = function ( num, decimalPoint ) {
1376		// Cache created regular expressions for speed as this function is called often
1377		if ( ! _re_dic[ decimalPoint ] ) {
1378			_re_dic[ decimalPoint ] = new RegExp( _fnEscapeRegex( decimalPoint ), 'g' );
1379		}
1380		return typeof num === 'string' && decimalPoint !== '.' ?
1381			num.replace( /\./g, '' ).replace( _re_dic[ decimalPoint ], '.' ) :
1382			num;
1383	};
1384
1385
1386	var _isNumber = function ( d, decimalPoint, formatted ) {
1387		var type = typeof d;
1388		var strType = type === 'string';
1389
1390		if ( type === 'number' || type === 'bigint') {
1391			return true;
1392		}
1393
1394		// If empty return immediately so there must be a number if it is a
1395		// formatted string (this stops the string "k", or "kr", etc being detected
1396		// as a formatted number for currency
1397		if ( _empty( d ) ) {
1398			return true;
1399		}
1400
1401		if ( decimalPoint && strType ) {
1402			d = _numToDecimal( d, decimalPoint );
1403		}
1404
1405		if ( formatted && strType ) {
1406			d = d.replace( _re_formatted_numeric, '' );
1407		}
1408
1409		return !isNaN( parseFloat(d) ) && isFinite( d );
1410	};
1411
1412
1413	// A string without HTML in it can be considered to be HTML still
1414	var _isHtml = function ( d ) {
1415		return _empty( d ) || typeof d === 'string';
1416	};
1417
1418
1419	var _htmlNumeric = function ( d, decimalPoint, formatted ) {
1420		if ( _empty( d ) ) {
1421			return true;
1422		}
1423
1424		var html = _isHtml( d );
1425		return ! html ?
1426			null :
1427			_isNumber( _stripHtml( d ), decimalPoint, formatted ) ?
1428				true :
1429				null;
1430	};
1431
1432
1433	var _pluck = function ( a, prop, prop2 ) {
1434		var out = [];
1435		var i=0, ien=a.length;
1436
1437		// Could have the test in the loop for slightly smaller code, but speed
1438		// is essential here
1439		if ( prop2 !== undefined ) {
1440			for ( ; i<ien ; i++ ) {
1441				if ( a[i] && a[i][ prop ] ) {
1442					out.push( a[i][ prop ][ prop2 ] );
1443				}
1444			}
1445		}
1446		else {
1447			for ( ; i<ien ; i++ ) {
1448				if ( a[i] ) {
1449					out.push( a[i][ prop ] );
1450				}
1451			}
1452		}
1453
1454		return out;
1455	};
1456
1457
1458	// Basically the same as _pluck, but rather than looping over `a` we use `order`
1459	// as the indexes to pick from `a`
1460	var _pluck_order = function ( a, order, prop, prop2 )
1461	{
1462		var out = [];
1463		var i=0, ien=order.length;
1464
1465		// Could have the test in the loop for slightly smaller code, but speed
1466		// is essential here
1467		if ( prop2 !== undefined ) {
1468			for ( ; i<ien ; i++ ) {
1469				if ( a[ order[i] ][ prop ] ) {
1470					out.push( a[ order[i] ][ prop ][ prop2 ] );
1471				}
1472			}
1473		}
1474		else {
1475			for ( ; i<ien ; i++ ) {
1476				out.push( a[ order[i] ][ prop ] );
1477			}
1478		}
1479
1480		return out;
1481	};
1482
1483
1484	var _range = function ( len, start )
1485	{
1486		var out = [];
1487		var end;
1488
1489		if ( start === undefined ) {
1490			start = 0;
1491			end = len;
1492		}
1493		else {
1494			end = start;
1495			start = len;
1496		}
1497
1498		for ( var i=start ; i<end ; i++ ) {
1499			out.push( i );
1500		}
1501
1502		return out;
1503	};
1504
1505
1506	var _removeEmpty = function ( a )
1507	{
1508		var out = [];
1509
1510		for ( var i=0, ien=a.length ; i<ien ; i++ ) {
1511			if ( a[i] ) { // careful - will remove all falsy values!
1512				out.push( a[i] );
1513			}
1514		}
1515
1516		return out;
1517	};
1518
1519
1520	var _stripHtml = function ( d ) {
1521		return d
1522			.replace( _re_html, '' ) // Complete tags
1523			.replace(/<script/i, ''); // Safety for incomplete script tag
1524	};
1525
1526
1527	/**
1528	 * Determine if all values in the array are unique. This means we can short
1529	 * cut the _unique method at the cost of a single loop. A sorted array is used
1530	 * to easily check the values.
1531	 *
1532	 * @param  {array} src Source array
1533	 * @return {boolean} true if all unique, false otherwise
1534	 * @ignore
1535	 */
1536	var _areAllUnique = function ( src ) {
1537		if ( src.length < 2 ) {
1538			return true;
1539		}
1540
1541		var sorted = src.slice().sort();
1542		var last = sorted[0];
1543
1544		for ( var i=1, ien=sorted.length ; i<ien ; i++ ) {
1545			if ( sorted[i] === last ) {
1546				return false;
1547			}
1548
1549			last = sorted[i];
1550		}
1551
1552		return true;
1553	};
1554
1555
1556	/**
1557	 * Find the unique elements in a source array.
1558	 *
1559	 * @param  {array} src Source array
1560	 * @return {array} Array of unique items
1561	 * @ignore
1562	 */
1563	var _unique = function ( src )
1564	{
1565		if ( _areAllUnique( src ) ) {
1566			return src.slice();
1567		}
1568
1569		// A faster unique method is to use object keys to identify used values,
1570		// but this doesn't work with arrays or objects, which we must also
1571		// consider. See jsperf.com/compare-array-unique-versions/4 for more
1572		// information.
1573		var
1574			out = [],
1575			val,
1576			i, ien=src.length,
1577			j, k=0;
1578
1579		again: for ( i=0 ; i<ien ; i++ ) {
1580			val = src[i];
1581
1582			for ( j=0 ; j<k ; j++ ) {
1583				if ( out[j] === val ) {
1584					continue again;
1585				}
1586			}
1587
1588			out.push( val );
1589			k++;
1590		}
1591
1592		return out;
1593	};
1594
1595	// Surprisingly this is faster than [].concat.apply
1596	// https://jsperf.com/flatten-an-array-loop-vs-reduce/2
1597	var _flatten = function (out, val) {
1598		if (Array.isArray(val)) {
1599			for (var i=0 ; i<val.length ; i++) {
1600				_flatten(out, val[i]);
1601			}
1602		}
1603		else {
1604			out.push(val);
1605		}
1606
1607		return out;
1608	}
1609
1610	var _includes = function (search, start) {
1611		if (start === undefined) {
1612			start = 0;
1613		}
1614
1615		return this.indexOf(search, start) !== -1;
1616	};
1617
1618	// Array.isArray polyfill.
1619	// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
1620	if (! Array.isArray) {
1621	    Array.isArray = function(arg) {
1622	        return Object.prototype.toString.call(arg) === '[object Array]';
1623	    };
1624	}
1625
1626	if (! Array.prototype.includes) {
1627		Array.prototype.includes = _includes;
1628	}
1629
1630	// .trim() polyfill
1631	// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trim
1632	if (!String.prototype.trim) {
1633	  String.prototype.trim = function () {
1634	    return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
1635	  };
1636	}
1637
1638	if (! String.prototype.includes) {
1639		String.prototype.includes = _includes;
1640	}
1641
1642	/**
1643	 * DataTables utility methods
1644	 *
1645	 * This namespace provides helper methods that DataTables uses internally to
1646	 * create a DataTable, but which are not exclusively used only for DataTables.
1647	 * These methods can be used by extension authors to save the duplication of
1648	 * code.
1649	 *
1650	 *  @namespace
1651	 */
1652	DataTable.util = {
1653		/**
1654		 * Throttle the calls to a function. Arguments and context are maintained
1655		 * for the throttled function.
1656		 *
1657		 * @param {function} fn Function to be called
1658		 * @param {integer} freq Call frequency in mS
1659		 * @return {function} Wrapped function
1660		 */
1661		throttle: function ( fn, freq ) {
1662			var
1663				frequency = freq !== undefined ? freq : 200,
1664				last,
1665				timer;
1666
1667			return function () {
1668				var
1669					that = this,
1670					now  = +new Date(),
1671					args = arguments;
1672
1673				if ( last && now < last + frequency ) {
1674					clearTimeout( timer );
1675
1676					timer = setTimeout( function () {
1677						last = undefined;
1678						fn.apply( that, args );
1679					}, frequency );
1680				}
1681				else {
1682					last = now;
1683					fn.apply( that, args );
1684				}
1685			};
1686		},
1687
1688
1689		/**
1690		 * Escape a string such that it can be used in a regular expression
1691		 *
1692		 *  @param {string} val string to escape
1693		 *  @returns {string} escaped string
1694		 */
1695		escapeRegex: function ( val ) {
1696			return val.replace( _re_escape_regex, '\\$1' );
1697		},
1698
1699		/**
1700		 * Create a function that will write to a nested object or array
1701		 * @param {*} source JSON notation string
1702		 * @returns Write function
1703		 */
1704		set: function ( source ) {
1705			if ( $.isPlainObject( source ) ) {
1706				/* Unlike get, only the underscore (global) option is used for for
1707				 * setting data since we don't know the type here. This is why an object
1708				 * option is not documented for `mData` (which is read/write), but it is
1709				 * for `mRender` which is read only.
1710				 */
1711				return DataTable.util.set( source._ );
1712			}
1713			else if ( source === null ) {
1714				// Nothing to do when the data source is null
1715				return function () {};
1716			}
1717			else if ( typeof source === 'function' ) {
1718				return function (data, val, meta) {
1719					source( data, 'set', val, meta );
1720				};
1721			}
1722			else if ( typeof source === 'string' && (source.indexOf('.') !== -1 ||
1723					  source.indexOf('[') !== -1 || source.indexOf('(') !== -1) )
1724			{
1725				// Like the get, we need to get data from a nested object
1726				var setData = function (data, val, src) {
1727					var a = _fnSplitObjNotation( src ), b;
1728					var aLast = a[a.length-1];
1729					var arrayNotation, funcNotation, o, innerSrc;
1730
1731					for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ ) {
1732						// Protect against prototype pollution
1733						if (a[i] === '__proto__' || a[i] === 'constructor') {
1734							throw new Error('Cannot set prototype values');
1735						}
1736
1737						// Check if we are dealing with an array notation request
1738						arrayNotation = a[i].match(__reArray);
1739						funcNotation = a[i].match(__reFn);
1740
1741						if ( arrayNotation ) {
1742							a[i] = a[i].replace(__reArray, '');
1743							data[ a[i] ] = [];
1744
1745							// Get the remainder of the nested object to set so we can recurse
1746							b = a.slice();
1747							b.splice( 0, i+1 );
1748							innerSrc = b.join('.');
1749
1750							// Traverse each entry in the array setting the properties requested
1751							if ( Array.isArray( val ) ) {
1752								for ( var j=0, jLen=val.length ; j<jLen ; j++ ) {
1753									o = {};
1754									setData( o, val[j], innerSrc );
1755									data[ a[i] ].push( o );
1756								}
1757							}
1758							else {
1759								// We've been asked to save data to an array, but it
1760								// isn't array data to be saved. Best that can be done
1761								// is to just save the value.
1762								data[ a[i] ] = val;
1763							}
1764
1765							// The inner call to setData has already traversed through the remainder
1766							// of the source and has set the data, thus we can exit here
1767							return;
1768						}
1769						else if ( funcNotation ) {
1770							// Function call
1771							a[i] = a[i].replace(__reFn, '');
1772							data = data[ a[i] ]( val );
1773						}
1774
1775						// If the nested object doesn't currently exist - since we are
1776						// trying to set the value - create it
1777						if ( data[ a[i] ] === null || data[ a[i] ] === undefined ) {
1778							data[ a[i] ] = {};
1779						}
1780						data = data[ a[i] ];
1781					}
1782
1783					// Last item in the input - i.e, the actual set
1784					if ( aLast.match(__reFn ) ) {
1785						// Function call
1786						data = data[ aLast.replace(__reFn, '') ]( val );
1787					}
1788					else {
1789						// If array notation is used, we just want to strip it and use the property name
1790						// and assign the value. If it isn't used, then we get the result we want anyway
1791						data[ aLast.replace(__reArray, '') ] = val;
1792					}
1793				};
1794
1795				return function (data, val) { // meta is also passed in, but not used
1796					return setData( data, val, source );
1797				};
1798			}
1799			else {
1800				// Array or flat object mapping
1801				return function (data, val) { // meta is also passed in, but not used
1802					data[source] = val;
1803				};
1804			}
1805		},
1806
1807		/**
1808		 * Create a function that will read nested objects from arrays, based on JSON notation
1809		 * @param {*} source JSON notation string
1810		 * @returns Value read
1811		 */
1812		get: function ( source ) {
1813			if ( $.isPlainObject( source ) ) {
1814				// Build an object of get functions, and wrap them in a single call
1815				var o = {};
1816				$.each( source, function (key, val) {
1817					if ( val ) {
1818						o[key] = DataTable.util.get( val );
1819					}
1820				} );
1821
1822				return function (data, type, row, meta) {
1823					var t = o[type] || o._;
1824					return t !== undefined ?
1825						t(data, type, row, meta) :
1826						data;
1827				};
1828			}
1829			else if ( source === null ) {
1830				// Give an empty string for rendering / sorting etc
1831				return function (data) { // type, row and meta also passed, but not used
1832					return data;
1833				};
1834			}
1835			else if ( typeof source === 'function' ) {
1836				return function (data, type, row, meta) {
1837					return source( data, type, row, meta );
1838				};
1839			}
1840			else if ( typeof source === 'string' && (source.indexOf('.') !== -1 ||
1841					  source.indexOf('[') !== -1 || source.indexOf('(') !== -1) )
1842			{
1843				/* If there is a . in the source string then the data source is in a
1844				 * nested object so we loop over the data for each level to get the next
1845				 * level down. On each loop we test for undefined, and if found immediately
1846				 * return. This allows entire objects to be missing and sDefaultContent to
1847				 * be used if defined, rather than throwing an error
1848				 */
1849				var fetchData = function (data, type, src) {
1850					var arrayNotation, funcNotation, out, innerSrc;
1851
1852					if ( src !== "" ) {
1853						var a = _fnSplitObjNotation( src );
1854
1855						for ( var i=0, iLen=a.length ; i<iLen ; i++ ) {
1856							// Check if we are dealing with special notation
1857							arrayNotation = a[i].match(__reArray);
1858							funcNotation = a[i].match(__reFn);
1859
1860							if ( arrayNotation ) {
1861								// Array notation
1862								a[i] = a[i].replace(__reArray, '');
1863
1864								// Condition allows simply [] to be passed in
1865								if ( a[i] !== "" ) {
1866									data = data[ a[i] ];
1867								}
1868								out = [];
1869
1870								// Get the remainder of the nested object to get
1871								a.splice( 0, i+1 );
1872								innerSrc = a.join('.');
1873
1874								// Traverse each entry in the array getting the properties requested
1875								if ( Array.isArray( data ) ) {
1876									for ( var j=0, jLen=data.length ; j<jLen ; j++ ) {
1877										out.push( fetchData( data[j], type, innerSrc ) );
1878									}
1879								}
1880
1881								// If a string is given in between the array notation indicators, that
1882								// is used to join the strings together, otherwise an array is returned
1883								var join = arrayNotation[0].substring(1, arrayNotation[0].length-1);
1884								data = (join==="") ? out : out.join(join);
1885
1886								// The inner call to fetchData has already traversed through the remainder
1887								// of the source requested, so we exit from the loop
1888								break;
1889							}
1890							else if ( funcNotation ) {
1891								// Function call
1892								a[i] = a[i].replace(__reFn, '');
1893								data = data[ a[i] ]();
1894								continue;
1895							}
1896
1897							if (data === null || data[ a[i] ] === null) {
1898								return null;
1899							}
1900							else if ( data === undefined || data[ a[i] ] === undefined ) {
1901								return undefined;
1902							}
1903
1904							data = data[ a[i] ];
1905						}
1906					}
1907
1908					return data;
1909				};
1910
1911				return function (data, type) { // row and meta also passed, but not used
1912					return fetchData( data, type, source );
1913				};
1914			}
1915			else {
1916				// Array or flat object mapping
1917				return function (data, type) { // row and meta also passed, but not used
1918					return data[source];
1919				};
1920			}
1921		}
1922	};
1923
1924
1925
1926	/**
1927	 * Create a mapping object that allows camel case parameters to be looked up
1928	 * for their Hungarian counterparts. The mapping is stored in a private
1929	 * parameter called `_hungarianMap` which can be accessed on the source object.
1930	 *  @param {object} o
1931	 *  @memberof DataTable#oApi
1932	 */
1933	function _fnHungarianMap ( o )
1934	{
1935		var
1936			hungarian = 'a aa ai ao as b fn i m o s ',
1937			match,
1938			newKey,
1939			map = {};
1940
1941		$.each( o, function (key, val) {
1942			match = key.match(/^([^A-Z]+?)([A-Z])/);
1943
1944			if ( match && hungarian.indexOf(match[1]+' ') !== -1 )
1945			{
1946				newKey = key.replace( match[0], match[2].toLowerCase() );
1947				map[ newKey ] = key;
1948
1949				if ( match[1] === 'o' )
1950				{
1951					_fnHungarianMap( o[key] );
1952				}
1953			}
1954		} );
1955
1956		o._hungarianMap = map;
1957	}
1958
1959
1960	/**
1961	 * Convert from camel case parameters to Hungarian, based on a Hungarian map
1962	 * created by _fnHungarianMap.
1963	 *  @param {object} src The model object which holds all parameters that can be
1964	 *    mapped.
1965	 *  @param {object} user The object to convert from camel case to Hungarian.
1966	 *  @param {boolean} force When set to `true`, properties which already have a
1967	 *    Hungarian value in the `user` object will be overwritten. Otherwise they
1968	 *    won't be.
1969	 *  @memberof DataTable#oApi
1970	 */
1971	function _fnCamelToHungarian ( src, user, force )
1972	{
1973		if ( ! src._hungarianMap ) {
1974			_fnHungarianMap( src );
1975		}
1976
1977		var hungarianKey;
1978
1979		$.each( user, function (key, val) {
1980			hungarianKey = src._hungarianMap[ key ];
1981
1982			if ( hungarianKey !== undefined && (force || user[hungarianKey] === undefined) )
1983			{
1984				// For objects, we need to buzz down into the object to copy parameters
1985				if ( hungarianKey.charAt(0) === 'o' )
1986				{
1987					// Copy the camelCase options over to the hungarian
1988					if ( ! user[ hungarianKey ] ) {
1989						user[ hungarianKey ] = {};
1990					}
1991					$.extend( true, user[hungarianKey], user[key] );
1992
1993					_fnCamelToHungarian( src[hungarianKey], user[hungarianKey], force );
1994				}
1995				else {
1996					user[hungarianKey] = user[ key ];
1997				}
1998			}
1999		} );
2000	}
2001
2002
2003	/**
2004	 * Language compatibility - when certain options are given, and others aren't, we
2005	 * need to duplicate the values over, in order to provide backwards compatibility
2006	 * with older language files.
2007	 *  @param {object} oSettings dataTables settings object
2008	 *  @memberof DataTable#oApi
2009	 */
2010	function _fnLanguageCompat( lang )
2011	{
2012		// Note the use of the Hungarian notation for the parameters in this method as
2013		// this is called after the mapping of camelCase to Hungarian
2014		var defaults = DataTable.defaults.oLanguage;
2015
2016		// Default mapping
2017		var defaultDecimal = defaults.sDecimal;
2018		if ( defaultDecimal ) {
2019			_addNumericSort( defaultDecimal );
2020		}
2021
2022		if ( lang ) {
2023			var zeroRecords = lang.sZeroRecords;
2024
2025			// Backwards compatibility - if there is no sEmptyTable given, then use the same as
2026			// sZeroRecords - assuming that is given.
2027			if ( ! lang.sEmptyTable && zeroRecords &&
2028				defaults.sEmptyTable === "No data available in table" )
2029			{
2030				_fnMap( lang, lang, 'sZeroRecords', 'sEmptyTable' );
2031			}
2032
2033			// Likewise with loading records
2034			if ( ! lang.sLoadingRecords && zeroRecords &&
2035				defaults.sLoadingRecords === "Loading..." )
2036			{
2037				_fnMap( lang, lang, 'sZeroRecords', 'sLoadingRecords' );
2038			}
2039
2040			// Old parameter name of the thousands separator mapped onto the new
2041			if ( lang.sInfoThousands ) {
2042				lang.sThousands = lang.sInfoThousands;
2043			}
2044
2045			var decimal = lang.sDecimal;
2046			if ( decimal && defaultDecimal !== decimal ) {
2047				_addNumericSort( decimal );
2048			}
2049		}
2050	}
2051
2052
2053	/**
2054	 * Map one parameter onto another
2055	 *  @param {object} o Object to map
2056	 *  @param {*} knew The new parameter name
2057	 *  @param {*} old The old parameter name
2058	 */
2059	var _fnCompatMap = function ( o, knew, old ) {
2060		if ( o[ knew ] !== undefined ) {
2061			o[ old ] = o[ knew ];
2062		}
2063	};
2064
2065
2066	/**
2067	 * Provide backwards compatibility for the main DT options. Note that the new
2068	 * options are mapped onto the old parameters, so this is an external interface
2069	 * change only.
2070	 *  @param {object} init Object to map
2071	 */
2072	function _fnCompatOpts ( init )
2073	{
2074		_fnCompatMap( init, 'ordering',      'bSort' );
2075		_fnCompatMap( init, 'orderMulti',    'bSortMulti' );
2076		_fnCompatMap( init, 'orderClasses',  'bSortClasses' );
2077		_fnCompatMap( init, 'orderCellsTop', 'bSortCellsTop' );
2078		_fnCompatMap( init, 'order',         'aaSorting' );
2079		_fnCompatMap( init, 'orderFixed',    'aaSortingFixed' );
2080		_fnCompatMap( init, 'paging',        'bPaginate' );
2081		_fnCompatMap( init, 'pagingType',    'sPaginationType' );
2082		_fnCompatMap( init, 'pageLength',    'iDisplayLength' );
2083		_fnCompatMap( init, 'searching',     'bFilter' );
2084
2085		// Boolean initialisation of x-scrolling
2086		if ( typeof init.sScrollX === 'boolean' ) {
2087			init.sScrollX = init.sScrollX ? '100%' : '';
2088		}
2089		if ( typeof init.scrollX === 'boolean' ) {
2090			init.scrollX = init.scrollX ? '100%' : '';
2091		}
2092
2093		// Column search objects are in an array, so it needs to be converted
2094		// element by element
2095		var searchCols = init.aoSearchCols;
2096
2097		if ( searchCols ) {
2098			for ( var i=0, ien=searchCols.length ; i<ien ; i++ ) {
2099				if ( searchCols[i] ) {
2100					_fnCamelToHungarian( DataTable.models.oSearch, searchCols[i] );
2101				}
2102			}
2103		}
2104	}
2105
2106
2107	/**
2108	 * Provide backwards compatibility for column options. Note that the new options
2109	 * are mapped onto the old parameters, so this is an external interface change
2110	 * only.
2111	 *  @param {object} init Object to map
2112	 */
2113	function _fnCompatCols ( init )
2114	{
2115		_fnCompatMap( init, 'orderable',     'bSortable' );
2116		_fnCompatMap( init, 'orderData',     'aDataSort' );
2117		_fnCompatMap( init, 'orderSequence', 'asSorting' );
2118		_fnCompatMap( init, 'orderDataType', 'sortDataType' );
2119
2120		// orderData can be given as an integer
2121		var dataSort = init.aDataSort;
2122		if ( typeof dataSort === 'number' && ! Array.isArray( dataSort ) ) {
2123			init.aDataSort = [ dataSort ];
2124		}
2125	}
2126
2127
2128	/**
2129	 * Browser feature detection for capabilities, quirks
2130	 *  @param {object} settings dataTables settings object
2131	 *  @memberof DataTable#oApi
2132	 */
2133	function _fnBrowserDetect( settings )
2134	{
2135		// We don't need to do this every time DataTables is constructed, the values
2136		// calculated are specific to the browser and OS configuration which we
2137		// don't expect to change between initialisations
2138		if ( ! DataTable.__browser ) {
2139			var browser = {};
2140			DataTable.__browser = browser;
2141
2142			// Scrolling feature / quirks detection
2143			var n = $('<div/>')
2144				.css( {
2145					position: 'fixed',
2146					top: 0,
2147					left: $(window).scrollLeft()*-1, // allow for scrolling
2148					height: 1,
2149					width: 1,
2150					overflow: 'hidden'
2151				} )
2152				.append(
2153					$('<div/>')
2154						.css( {
2155							position: 'absolute',
2156							top: 1,
2157							left: 1,
2158							width: 100,
2159							overflow: 'scroll'
2160						} )
2161						.append(
2162							$('<div/>')
2163								.css( {
2164									width: '100%',
2165									height: 10
2166								} )
2167						)
2168				)
2169				.appendTo( 'body' );
2170
2171			var outer = n.children();
2172			var inner = outer.children();
2173
2174			// Numbers below, in order, are:
2175			// inner.offsetWidth, inner.clientWidth, outer.offsetWidth, outer.clientWidth
2176			//
2177			// IE6 XP:                           100 100 100  83
2178			// IE7 Vista:                        100 100 100  83
2179			// IE 8+ Windows:                     83  83 100  83
2180			// Evergreen Windows:                 83  83 100  83
2181			// Evergreen Mac with scrollbars:     85  85 100  85
2182			// Evergreen Mac without scrollbars: 100 100 100 100
2183
2184			// Get scrollbar width
2185			browser.barWidth = outer[0].offsetWidth - outer[0].clientWidth;
2186
2187			// IE6/7 will oversize a width 100% element inside a scrolling element, to
2188			// include the width of the scrollbar, while other browsers ensure the inner
2189			// element is contained without forcing scrolling
2190			browser.bScrollOversize = inner[0].offsetWidth === 100 && outer[0].clientWidth !== 100;
2191
2192			// In rtl text layout, some browsers (most, but not all) will place the
2193			// scrollbar on the left, rather than the right.
2194			browser.bScrollbarLeft = Math.round( inner.offset().left ) !== 1;
2195
2196			// IE8- don't provide height and width for getBoundingClientRect
2197			browser.bBounding = n[0].getBoundingClientRect().width ? true : false;
2198
2199			n.remove();
2200		}
2201
2202		$.extend( settings.oBrowser, DataTable.__browser );
2203		settings.oScroll.iBarWidth = DataTable.__browser.barWidth;
2204	}
2205
2206
2207	/**
2208	 * Array.prototype reduce[Right] method, used for browsers which don't support
2209	 * JS 1.6. Done this way to reduce code size, since we iterate either way
2210	 *  @param {object} settings dataTables settings object
2211	 *  @memberof DataTable#oApi
2212	 */
2213	function _fnReduce ( that, fn, init, start, end, inc )
2214	{
2215		var
2216			i = start,
2217			value,
2218			isSet = false;
2219
2220		if ( init !== undefined ) {
2221			value = init;
2222			isSet = true;
2223		}
2224
2225		while ( i !== end ) {
2226			if ( ! that.hasOwnProperty(i) ) {
2227				continue;
2228			}
2229
2230			value = isSet ?
2231				fn( value, that[i], i, that ) :
2232				that[i];
2233
2234			isSet = true;
2235			i += inc;
2236		}
2237
2238		return value;
2239	}
2240
2241	/**
2242	 * Add a column to the list used for the table with default values
2243	 *  @param {object} oSettings dataTables settings object
2244	 *  @param {node} nTh The th element for this column
2245	 *  @memberof DataTable#oApi
2246	 */
2247	function _fnAddColumn( oSettings, nTh )
2248	{
2249		// Add column to aoColumns array
2250		var oDefaults = DataTable.defaults.column;
2251		var iCol = oSettings.aoColumns.length;
2252		var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {
2253			"nTh": nTh ? nTh : document.createElement('th'),
2254			"sTitle":    oDefaults.sTitle    ? oDefaults.sTitle    : nTh ? nTh.innerHTML : '',
2255			"aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],
2256			"mData": oDefaults.mData ? oDefaults.mData : iCol,
2257			idx: iCol
2258		} );
2259		oSettings.aoColumns.push( oCol );
2260
2261		// Add search object for column specific search. Note that the `searchCols[ iCol ]`
2262		// passed into extend can be undefined. This allows the user to give a default
2263		// with only some of the parameters defined, and also not give a default
2264		var searchCols = oSettings.aoPreSearchCols;
2265		searchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] );
2266
2267		// Use the default column options function to initialise classes etc
2268		_fnColumnOptions( oSettings, iCol, $(nTh).data() );
2269	}
2270
2271
2272	/**
2273	 * Apply options for a column
2274	 *  @param {object} oSettings dataTables settings object
2275	 *  @param {int} iCol column index to consider
2276	 *  @param {object} oOptions object with sType, bVisible and bSearchable etc
2277	 *  @memberof DataTable#oApi
2278	 */
2279	function _fnColumnOptions( oSettings, iCol, oOptions )
2280	{
2281		var oCol = oSettings.aoColumns[ iCol ];
2282		var oClasses = oSettings.oClasses;
2283		var th = $(oCol.nTh);
2284
2285		// Try to get width information from the DOM. We can't get it from CSS
2286		// as we'd need to parse the CSS stylesheet. `width` option can override
2287		if ( ! oCol.sWidthOrig ) {
2288			// Width attribute
2289			oCol.sWidthOrig = th.attr('width') || null;
2290
2291			// Style attribute
2292			var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/);
2293			if ( t ) {
2294				oCol.sWidthOrig = t[1];
2295			}
2296		}
2297
2298		/* User specified column options */
2299		if ( oOptions !== undefined && oOptions !== null )
2300		{
2301			// Backwards compatibility
2302			_fnCompatCols( oOptions );
2303
2304			// Map camel case parameters to their Hungarian counterparts
2305			_fnCamelToHungarian( DataTable.defaults.column, oOptions, true );
2306
2307			/* Backwards compatibility for mDataProp */
2308			if ( oOptions.mDataProp !== undefined && !oOptions.mData )
2309			{
2310				oOptions.mData = oOptions.mDataProp;
2311			}
2312
2313			if ( oOptions.sType )
2314			{
2315				oCol._sManualType = oOptions.sType;
2316			}
2317
2318			// `class` is a reserved word in Javascript, so we need to provide
2319			// the ability to use a valid name for the camel case input
2320			if ( oOptions.className && ! oOptions.sClass )
2321			{
2322				oOptions.sClass = oOptions.className;
2323			}
2324			if ( oOptions.sClass ) {
2325				th.addClass( oOptions.sClass );
2326			}
2327
2328			var origClass = oCol.sClass;
2329
2330			$.extend( oCol, oOptions );
2331			_fnMap( oCol, oOptions, "sWidth", "sWidthOrig" );
2332
2333			// Merge class from previously defined classes with this one, rather than just
2334			// overwriting it in the extend above
2335			if (origClass !== oCol.sClass) {
2336				oCol.sClass = origClass + ' ' + oCol.sClass;
2337			}
2338
2339			/* iDataSort to be applied (backwards compatibility), but aDataSort will take
2340			 * priority if defined
2341			 */
2342			if ( oOptions.iDataSort !== undefined )
2343			{
2344				oCol.aDataSort = [ oOptions.iDataSort ];
2345			}
2346			_fnMap( oCol, oOptions, "aDataSort" );
2347		}
2348
2349		/* Cache the data get and set functions for speed */
2350		var mDataSrc = oCol.mData;
2351		var mData = _fnGetObjectDataFn( mDataSrc );
2352		var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null;
2353
2354		var attrTest = function( src ) {
2355			return typeof src === 'string' && src.indexOf('@') !== -1;
2356		};
2357		oCol._bAttrSrc = $.isPlainObject( mDataSrc ) && (
2358			attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter)
2359		);
2360		oCol._setter = null;
2361
2362		oCol.fnGetData = function (rowData, type, meta) {
2363			var innerData = mData( rowData, type, undefined, meta );
2364
2365			return mRender && type ?
2366				mRender( innerData, type, rowData, meta ) :
2367				innerData;
2368		};
2369		oCol.fnSetData = function ( rowData, val, meta ) {
2370			return _fnSetObjectDataFn( mDataSrc )( rowData, val, meta );
2371		};
2372
2373		// Indicate if DataTables should read DOM data as an object or array
2374		// Used in _fnGetRowElements
2375		if ( typeof mDataSrc !== 'number' && ! oCol._isArrayHost ) {
2376			oSettings._rowReadObject = true;
2377		}
2378
2379		/* Feature sorting overrides column specific when off */
2380		if ( !oSettings.oFeatures.bSort )
2381		{
2382			oCol.bSortable = false;
2383			th.addClass( oClasses.sSortableNone ); // Have to add class here as order event isn't called
2384		}
2385
2386		/* Check that the class assignment is correct for sorting */
2387		var bAsc = $.inArray('asc', oCol.asSorting) !== -1;
2388		var bDesc = $.inArray('desc', oCol.asSorting) !== -1;
2389		if ( !oCol.bSortable || (!bAsc && !bDesc) )
2390		{
2391			oCol.sSortingClass = oClasses.sSortableNone;
2392			oCol.sSortingClassJUI = "";
2393		}
2394		else if ( bAsc && !bDesc )
2395		{
2396			oCol.sSortingClass = oClasses.sSortableAsc;
2397			oCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed;
2398		}
2399		else if ( !bAsc && bDesc )
2400		{
2401			oCol.sSortingClass = oClasses.sSortableDesc;
2402			oCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed;
2403		}
2404		else
2405		{
2406			oCol.sSortingClass = oClasses.sSortable;
2407			oCol.sSortingClassJUI = oClasses.sSortJUI;
2408		}
2409	}
2410
2411
2412	/**
2413	 * Adjust the table column widths for new data. Note: you would probably want to
2414	 * do a redraw after calling this function!
2415	 *  @param {object} settings dataTables settings object
2416	 *  @memberof DataTable#oApi
2417	 */
2418	function _fnAdjustColumnSizing ( settings )
2419	{
2420		/* Not interested in doing column width calculation if auto-width is disabled */
2421		if ( settings.oFeatures.bAutoWidth !== false )
2422		{
2423			var columns = settings.aoColumns;
2424
2425			_fnCalculateColumnWidths( settings );
2426			for ( var i=0 , iLen=columns.length ; i<iLen ; i++ )
2427			{
2428				columns[i].nTh.style.width = columns[i].sWidth;
2429			}
2430		}
2431
2432		var scroll = settings.oScroll;
2433		if ( scroll.sY !== '' || scroll.sX !== '')
2434		{
2435			_fnScrollDraw( settings );
2436		}
2437
2438		_fnCallbackFire( settings, null, 'column-sizing', [settings] );
2439	}
2440
2441
2442	/**
2443	 * Convert the index of a visible column to the index in the data array (take account
2444	 * of hidden columns)
2445	 *  @param {object} oSettings dataTables settings object
2446	 *  @param {int} iMatch Visible column index to lookup
2447	 *  @returns {int} i the data index
2448	 *  @memberof DataTable#oApi
2449	 */
2450	function _fnVisibleToColumnIndex( oSettings, iMatch )
2451	{
2452		var aiVis = _fnGetColumns( oSettings, 'bVisible' );
2453
2454		return typeof aiVis[iMatch] === 'number' ?
2455			aiVis[iMatch] :
2456			null;
2457	}
2458
2459
2460	/**
2461	 * Convert the index of an index in the data array and convert it to the visible
2462	 *   column index (take account of hidden columns)
2463	 *  @param {int} iMatch Column index to lookup
2464	 *  @param {object} oSettings dataTables settings object
2465	 *  @returns {int} i the data index
2466	 *  @memberof DataTable#oApi
2467	 */
2468	function _fnColumnIndexToVisible( oSettings, iMatch )
2469	{
2470		var aiVis = _fnGetColumns( oSettings, 'bVisible' );
2471		var iPos = $.inArray( iMatch, aiVis );
2472
2473		return iPos !== -1 ? iPos : null;
2474	}
2475
2476
2477	/**
2478	 * Get the number of visible columns
2479	 *  @param {object} oSettings dataTables settings object
2480	 *  @returns {int} i the number of visible columns
2481	 *  @memberof DataTable#oApi
2482	 */
2483	function _fnVisbleColumns( oSettings )
2484	{
2485		var vis = 0;
2486
2487		// No reduce in IE8, use a loop for now
2488		$.each( oSettings.aoColumns, function ( i, col ) {
2489			if ( col.bVisible && $(col.nTh).css('display') !== 'none' ) {
2490				vis++;
2491			}
2492		} );
2493
2494		return vis;
2495	}
2496
2497
2498	/**
2499	 * Get an array of column indexes that match a given property
2500	 *  @param {object} oSettings dataTables settings object
2501	 *  @param {string} sParam Parameter in aoColumns to look for - typically
2502	 *    bVisible or bSearchable
2503	 *  @returns {array} Array of indexes with matched properties
2504	 *  @memberof DataTable#oApi
2505	 */
2506	function _fnGetColumns( oSettings, sParam )
2507	{
2508		var a = [];
2509
2510		$.map( oSettings.aoColumns, function(val, i) {
2511			if ( val[sParam] ) {
2512				a.push( i );
2513			}
2514		} );
2515
2516		return a;
2517	}
2518
2519
2520	/**
2521	 * Calculate the 'type' of a column
2522	 *  @param {object} settings dataTables settings object
2523	 *  @memberof DataTable#oApi
2524	 */
2525	function _fnColumnTypes ( settings )
2526	{
2527		var columns = settings.aoColumns;
2528		var data = settings.aoData;
2529		var types = DataTable.ext.type.detect;
2530		var i, ien, j, jen, k, ken;
2531		var col, cell, detectedType, cache;
2532
2533		// For each column, spin over the
2534		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
2535			col = columns[i];
2536			cache = [];
2537
2538			if ( ! col.sType && col._sManualType ) {
2539				col.sType = col._sManualType;
2540			}
2541			else if ( ! col.sType ) {
2542				for ( j=0, jen=types.length ; j<jen ; j++ ) {
2543					for ( k=0, ken=data.length ; k<ken ; k++ ) {
2544						// Use a cache array so we only need to get the type data
2545						// from the formatter once (when using multiple detectors)
2546						if ( cache[k] === undefined ) {
2547							cache[k] = _fnGetCellData( settings, k, i, 'type' );
2548						}
2549
2550						detectedType = types[j]( cache[k], settings );
2551
2552						// If null, then this type can't apply to this column, so
2553						// rather than testing all cells, break out. There is an
2554						// exception for the last type which is `html`. We need to
2555						// scan all rows since it is possible to mix string and HTML
2556						// types
2557						if ( ! detectedType && j !== types.length-1 ) {
2558							break;
2559						}
2560
2561						// Only a single match is needed for html type since it is
2562						// bottom of the pile and very similar to string - but it
2563						// must not be empty
2564						if ( detectedType === 'html' && ! _empty(cache[k]) ) {
2565							break;
2566						}
2567					}
2568
2569					// Type is valid for all data points in the column - use this
2570					// type
2571					if ( detectedType ) {
2572						col.sType = detectedType;
2573						break;
2574					}
2575				}
2576
2577				// Fall back - if no type was detected, always use string
2578				if ( ! col.sType ) {
2579					col.sType = 'string';
2580				}
2581			}
2582		}
2583	}
2584
2585
2586	/**
2587	 * Take the column definitions and static columns arrays and calculate how
2588	 * they relate to column indexes. The callback function will then apply the
2589	 * definition found for a column to a suitable configuration object.
2590	 *  @param {object} oSettings dataTables settings object
2591	 *  @param {array} aoColDefs The aoColumnDefs array that is to be applied
2592	 *  @param {array} aoCols The aoColumns array that defines columns individually
2593	 *  @param {function} fn Callback function - takes two parameters, the calculated
2594	 *    column index and the definition for that column.
2595	 *  @memberof DataTable#oApi
2596	 */
2597	function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )
2598	{
2599		var i, iLen, j, jLen, k, kLen, def;
2600		var columns = oSettings.aoColumns;
2601
2602		// Column definitions with aTargets
2603		if ( aoColDefs )
2604		{
2605			/* Loop over the definitions array - loop in reverse so first instance has priority */
2606			for ( i=aoColDefs.length-1 ; i>=0 ; i-- )
2607			{
2608				def = aoColDefs[i];
2609
2610				/* Each definition can target multiple columns, as it is an array */
2611				var aTargets = def.target !== undefined
2612					? def.target
2613					: def.targets !== undefined
2614						? def.targets
2615						: def.aTargets;
2616
2617				if ( ! Array.isArray( aTargets ) )
2618				{
2619					aTargets = [ aTargets ];
2620				}
2621
2622				for ( j=0, jLen=aTargets.length ; j<jLen ; j++ )
2623				{
2624					if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 )
2625					{
2626						/* Add columns that we don't yet know about */
2627						while( columns.length <= aTargets[j] )
2628						{
2629							_fnAddColumn( oSettings );
2630						}
2631
2632						/* Integer, basic index */
2633						fn( aTargets[j], def );
2634					}
2635					else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 )
2636					{
2637						/* Negative integer, right to left column counting */
2638						fn( columns.length+aTargets[j], def );
2639					}
2640					else if ( typeof aTargets[j] === 'string' )
2641					{
2642						/* Class name matching on TH element */
2643						for ( k=0, kLen=columns.length ; k<kLen ; k++ )
2644						{
2645							if ( aTargets[j] == "_all" ||
2646							     $(columns[k].nTh).hasClass( aTargets[j] ) )
2647							{
2648								fn( k, def );
2649							}
2650						}
2651					}
2652				}
2653			}
2654		}
2655
2656		// Statically defined columns array
2657		if ( aoCols )
2658		{
2659			for ( i=0, iLen=aoCols.length ; i<iLen ; i++ )
2660			{
2661				fn( i, aoCols[i] );
2662			}
2663		}
2664	}
2665
2666	/**
2667	 * Add a data array to the table, creating DOM node etc. This is the parallel to
2668	 * _fnGatherData, but for adding rows from a Javascript source, rather than a
2669	 * DOM source.
2670	 *  @param {object} oSettings dataTables settings object
2671	 *  @param {array} aData data array to be added
2672	 *  @param {node} [nTr] TR element to add to the table - optional. If not given,
2673	 *    DataTables will create a row automatically
2674	 *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
2675	 *    if nTr is.
2676	 *  @returns {int} >=0 if successful (index of new aoData entry), -1 if failed
2677	 *  @memberof DataTable#oApi
2678	 */
2679	function _fnAddData ( oSettings, aDataIn, nTr, anTds )
2680	{
2681		/* Create the object for storing information about this new row */
2682		var iRow = oSettings.aoData.length;
2683		var oData = $.extend( true, {}, DataTable.models.oRow, {
2684			src: nTr ? 'dom' : 'data',
2685			idx: iRow
2686		} );
2687
2688		oData._aData = aDataIn;
2689		oSettings.aoData.push( oData );
2690
2691		/* Create the cells */
2692		var nTd, sThisType;
2693		var columns = oSettings.aoColumns;
2694
2695		// Invalidate the column types as the new data needs to be revalidated
2696		for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
2697		{
2698			columns[i].sType = null;
2699		}
2700
2701		/* Add to the display array */
2702		oSettings.aiDisplayMaster.push( iRow );
2703
2704		var id = oSettings.rowIdFn( aDataIn );
2705		if ( id !== undefined ) {
2706			oSettings.aIds[ id ] = oData;
2707		}
2708
2709		/* Create the DOM information, or register it if already present */
2710		if ( nTr || ! oSettings.oFeatures.bDeferRender )
2711		{
2712			_fnCreateTr( oSettings, iRow, nTr, anTds );
2713		}
2714
2715		return iRow;
2716	}
2717
2718
2719	/**
2720	 * Add one or more TR elements to the table. Generally we'd expect to
2721	 * use this for reading data from a DOM sourced table, but it could be
2722	 * used for an TR element. Note that if a TR is given, it is used (i.e.
2723	 * it is not cloned).
2724	 *  @param {object} settings dataTables settings object
2725	 *  @param {array|node|jQuery} trs The TR element(s) to add to the table
2726	 *  @returns {array} Array of indexes for the added rows
2727	 *  @memberof DataTable#oApi
2728	 */
2729	function _fnAddTr( settings, trs )
2730	{
2731		var row;
2732
2733		// Allow an individual node to be passed in
2734		if ( ! (trs instanceof $) ) {
2735			trs = $(trs);
2736		}
2737
2738		return trs.map( function (i, el) {
2739			row = _fnGetRowElements( settings, el );
2740			return _fnAddData( settings, row.data, el, row.cells );
2741		} );
2742	}
2743
2744
2745	/**
2746	 * Take a TR element and convert it to an index in aoData
2747	 *  @param {object} oSettings dataTables settings object
2748	 *  @param {node} n the TR element to find
2749	 *  @returns {int} index if the node is found, null if not
2750	 *  @memberof DataTable#oApi
2751	 */
2752	function _fnNodeToDataIndex( oSettings, n )
2753	{
2754		return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null;
2755	}
2756
2757
2758	/**
2759	 * Take a TD element and convert it into a column data index (not the visible index)
2760	 *  @param {object} oSettings dataTables settings object
2761	 *  @param {int} iRow The row number the TD/TH can be found in
2762	 *  @param {node} n The TD/TH element to find
2763	 *  @returns {int} index if the node is found, -1 if not
2764	 *  @memberof DataTable#oApi
2765	 */
2766	function _fnNodeToColumnIndex( oSettings, iRow, n )
2767	{
2768		return $.inArray( n, oSettings.aoData[ iRow ].anCells );
2769	}
2770
2771
2772	/**
2773	 * Get the data for a given cell from the internal cache, taking into account data mapping
2774	 *  @param {object} settings dataTables settings object
2775	 *  @param {int} rowIdx aoData row id
2776	 *  @param {int} colIdx Column index
2777	 *  @param {string} type data get type ('display', 'type' 'filter|search' 'sort|order')
2778	 *  @returns {*} Cell data
2779	 *  @memberof DataTable#oApi
2780	 */
2781	function _fnGetCellData( settings, rowIdx, colIdx, type )
2782	{
2783		if (type === 'search') {
2784			type = 'filter';
2785		}
2786		else if (type === 'order') {
2787			type = 'sort';
2788		}
2789
2790		var draw           = settings.iDraw;
2791		var col            = settings.aoColumns[colIdx];
2792		var rowData        = settings.aoData[rowIdx]._aData;
2793		var defaultContent = col.sDefaultContent;
2794		var cellData       = col.fnGetData( rowData, type, {
2795			settings: settings,
2796			row:      rowIdx,
2797			col:      colIdx
2798		} );
2799
2800		if ( cellData === undefined ) {
2801			if ( settings.iDrawError != draw && defaultContent === null ) {
2802				_fnLog( settings, 0, "Requested unknown parameter "+
2803					(typeof col.mData=='function' ? '{function}' : "'"+col.mData+"'")+
2804					" for row "+rowIdx+", column "+colIdx, 4 );
2805				settings.iDrawError = draw;
2806			}
2807			return defaultContent;
2808		}
2809
2810		// When the data source is null and a specific data type is requested (i.e.
2811		// not the original data), we can use default column data
2812		if ( (cellData === rowData || cellData === null) && defaultContent !== null && type !== undefined ) {
2813			cellData = defaultContent;
2814		}
2815		else if ( typeof cellData === 'function' ) {
2816			// If the data source is a function, then we run it and use the return,
2817			// executing in the scope of the data object (for instances)
2818			return cellData.call( rowData );
2819		}
2820
2821		if ( cellData === null && type === 'display' ) {
2822			return '';
2823		}
2824
2825		if ( type === 'filter' ) {
2826			var fomatters = DataTable.ext.type.search;
2827
2828			if ( fomatters[ col.sType ] ) {
2829				cellData = fomatters[ col.sType ]( cellData );
2830			}
2831		}
2832
2833		return cellData;
2834	}
2835
2836
2837	/**
2838	 * Set the value for a specific cell, into the internal data cache
2839	 *  @param {object} settings dataTables settings object
2840	 *  @param {int} rowIdx aoData row id
2841	 *  @param {int} colIdx Column index
2842	 *  @param {*} val Value to set
2843	 *  @memberof DataTable#oApi
2844	 */
2845	function _fnSetCellData( settings, rowIdx, colIdx, val )
2846	{
2847		var col     = settings.aoColumns[colIdx];
2848		var rowData = settings.aoData[rowIdx]._aData;
2849
2850		col.fnSetData( rowData, val, {
2851			settings: settings,
2852			row:      rowIdx,
2853			col:      colIdx
2854		}  );
2855	}
2856
2857
2858	// Private variable that is used to match action syntax in the data property object
2859	var __reArray = /\[.*?\]$/;
2860	var __reFn = /\(\)$/;
2861
2862	/**
2863	 * Split string on periods, taking into account escaped periods
2864	 * @param  {string} str String to split
2865	 * @return {array} Split string
2866	 */
2867	function _fnSplitObjNotation( str )
2868	{
2869		return $.map( str.match(/(\\.|[^\.])+/g) || [''], function ( s ) {
2870			return s.replace(/\\\./g, '.');
2871		} );
2872	}
2873
2874
2875	/**
2876	 * Return a function that can be used to get data from a source object, taking
2877	 * into account the ability to use nested objects as a source
2878	 *  @param {string|int|function} mSource The data source for the object
2879	 *  @returns {function} Data get function
2880	 *  @memberof DataTable#oApi
2881	 */
2882	var _fnGetObjectDataFn = DataTable.util.get;
2883
2884
2885	/**
2886	 * Return a function that can be used to set data from a source object, taking
2887	 * into account the ability to use nested objects as a source
2888	 *  @param {string|int|function} mSource The data source for the object
2889	 *  @returns {function} Data set function
2890	 *  @memberof DataTable#oApi
2891	 */
2892	var _fnSetObjectDataFn = DataTable.util.set;
2893
2894
2895	/**
2896	 * Return an array with the full table data
2897	 *  @param {object} oSettings dataTables settings object
2898	 *  @returns array {array} aData Master data array
2899	 *  @memberof DataTable#oApi
2900	 */
2901	function _fnGetDataMaster ( settings )
2902	{
2903		return _pluck( settings.aoData, '_aData' );
2904	}
2905
2906
2907	/**
2908	 * Nuke the table
2909	 *  @param {object} oSettings dataTables settings object
2910	 *  @memberof DataTable#oApi
2911	 */
2912	function _fnClearTable( settings )
2913	{
2914		settings.aoData.length = 0;
2915		settings.aiDisplayMaster.length = 0;
2916		settings.aiDisplay.length = 0;
2917		settings.aIds = {};
2918	}
2919
2920
2921	 /**
2922	 * Take an array of integers (index array) and remove a target integer (value - not
2923	 * the key!)
2924	 *  @param {array} a Index array to target
2925	 *  @param {int} iTarget value to find
2926	 *  @memberof DataTable#oApi
2927	 */
2928	function _fnDeleteIndex( a, iTarget, splice )
2929	{
2930		var iTargetIndex = -1;
2931
2932		for ( var i=0, iLen=a.length ; i<iLen ; i++ )
2933		{
2934			if ( a[i] == iTarget )
2935			{
2936				iTargetIndex = i;
2937			}
2938			else if ( a[i] > iTarget )
2939			{
2940				a[i]--;
2941			}
2942		}
2943
2944		if ( iTargetIndex != -1 && splice === undefined )
2945		{
2946			a.splice( iTargetIndex, 1 );
2947		}
2948	}
2949
2950
2951	/**
2952	 * Mark cached data as invalid such that a re-read of the data will occur when
2953	 * the cached data is next requested. Also update from the data source object.
2954	 *
2955	 * @param {object} settings DataTables settings object
2956	 * @param {int}    rowIdx   Row index to invalidate
2957	 * @param {string} [src]    Source to invalidate from: undefined, 'auto', 'dom'
2958	 *     or 'data'
2959	 * @param {int}    [colIdx] Column index to invalidate. If undefined the whole
2960	 *     row will be invalidated
2961	 * @memberof DataTable#oApi
2962	 *
2963	 * @todo For the modularisation of v1.11 this will need to become a callback, so
2964	 *   the sort and filter methods can subscribe to it. That will required
2965	 *   initialisation options for sorting, which is why it is not already baked in
2966	 */
2967	function _fnInvalidate( settings, rowIdx, src, colIdx )
2968	{
2969		var row = settings.aoData[ rowIdx ];
2970		var i, ien;
2971		var cellWrite = function ( cell, col ) {
2972			// This is very frustrating, but in IE if you just write directly
2973			// to innerHTML, and elements that are overwritten are GC'ed,
2974			// even if there is a reference to them elsewhere
2975			while ( cell.childNodes.length ) {
2976				cell.removeChild( cell.firstChild );
2977			}
2978
2979			cell.innerHTML = _fnGetCellData( settings, rowIdx, col, 'display' );
2980		};
2981
2982		// Are we reading last data from DOM or the data object?
2983		if ( src === 'dom' || ((! src || src === 'auto') && row.src === 'dom') ) {
2984			// Read the data from the DOM
2985			row._aData = _fnGetRowElements(
2986					settings, row, colIdx, colIdx === undefined ? undefined : row._aData
2987				)
2988				.data;
2989		}
2990		else {
2991			// Reading from data object, update the DOM
2992			var cells = row.anCells;
2993
2994			if ( cells ) {
2995				if ( colIdx !== undefined ) {
2996					cellWrite( cells[colIdx], colIdx );
2997				}
2998				else {
2999					for ( i=0, ien=cells.length ; i<ien ; i++ ) {
3000						cellWrite( cells[i], i );
3001					}
3002				}
3003			}
3004		}
3005
3006		// For both row and cell invalidation, the cached data for sorting and
3007		// filtering is nulled out
3008		row._aSortData = null;
3009		row._aFilterData = null;
3010
3011		// Invalidate the type for a specific column (if given) or all columns since
3012		// the data might have changed
3013		var cols = settings.aoColumns;
3014		if ( colIdx !== undefined ) {
3015			cols[ colIdx ].sType = null;
3016		}
3017		else {
3018			for ( i=0, ien=cols.length ; i<ien ; i++ ) {
3019				cols[i].sType = null;
3020			}
3021
3022			// Update DataTables special `DT_*` attributes for the row
3023			_fnRowAttributes( settings, row );
3024		}
3025	}
3026
3027
3028	/**
3029	 * Build a data source object from an HTML row, reading the contents of the
3030	 * cells that are in the row.
3031	 *
3032	 * @param {object} settings DataTables settings object
3033	 * @param {node|object} TR element from which to read data or existing row
3034	 *   object from which to re-read the data from the cells
3035	 * @param {int} [colIdx] Optional column index
3036	 * @param {array|object} [d] Data source object. If `colIdx` is given then this
3037	 *   parameter should also be given and will be used to write the data into.
3038	 *   Only the column in question will be written
3039	 * @returns {object} Object with two parameters: `data` the data read, in
3040	 *   document order, and `cells` and array of nodes (they can be useful to the
3041	 *   caller, so rather than needing a second traversal to get them, just return
3042	 *   them from here).
3043	 * @memberof DataTable#oApi
3044	 */
3045	function _fnGetRowElements( settings, row, colIdx, d )
3046	{
3047		var
3048			tds = [],
3049			td = row.firstChild,
3050			name, col, o, i=0, contents,
3051			columns = settings.aoColumns,
3052			objectRead = settings._rowReadObject;
3053
3054		// Allow the data object to be passed in, or construct
3055		d = d !== undefined ?
3056			d :
3057			objectRead ?
3058				{} :
3059				[];
3060
3061		var attr = function ( str, td  ) {
3062			if ( typeof str === 'string' ) {
3063				var idx = str.indexOf('@');
3064
3065				if ( idx !== -1 ) {
3066					var attr = str.substring( idx+1 );
3067					var setter = _fnSetObjectDataFn( str );
3068					setter( d, td.getAttribute( attr ) );
3069				}
3070			}
3071		};
3072
3073		// Read data from a cell and store into the data object
3074		var cellProcess = function ( cell ) {
3075			if ( colIdx === undefined || colIdx === i ) {
3076				col = columns[i];
3077				contents = (cell.innerHTML).trim();
3078
3079				if ( col && col._bAttrSrc ) {
3080					var setter = _fnSetObjectDataFn( col.mData._ );
3081					setter( d, contents );
3082
3083					attr( col.mData.sort, cell );
3084					attr( col.mData.type, cell );
3085					attr( col.mData.filter, cell );
3086				}
3087				else {
3088					// Depending on the `data` option for the columns the data can
3089					// be read to either an object or an array.
3090					if ( objectRead ) {
3091						if ( ! col._setter ) {
3092							// Cache the setter function
3093							col._setter = _fnSetObjectDataFn( col.mData );
3094						}
3095						col._setter( d, contents );
3096					}
3097					else {
3098						d[i] = contents;
3099					}
3100				}
3101			}
3102
3103			i++;
3104		};
3105
3106		if ( td ) {
3107			// `tr` element was passed in
3108			while ( td ) {
3109				name = td.nodeName.toUpperCase();
3110
3111				if ( name == "TD" || name == "TH" ) {
3112					cellProcess( td );
3113					tds.push( td );
3114				}
3115
3116				td = td.nextSibling;
3117			}
3118		}
3119		else {
3120			// Existing row object passed in
3121			tds = row.anCells;
3122
3123			for ( var j=0, jen=tds.length ; j<jen ; j++ ) {
3124				cellProcess( tds[j] );
3125			}
3126		}
3127
3128		// Read the ID from the DOM if present
3129		var rowNode = row.firstChild ? row : row.nTr;
3130
3131		if ( rowNode ) {
3132			var id = rowNode.getAttribute( 'id' );
3133
3134			if ( id ) {
3135				_fnSetObjectDataFn( settings.rowId )( d, id );
3136			}
3137		}
3138
3139		return {
3140			data: d,
3141			cells: tds
3142		};
3143	}
3144	/**
3145	 * Create a new TR element (and it's TD children) for a row
3146	 *  @param {object} oSettings dataTables settings object
3147	 *  @param {int} iRow Row to consider
3148	 *  @param {node} [nTrIn] TR element to add to the table - optional. If not given,
3149	 *    DataTables will create a row automatically
3150	 *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
3151	 *    if nTr is.
3152	 *  @memberof DataTable#oApi
3153	 */
3154	function _fnCreateTr ( oSettings, iRow, nTrIn, anTds )
3155	{
3156		var
3157			row = oSettings.aoData[iRow],
3158			rowData = row._aData,
3159			cells = [],
3160			nTr, nTd, oCol,
3161			i, iLen, create;
3162
3163		if ( row.nTr === null )
3164		{
3165			nTr = nTrIn || document.createElement('tr');
3166
3167			row.nTr = nTr;
3168			row.anCells = cells;
3169
3170			/* Use a private property on the node to allow reserve mapping from the node
3171			 * to the aoData array for fast look up
3172			 */
3173			nTr._DT_RowIndex = iRow;
3174
3175			/* Special parameters can be given by the data source to be used on the row */
3176			_fnRowAttributes( oSettings, row );
3177
3178			/* Process each column */
3179			for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
3180			{
3181				oCol = oSettings.aoColumns[i];
3182				create = nTrIn ? false : true;
3183
3184				nTd = create ? document.createElement( oCol.sCellType ) : anTds[i];
3185
3186				if (! nTd) {
3187					_fnLog( oSettings, 0, 'Incorrect column count', 18 );
3188				}
3189
3190				nTd._DT_CellIndex = {
3191					row: iRow,
3192					column: i
3193				};
3194
3195				cells.push( nTd );
3196
3197				// Need to create the HTML if new, or if a rendering function is defined
3198				if ( create || ((oCol.mRender || oCol.mData !== i) &&
3199					 (!$.isPlainObject(oCol.mData) || oCol.mData._ !== i+'.display')
3200				)) {
3201					nTd.innerHTML = _fnGetCellData( oSettings, iRow, i, 'display' );
3202				}
3203
3204				/* Add user defined class */
3205				if ( oCol.sClass )
3206				{
3207					nTd.className += ' '+oCol.sClass;
3208				}
3209
3210				// Visibility - add or remove as required
3211				if ( oCol.bVisible && ! nTrIn )
3212				{
3213					nTr.appendChild( nTd );
3214				}
3215				else if ( ! oCol.bVisible && nTrIn )
3216				{
3217					nTd.parentNode.removeChild( nTd );
3218				}
3219
3220				if ( oCol.fnCreatedCell )
3221				{
3222					oCol.fnCreatedCell.call( oSettings.oInstance,
3223						nTd, _fnGetCellData( oSettings, iRow, i ), rowData, iRow, i
3224					);
3225				}
3226			}
3227
3228			_fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow, cells] );
3229		}
3230	}
3231
3232
3233	/**
3234	 * Add attributes to a row based on the special `DT_*` parameters in a data
3235	 * source object.
3236	 *  @param {object} settings DataTables settings object
3237	 *  @param {object} DataTables row object for the row to be modified
3238	 *  @memberof DataTable#oApi
3239	 */
3240	function _fnRowAttributes( settings, row )
3241	{
3242		var tr = row.nTr;
3243		var data = row._aData;
3244
3245		if ( tr ) {
3246			var id = settings.rowIdFn( data );
3247
3248			if ( id ) {
3249				tr.id = id;
3250			}
3251
3252			if ( data.DT_RowClass ) {
3253				// Remove any classes added by DT_RowClass before
3254				var a = data.DT_RowClass.split(' ');
3255				row.__rowc = row.__rowc ?
3256					_unique( row.__rowc.concat( a ) ) :
3257					a;
3258
3259				$(tr)
3260					.removeClass( row.__rowc.join(' ') )
3261					.addClass( data.DT_RowClass );
3262			}
3263
3264			if ( data.DT_RowAttr ) {
3265				$(tr).attr( data.DT_RowAttr );
3266			}
3267
3268			if ( data.DT_RowData ) {
3269				$(tr).data( data.DT_RowData );
3270			}
3271		}
3272	}
3273
3274
3275	/**
3276	 * Create the HTML header for the table
3277	 *  @param {object} oSettings dataTables settings object
3278	 *  @memberof DataTable#oApi
3279	 */
3280	function _fnBuildHead( oSettings )
3281	{
3282		var i, ien, cell, row, column;
3283		var thead = oSettings.nTHead;
3284		var tfoot = oSettings.nTFoot;
3285		var createHeader = $('th, td', thead).length === 0;
3286		var classes = oSettings.oClasses;
3287		var columns = oSettings.aoColumns;
3288
3289		if ( createHeader ) {
3290			row = $('<tr/>').appendTo( thead );
3291		}
3292
3293		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
3294			column = columns[i];
3295			cell = $( column.nTh ).addClass( column.sClass );
3296
3297			if ( createHeader ) {
3298				cell.appendTo( row );
3299			}
3300
3301			// 1.11 move into sorting
3302			if ( oSettings.oFeatures.bSort ) {
3303				cell.addClass( column.sSortingClass );
3304
3305				if ( column.bSortable !== false ) {
3306					cell
3307						.attr( 'tabindex', oSettings.iTabIndex )
3308						.attr( 'aria-controls', oSettings.sTableId );
3309
3310					_fnSortAttachListener( oSettings, column.nTh, i );
3311				}
3312			}
3313
3314			if ( column.sTitle != cell[0].innerHTML ) {
3315				cell.html( column.sTitle );
3316			}
3317
3318			_fnRenderer( oSettings, 'header' )(
3319				oSettings, cell, column, classes
3320			);
3321		}
3322
3323		if ( createHeader ) {
3324			_fnDetectHeader( oSettings.aoHeader, thead );
3325		}
3326
3327		/* Deal with the footer - add classes if required */
3328		$(thead).children('tr').children('th, td').addClass( classes.sHeaderTH );
3329		$(tfoot).children('tr').children('th, td').addClass( classes.sFooterTH );
3330
3331		// Cache the footer cells. Note that we only take the cells from the first
3332		// row in the footer. If there is more than one row the user wants to
3333		// interact with, they need to use the table().foot() method. Note also this
3334		// allows cells to be used for multiple columns using colspan
3335		if ( tfoot !== null ) {
3336			var cells = oSettings.aoFooter[0];
3337
3338			for ( i=0, ien=cells.length ; i<ien ; i++ ) {
3339				column = columns[i];
3340
3341				if (column) {
3342					column.nTf = cells[i].cell;
3343
3344					if ( column.sClass ) {
3345						$(column.nTf).addClass( column.sClass );
3346					}
3347				}
3348				else {
3349					_fnLog( oSettings, 0, 'Incorrect column count', 18 );
3350				}
3351			}
3352		}
3353	}
3354
3355
3356	/**
3357	 * Draw the header (or footer) element based on the column visibility states. The
3358	 * methodology here is to use the layout array from _fnDetectHeader, modified for
3359	 * the instantaneous column visibility, to construct the new layout. The grid is
3360	 * traversed over cell at a time in a rows x columns grid fashion, although each
3361	 * cell insert can cover multiple elements in the grid - which is tracks using the
3362	 * aApplied array. Cell inserts in the grid will only occur where there isn't
3363	 * already a cell in that position.
3364	 *  @param {object} oSettings dataTables settings object
3365	 *  @param array {objects} aoSource Layout array from _fnDetectHeader
3366	 *  @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,
3367	 *  @memberof DataTable#oApi
3368	 */
3369	function _fnDrawHead( oSettings, aoSource, bIncludeHidden )
3370	{
3371		var i, iLen, j, jLen, k, kLen, n, nLocalTr;
3372		var aoLocal = [];
3373		var aApplied = [];
3374		var iColumns = oSettings.aoColumns.length;
3375		var iRowspan, iColspan;
3376
3377		if ( ! aoSource )
3378		{
3379			return;
3380		}
3381
3382		if (  bIncludeHidden === undefined )
3383		{
3384			bIncludeHidden = false;
3385		}
3386
3387		/* Make a copy of the master layout array, but without the visible columns in it */
3388		for ( i=0, iLen=aoSource.length ; i<iLen ; i++ )
3389		{
3390			aoLocal[i] = aoSource[i].slice();
3391			aoLocal[i].nTr = aoSource[i].nTr;
3392
3393			/* Remove any columns which are currently hidden */
3394			for ( j=iColumns-1 ; j>=0 ; j-- )
3395			{
3396				if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden )
3397				{
3398					aoLocal[i].splice( j, 1 );
3399				}
3400			}
3401
3402			/* Prep the applied array - it needs an element for each row */
3403			aApplied.push( [] );
3404		}
3405
3406		for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ )
3407		{
3408			nLocalTr = aoLocal[i].nTr;
3409
3410			/* All cells are going to be replaced, so empty out the row */
3411			if ( nLocalTr )
3412			{
3413				while( (n = nLocalTr.firstChild) )
3414				{
3415					nLocalTr.removeChild( n );
3416				}
3417			}
3418
3419			for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ )
3420			{
3421				iRowspan = 1;
3422				iColspan = 1;
3423
3424				/* Check to see if there is already a cell (row/colspan) covering our target
3425				 * insert point. If there is, then there is nothing to do.
3426				 */
3427				if ( aApplied[i][j] === undefined )
3428				{
3429					nLocalTr.appendChild( aoLocal[i][j].cell );
3430					aApplied[i][j] = 1;
3431
3432					/* Expand the cell to cover as many rows as needed */
3433					while ( aoLocal[i+iRowspan] !== undefined &&
3434					        aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell )
3435					{
3436						aApplied[i+iRowspan][j] = 1;
3437						iRowspan++;
3438					}
3439
3440					/* Expand the cell to cover as many columns as needed */
3441					while ( aoLocal[i][j+iColspan] !== undefined &&
3442					        aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell )
3443					{
3444						/* Must update the applied array over the rows for the columns */
3445						for ( k=0 ; k<iRowspan ; k++ )
3446						{
3447							aApplied[i+k][j+iColspan] = 1;
3448						}
3449						iColspan++;
3450					}
3451
3452					/* Do the actual expansion in the DOM */
3453					$(aoLocal[i][j].cell)
3454						.attr('rowspan', iRowspan)
3455						.attr('colspan', iColspan);
3456				}
3457			}
3458		}
3459	}
3460
3461
3462	/**
3463	 * Insert the required TR nodes into the table for display
3464	 *  @param {object} oSettings dataTables settings object
3465	 *  @param ajaxComplete true after ajax call to complete rendering
3466	 *  @memberof DataTable#oApi
3467	 */
3468	function _fnDraw( oSettings, ajaxComplete )
3469	{
3470		// Allow for state saving and a custom start position
3471		_fnStart( oSettings );
3472
3473		/* Provide a pre-callback function which can be used to cancel the draw is false is returned */
3474		var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] );
3475		if ( $.inArray( false, aPreDraw ) !== -1 )
3476		{
3477			_fnProcessingDisplay( oSettings, false );
3478			return;
3479		}
3480
3481		var anRows = [];
3482		var iRowCount = 0;
3483		var asStripeClasses = oSettings.asStripeClasses;
3484		var iStripes = asStripeClasses.length;
3485		var oLang = oSettings.oLanguage;
3486		var bServerSide = _fnDataSource( oSettings ) == 'ssp';
3487		var aiDisplay = oSettings.aiDisplay;
3488		var iDisplayStart = oSettings._iDisplayStart;
3489		var iDisplayEnd = oSettings.fnDisplayEnd();
3490
3491		oSettings.bDrawing = true;
3492
3493		/* Server-side processing draw intercept */
3494		if ( oSettings.bDeferLoading )
3495		{
3496			oSettings.bDeferLoading = false;
3497			oSettings.iDraw++;
3498			_fnProcessingDisplay( oSettings, false );
3499		}
3500		else if ( !bServerSide )
3501		{
3502			oSettings.iDraw++;
3503		}
3504		else if ( !oSettings.bDestroying && !ajaxComplete)
3505		{
3506			_fnAjaxUpdate( oSettings );
3507			return;
3508		}
3509
3510		if ( aiDisplay.length !== 0 )
3511		{
3512			var iStart = bServerSide ? 0 : iDisplayStart;
3513			var iEnd = bServerSide ? oSettings.aoData.length : iDisplayEnd;
3514
3515			for ( var j=iStart ; j<iEnd ; j++ )
3516			{
3517				var iDataIndex = aiDisplay[j];
3518				var aoData = oSettings.aoData[ iDataIndex ];
3519				if ( aoData.nTr === null )
3520				{
3521					_fnCreateTr( oSettings, iDataIndex );
3522				}
3523
3524				var nRow = aoData.nTr;
3525
3526				/* Remove the old striping classes and then add the new one */
3527				if ( iStripes !== 0 )
3528				{
3529					var sStripe = asStripeClasses[ iRowCount % iStripes ];
3530					if ( aoData._sRowStripe != sStripe )
3531					{
3532						$(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe );
3533						aoData._sRowStripe = sStripe;
3534					}
3535				}
3536
3537				// Row callback functions - might want to manipulate the row
3538				// iRowCount and j are not currently documented. Are they at all
3539				// useful?
3540				_fnCallbackFire( oSettings, 'aoRowCallback', null,
3541					[nRow, aoData._aData, iRowCount, j, iDataIndex] );
3542
3543				anRows.push( nRow );
3544				iRowCount++;
3545			}
3546		}
3547		else
3548		{
3549			/* Table is empty - create a row with an empty message in it */
3550			var sZero = oLang.sZeroRecords;
3551			if ( oSettings.iDraw == 1 &&  _fnDataSource( oSettings ) == 'ajax' )
3552			{
3553				sZero = oLang.sLoadingRecords;
3554			}
3555			else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 )
3556			{
3557				sZero = oLang.sEmptyTable;
3558			}
3559
3560			anRows[ 0 ] = $( '<tr/>', { 'class': iStripes ? asStripeClasses[0] : '' } )
3561				.append( $('<td />', {
3562					'valign':  'top',
3563					'colSpan': _fnVisbleColumns( oSettings ),
3564					'class':   oSettings.oClasses.sRowEmpty
3565				} ).html( sZero ) )[0];
3566		}
3567
3568		/* Header and footer callbacks */
3569		_fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0],
3570			_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
3571
3572		_fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0],
3573			_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
3574
3575		var body = $(oSettings.nTBody);
3576
3577		body.children().detach();
3578		body.append( $(anRows) );
3579
3580		/* Call all required callback functions for the end of a draw */
3581		_fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] );
3582
3583		/* Draw is complete, sorting and filtering must be as well */
3584		oSettings.bSorted = false;
3585		oSettings.bFiltered = false;
3586		oSettings.bDrawing = false;
3587	}
3588
3589
3590	/**
3591	 * Redraw the table - taking account of the various features which are enabled
3592	 *  @param {object} oSettings dataTables settings object
3593	 *  @param {boolean} [holdPosition] Keep the current paging position. By default
3594	 *    the paging is reset to the first page
3595	 *  @memberof DataTable#oApi
3596	 */
3597	function _fnReDraw( settings, holdPosition )
3598	{
3599		var
3600			features = settings.oFeatures,
3601			sort     = features.bSort,
3602			filter   = features.bFilter;
3603
3604		if ( sort ) {
3605			_fnSort( settings );
3606		}
3607
3608		if ( filter ) {
3609			_fnFilterComplete( settings, settings.oPreviousSearch );
3610		}
3611		else {
3612			// No filtering, so we want to just use the display master
3613			settings.aiDisplay = settings.aiDisplayMaster.slice();
3614		}
3615
3616		if ( holdPosition !== true ) {
3617			settings._iDisplayStart = 0;
3618		}
3619
3620		// Let any modules know about the draw hold position state (used by
3621		// scrolling internally)
3622		settings._drawHold = holdPosition;
3623
3624		_fnDraw( settings );
3625
3626		settings._drawHold = false;
3627	}
3628
3629
3630	/**
3631	 * Add the options to the page HTML for the table
3632	 *  @param {object} oSettings dataTables settings object
3633	 *  @memberof DataTable#oApi
3634	 */
3635	function _fnAddOptionsHtml ( oSettings )
3636	{
3637		var classes = oSettings.oClasses;
3638		var table = $(oSettings.nTable);
3639		var holding = $('<div/>').insertBefore( table ); // Holding element for speed
3640		var features = oSettings.oFeatures;
3641
3642		// All DataTables are wrapped in a div
3643		var insert = $('<div/>', {
3644			id:      oSettings.sTableId+'_wrapper',
3645			'class': classes.sWrapper + (oSettings.nTFoot ? '' : ' '+classes.sNoFooter)
3646		} );
3647
3648		oSettings.nHolding = holding[0];
3649		oSettings.nTableWrapper = insert[0];
3650		oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;
3651
3652		/* Loop over the user set positioning and place the elements as needed */
3653		var aDom = oSettings.sDom.split('');
3654		var featureNode, cOption, nNewNode, cNext, sAttr, j;
3655		for ( var i=0 ; i<aDom.length ; i++ )
3656		{
3657			featureNode = null;
3658			cOption = aDom[i];
3659
3660			if ( cOption == '<' )
3661			{
3662				/* New container div */
3663				nNewNode = $('<div/>')[0];
3664
3665				/* Check to see if we should append an id and/or a class name to the container */
3666				cNext = aDom[i+1];
3667				if ( cNext == "'" || cNext == '"' )
3668				{
3669					sAttr = "";
3670					j = 2;
3671					while ( aDom[i+j] != cNext )
3672					{
3673						sAttr += aDom[i+j];
3674						j++;
3675					}
3676
3677					/* Replace jQuery UI constants @todo depreciated */
3678					if ( sAttr == "H" )
3679					{
3680						sAttr = classes.sJUIHeader;
3681					}
3682					else if ( sAttr == "F" )
3683					{
3684						sAttr = classes.sJUIFooter;
3685					}
3686
3687					/* The attribute can be in the format of "#id.class", "#id" or "class" This logic
3688					 * breaks the string into parts and applies them as needed
3689					 */
3690					if ( sAttr.indexOf('.') != -1 )
3691					{
3692						var aSplit = sAttr.split('.');
3693						nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);
3694						nNewNode.className = aSplit[1];
3695					}
3696					else if ( sAttr.charAt(0) == "#" )
3697					{
3698						nNewNode.id = sAttr.substr(1, sAttr.length-1);
3699					}
3700					else
3701					{
3702						nNewNode.className = sAttr;
3703					}
3704
3705					i += j; /* Move along the position array */
3706				}
3707
3708				insert.append( nNewNode );
3709				insert = $(nNewNode);
3710			}
3711			else if ( cOption == '>' )
3712			{
3713				/* End container div */
3714				insert = insert.parent();
3715			}
3716			// @todo Move options into their own plugins?
3717			else if ( cOption == 'l' && features.bPaginate && features.bLengthChange )
3718			{
3719				/* Length */
3720				featureNode = _fnFeatureHtmlLength( oSettings );
3721			}
3722			else if ( cOption == 'f' && features.bFilter )
3723			{
3724				/* Filter */
3725				featureNode = _fnFeatureHtmlFilter( oSettings );
3726			}
3727			else if ( cOption == 'r' && features.bProcessing )
3728			{
3729				/* pRocessing */
3730				featureNode = _fnFeatureHtmlProcessing( oSettings );
3731			}
3732			else if ( cOption == 't' )
3733			{
3734				/* Table */
3735				featureNode = _fnFeatureHtmlTable( oSettings );
3736			}
3737			else if ( cOption ==  'i' && features.bInfo )
3738			{
3739				/* Info */
3740				featureNode = _fnFeatureHtmlInfo( oSettings );
3741			}
3742			else if ( cOption == 'p' && features.bPaginate )
3743			{
3744				/* Pagination */
3745				featureNode = _fnFeatureHtmlPaginate( oSettings );
3746			}
3747			else if ( DataTable.ext.feature.length !== 0 )
3748			{
3749				/* Plug-in features */
3750				var aoFeatures = DataTable.ext.feature;
3751				for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )
3752				{
3753					if ( cOption == aoFeatures[k].cFeature )
3754					{
3755						featureNode = aoFeatures[k].fnInit( oSettings );
3756						break;
3757					}
3758				}
3759			}
3760
3761			/* Add to the 2D features array */
3762			if ( featureNode )
3763			{
3764				var aanFeatures = oSettings.aanFeatures;
3765
3766				if ( ! aanFeatures[cOption] )
3767				{
3768					aanFeatures[cOption] = [];
3769				}
3770
3771				aanFeatures[cOption].push( featureNode );
3772				insert.append( featureNode );
3773			}
3774		}
3775
3776		/* Built our DOM structure - replace the holding div with what we want */
3777		holding.replaceWith( insert );
3778		oSettings.nHolding = null;
3779	}
3780
3781
3782	/**
3783	 * Use the DOM source to create up an array of header cells. The idea here is to
3784	 * create a layout grid (array) of rows x columns, which contains a reference
3785	 * to the cell that that point in the grid (regardless of col/rowspan), such that
3786	 * any column / row could be removed and the new grid constructed
3787	 *  @param array {object} aLayout Array to store the calculated layout in
3788	 *  @param {node} nThead The header/footer element for the table
3789	 *  @memberof DataTable#oApi
3790	 */
3791	function _fnDetectHeader ( aLayout, nThead )
3792	{
3793		var nTrs = $(nThead).children('tr');
3794		var nTr, nCell;
3795		var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan;
3796		var bUnique;
3797		var fnShiftCol = function ( a, i, j ) {
3798			var k = a[i];
3799	                while ( k[j] ) {
3800				j++;
3801			}
3802			return j;
3803		};
3804
3805		aLayout.splice( 0, aLayout.length );
3806
3807		/* We know how many rows there are in the layout - so prep it */
3808		for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
3809		{
3810			aLayout.push( [] );
3811		}
3812
3813		/* Calculate a layout array */
3814		for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
3815		{
3816			nTr = nTrs[i];
3817			iColumn = 0;
3818
3819			/* For every cell in the row... */
3820			nCell = nTr.firstChild;
3821			while ( nCell ) {
3822				if ( nCell.nodeName.toUpperCase() == "TD" ||
3823				     nCell.nodeName.toUpperCase() == "TH" )
3824				{
3825					/* Get the col and rowspan attributes from the DOM and sanitise them */
3826					iColspan = nCell.getAttribute('colspan') * 1;
3827					iRowspan = nCell.getAttribute('rowspan') * 1;
3828					iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan;
3829					iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan;
3830
3831					/* There might be colspan cells already in this row, so shift our target
3832					 * accordingly
3833					 */
3834					iColShifted = fnShiftCol( aLayout, i, iColumn );
3835
3836					/* Cache calculation for unique columns */
3837					bUnique = iColspan === 1 ? true : false;
3838
3839					/* If there is col / rowspan, copy the information into the layout grid */
3840					for ( l=0 ; l<iColspan ; l++ )
3841					{
3842						for ( k=0 ; k<iRowspan ; k++ )
3843						{
3844							aLayout[i+k][iColShifted+l] = {
3845								"cell": nCell,
3846								"unique": bUnique
3847							};
3848							aLayout[i+k].nTr = nTr;
3849						}
3850					}
3851				}
3852				nCell = nCell.nextSibling;
3853			}
3854		}
3855	}
3856
3857
3858	/**
3859	 * Get an array of unique th elements, one for each column
3860	 *  @param {object} oSettings dataTables settings object
3861	 *  @param {node} nHeader automatically detect the layout from this node - optional
3862	 *  @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional
3863	 *  @returns array {node} aReturn list of unique th's
3864	 *  @memberof DataTable#oApi
3865	 */
3866	function _fnGetUniqueThs ( oSettings, nHeader, aLayout )
3867	{
3868		var aReturn = [];
3869		if ( !aLayout )
3870		{
3871			aLayout = oSettings.aoHeader;
3872			if ( nHeader )
3873			{
3874				aLayout = [];
3875				_fnDetectHeader( aLayout, nHeader );
3876			}
3877		}
3878
3879		for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ )
3880		{
3881			for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ )
3882			{
3883				if ( aLayout[i][j].unique &&
3884					 (!aReturn[j] || !oSettings.bSortCellsTop) )
3885				{
3886					aReturn[j] = aLayout[i][j].cell;
3887				}
3888			}
3889		}
3890
3891		return aReturn;
3892	}
3893
3894	/**
3895	 * Set the start position for draw
3896	 *  @param {object} oSettings dataTables settings object
3897	 */
3898	function _fnStart( oSettings )
3899	{
3900		var bServerSide = _fnDataSource( oSettings ) == 'ssp';
3901		var iInitDisplayStart = oSettings.iInitDisplayStart;
3902
3903		// Check and see if we have an initial draw position from state saving
3904		if ( iInitDisplayStart !== undefined && iInitDisplayStart !== -1 )
3905		{
3906			oSettings._iDisplayStart = bServerSide ?
3907				iInitDisplayStart :
3908				iInitDisplayStart >= oSettings.fnRecordsDisplay() ?
3909					0 :
3910					iInitDisplayStart;
3911
3912			oSettings.iInitDisplayStart = -1;
3913		}
3914	}
3915
3916	/**
3917	 * Create an Ajax call based on the table's settings, taking into account that
3918	 * parameters can have multiple forms, and backwards compatibility.
3919	 *
3920	 * @param {object} oSettings dataTables settings object
3921	 * @param {array} data Data to send to the server, required by
3922	 *     DataTables - may be augmented by developer callbacks
3923	 * @param {function} fn Callback function to run when data is obtained
3924	 */
3925	function _fnBuildAjax( oSettings, data, fn )
3926	{
3927		// Compatibility with 1.9-, allow fnServerData and event to manipulate
3928		_fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [data] );
3929
3930		// Convert to object based for 1.10+ if using the old array scheme which can
3931		// come from server-side processing or serverParams
3932		if ( data && Array.isArray(data) ) {
3933			var tmp = {};
3934			var rbracket = /(.*?)\[\]$/;
3935
3936			$.each( data, function (key, val) {
3937				var match = val.name.match(rbracket);
3938
3939				if ( match ) {
3940					// Support for arrays
3941					var name = match[0];
3942
3943					if ( ! tmp[ name ] ) {
3944						tmp[ name ] = [];
3945					}
3946					tmp[ name ].push( val.value );
3947				}
3948				else {
3949					tmp[val.name] = val.value;
3950				}
3951			} );
3952			data = tmp;
3953		}
3954
3955		var ajaxData;
3956		var ajax = oSettings.ajax;
3957		var instance = oSettings.oInstance;
3958		var callback = function ( json ) {
3959			var status = oSettings.jqXHR
3960				? oSettings.jqXHR.status
3961				: null;
3962
3963			if ( json === null || (typeof status === 'number' && status == 204 ) ) {
3964				json = {};
3965				_fnAjaxDataSrc( oSettings, json, [] );
3966			}
3967
3968			var error = json.error || json.sError;
3969			if ( error ) {
3970				_fnLog( oSettings, 0, error );
3971			}
3972
3973			oSettings.json = json;
3974
3975			_fnCallbackFire( oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR] );
3976			fn( json );
3977		};
3978
3979		if ( $.isPlainObject( ajax ) && ajax.data )
3980		{
3981			ajaxData = ajax.data;
3982
3983			var newData = typeof ajaxData === 'function' ?
3984				ajaxData( data, oSettings ) :  // fn can manipulate data or return
3985				ajaxData;                      // an object object or array to merge
3986
3987			// If the function returned something, use that alone
3988			data = typeof ajaxData === 'function' && newData ?
3989				newData :
3990				$.extend( true, data, newData );
3991
3992			// Remove the data property as we've resolved it already and don't want
3993			// jQuery to do it again (it is restored at the end of the function)
3994			delete ajax.data;
3995		}
3996
3997		var baseAjax = {
3998			"data": data,
3999			"success": callback,
4000			"dataType": "json",
4001			"cache": false,
4002			"type": oSettings.sServerMethod,
4003			"error": function (xhr, error, thrown) {
4004				var ret = _fnCallbackFire( oSettings, null, 'xhr', [oSettings, null, oSettings.jqXHR] );
4005
4006				if ( $.inArray( true, ret ) === -1 ) {
4007					if ( error == "parsererror" ) {
4008						_fnLog( oSettings, 0, 'Invalid JSON response', 1 );
4009					}
4010					else if ( xhr.readyState === 4 ) {
4011						_fnLog( oSettings, 0, 'Ajax error', 7 );
4012					}
4013				}
4014
4015				_fnProcessingDisplay( oSettings, false );
4016			}
4017		};
4018
4019		// Store the data submitted for the API
4020		oSettings.oAjaxData = data;
4021
4022		// Allow plug-ins and external processes to modify the data
4023		_fnCallbackFire( oSettings, null, 'preXhr', [oSettings, data] );
4024
4025		if ( oSettings.fnServerData )
4026		{
4027			// DataTables 1.9- compatibility
4028			oSettings.fnServerData.call( instance,
4029				oSettings.sAjaxSource,
4030				$.map( data, function (val, key) { // Need to convert back to 1.9 trad format
4031					return { name: key, value: val };
4032				} ),
4033				callback,
4034				oSettings
4035			);
4036		}
4037		else if ( oSettings.sAjaxSource || typeof ajax === 'string' )
4038		{
4039			// DataTables 1.9- compatibility
4040			oSettings.jqXHR = $.ajax( $.extend( baseAjax, {
4041				url: ajax || oSettings.sAjaxSource
4042			} ) );
4043		}
4044		else if ( typeof ajax === 'function' )
4045		{
4046			// Is a function - let the caller define what needs to be done
4047			oSettings.jqXHR = ajax.call( instance, data, callback, oSettings );
4048		}
4049		else
4050		{
4051			// Object to extend the base settings
4052			oSettings.jqXHR = $.ajax( $.extend( baseAjax, ajax ) );
4053
4054			// Restore for next time around
4055			ajax.data = ajaxData;
4056		}
4057	}
4058
4059
4060	/**
4061	 * Update the table using an Ajax call
4062	 *  @param {object} settings dataTables settings object
4063	 *  @returns {boolean} Block the table drawing or not
4064	 *  @memberof DataTable#oApi
4065	 */
4066	function _fnAjaxUpdate( settings )
4067	{
4068		settings.iDraw++;
4069		_fnProcessingDisplay( settings, true );
4070
4071		// Keep track of drawHold state to handle scrolling after the Ajax call
4072		var drawHold = settings._drawHold;
4073
4074		_fnBuildAjax(
4075			settings,
4076			_fnAjaxParameters( settings ),
4077			function(json) {
4078				settings._drawHold = drawHold;
4079				_fnAjaxUpdateDraw( settings, json );
4080				settings._drawHold = false;
4081			}
4082		);
4083	}
4084
4085
4086	/**
4087	 * Build up the parameters in an object needed for a server-side processing
4088	 * request. Note that this is basically done twice, is different ways - a modern
4089	 * method which is used by default in DataTables 1.10 which uses objects and
4090	 * arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if
4091	 * the sAjaxSource option is used in the initialisation, or the legacyAjax
4092	 * option is set.
4093	 *  @param {object} oSettings dataTables settings object
4094	 *  @returns {bool} block the table drawing or not
4095	 *  @memberof DataTable#oApi
4096	 */
4097	function _fnAjaxParameters( settings )
4098	{
4099		var
4100			columns = settings.aoColumns,
4101			columnCount = columns.length,
4102			features = settings.oFeatures,
4103			preSearch = settings.oPreviousSearch,
4104			preColSearch = settings.aoPreSearchCols,
4105			i, data = [], dataProp, column, columnSearch,
4106			sort = _fnSortFlatten( settings ),
4107			displayStart = settings._iDisplayStart,
4108			displayLength = features.bPaginate !== false ?
4109				settings._iDisplayLength :
4110				-1;
4111
4112		var param = function ( name, value ) {
4113			data.push( { 'name': name, 'value': value } );
4114		};
4115
4116		// DataTables 1.9- compatible method
4117		param( 'sEcho',          settings.iDraw );
4118		param( 'iColumns',       columnCount );
4119		param( 'sColumns',       _pluck( columns, 'sName' ).join(',') );
4120		param( 'iDisplayStart',  displayStart );
4121		param( 'iDisplayLength', displayLength );
4122
4123		// DataTables 1.10+ method
4124		var d = {
4125			draw:    settings.iDraw,
4126			columns: [],
4127			order:   [],
4128			start:   displayStart,
4129			length:  displayLength,
4130			search:  {
4131				value: preSearch.sSearch,
4132				regex: preSearch.bRegex
4133			}
4134		};
4135
4136		for ( i=0 ; i<columnCount ; i++ ) {
4137			column = columns[i];
4138			columnSearch = preColSearch[i];
4139			dataProp = typeof column.mData=="function" ? 'function' : column.mData ;
4140
4141			d.columns.push( {
4142				data:       dataProp,
4143				name:       column.sName,
4144				searchable: column.bSearchable,
4145				orderable:  column.bSortable,
4146				search:     {
4147					value: columnSearch.sSearch,
4148					regex: columnSearch.bRegex
4149				}
4150			} );
4151
4152			param( "mDataProp_"+i, dataProp );
4153
4154			if ( features.bFilter ) {
4155				param( 'sSearch_'+i,     columnSearch.sSearch );
4156				param( 'bRegex_'+i,      columnSearch.bRegex );
4157				param( 'bSearchable_'+i, column.bSearchable );
4158			}
4159
4160			if ( features.bSort ) {
4161				param( 'bSortable_'+i, column.bSortable );
4162			}
4163		}
4164
4165		if ( features.bFilter ) {
4166			param( 'sSearch', preSearch.sSearch );
4167			param( 'bRegex', preSearch.bRegex );
4168		}
4169
4170		if ( features.bSort ) {
4171			$.each( sort, function ( i, val ) {
4172				d.order.push( { column: val.col, dir: val.dir } );
4173
4174				param( 'iSortCol_'+i, val.col );
4175				param( 'sSortDir_'+i, val.dir );
4176			} );
4177
4178			param( 'iSortingCols', sort.length );
4179		}
4180
4181		// If the legacy.ajax parameter is null, then we automatically decide which
4182		// form to use, based on sAjaxSource
4183		var legacy = DataTable.ext.legacy.ajax;
4184		if ( legacy === null ) {
4185			return settings.sAjaxSource ? data : d;
4186		}
4187
4188		// Otherwise, if legacy has been specified then we use that to decide on the
4189		// form
4190		return legacy ? data : d;
4191	}
4192
4193
4194	/**
4195	 * Data the data from the server (nuking the old) and redraw the table
4196	 *  @param {object} oSettings dataTables settings object
4197	 *  @param {object} json json data return from the server.
4198	 *  @param {string} json.sEcho Tracking flag for DataTables to match requests
4199	 *  @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering
4200	 *  @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering
4201	 *  @param {array} json.aaData The data to display on this page
4202	 *  @param {string} [json.sColumns] Column ordering (sName, comma separated)
4203	 *  @memberof DataTable#oApi
4204	 */
4205	function _fnAjaxUpdateDraw ( settings, json )
4206	{
4207		// v1.10 uses camelCase variables, while 1.9 uses Hungarian notation.
4208		// Support both
4209		var compat = function ( old, modern ) {
4210			return json[old] !== undefined ? json[old] : json[modern];
4211		};
4212
4213		var data = _fnAjaxDataSrc( settings, json );
4214		var draw            = compat( 'sEcho',                'draw' );
4215		var recordsTotal    = compat( 'iTotalRecords',        'recordsTotal' );
4216		var recordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' );
4217
4218		if ( draw !== undefined ) {
4219			// Protect against out of sequence returns
4220			if ( draw*1 < settings.iDraw ) {
4221				return;
4222			}
4223			settings.iDraw = draw * 1;
4224		}
4225
4226		// No data in returned object, so rather than an array, we show an empty table
4227		if ( ! data ) {
4228			data = [];
4229		}
4230
4231		_fnClearTable( settings );
4232		settings._iRecordsTotal   = parseInt(recordsTotal, 10);
4233		settings._iRecordsDisplay = parseInt(recordsFiltered, 10);
4234
4235		for ( var i=0, ien=data.length ; i<ien ; i++ ) {
4236			_fnAddData( settings, data[i] );
4237		}
4238		settings.aiDisplay = settings.aiDisplayMaster.slice();
4239
4240		_fnDraw( settings, true );
4241
4242		if ( ! settings._bInitComplete ) {
4243			_fnInitComplete( settings, json );
4244		}
4245
4246		_fnProcessingDisplay( settings, false );
4247	}
4248
4249
4250	/**
4251	 * Get the data from the JSON data source to use for drawing a table. Using
4252	 * `_fnGetObjectDataFn` allows the data to be sourced from a property of the
4253	 * source object, or from a processing function.
4254	 *  @param {object} oSettings dataTables settings object
4255	 *  @param  {object} json Data source object / array from the server
4256	 *  @return {array} Array of data to use
4257	 */
4258	 function _fnAjaxDataSrc ( oSettings, json, write )
4259	 {
4260		var dataSrc = $.isPlainObject( oSettings.ajax ) && oSettings.ajax.dataSrc !== undefined ?
4261			oSettings.ajax.dataSrc :
4262			oSettings.sAjaxDataProp; // Compatibility with 1.9-.
4263
4264		if ( ! write ) {
4265			if ( dataSrc === 'data' ) {
4266				// If the default, then we still want to support the old style, and safely ignore
4267				// it if possible
4268				return json.aaData || json[dataSrc];
4269			}
4270
4271			return dataSrc !== "" ?
4272				_fnGetObjectDataFn( dataSrc )( json ) :
4273				json;
4274		}
4275
4276		// set
4277		_fnSetObjectDataFn( dataSrc )( json, write );
4278	}
4279
4280	/**
4281	 * Generate the node required for filtering text
4282	 *  @returns {node} Filter control element
4283	 *  @param {object} oSettings dataTables settings object
4284	 *  @memberof DataTable#oApi
4285	 */
4286	function _fnFeatureHtmlFilter ( settings )
4287	{
4288		var classes = settings.oClasses;
4289		var tableId = settings.sTableId;
4290		var language = settings.oLanguage;
4291		var previousSearch = settings.oPreviousSearch;
4292		var features = settings.aanFeatures;
4293		var input = '<input type="search" class="'+classes.sFilterInput+'"/>';
4294
4295		var str = language.sSearch;
4296		str = str.match(/_INPUT_/) ?
4297			str.replace('_INPUT_', input) :
4298			str+input;
4299
4300		var filter = $('<div/>', {
4301				'id': ! features.f ? tableId+'_filter' : null,
4302				'class': classes.sFilter
4303			} )
4304			.append( $('<label/>' ).append( str ) );
4305
4306		var searchFn = function(event) {
4307			/* Update all other filter input elements for the new display */
4308			var n = features.f;
4309			var val = !this.value ? "" : this.value; // mental IE8 fix :-(
4310			if(previousSearch.return && event.key !== "Enter") {
4311				return;
4312			}
4313			/* Now do the filter */
4314			if ( val != previousSearch.sSearch ) {
4315				_fnFilterComplete( settings, {
4316					"sSearch": val,
4317					"bRegex": previousSearch.bRegex,
4318					"bSmart": previousSearch.bSmart ,
4319					"bCaseInsensitive": previousSearch.bCaseInsensitive,
4320					"return": previousSearch.return
4321				} );
4322
4323				// Need to redraw, without resorting
4324				settings._iDisplayStart = 0;
4325				_fnDraw( settings );
4326			}
4327		};
4328
4329		var searchDelay = settings.searchDelay !== null ?
4330			settings.searchDelay :
4331			_fnDataSource( settings ) === 'ssp' ?
4332				400 :
4333				0;
4334
4335		var jqFilter = $('input', filter)
4336			.val( previousSearch.sSearch )
4337			.attr( 'placeholder', language.sSearchPlaceholder )
4338			.on(
4339				'keyup.DT search.DT input.DT paste.DT cut.DT',
4340				searchDelay ?
4341					_fnThrottle( searchFn, searchDelay ) :
4342					searchFn
4343			)
4344			.on( 'mouseup.DT', function(e) {
4345				// Edge fix! Edge 17 does not trigger anything other than mouse events when clicking
4346				// on the clear icon (Edge bug 17584515). This is safe in other browsers as `searchFn`
4347				// checks the value to see if it has changed. In other browsers it won't have.
4348				setTimeout( function () {
4349					searchFn.call(jqFilter[0], e);
4350				}, 10);
4351			} )
4352			.on( 'keypress.DT', function(e) {
4353				/* Prevent form submission */
4354				if ( e.keyCode == 13 ) {
4355					return false;
4356				}
4357			} )
4358			.attr('aria-controls', tableId);
4359
4360		// Update the input elements whenever the table is filtered
4361		$(settings.nTable).on( 'search.dt.DT', function ( ev, s ) {
4362			if ( settings === s ) {
4363				// IE9 throws an 'unknown error' if document.activeElement is used
4364				// inside an iframe or frame...
4365				try {
4366					if ( jqFilter[0] !== document.activeElement ) {
4367						jqFilter.val( previousSearch.sSearch );
4368					}
4369				}
4370				catch ( e ) {}
4371			}
4372		} );
4373
4374		return filter[0];
4375	}
4376
4377
4378	/**
4379	 * Filter the table using both the global filter and column based filtering
4380	 *  @param {object} oSettings dataTables settings object
4381	 *  @param {object} oSearch search information
4382	 *  @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)
4383	 *  @memberof DataTable#oApi
4384	 */
4385	function _fnFilterComplete ( oSettings, oInput, iForce )
4386	{
4387		var oPrevSearch = oSettings.oPreviousSearch;
4388		var aoPrevSearch = oSettings.aoPreSearchCols;
4389		var fnSaveFilter = function ( oFilter ) {
4390			/* Save the filtering values */
4391			oPrevSearch.sSearch = oFilter.sSearch;
4392			oPrevSearch.bRegex = oFilter.bRegex;
4393			oPrevSearch.bSmart = oFilter.bSmart;
4394			oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive;
4395			oPrevSearch.return = oFilter.return;
4396		};
4397		var fnRegex = function ( o ) {
4398			// Backwards compatibility with the bEscapeRegex option
4399			return o.bEscapeRegex !== undefined ? !o.bEscapeRegex : o.bRegex;
4400		};
4401
4402		// Resolve any column types that are unknown due to addition or invalidation
4403		// @todo As per sort - can this be moved into an event handler?
4404		_fnColumnTypes( oSettings );
4405
4406		/* In server-side processing all filtering is done by the server, so no point hanging around here */
4407		if ( _fnDataSource( oSettings ) != 'ssp' )
4408		{
4409			/* Global filter */
4410			_fnFilter( oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive );
4411			fnSaveFilter( oInput );
4412
4413			/* Now do the individual column filter */
4414			for ( var i=0 ; i<aoPrevSearch.length ; i++ )
4415			{
4416				_fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, fnRegex(aoPrevSearch[i]),
4417					aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive );
4418			}
4419
4420			/* Custom filtering */
4421			_fnFilterCustom( oSettings );
4422		}
4423		else
4424		{
4425			fnSaveFilter( oInput );
4426		}
4427
4428		/* Tell the draw function we have been filtering */
4429		oSettings.bFiltered = true;
4430		_fnCallbackFire( oSettings, null, 'search', [oSettings] );
4431	}
4432
4433
4434	/**
4435	 * Apply custom filtering functions
4436	 *  @param {object} oSettings dataTables settings object
4437	 *  @memberof DataTable#oApi
4438	 */
4439	function _fnFilterCustom( settings )
4440	{
4441		var filters = DataTable.ext.search;
4442		var displayRows = settings.aiDisplay;
4443		var row, rowIdx;
4444
4445		for ( var i=0, ien=filters.length ; i<ien ; i++ ) {
4446			var rows = [];
4447
4448			// Loop over each row and see if it should be included
4449			for ( var j=0, jen=displayRows.length ; j<jen ; j++ ) {
4450				rowIdx = displayRows[ j ];
4451				row = settings.aoData[ rowIdx ];
4452
4453				if ( filters[i]( settings, row._aFilterData, rowIdx, row._aData, j ) ) {
4454					rows.push( rowIdx );
4455				}
4456			}
4457
4458			// So the array reference doesn't break set the results into the
4459			// existing array
4460			displayRows.length = 0;
4461			$.merge( displayRows, rows );
4462		}
4463	}
4464
4465
4466	/**
4467	 * Filter the table on a per-column basis
4468	 *  @param {object} oSettings dataTables settings object
4469	 *  @param {string} sInput string to filter on
4470	 *  @param {int} iColumn column to filter
4471	 *  @param {bool} bRegex treat search string as a regular expression or not
4472	 *  @param {bool} bSmart use smart filtering or not
4473	 *  @param {bool} bCaseInsensitive Do case insensitive matching or not
4474	 *  @memberof DataTable#oApi
4475	 */
4476	function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, caseInsensitive )
4477	{
4478		if ( searchStr === '' ) {
4479			return;
4480		}
4481
4482		var data;
4483		var out = [];
4484		var display = settings.aiDisplay;
4485		var rpSearch = _fnFilterCreateSearch( searchStr, regex, smart, caseInsensitive );
4486
4487		for ( var i=0 ; i<display.length ; i++ ) {
4488			data = settings.aoData[ display[i] ]._aFilterData[ colIdx ];
4489
4490			if ( rpSearch.test( data ) ) {
4491				out.push( display[i] );
4492			}
4493		}
4494
4495		settings.aiDisplay = out;
4496	}
4497
4498
4499	/**
4500	 * Filter the data table based on user input and draw the table
4501	 *  @param {object} settings dataTables settings object
4502	 *  @param {string} input string to filter on
4503	 *  @param {int} force optional - force a research of the master array (1) or not (undefined or 0)
4504	 *  @param {bool} regex treat as a regular expression or not
4505	 *  @param {bool} smart perform smart filtering or not
4506	 *  @param {bool} caseInsensitive Do case insensitive matching or not
4507	 *  @memberof DataTable#oApi
4508	 */
4509	function _fnFilter( settings, input, force, regex, smart, caseInsensitive )
4510	{
4511		var rpSearch = _fnFilterCreateSearch( input, regex, smart, caseInsensitive );
4512		var prevSearch = settings.oPreviousSearch.sSearch;
4513		var displayMaster = settings.aiDisplayMaster;
4514		var display, invalidated, i;
4515		var filtered = [];
4516
4517		// Need to take account of custom filtering functions - always filter
4518		if ( DataTable.ext.search.length !== 0 ) {
4519			force = true;
4520		}
4521
4522		// Check if any of the rows were invalidated
4523		invalidated = _fnFilterData( settings );
4524
4525		// If the input is blank - we just want the full data set
4526		if ( input.length <= 0 ) {
4527			settings.aiDisplay = displayMaster.slice();
4528		}
4529		else {
4530			// New search - start from the master array
4531			if ( invalidated ||
4532				 force ||
4533				 regex ||
4534				 prevSearch.length > input.length ||
4535				 input.indexOf(prevSearch) !== 0 ||
4536				 settings.bSorted // On resort, the display master needs to be
4537				                  // re-filtered since indexes will have changed
4538			) {
4539				settings.aiDisplay = displayMaster.slice();
4540			}
4541
4542			// Search the display array
4543			display = settings.aiDisplay;
4544
4545			for ( i=0 ; i<display.length ; i++ ) {
4546				if ( rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) {
4547					filtered.push( display[i] );
4548				}
4549			}
4550
4551			settings.aiDisplay = filtered;
4552		}
4553	}
4554
4555
4556	/**
4557	 * Build a regular expression object suitable for searching a table
4558	 *  @param {string} sSearch string to search for
4559	 *  @param {bool} bRegex treat as a regular expression or not
4560	 *  @param {bool} bSmart perform smart filtering or not
4561	 *  @param {bool} bCaseInsensitive Do case insensitive matching or not
4562	 *  @returns {RegExp} constructed object
4563	 *  @memberof DataTable#oApi
4564	 */
4565	function _fnFilterCreateSearch( search, regex, smart, caseInsensitive )
4566	{
4567		search = regex ?
4568			search :
4569			_fnEscapeRegex( search );
4570
4571		if ( smart ) {
4572			/* For smart filtering we want to allow the search to work regardless of
4573			 * word order. We also want double quoted text to be preserved, so word
4574			 * order is important - a la google. So this is what we want to
4575			 * generate:
4576			 *
4577			 * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$
4578			 */
4579			var a = $.map( search.match( /["\u201C][^"\u201D]+["\u201D]|[^ ]+/g ) || [''], function ( word ) {
4580				if ( word.charAt(0) === '"' ) {
4581					var m = word.match( /^"(.*)"$/ );
4582					word = m ? m[1] : word;
4583				}
4584				else if ( word.charAt(0) === '\u201C' ) {
4585					var m = word.match( /^\u201C(.*)\u201D$/ );
4586					word = m ? m[1] : word;
4587				}
4588
4589				return word.replace('"', '');
4590			} );
4591
4592			search = '^(?=.*?'+a.join( ')(?=.*?' )+').*$';
4593		}
4594
4595		return new RegExp( search, caseInsensitive ? 'i' : '' );
4596	}
4597
4598
4599	/**
4600	 * Escape a string such that it can be used in a regular expression
4601	 *  @param {string} sVal string to escape
4602	 *  @returns {string} escaped string
4603	 *  @memberof DataTable#oApi
4604	 */
4605	var _fnEscapeRegex = DataTable.util.escapeRegex;
4606
4607	var __filter_div = $('<div>')[0];
4608	var __filter_div_textContent = __filter_div.textContent !== undefined;
4609
4610	// Update the filtering data for each row if needed (by invalidation or first run)
4611	function _fnFilterData ( settings )
4612	{
4613		var columns = settings.aoColumns;
4614		var column;
4615		var i, j, ien, jen, filterData, cellData, row;
4616		var wasInvalidated = false;
4617
4618		for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
4619			row = settings.aoData[i];
4620
4621			if ( ! row._aFilterData ) {
4622				filterData = [];
4623
4624				for ( j=0, jen=columns.length ; j<jen ; j++ ) {
4625					column = columns[j];
4626
4627					if ( column.bSearchable ) {
4628						cellData = _fnGetCellData( settings, i, j, 'filter' );
4629
4630						// Search in DataTables 1.10 is string based. In 1.11 this
4631						// should be altered to also allow strict type checking.
4632						if ( cellData === null ) {
4633							cellData = '';
4634						}
4635
4636						if ( typeof cellData !== 'string' && cellData.toString ) {
4637							cellData = cellData.toString();
4638						}
4639					}
4640					else {
4641						cellData = '';
4642					}
4643
4644					// If it looks like there is an HTML entity in the string,
4645					// attempt to decode it so sorting works as expected. Note that
4646					// we could use a single line of jQuery to do this, but the DOM
4647					// method used here is much faster http://jsperf.com/html-decode
4648					if ( cellData.indexOf && cellData.indexOf('&') !== -1 ) {
4649						__filter_div.innerHTML = cellData;
4650						cellData = __filter_div_textContent ?
4651							__filter_div.textContent :
4652							__filter_div.innerText;
4653					}
4654
4655					if ( cellData.replace ) {
4656						cellData = cellData.replace(/[\r\n\u2028]/g, '');
4657					}
4658
4659					filterData.push( cellData );
4660				}
4661
4662				row._aFilterData = filterData;
4663				row._sFilterRow = filterData.join('  ');
4664				wasInvalidated = true;
4665			}
4666		}
4667
4668		return wasInvalidated;
4669	}
4670
4671
4672	/**
4673	 * Convert from the internal Hungarian notation to camelCase for external
4674	 * interaction
4675	 *  @param {object} obj Object to convert
4676	 *  @returns {object} Inverted object
4677	 *  @memberof DataTable#oApi
4678	 */
4679	function _fnSearchToCamel ( obj )
4680	{
4681		return {
4682			search:          obj.sSearch,
4683			smart:           obj.bSmart,
4684			regex:           obj.bRegex,
4685			caseInsensitive: obj.bCaseInsensitive
4686		};
4687	}
4688
4689
4690
4691	/**
4692	 * Convert from camelCase notation to the internal Hungarian. We could use the
4693	 * Hungarian convert function here, but this is cleaner
4694	 *  @param {object} obj Object to convert
4695	 *  @returns {object} Inverted object
4696	 *  @memberof DataTable#oApi
4697	 */
4698	function _fnSearchToHung ( obj )
4699	{
4700		return {
4701			sSearch:          obj.search,
4702			bSmart:           obj.smart,
4703			bRegex:           obj.regex,
4704			bCaseInsensitive: obj.caseInsensitive
4705		};
4706	}
4707
4708	/**
4709	 * Generate the node required for the info display
4710	 *  @param {object} oSettings dataTables settings object
4711	 *  @returns {node} Information element
4712	 *  @memberof DataTable#oApi
4713	 */
4714	function _fnFeatureHtmlInfo ( settings )
4715	{
4716		var
4717			tid = settings.sTableId,
4718			nodes = settings.aanFeatures.i,
4719			n = $('<div/>', {
4720				'class': settings.oClasses.sInfo,
4721				'id': ! nodes ? tid+'_info' : null
4722			} );
4723
4724		if ( ! nodes ) {
4725			// Update display on each draw
4726			settings.aoDrawCallback.push( {
4727				"fn": _fnUpdateInfo,
4728				"sName": "information"
4729			} );
4730
4731			n
4732				.attr( 'role', 'status' )
4733				.attr( 'aria-live', 'polite' );
4734
4735			// Table is described by our info div
4736			$(settings.nTable).attr( 'aria-describedby', tid+'_info' );
4737		}
4738
4739		return n[0];
4740	}
4741
4742
4743	/**
4744	 * Update the information elements in the display
4745	 *  @param {object} settings dataTables settings object
4746	 *  @memberof DataTable#oApi
4747	 */
4748	function _fnUpdateInfo ( settings )
4749	{
4750		/* Show information about the table */
4751		var nodes = settings.aanFeatures.i;
4752		if ( nodes.length === 0 ) {
4753			return;
4754		}
4755
4756		var
4757			lang  = settings.oLanguage,
4758			start = settings._iDisplayStart+1,
4759			end   = settings.fnDisplayEnd(),
4760			max   = settings.fnRecordsTotal(),
4761			total = settings.fnRecordsDisplay(),
4762			out   = total ?
4763				lang.sInfo :
4764				lang.sInfoEmpty;
4765
4766		if ( total !== max ) {
4767			/* Record set after filtering */
4768			out += ' ' + lang.sInfoFiltered;
4769		}
4770
4771		// Convert the macros
4772		out += lang.sInfoPostFix;
4773		out = _fnInfoMacros( settings, out );
4774
4775		var callback = lang.fnInfoCallback;
4776		if ( callback !== null ) {
4777			out = callback.call( settings.oInstance,
4778				settings, start, end, max, total, out
4779			);
4780		}
4781
4782		$(nodes).html( out );
4783	}
4784
4785
4786	function _fnInfoMacros ( settings, str )
4787	{
4788		// When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
4789		// internally
4790		var
4791			formatter  = settings.fnFormatNumber,
4792			start      = settings._iDisplayStart+1,
4793			len        = settings._iDisplayLength,
4794			vis        = settings.fnRecordsDisplay(),
4795			all        = len === -1;
4796
4797		return str.
4798			replace(/_START_/g, formatter.call( settings, start ) ).
4799			replace(/_END_/g,   formatter.call( settings, settings.fnDisplayEnd() ) ).
4800			replace(/_MAX_/g,   formatter.call( settings, settings.fnRecordsTotal() ) ).
4801			replace(/_TOTAL_/g, formatter.call( settings, vis ) ).
4802			replace(/_PAGE_/g,  formatter.call( settings, all ? 1 : Math.ceil( start / len ) ) ).
4803			replace(/_PAGES_/g, formatter.call( settings, all ? 1 : Math.ceil( vis / len ) ) );
4804	}
4805
4806
4807
4808	/**
4809	 * Draw the table for the first time, adding all required features
4810	 *  @param {object} settings dataTables settings object
4811	 *  @memberof DataTable#oApi
4812	 */
4813	function _fnInitialise ( settings )
4814	{
4815		var i, iLen, iAjaxStart=settings.iInitDisplayStart;
4816		var columns = settings.aoColumns, column;
4817		var features = settings.oFeatures;
4818		var deferLoading = settings.bDeferLoading; // value modified by the draw
4819
4820		/* Ensure that the table data is fully initialised */
4821		if ( ! settings.bInitialised ) {
4822			setTimeout( function(){ _fnInitialise( settings ); }, 200 );
4823			return;
4824		}
4825
4826		/* Show the display HTML options */
4827		_fnAddOptionsHtml( settings );
4828
4829		/* Build and draw the header / footer for the table */
4830		_fnBuildHead( settings );
4831		_fnDrawHead( settings, settings.aoHeader );
4832		_fnDrawHead( settings, settings.aoFooter );
4833
4834		/* Okay to show that something is going on now */
4835		_fnProcessingDisplay( settings, true );
4836
4837		/* Calculate sizes for columns */
4838		if ( features.bAutoWidth ) {
4839			_fnCalculateColumnWidths( settings );
4840		}
4841
4842		for ( i=0, iLen=columns.length ; i<iLen ; i++ ) {
4843			column = columns[i];
4844
4845			if ( column.sWidth ) {
4846				column.nTh.style.width = _fnStringToCss( column.sWidth );
4847			}
4848		}
4849
4850		_fnCallbackFire( settings, null, 'preInit', [settings] );
4851
4852		// If there is default sorting required - let's do it. The sort function
4853		// will do the drawing for us. Otherwise we draw the table regardless of the
4854		// Ajax source - this allows the table to look initialised for Ajax sourcing
4855		// data (show 'loading' message possibly)
4856		_fnReDraw( settings );
4857
4858		// Server-side processing init complete is done by _fnAjaxUpdateDraw
4859		var dataSrc = _fnDataSource( settings );
4860		if ( dataSrc != 'ssp' || deferLoading ) {
4861			// if there is an ajax source load the data
4862			if ( dataSrc == 'ajax' ) {
4863				_fnBuildAjax( settings, [], function(json) {
4864					var aData = _fnAjaxDataSrc( settings, json );
4865
4866					// Got the data - add it to the table
4867					for ( i=0 ; i<aData.length ; i++ ) {
4868						_fnAddData( settings, aData[i] );
4869					}
4870
4871					// Reset the init display for cookie saving. We've already done
4872					// a filter, and therefore cleared it before. So we need to make
4873					// it appear 'fresh'
4874					settings.iInitDisplayStart = iAjaxStart;
4875
4876					_fnReDraw( settings );
4877
4878					_fnProcessingDisplay( settings, false );
4879					_fnInitComplete( settings, json );
4880				}, settings );
4881			}
4882			else {
4883				_fnProcessingDisplay( settings, false );
4884				_fnInitComplete( settings );
4885			}
4886		}
4887	}
4888
4889
4890	/**
4891	 * Draw the table for the first time, adding all required features
4892	 *  @param {object} oSettings dataTables settings object
4893	 *  @param {object} [json] JSON from the server that completed the table, if using Ajax source
4894	 *    with client-side processing (optional)
4895	 *  @memberof DataTable#oApi
4896	 */
4897	function _fnInitComplete ( settings, json )
4898	{
4899		settings._bInitComplete = true;
4900
4901		// When data was added after the initialisation (data or Ajax) we need to
4902		// calculate the column sizing
4903		if ( json || settings.oInit.aaData ) {
4904			_fnAdjustColumnSizing( settings );
4905		}
4906
4907		_fnCallbackFire( settings, null, 'plugin-init', [settings, json] );
4908		_fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] );
4909	}
4910
4911
4912	function _fnLengthChange ( settings, val )
4913	{
4914		var len = parseInt( val, 10 );
4915		settings._iDisplayLength = len;
4916
4917		_fnLengthOverflow( settings );
4918
4919		// Fire length change event
4920		_fnCallbackFire( settings, null, 'length', [settings, len] );
4921	}
4922
4923
4924	/**
4925	 * Generate the node required for user display length changing
4926	 *  @param {object} settings dataTables settings object
4927	 *  @returns {node} Display length feature node
4928	 *  @memberof DataTable#oApi
4929	 */
4930	function _fnFeatureHtmlLength ( settings )
4931	{
4932		var
4933			classes  = settings.oClasses,
4934			tableId  = settings.sTableId,
4935			menu     = settings.aLengthMenu,
4936			d2       = Array.isArray( menu[0] ),
4937			lengths  = d2 ? menu[0] : menu,
4938			language = d2 ? menu[1] : menu;
4939
4940		var select = $('<select/>', {
4941			'name':          tableId+'_length',
4942			'aria-controls': tableId,
4943			'class':         classes.sLengthSelect
4944		} );
4945
4946		for ( var i=0, ien=lengths.length ; i<ien ; i++ ) {
4947			select[0][ i ] = new Option(
4948				typeof language[i] === 'number' ?
4949					settings.fnFormatNumber( language[i] ) :
4950					language[i],
4951				lengths[i]
4952			);
4953		}
4954
4955		var div = $('<div><label/></div>').addClass( classes.sLength );
4956		if ( ! settings.aanFeatures.l ) {
4957			div[0].id = tableId+'_length';
4958		}
4959
4960		div.children().append(
4961			settings.oLanguage.sLengthMenu.replace( '_MENU_', select[0].outerHTML )
4962		);
4963
4964		// Can't use `select` variable as user might provide their own and the
4965		// reference is broken by the use of outerHTML
4966		$('select', div)
4967			.val( settings._iDisplayLength )
4968			.on( 'change.DT', function(e) {
4969				_fnLengthChange( settings, $(this).val() );
4970				_fnDraw( settings );
4971			} );
4972
4973		// Update node value whenever anything changes the table's length
4974		$(settings.nTable).on( 'length.dt.DT', function (e, s, len) {
4975			if ( settings === s ) {
4976				$('select', div).val( len );
4977			}
4978		} );
4979
4980		return div[0];
4981	}
4982
4983
4984
4985	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
4986	 * Note that most of the paging logic is done in
4987	 * DataTable.ext.pager
4988	 */
4989
4990	/**
4991	 * Generate the node required for default pagination
4992	 *  @param {object} oSettings dataTables settings object
4993	 *  @returns {node} Pagination feature node
4994	 *  @memberof DataTable#oApi
4995	 */
4996	function _fnFeatureHtmlPaginate ( settings )
4997	{
4998		var
4999			type   = settings.sPaginationType,
5000			plugin = DataTable.ext.pager[ type ],
5001			modern = typeof plugin === 'function',
5002			redraw = function( settings ) {
5003				_fnDraw( settings );
5004			},
5005			node = $('<div/>').addClass( settings.oClasses.sPaging + type )[0],
5006			features = settings.aanFeatures;
5007
5008		if ( ! modern ) {
5009			plugin.fnInit( settings, node, redraw );
5010		}
5011
5012		/* Add a draw callback for the pagination on first instance, to update the paging display */
5013		if ( ! features.p )
5014		{
5015			node.id = settings.sTableId+'_paginate';
5016
5017			settings.aoDrawCallback.push( {
5018				"fn": function( settings ) {
5019					if ( modern ) {
5020						var
5021							start      = settings._iDisplayStart,
5022							len        = settings._iDisplayLength,
5023							visRecords = settings.fnRecordsDisplay(),
5024							all        = len === -1,
5025							page = all ? 0 : Math.ceil( start / len ),
5026							pages = all ? 1 : Math.ceil( visRecords / len ),
5027							buttons = plugin(page, pages),
5028							i, ien;
5029
5030						for ( i=0, ien=features.p.length ; i<ien ; i++ ) {
5031							_fnRenderer( settings, 'pageButton' )(
5032								settings, features.p[i], i, buttons, page, pages
5033							);
5034						}
5035					}
5036					else {
5037						plugin.fnUpdate( settings, redraw );
5038					}
5039				},
5040				"sName": "pagination"
5041			} );
5042		}
5043
5044		return node;
5045	}
5046
5047
5048	/**
5049	 * Alter the display settings to change the page
5050	 *  @param {object} settings DataTables settings object
5051	 *  @param {string|int} action Paging action to take: "first", "previous",
5052	 *    "next" or "last" or page number to jump to (integer)
5053	 *  @param [bool] redraw Automatically draw the update or not
5054	 *  @returns {bool} true page has changed, false - no change
5055	 *  @memberof DataTable#oApi
5056	 */
5057	function _fnPageChange ( settings, action, redraw )
5058	{
5059		var
5060			start     = settings._iDisplayStart,
5061			len       = settings._iDisplayLength,
5062			records   = settings.fnRecordsDisplay();
5063
5064		if ( records === 0 || len === -1 )
5065		{
5066			start = 0;
5067		}
5068		else if ( typeof action === "number" )
5069		{
5070			start = action * len;
5071
5072			if ( start > records )
5073			{
5074				start = 0;
5075			}
5076		}
5077		else if ( action == "first" )
5078		{
5079			start = 0;
5080		}
5081		else if ( action == "previous" )
5082		{
5083			start = len >= 0 ?
5084				start - len :
5085				0;
5086
5087			if ( start < 0 )
5088			{
5089			  start = 0;
5090			}
5091		}
5092		else if ( action == "next" )
5093		{
5094			if ( start + len < records )
5095			{
5096				start += len;
5097			}
5098		}
5099		else if ( action == "last" )
5100		{
5101			start = Math.floor( (records-1) / len) * len;
5102		}
5103		else
5104		{
5105			_fnLog( settings, 0, "Unknown paging action: "+action, 5 );
5106		}
5107
5108		var changed = settings._iDisplayStart !== start;
5109		settings._iDisplayStart = start;
5110
5111		if ( changed ) {
5112			_fnCallbackFire( settings, null, 'page', [settings] );
5113
5114			if ( redraw ) {
5115				_fnDraw( settings );
5116			}
5117		}
5118		else {
5119			// No change event - paging was called, but no change
5120			_fnCallbackFire( settings, null, 'page-nc', [settings] );
5121		}
5122
5123		return changed;
5124	}
5125
5126
5127
5128	/**
5129	 * Generate the node required for the processing node
5130	 *  @param {object} settings dataTables settings object
5131	 *  @returns {node} Processing element
5132	 *  @memberof DataTable#oApi
5133	 */
5134	function _fnFeatureHtmlProcessing ( settings )
5135	{
5136		return $('<div/>', {
5137				'id': ! settings.aanFeatures.r ? settings.sTableId+'_processing' : null,
5138				'class': settings.oClasses.sProcessing,
5139				'role': 'status'
5140			} )
5141			.html( settings.oLanguage.sProcessing )
5142			.append('<div><div></div><div></div><div></div><div></div></div>')
5143			.insertBefore( settings.nTable )[0];
5144	}
5145
5146
5147	/**
5148	 * Display or hide the processing indicator
5149	 *  @param {object} settings dataTables settings object
5150	 *  @param {bool} show Show the processing indicator (true) or not (false)
5151	 *  @memberof DataTable#oApi
5152	 */
5153	function _fnProcessingDisplay ( settings, show )
5154	{
5155		if ( settings.oFeatures.bProcessing ) {
5156			$(settings.aanFeatures.r).css( 'display', show ? 'block' : 'none' );
5157		}
5158
5159		_fnCallbackFire( settings, null, 'processing', [settings, show] );
5160	}
5161
5162	/**
5163	 * Add any control elements for the table - specifically scrolling
5164	 *  @param {object} settings dataTables settings object
5165	 *  @returns {node} Node to add to the DOM
5166	 *  @memberof DataTable#oApi
5167	 */
5168	function _fnFeatureHtmlTable ( settings )
5169	{
5170		var table = $(settings.nTable);
5171
5172		// Scrolling from here on in
5173		var scroll = settings.oScroll;
5174
5175		if ( scroll.sX === '' && scroll.sY === '' ) {
5176			return settings.nTable;
5177		}
5178
5179		var scrollX = scroll.sX;
5180		var scrollY = scroll.sY;
5181		var classes = settings.oClasses;
5182		var caption = table.children('caption');
5183		var captionSide = caption.length ? caption[0]._captionSide : null;
5184		var headerClone = $( table[0].cloneNode(false) );
5185		var footerClone = $( table[0].cloneNode(false) );
5186		var footer = table.children('tfoot');
5187		var _div = '<div/>';
5188		var size = function ( s ) {
5189			return !s ? null : _fnStringToCss( s );
5190		};
5191
5192		if ( ! footer.length ) {
5193			footer = null;
5194		}
5195
5196		/*
5197		 * The HTML structure that we want to generate in this function is:
5198		 *  div - scroller
5199		 *    div - scroll head
5200		 *      div - scroll head inner
5201		 *        table - scroll head table
5202		 *          thead - thead
5203		 *    div - scroll body
5204		 *      table - table (master table)
5205		 *        thead - thead clone for sizing
5206		 *        tbody - tbody
5207		 *    div - scroll foot
5208		 *      div - scroll foot inner
5209		 *        table - scroll foot table
5210		 *          tfoot - tfoot
5211		 */
5212		var scroller = $( _div, { 'class': classes.sScrollWrapper } )
5213			.append(
5214				$(_div, { 'class': classes.sScrollHead } )
5215					.css( {
5216						overflow: 'hidden',
5217						position: 'relative',
5218						border: 0,
5219						width: scrollX ? size(scrollX) : '100%'
5220					} )
5221					.append(
5222						$(_div, { 'class': classes.sScrollHeadInner } )
5223							.css( {
5224								'box-sizing': 'content-box',
5225								width: scroll.sXInner || '100%'
5226							} )
5227							.append(
5228								headerClone
5229									.removeAttr('id')
5230									.css( 'margin-left', 0 )
5231									.append( captionSide === 'top' ? caption : null )
5232									.append(
5233										table.children('thead')
5234									)
5235							)
5236					)
5237			)
5238			.append(
5239				$(_div, { 'class': classes.sScrollBody } )
5240					.css( {
5241						position: 'relative',
5242						overflow: 'auto',
5243						width: size( scrollX )
5244					} )
5245					.append( table )
5246			);
5247
5248		if ( footer ) {
5249			scroller.append(
5250				$(_div, { 'class': classes.sScrollFoot } )
5251					.css( {
5252						overflow: 'hidden',
5253						border: 0,
5254						width: scrollX ? size(scrollX) : '100%'
5255					} )
5256					.append(
5257						$(_div, { 'class': classes.sScrollFootInner } )
5258							.append(
5259								footerClone
5260									.removeAttr('id')
5261									.css( 'margin-left', 0 )
5262									.append( captionSide === 'bottom' ? caption : null )
5263									.append(
5264										table.children('tfoot')
5265									)
5266							)
5267					)
5268			);
5269		}
5270
5271		var children = scroller.children();
5272		var scrollHead = children[0];
5273		var scrollBody = children[1];
5274		var scrollFoot = footer ? children[2] : null;
5275
5276		// When the body is scrolled, then we also want to scroll the headers
5277		if ( scrollX ) {
5278			$(scrollBody).on( 'scroll.DT', function (e) {
5279				var scrollLeft = this.scrollLeft;
5280
5281				scrollHead.scrollLeft = scrollLeft;
5282
5283				if ( footer ) {
5284					scrollFoot.scrollLeft = scrollLeft;
5285				}
5286			} );
5287		}
5288
5289		$(scrollBody).css('max-height', scrollY);
5290		if (! scroll.bCollapse) {
5291			$(scrollBody).css('height', scrollY);
5292		}
5293
5294		settings.nScrollHead = scrollHead;
5295		settings.nScrollBody = scrollBody;
5296		settings.nScrollFoot = scrollFoot;
5297
5298		// On redraw - align columns
5299		settings.aoDrawCallback.push( {
5300			"fn": _fnScrollDraw,
5301			"sName": "scrolling"
5302		} );
5303
5304		return scroller[0];
5305	}
5306
5307
5308
5309	/**
5310	 * Update the header, footer and body tables for resizing - i.e. column
5311	 * alignment.
5312	 *
5313	 * Welcome to the most horrible function DataTables. The process that this
5314	 * function follows is basically:
5315	 *   1. Re-create the table inside the scrolling div
5316	 *   2. Take live measurements from the DOM
5317	 *   3. Apply the measurements to align the columns
5318	 *   4. Clean up
5319	 *
5320	 *  @param {object} settings dataTables settings object
5321	 *  @memberof DataTable#oApi
5322	 */
5323	function _fnScrollDraw ( settings )
5324	{
5325		// Given that this is such a monster function, a lot of variables are use
5326		// to try and keep the minimised size as small as possible
5327		var
5328			scroll         = settings.oScroll,
5329			scrollX        = scroll.sX,
5330			scrollXInner   = scroll.sXInner,
5331			scrollY        = scroll.sY,
5332			barWidth       = scroll.iBarWidth,
5333			divHeader      = $(settings.nScrollHead),
5334			divHeaderStyle = divHeader[0].style,
5335			divHeaderInner = divHeader.children('div'),
5336			divHeaderInnerStyle = divHeaderInner[0].style,
5337			divHeaderTable = divHeaderInner.children('table'),
5338			divBodyEl      = settings.nScrollBody,
5339			divBody        = $(divBodyEl),
5340			divBodyStyle   = divBodyEl.style,
5341			divFooter      = $(settings.nScrollFoot),
5342			divFooterInner = divFooter.children('div'),
5343			divFooterTable = divFooterInner.children('table'),
5344			header         = $(settings.nTHead),
5345			table          = $(settings.nTable),
5346			tableEl        = table[0],
5347			tableStyle     = tableEl.style,
5348			footer         = settings.nTFoot ? $(settings.nTFoot) : null,
5349			browser        = settings.oBrowser,
5350			ie67           = browser.bScrollOversize,
5351			dtHeaderCells  = _pluck( settings.aoColumns, 'nTh' ),
5352			headerTrgEls, footerTrgEls,
5353			headerSrcEls, footerSrcEls,
5354			headerCopy, footerCopy,
5355			headerWidths=[], footerWidths=[],
5356			headerContent=[], footerContent=[],
5357			idx, correction, sanityWidth,
5358			zeroOut = function(nSizer) {
5359				var style = nSizer.style;
5360				style.paddingTop = "0";
5361				style.paddingBottom = "0";
5362				style.borderTopWidth = "0";
5363				style.borderBottomWidth = "0";
5364				style.height = 0;
5365			};
5366
5367		// If the scrollbar visibility has changed from the last draw, we need to
5368		// adjust the column sizes as the table width will have changed to account
5369		// for the scrollbar
5370		var scrollBarVis = divBodyEl.scrollHeight > divBodyEl.clientHeight;
5371
5372		if ( settings.scrollBarVis !== scrollBarVis && settings.scrollBarVis !== undefined ) {
5373			settings.scrollBarVis = scrollBarVis;
5374			_fnAdjustColumnSizing( settings );
5375			return; // adjust column sizing will call this function again
5376		}
5377		else {
5378			settings.scrollBarVis = scrollBarVis;
5379		}
5380
5381		/*
5382		 * 1. Re-create the table inside the scrolling div
5383		 */
5384
5385		// Remove the old minimised thead and tfoot elements in the inner table
5386		table.children('thead, tfoot').remove();
5387
5388		if ( footer ) {
5389			footerCopy = footer.clone().prependTo( table );
5390			footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized
5391			footerSrcEls = footerCopy.find('tr');
5392			footerCopy.find('[id]').removeAttr('id');
5393		}
5394
5395		// Clone the current header and footer elements and then place it into the inner table
5396		headerCopy = header.clone().prependTo( table );
5397		headerTrgEls = header.find('tr'); // original header is in its own table
5398		headerSrcEls = headerCopy.find('tr');
5399		headerCopy.find('th, td').removeAttr('tabindex');
5400		headerCopy.find('[id]').removeAttr('id');
5401
5402
5403		/*
5404		 * 2. Take live measurements from the DOM - do not alter the DOM itself!
5405		 */
5406
5407		// Remove old sizing and apply the calculated column widths
5408		// Get the unique column headers in the newly created (cloned) header. We want to apply the
5409		// calculated sizes to this header
5410		if ( ! scrollX )
5411		{
5412			divBodyStyle.width = '100%';
5413			divHeader[0].style.width = '100%';
5414		}
5415
5416		$.each( _fnGetUniqueThs( settings, headerCopy ), function ( i, el ) {
5417			idx = _fnVisibleToColumnIndex( settings, i );
5418			el.style.width = settings.aoColumns[idx].sWidth;
5419		} );
5420
5421		if ( footer ) {
5422			_fnApplyToChildren( function(n) {
5423				n.style.width = "";
5424			}, footerSrcEls );
5425		}
5426
5427		// Size the table as a whole
5428		sanityWidth = table.outerWidth();
5429		if ( scrollX === "" ) {
5430			// No x scrolling
5431			tableStyle.width = "100%";
5432
5433			// IE7 will make the width of the table when 100% include the scrollbar
5434			// - which is shouldn't. When there is a scrollbar we need to take this
5435			// into account.
5436			if ( ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight ||
5437				divBody.css('overflow-y') == "scroll")
5438			) {
5439				tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth);
5440			}
5441
5442			// Recalculate the sanity width
5443			sanityWidth = table.outerWidth();
5444		}
5445		else if ( scrollXInner !== "" ) {
5446			// legacy x scroll inner has been given - use it
5447			tableStyle.width = _fnStringToCss(scrollXInner);
5448
5449			// Recalculate the sanity width
5450			sanityWidth = table.outerWidth();
5451		}
5452
5453		// Hidden header should have zero height, so remove padding and borders. Then
5454		// set the width based on the real headers
5455
5456		// Apply all styles in one pass
5457		_fnApplyToChildren( zeroOut, headerSrcEls );
5458
5459		// Read all widths in next pass
5460		_fnApplyToChildren( function(nSizer) {
5461			var style = window.getComputedStyle ?
5462				window.getComputedStyle(nSizer).width :
5463				_fnStringToCss( $(nSizer).width() );
5464
5465			headerContent.push( nSizer.innerHTML );
5466			headerWidths.push( style );
5467		}, headerSrcEls );
5468
5469		// Apply all widths in final pass
5470		_fnApplyToChildren( function(nToSize, i) {
5471			nToSize.style.width = headerWidths[i];
5472		}, headerTrgEls );
5473
5474		$(headerSrcEls).css('height', 0);
5475
5476		/* Same again with the footer if we have one */
5477		if ( footer )
5478		{
5479			_fnApplyToChildren( zeroOut, footerSrcEls );
5480
5481			_fnApplyToChildren( function(nSizer) {
5482				footerContent.push( nSizer.innerHTML );
5483				footerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
5484			}, footerSrcEls );
5485
5486			_fnApplyToChildren( function(nToSize, i) {
5487				nToSize.style.width = footerWidths[i];
5488			}, footerTrgEls );
5489
5490			$(footerSrcEls).height(0);
5491		}
5492
5493
5494		/*
5495		 * 3. Apply the measurements
5496		 */
5497
5498		// "Hide" the header and footer that we used for the sizing. We need to keep
5499		// the content of the cell so that the width applied to the header and body
5500		// both match, but we want to hide it completely. We want to also fix their
5501		// width to what they currently are
5502		_fnApplyToChildren( function(nSizer, i) {
5503			nSizer.innerHTML = '<div class="dataTables_sizing">'+headerContent[i]+'</div>';
5504			nSizer.childNodes[0].style.height = "0";
5505			nSizer.childNodes[0].style.overflow = "hidden";
5506			nSizer.style.width = headerWidths[i];
5507		}, headerSrcEls );
5508
5509		if ( footer )
5510		{
5511			_fnApplyToChildren( function(nSizer, i) {
5512				nSizer.innerHTML = '<div class="dataTables_sizing">'+footerContent[i]+'</div>';
5513				nSizer.childNodes[0].style.height = "0";
5514				nSizer.childNodes[0].style.overflow = "hidden";
5515				nSizer.style.width = footerWidths[i];
5516			}, footerSrcEls );
5517		}
5518
5519		// Sanity check that the table is of a sensible width. If not then we are going to get
5520		// misalignment - try to prevent this by not allowing the table to shrink below its min width
5521		if ( Math.round(table.outerWidth()) < Math.round(sanityWidth) )
5522		{
5523			// The min width depends upon if we have a vertical scrollbar visible or not */
5524			correction = ((divBodyEl.scrollHeight > divBodyEl.offsetHeight ||
5525				divBody.css('overflow-y') == "scroll")) ?
5526					sanityWidth+barWidth :
5527					sanityWidth;
5528
5529			// IE6/7 are a law unto themselves...
5530			if ( ie67 && (divBodyEl.scrollHeight >
5531				divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll")
5532			) {
5533				tableStyle.width = _fnStringToCss( correction-barWidth );
5534			}
5535
5536			// And give the user a warning that we've stopped the table getting too small
5537			if ( scrollX === "" || scrollXInner !== "" ) {
5538				_fnLog( settings, 1, 'Possible column misalignment', 6 );
5539			}
5540		}
5541		else
5542		{
5543			correction = '100%';
5544		}
5545
5546		// Apply to the container elements
5547		divBodyStyle.width = _fnStringToCss( correction );
5548		divHeaderStyle.width = _fnStringToCss( correction );
5549
5550		if ( footer ) {
5551			settings.nScrollFoot.style.width = _fnStringToCss( correction );
5552		}
5553
5554
5555		/*
5556		 * 4. Clean up
5557		 */
5558		if ( ! scrollY ) {
5559			/* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
5560			 * the scrollbar height from the visible display, rather than adding it on. We need to
5561			 * set the height in order to sort this. Don't want to do it in any other browsers.
5562			 */
5563			if ( ie67 ) {
5564				divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+barWidth );
5565			}
5566		}
5567
5568		/* Finally set the width's of the header and footer tables */
5569		var iOuterWidth = table.outerWidth();
5570		divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth );
5571		divHeaderInnerStyle.width = _fnStringToCss( iOuterWidth );
5572
5573		// Figure out if there are scrollbar present - if so then we need a the header and footer to
5574		// provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
5575		var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll";
5576		var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' );
5577		divHeaderInnerStyle[ padding ] = bScrolling ? barWidth+"px" : "0px";
5578
5579		if ( footer ) {
5580			divFooterTable[0].style.width = _fnStringToCss( iOuterWidth );
5581			divFooterInner[0].style.width = _fnStringToCss( iOuterWidth );
5582			divFooterInner[0].style[padding] = bScrolling ? barWidth+"px" : "0px";
5583		}
5584
5585		// Correct DOM ordering for colgroup - comes before the thead
5586		table.children('colgroup').insertBefore( table.children('thead') );
5587
5588		/* Adjust the position of the header in case we loose the y-scrollbar */
5589		divBody.trigger('scroll');
5590
5591		// If sorting or filtering has occurred, jump the scrolling back to the top
5592		// only if we aren't holding the position
5593		if ( (settings.bSorted || settings.bFiltered) && ! settings._drawHold ) {
5594			divBodyEl.scrollTop = 0;
5595		}
5596	}
5597
5598
5599
5600	/**
5601	 * Apply a given function to the display child nodes of an element array (typically
5602	 * TD children of TR rows
5603	 *  @param {function} fn Method to apply to the objects
5604	 *  @param array {nodes} an1 List of elements to look through for display children
5605	 *  @param array {nodes} an2 Another list (identical structure to the first) - optional
5606	 *  @memberof DataTable#oApi
5607	 */
5608	function _fnApplyToChildren( fn, an1, an2 )
5609	{
5610		var index=0, i=0, iLen=an1.length;
5611		var nNode1, nNode2;
5612
5613		while ( i < iLen ) {
5614			nNode1 = an1[i].firstChild;
5615			nNode2 = an2 ? an2[i].firstChild : null;
5616
5617			while ( nNode1 ) {
5618				if ( nNode1.nodeType === 1 ) {
5619					if ( an2 ) {
5620						fn( nNode1, nNode2, index );
5621					}
5622					else {
5623						fn( nNode1, index );
5624					}
5625
5626					index++;
5627				}
5628
5629				nNode1 = nNode1.nextSibling;
5630				nNode2 = an2 ? nNode2.nextSibling : null;
5631			}
5632
5633			i++;
5634		}
5635	}
5636
5637
5638
5639	var __re_html_remove = /<.*?>/g;
5640
5641
5642	/**
5643	 * Calculate the width of columns for the table
5644	 *  @param {object} oSettings dataTables settings object
5645	 *  @memberof DataTable#oApi
5646	 */
5647	function _fnCalculateColumnWidths ( oSettings )
5648	{
5649		var
5650			table = oSettings.nTable,
5651			columns = oSettings.aoColumns,
5652			scroll = oSettings.oScroll,
5653			scrollY = scroll.sY,
5654			scrollX = scroll.sX,
5655			scrollXInner = scroll.sXInner,
5656			columnCount = columns.length,
5657			visibleColumns = _fnGetColumns( oSettings, 'bVisible' ),
5658			headerCells = $('th', oSettings.nTHead),
5659			tableWidthAttr = table.getAttribute('width'), // from DOM element
5660			tableContainer = table.parentNode,
5661			userInputs = false,
5662			i, column, columnIdx, width, outerWidth,
5663			browser = oSettings.oBrowser,
5664			ie67 = browser.bScrollOversize;
5665
5666		var styleWidth = table.style.width;
5667		if ( styleWidth && styleWidth.indexOf('%') !== -1 ) {
5668			tableWidthAttr = styleWidth;
5669		}
5670
5671		/* Convert any user input sizes into pixel sizes */
5672		for ( i=0 ; i<visibleColumns.length ; i++ ) {
5673			column = columns[ visibleColumns[i] ];
5674
5675			if ( column.sWidth !== null ) {
5676				column.sWidth = _fnConvertToWidth( column.sWidthOrig, tableContainer );
5677
5678				userInputs = true;
5679			}
5680		}
5681
5682		/* If the number of columns in the DOM equals the number that we have to
5683		 * process in DataTables, then we can use the offsets that are created by
5684		 * the web- browser. No custom sizes can be set in order for this to happen,
5685		 * nor scrolling used
5686		 */
5687		if ( ie67 || ! userInputs && ! scrollX && ! scrollY &&
5688		     columnCount == _fnVisbleColumns( oSettings ) &&
5689		     columnCount == headerCells.length
5690		) {
5691			for ( i=0 ; i<columnCount ; i++ ) {
5692				var colIdx = _fnVisibleToColumnIndex( oSettings, i );
5693
5694				if ( colIdx !== null ) {
5695					columns[ colIdx ].sWidth = _fnStringToCss( headerCells.eq(i).width() );
5696				}
5697			}
5698		}
5699		else
5700		{
5701			// Otherwise construct a single row, worst case, table with the widest
5702			// node in the data, assign any user defined widths, then insert it into
5703			// the DOM and allow the browser to do all the hard work of calculating
5704			// table widths
5705			var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table
5706				.css( 'visibility', 'hidden' )
5707				.removeAttr( 'id' );
5708
5709			// Clean up the table body
5710			tmpTable.find('tbody tr').remove();
5711			var tr = $('<tr/>').appendTo( tmpTable.find('tbody') );
5712
5713			// Clone the table header and footer - we can't use the header / footer
5714			// from the cloned table, since if scrolling is active, the table's
5715			// real header and footer are contained in different table tags
5716			tmpTable.find('thead, tfoot').remove();
5717			tmpTable
5718				.append( $(oSettings.nTHead).clone() )
5719				.append( $(oSettings.nTFoot).clone() );
5720
5721			// Remove any assigned widths from the footer (from scrolling)
5722			tmpTable.find('tfoot th, tfoot td').css('width', '');
5723
5724			// Apply custom sizing to the cloned header
5725			headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] );
5726
5727			for ( i=0 ; i<visibleColumns.length ; i++ ) {
5728				column = columns[ visibleColumns[i] ];
5729
5730				headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ?
5731					_fnStringToCss( column.sWidthOrig ) :
5732					'';
5733
5734				// For scrollX we need to force the column width otherwise the
5735				// browser will collapse it. If this width is smaller than the
5736				// width the column requires, then it will have no effect
5737				if ( column.sWidthOrig && scrollX ) {
5738					$( headerCells[i] ).append( $('<div/>').css( {
5739						width: column.sWidthOrig,
5740						margin: 0,
5741						padding: 0,
5742						border: 0,
5743						height: 1
5744					} ) );
5745				}
5746			}
5747
5748			// Find the widest cell for each column and put it into the table
5749			if ( oSettings.aoData.length ) {
5750				for ( i=0 ; i<visibleColumns.length ; i++ ) {
5751					columnIdx = visibleColumns[i];
5752					column = columns[ columnIdx ];
5753
5754					$( _fnGetWidestNode( oSettings, columnIdx ) )
5755						.clone( false )
5756						.append( column.sContentPadding )
5757						.appendTo( tr );
5758				}
5759			}
5760
5761			// Tidy the temporary table - remove name attributes so there aren't
5762			// duplicated in the dom (radio elements for example)
5763			$('[name]', tmpTable).removeAttr('name');
5764
5765			// Table has been built, attach to the document so we can work with it.
5766			// A holding element is used, positioned at the top of the container
5767			// with minimal height, so it has no effect on if the container scrolls
5768			// or not. Otherwise it might trigger scrolling when it actually isn't
5769			// needed
5770			var holder = $('<div/>').css( scrollX || scrollY ?
5771					{
5772						position: 'absolute',
5773						top: 0,
5774						left: 0,
5775						height: 1,
5776						right: 0,
5777						overflow: 'hidden'
5778					} :
5779					{}
5780				)
5781				.append( tmpTable )
5782				.appendTo( tableContainer );
5783
5784			// When scrolling (X or Y) we want to set the width of the table as
5785			// appropriate. However, when not scrolling leave the table width as it
5786			// is. This results in slightly different, but I think correct behaviour
5787			if ( scrollX && scrollXInner ) {
5788				tmpTable.width( scrollXInner );
5789			}
5790			else if ( scrollX ) {
5791				tmpTable.css( 'width', 'auto' );
5792				tmpTable.removeAttr('width');
5793
5794				// If there is no width attribute or style, then allow the table to
5795				// collapse
5796				if ( tmpTable.width() < tableContainer.clientWidth && tableWidthAttr ) {
5797					tmpTable.width( tableContainer.clientWidth );
5798				}
5799			}
5800			else if ( scrollY ) {
5801				tmpTable.width( tableContainer.clientWidth );
5802			}
5803			else if ( tableWidthAttr ) {
5804				tmpTable.width( tableWidthAttr );
5805			}
5806
5807			// Get the width of each column in the constructed table - we need to
5808			// know the inner width (so it can be assigned to the other table's
5809			// cells) and the outer width so we can calculate the full width of the
5810			// table. This is safe since DataTables requires a unique cell for each
5811			// column, but if ever a header can span multiple columns, this will
5812			// need to be modified.
5813			var total = 0;
5814			for ( i=0 ; i<visibleColumns.length ; i++ ) {
5815				var cell = $(headerCells[i]);
5816				var border = cell.outerWidth() - cell.width();
5817
5818				// Use getBounding... where possible (not IE8-) because it can give
5819				// sub-pixel accuracy, which we then want to round up!
5820				var bounding = browser.bBounding ?
5821					Math.ceil( headerCells[i].getBoundingClientRect().width ) :
5822					cell.outerWidth();
5823
5824				// Total is tracked to remove any sub-pixel errors as the outerWidth
5825				// of the table might not equal the total given here (IE!).
5826				total += bounding;
5827
5828				// Width for each column to use
5829				columns[ visibleColumns[i] ].sWidth = _fnStringToCss( bounding - border );
5830			}
5831
5832			table.style.width = _fnStringToCss( total );
5833
5834			// Finished with the table - ditch it
5835			holder.remove();
5836		}
5837
5838		// If there is a width attr, we want to attach an event listener which
5839		// allows the table sizing to automatically adjust when the window is
5840		// resized. Use the width attr rather than CSS, since we can't know if the
5841		// CSS is a relative value or absolute - DOM read is always px.
5842		if ( tableWidthAttr ) {
5843			table.style.width = _fnStringToCss( tableWidthAttr );
5844		}
5845
5846		if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) {
5847			var bindResize = function () {
5848				$(window).on('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {
5849					_fnAdjustColumnSizing( oSettings );
5850				} ) );
5851			};
5852
5853			// IE6/7 will crash if we bind a resize event handler on page load.
5854			// To be removed in 1.11 which drops IE6/7 support
5855			if ( ie67 ) {
5856				setTimeout( bindResize, 1000 );
5857			}
5858			else {
5859				bindResize();
5860			}
5861
5862			oSettings._reszEvt = true;
5863		}
5864	}
5865
5866
5867	/**
5868	 * Throttle the calls to a function. Arguments and context are maintained for
5869	 * the throttled function
5870	 *  @param {function} fn Function to be called
5871	 *  @param {int} [freq=200] call frequency in mS
5872	 *  @returns {function} wrapped function
5873	 *  @memberof DataTable#oApi
5874	 */
5875	var _fnThrottle = DataTable.util.throttle;
5876
5877
5878	/**
5879	 * Convert a CSS unit width to pixels (e.g. 2em)
5880	 *  @param {string} width width to be converted
5881	 *  @param {node} parent parent to get the with for (required for relative widths) - optional
5882	 *  @returns {int} width in pixels
5883	 *  @memberof DataTable#oApi
5884	 */
5885	function _fnConvertToWidth ( width, parent )
5886	{
5887		if ( ! width ) {
5888			return 0;
5889		}
5890
5891		var n = $('<div/>')
5892			.css( 'width', _fnStringToCss( width ) )
5893			.appendTo( parent || document.body );
5894
5895		var val = n[0].offsetWidth;
5896		n.remove();
5897
5898		return val;
5899	}
5900
5901
5902	/**
5903	 * Get the widest node
5904	 *  @param {object} settings dataTables settings object
5905	 *  @param {int} colIdx column of interest
5906	 *  @returns {node} widest table node
5907	 *  @memberof DataTable#oApi
5908	 */
5909	function _fnGetWidestNode( settings, colIdx )
5910	{
5911		var idx = _fnGetMaxLenString( settings, colIdx );
5912		if ( idx < 0 ) {
5913			return null;
5914		}
5915
5916		var data = settings.aoData[ idx ];
5917		return ! data.nTr ? // Might not have been created when deferred rendering
5918			$('<td/>').html( _fnGetCellData( settings, idx, colIdx, 'display' ) )[0] :
5919			data.anCells[ colIdx ];
5920	}
5921
5922
5923	/**
5924	 * Get the maximum strlen for each data column
5925	 *  @param {object} settings dataTables settings object
5926	 *  @param {int} colIdx column of interest
5927	 *  @returns {string} max string length for each column
5928	 *  @memberof DataTable#oApi
5929	 */
5930	function _fnGetMaxLenString( settings, colIdx )
5931	{
5932		var s, max=-1, maxIdx = -1;
5933
5934		for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
5935			s = _fnGetCellData( settings, i, colIdx, 'display' )+'';
5936			s = s.replace( __re_html_remove, '' );
5937			s = s.replace( /&nbsp;/g, ' ' );
5938
5939			if ( s.length > max ) {
5940				max = s.length;
5941				maxIdx = i;
5942			}
5943		}
5944
5945		return maxIdx;
5946	}
5947
5948
5949	/**
5950	 * Append a CSS unit (only if required) to a string
5951	 *  @param {string} value to css-ify
5952	 *  @returns {string} value with css unit
5953	 *  @memberof DataTable#oApi
5954	 */
5955	function _fnStringToCss( s )
5956	{
5957		if ( s === null ) {
5958			return '0px';
5959		}
5960
5961		if ( typeof s == 'number' ) {
5962			return s < 0 ?
5963				'0px' :
5964				s+'px';
5965		}
5966
5967		// Check it has a unit character already
5968		return s.match(/\d$/) ?
5969			s+'px' :
5970			s;
5971	}
5972
5973
5974
5975	function _fnSortFlatten ( settings )
5976	{
5977		var
5978			i, iLen, k, kLen,
5979			aSort = [],
5980			aiOrig = [],
5981			aoColumns = settings.aoColumns,
5982			aDataSort, iCol, sType, srcCol,
5983			fixed = settings.aaSortingFixed,
5984			fixedObj = $.isPlainObject( fixed ),
5985			nestedSort = [],
5986			add = function ( a ) {
5987				if ( a.length && ! Array.isArray( a[0] ) ) {
5988					// 1D array
5989					nestedSort.push( a );
5990				}
5991				else {
5992					// 2D array
5993					$.merge( nestedSort, a );
5994				}
5995			};
5996
5997		// Build the sort array, with pre-fix and post-fix options if they have been
5998		// specified
5999		if ( Array.isArray( fixed ) ) {
6000			add( fixed );
6001		}
6002
6003		if ( fixedObj && fixed.pre ) {
6004			add( fixed.pre );
6005		}
6006
6007		add( settings.aaSorting );
6008
6009		if (fixedObj && fixed.post ) {
6010			add( fixed.post );
6011		}
6012
6013		for ( i=0 ; i<nestedSort.length ; i++ )
6014		{
6015			srcCol = nestedSort[i][0];
6016			aDataSort = aoColumns[ srcCol ].aDataSort;
6017
6018			for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ )
6019			{
6020				iCol = aDataSort[k];
6021				sType = aoColumns[ iCol ].sType || 'string';
6022
6023				if ( nestedSort[i]._idx === undefined ) {
6024					nestedSort[i]._idx = $.inArray( nestedSort[i][1], aoColumns[iCol].asSorting );
6025				}
6026
6027				aSort.push( {
6028					src:       srcCol,
6029					col:       iCol,
6030					dir:       nestedSort[i][1],
6031					index:     nestedSort[i]._idx,
6032					type:      sType,
6033					formatter: DataTable.ext.type.order[ sType+"-pre" ]
6034				} );
6035			}
6036		}
6037
6038		return aSort;
6039	}
6040
6041	/**
6042	 * Change the order of the table
6043	 *  @param {object} oSettings dataTables settings object
6044	 *  @memberof DataTable#oApi
6045	 *  @todo This really needs split up!
6046	 */
6047	function _fnSort ( oSettings )
6048	{
6049		var
6050			i, ien, iLen, j, jLen, k, kLen,
6051			sDataType, nTh,
6052			aiOrig = [],
6053			oExtSort = DataTable.ext.type.order,
6054			aoData = oSettings.aoData,
6055			aoColumns = oSettings.aoColumns,
6056			aDataSort, data, iCol, sType, oSort,
6057			formatters = 0,
6058			sortCol,
6059			displayMaster = oSettings.aiDisplayMaster,
6060			aSort;
6061
6062		// Resolve any column types that are unknown due to addition or invalidation
6063		// @todo Can this be moved into a 'data-ready' handler which is called when
6064		//   data is going to be used in the table?
6065		_fnColumnTypes( oSettings );
6066
6067		aSort = _fnSortFlatten( oSettings );
6068
6069		for ( i=0, ien=aSort.length ; i<ien ; i++ ) {
6070			sortCol = aSort[i];
6071
6072			// Track if we can use the fast sort algorithm
6073			if ( sortCol.formatter ) {
6074				formatters++;
6075			}
6076
6077			// Load the data needed for the sort, for each cell
6078			_fnSortData( oSettings, sortCol.col );
6079		}
6080
6081		/* No sorting required if server-side or no sorting array */
6082		if ( _fnDataSource( oSettings ) != 'ssp' && aSort.length !== 0 )
6083		{
6084			// Create a value - key array of the current row positions such that we can use their
6085			// current position during the sort, if values match, in order to perform stable sorting
6086			for ( i=0, iLen=displayMaster.length ; i<iLen ; i++ ) {
6087				aiOrig[ displayMaster[i] ] = i;
6088			}
6089
6090			/* Do the sort - here we want multi-column sorting based on a given data source (column)
6091			 * and sorting function (from oSort) in a certain direction. It's reasonably complex to
6092			 * follow on it's own, but this is what we want (example two column sorting):
6093			 *  fnLocalSorting = function(a,b){
6094			 *    var iTest;
6095			 *    iTest = oSort['string-asc']('data11', 'data12');
6096			 *      if (iTest !== 0)
6097			 *        return iTest;
6098			 *    iTest = oSort['numeric-desc']('data21', 'data22');
6099			 *    if (iTest !== 0)
6100			 *      return iTest;
6101			 *    return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
6102			 *  }
6103			 * Basically we have a test for each sorting column, if the data in that column is equal,
6104			 * test the next column. If all columns match, then we use a numeric sort on the row
6105			 * positions in the original data array to provide a stable sort.
6106			 *
6107			 * Note - I know it seems excessive to have two sorting methods, but the first is around
6108			 * 15% faster, so the second is only maintained for backwards compatibility with sorting
6109			 * methods which do not have a pre-sort formatting function.
6110			 */
6111			if ( formatters === aSort.length ) {
6112				// All sort types have formatting functions
6113				displayMaster.sort( function ( a, b ) {
6114					var
6115						x, y, k, test, sort,
6116						len=aSort.length,
6117						dataA = aoData[a]._aSortData,
6118						dataB = aoData[b]._aSortData;
6119
6120					for ( k=0 ; k<len ; k++ ) {
6121						sort = aSort[k];
6122
6123						x = dataA[ sort.col ];
6124						y = dataB[ sort.col ];
6125
6126						test = x<y ? -1 : x>y ? 1 : 0;
6127						if ( test !== 0 ) {
6128							return sort.dir === 'asc' ? test : -test;
6129						}
6130					}
6131
6132					x = aiOrig[a];
6133					y = aiOrig[b];
6134					return x<y ? -1 : x>y ? 1 : 0;
6135				} );
6136			}
6137			else {
6138				// Depreciated - remove in 1.11 (providing a plug-in option)
6139				// Not all sort types have formatting methods, so we have to call their sorting
6140				// methods.
6141				displayMaster.sort( function ( a, b ) {
6142					var
6143						x, y, k, l, test, sort, fn,
6144						len=aSort.length,
6145						dataA = aoData[a]._aSortData,
6146						dataB = aoData[b]._aSortData;
6147
6148					for ( k=0 ; k<len ; k++ ) {
6149						sort = aSort[k];
6150
6151						x = dataA[ sort.col ];
6152						y = dataB[ sort.col ];
6153
6154						fn = oExtSort[ sort.type+"-"+sort.dir ] || oExtSort[ "string-"+sort.dir ];
6155						test = fn( x, y );
6156						if ( test !== 0 ) {
6157							return test;
6158						}
6159					}
6160
6161					x = aiOrig[a];
6162					y = aiOrig[b];
6163					return x<y ? -1 : x>y ? 1 : 0;
6164				} );
6165			}
6166		}
6167
6168		/* Tell the draw function that we have sorted the data */
6169		oSettings.bSorted = true;
6170	}
6171
6172
6173	function _fnSortAria ( settings )
6174	{
6175		var label;
6176		var nextSort;
6177		var columns = settings.aoColumns;
6178		var aSort = _fnSortFlatten( settings );
6179		var oAria = settings.oLanguage.oAria;
6180
6181		// ARIA attributes - need to loop all columns, to update all (removing old
6182		// attributes as needed)
6183		for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
6184		{
6185			var col = columns[i];
6186			var asSorting = col.asSorting;
6187			var sTitle = col.ariaTitle || col.sTitle.replace( /<.*?>/g, "" );
6188			var th = col.nTh;
6189
6190			// IE7 is throwing an error when setting these properties with jQuery's
6191			// attr() and removeAttr() methods...
6192			th.removeAttribute('aria-sort');
6193
6194			/* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
6195			if ( col.bSortable ) {
6196				if ( aSort.length > 0 && aSort[0].col == i ) {
6197					th.setAttribute('aria-sort', aSort[0].dir=="asc" ? "ascending" : "descending" );
6198					nextSort = asSorting[ aSort[0].index+1 ] || asSorting[0];
6199				}
6200				else {
6201					nextSort = asSorting[0];
6202				}
6203
6204				label = sTitle + ( nextSort === "asc" ?
6205					oAria.sSortAscending :
6206					oAria.sSortDescending
6207				);
6208			}
6209			else {
6210				label = sTitle;
6211			}
6212
6213			th.setAttribute('aria-label', label);
6214		}
6215	}
6216
6217
6218	/**
6219	 * Function to run on user sort request
6220	 *  @param {object} settings dataTables settings object
6221	 *  @param {node} attachTo node to attach the handler to
6222	 *  @param {int} colIdx column sorting index
6223	 *  @param {boolean} [append=false] Append the requested sort to the existing
6224	 *    sort if true (i.e. multi-column sort)
6225	 *  @param {function} [callback] callback function
6226	 *  @memberof DataTable#oApi
6227	 */
6228	function _fnSortListener ( settings, colIdx, append, callback )
6229	{
6230		var col = settings.aoColumns[ colIdx ];
6231		var sorting = settings.aaSorting;
6232		var asSorting = col.asSorting;
6233		var nextSortIdx;
6234		var next = function ( a, overflow ) {
6235			var idx = a._idx;
6236			if ( idx === undefined ) {
6237				idx = $.inArray( a[1], asSorting );
6238			}
6239
6240			return idx+1 < asSorting.length ?
6241				idx+1 :
6242				overflow ?
6243					null :
6244					0;
6245		};
6246
6247		// Convert to 2D array if needed
6248		if ( typeof sorting[0] === 'number' ) {
6249			sorting = settings.aaSorting = [ sorting ];
6250		}
6251
6252		// If appending the sort then we are multi-column sorting
6253		if ( append && settings.oFeatures.bSortMulti ) {
6254			// Are we already doing some kind of sort on this column?
6255			var sortIdx = $.inArray( colIdx, _pluck(sorting, '0') );
6256
6257			if ( sortIdx !== -1 ) {
6258				// Yes, modify the sort
6259				nextSortIdx = next( sorting[sortIdx], true );
6260
6261				if ( nextSortIdx === null && sorting.length === 1 ) {
6262					nextSortIdx = 0; // can't remove sorting completely
6263				}
6264
6265				if ( nextSortIdx === null ) {
6266					sorting.splice( sortIdx, 1 );
6267				}
6268				else {
6269					sorting[sortIdx][1] = asSorting[ nextSortIdx ];
6270					sorting[sortIdx]._idx = nextSortIdx;
6271				}
6272			}
6273			else {
6274				// No sort on this column yet
6275				sorting.push( [ colIdx, asSorting[0], 0 ] );
6276				sorting[sorting.length-1]._idx = 0;
6277			}
6278		}
6279		else if ( sorting.length && sorting[0][0] == colIdx ) {
6280			// Single column - already sorting on this column, modify the sort
6281			nextSortIdx = next( sorting[0] );
6282
6283			sorting.length = 1;
6284			sorting[0][1] = asSorting[ nextSortIdx ];
6285			sorting[0]._idx = nextSortIdx;
6286		}
6287		else {
6288			// Single column - sort only on this column
6289			sorting.length = 0;
6290			sorting.push( [ colIdx, asSorting[0] ] );
6291			sorting[0]._idx = 0;
6292		}
6293
6294		// Run the sort by calling a full redraw
6295		_fnReDraw( settings );
6296
6297		// callback used for async user interaction
6298		if ( typeof callback == 'function' ) {
6299			callback( settings );
6300		}
6301	}
6302
6303
6304	/**
6305	 * Attach a sort handler (click) to a node
6306	 *  @param {object} settings dataTables settings object
6307	 *  @param {node} attachTo node to attach the handler to
6308	 *  @param {int} colIdx column sorting index
6309	 *  @param {function} [callback] callback function
6310	 *  @memberof DataTable#oApi
6311	 */
6312	function _fnSortAttachListener ( settings, attachTo, colIdx, callback )
6313	{
6314		var col = settings.aoColumns[ colIdx ];
6315
6316		_fnBindAction( attachTo, {}, function (e) {
6317			/* If the column is not sortable - don't to anything */
6318			if ( col.bSortable === false ) {
6319				return;
6320			}
6321
6322			// If processing is enabled use a timeout to allow the processing
6323			// display to be shown - otherwise to it synchronously
6324			if ( settings.oFeatures.bProcessing ) {
6325				_fnProcessingDisplay( settings, true );
6326
6327				setTimeout( function() {
6328					_fnSortListener( settings, colIdx, e.shiftKey, callback );
6329
6330					// In server-side processing, the draw callback will remove the
6331					// processing display
6332					if ( _fnDataSource( settings ) !== 'ssp' ) {
6333						_fnProcessingDisplay( settings, false );
6334					}
6335				}, 0 );
6336			}
6337			else {
6338				_fnSortListener( settings, colIdx, e.shiftKey, callback );
6339			}
6340		} );
6341	}
6342
6343
6344	/**
6345	 * Set the sorting classes on table's body, Note: it is safe to call this function
6346	 * when bSort and bSortClasses are false
6347	 *  @param {object} oSettings dataTables settings object
6348	 *  @memberof DataTable#oApi
6349	 */
6350	function _fnSortingClasses( settings )
6351	{
6352		var oldSort = settings.aLastSort;
6353		var sortClass = settings.oClasses.sSortColumn;
6354		var sort = _fnSortFlatten( settings );
6355		var features = settings.oFeatures;
6356		var i, ien, colIdx;
6357
6358		if ( features.bSort && features.bSortClasses ) {
6359			// Remove old sorting classes
6360			for ( i=0, ien=oldSort.length ; i<ien ; i++ ) {
6361				colIdx = oldSort[i].src;
6362
6363				// Remove column sorting
6364				$( _pluck( settings.aoData, 'anCells', colIdx ) )
6365					.removeClass( sortClass + (i<2 ? i+1 : 3) );
6366			}
6367
6368			// Add new column sorting
6369			for ( i=0, ien=sort.length ; i<ien ; i++ ) {
6370				colIdx = sort[i].src;
6371
6372				$( _pluck( settings.aoData, 'anCells', colIdx ) )
6373					.addClass( sortClass + (i<2 ? i+1 : 3) );
6374			}
6375		}
6376
6377		settings.aLastSort = sort;
6378	}
6379
6380
6381	// Get the data to sort a column, be it from cache, fresh (populating the
6382	// cache), or from a sort formatter
6383	function _fnSortData( settings, idx )
6384	{
6385		// Custom sorting function - provided by the sort data type
6386		var column = settings.aoColumns[ idx ];
6387		var customSort = DataTable.ext.order[ column.sSortDataType ];
6388		var customData;
6389
6390		if ( customSort ) {
6391			customData = customSort.call( settings.oInstance, settings, idx,
6392				_fnColumnIndexToVisible( settings, idx )
6393			);
6394		}
6395
6396		// Use / populate cache
6397		var row, cellData;
6398		var formatter = DataTable.ext.type.order[ column.sType+"-pre" ];
6399
6400		for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
6401			row = settings.aoData[i];
6402
6403			if ( ! row._aSortData ) {
6404				row._aSortData = [];
6405			}
6406
6407			if ( ! row._aSortData[idx] || customSort ) {
6408				cellData = customSort ?
6409					customData[i] : // If there was a custom sort function, use data from there
6410					_fnGetCellData( settings, i, idx, 'sort' );
6411
6412				row._aSortData[ idx ] = formatter ?
6413					formatter( cellData ) :
6414					cellData;
6415			}
6416		}
6417	}
6418
6419
6420
6421	/**
6422	 * Save the state of a table
6423	 *  @param {object} oSettings dataTables settings object
6424	 *  @memberof DataTable#oApi
6425	 */
6426	function _fnSaveState ( settings )
6427	{
6428		if (settings._bLoadingState) {
6429			return;
6430		}
6431
6432		/* Store the interesting variables */
6433		var state = {
6434			time:    +new Date(),
6435			start:   settings._iDisplayStart,
6436			length:  settings._iDisplayLength,
6437			order:   $.extend( true, [], settings.aaSorting ),
6438			search:  _fnSearchToCamel( settings.oPreviousSearch ),
6439			columns: $.map( settings.aoColumns, function ( col, i ) {
6440				return {
6441					visible: col.bVisible,
6442					search: _fnSearchToCamel( settings.aoPreSearchCols[i] )
6443				};
6444			} )
6445		};
6446
6447		settings.oSavedState = state;
6448		_fnCallbackFire( settings, "aoStateSaveParams", 'stateSaveParams', [settings, state] );
6449
6450		if ( settings.oFeatures.bStateSave && !settings.bDestroying )
6451		{
6452			settings.fnStateSaveCallback.call( settings.oInstance, settings, state );
6453		}
6454	}
6455
6456
6457	/**
6458	 * Attempt to load a saved table state
6459	 *  @param {object} oSettings dataTables settings object
6460	 *  @param {object} oInit DataTables init object so we can override settings
6461	 *  @param {function} callback Callback to execute when the state has been loaded
6462	 *  @memberof DataTable#oApi
6463	 */
6464	function _fnLoadState ( settings, oInit, callback )
6465	{
6466		if ( ! settings.oFeatures.bStateSave ) {
6467			callback();
6468			return;
6469		}
6470
6471		var loaded = function(state) {
6472			_fnImplementState(settings, state, callback);
6473		}
6474
6475		var state = settings.fnStateLoadCallback.call( settings.oInstance, settings, loaded );
6476
6477		if ( state !== undefined ) {
6478			_fnImplementState( settings, state, callback );
6479		}
6480		// otherwise, wait for the loaded callback to be executed
6481
6482		return true;
6483	}
6484
6485	function _fnImplementState ( settings, s, callback) {
6486		var i, ien;
6487		var columns = settings.aoColumns;
6488		settings._bLoadingState = true;
6489
6490		// When StateRestore was introduced the state could now be implemented at any time
6491		// Not just initialisation. To do this an api instance is required in some places
6492		var api = settings._bInitComplete ? new DataTable.Api(settings) : null;
6493
6494		if ( ! s || ! s.time ) {
6495			settings._bLoadingState = false;
6496			callback();
6497			return;
6498		}
6499
6500		// Allow custom and plug-in manipulation functions to alter the saved data set and
6501		// cancelling of loading by returning false
6502		var abStateLoad = _fnCallbackFire( settings, 'aoStateLoadParams', 'stateLoadParams', [settings, s] );
6503		if ( $.inArray( false, abStateLoad ) !== -1 ) {
6504			settings._bLoadingState = false;
6505			callback();
6506			return;
6507		}
6508
6509		// Reject old data
6510		var duration = settings.iStateDuration;
6511		if ( duration > 0 && s.time < +new Date() - (duration*1000) ) {
6512			settings._bLoadingState = false;
6513			callback();
6514			return;
6515		}
6516
6517		// Number of columns have changed - all bets are off, no restore of settings
6518		if ( s.columns && columns.length !== s.columns.length ) {
6519			settings._bLoadingState = false;
6520			callback();
6521			return;
6522		}
6523
6524		// Store the saved state so it might be accessed at any time
6525		settings.oLoadedState = $.extend( true, {}, s );
6526
6527		// Page Length
6528		if ( s.length !== undefined ) {
6529			// If already initialised just set the value directly so that the select element is also updated
6530			if (api) {
6531				api.page.len(s.length)
6532			}
6533			else {
6534				settings._iDisplayLength   = s.length;
6535			}
6536		}
6537
6538		// Restore key features - todo - for 1.11 this needs to be done by
6539		// subscribed events
6540		if ( s.start !== undefined ) {
6541			if(api === null) {
6542				settings._iDisplayStart    = s.start;
6543				settings.iInitDisplayStart = s.start;
6544			}
6545			else {
6546				_fnPageChange(settings, s.start/settings._iDisplayLength);
6547			}
6548		}
6549
6550		// Order
6551		if ( s.order !== undefined ) {
6552			settings.aaSorting = [];
6553			$.each( s.order, function ( i, col ) {
6554				settings.aaSorting.push( col[0] >= columns.length ?
6555					[ 0, col[1] ] :
6556					col
6557				);
6558			} );
6559		}
6560
6561		// Search
6562		if ( s.search !== undefined ) {
6563			$.extend( settings.oPreviousSearch, _fnSearchToHung( s.search ) );
6564		}
6565
6566		// Columns
6567		if ( s.columns ) {
6568			for ( i=0, ien=s.columns.length ; i<ien ; i++ ) {
6569				var col = s.columns[i];
6570
6571				// Visibility
6572				if ( col.visible !== undefined ) {
6573					// If the api is defined, the table has been initialised so we need to use it rather than internal settings
6574					if (api) {
6575						// Don't redraw the columns on every iteration of this loop, we will do this at the end instead
6576						api.column(i).visible(col.visible, false);
6577					}
6578					else {
6579						columns[i].bVisible = col.visible;
6580					}
6581				}
6582
6583				// Search
6584				if ( col.search !== undefined ) {
6585					$.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) );
6586				}
6587			}
6588
6589			// If the api is defined then we need to adjust the columns once the visibility has been changed
6590			if (api) {
6591				api.columns.adjust();
6592			}
6593		}
6594
6595		settings._bLoadingState = false;
6596		_fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, s] );
6597		callback();
6598	};
6599
6600
6601	/**
6602	 * Return the settings object for a particular table
6603	 *  @param {node} table table we are using as a dataTable
6604	 *  @returns {object} Settings object - or null if not found
6605	 *  @memberof DataTable#oApi
6606	 */
6607	function _fnSettingsFromNode ( table )
6608	{
6609		var settings = DataTable.settings;
6610		var idx = $.inArray( table, _pluck( settings, 'nTable' ) );
6611
6612		return idx !== -1 ?
6613			settings[ idx ] :
6614			null;
6615	}
6616
6617
6618	/**
6619	 * Log an error message
6620	 *  @param {object} settings dataTables settings object
6621	 *  @param {int} level log error messages, or display them to the user
6622	 *  @param {string} msg error message
6623	 *  @param {int} tn Technical note id to get more information about the error.
6624	 *  @memberof DataTable#oApi
6625	 */
6626	function _fnLog( settings, level, msg, tn )
6627	{
6628		msg = 'DataTables warning: '+
6629			(settings ? 'table id='+settings.sTableId+' - ' : '')+msg;
6630
6631		if ( tn ) {
6632			msg += '. For more information about this error, please see '+
6633			'http://datatables.net/tn/'+tn;
6634		}
6635
6636		if ( ! level  ) {
6637			// Backwards compatibility pre 1.10
6638			var ext = DataTable.ext;
6639			var type = ext.sErrMode || ext.errMode;
6640
6641			if ( settings ) {
6642				_fnCallbackFire( settings, null, 'error', [ settings, tn, msg ] );
6643			}
6644
6645			if ( type == 'alert' ) {
6646				alert( msg );
6647			}
6648			else if ( type == 'throw' ) {
6649				throw new Error(msg);
6650			}
6651			else if ( typeof type == 'function' ) {
6652				type( settings, tn, msg );
6653			}
6654		}
6655		else if ( window.console && console.log ) {
6656			console.log( msg );
6657		}
6658	}
6659
6660
6661	/**
6662	 * See if a property is defined on one object, if so assign it to the other object
6663	 *  @param {object} ret target object
6664	 *  @param {object} src source object
6665	 *  @param {string} name property
6666	 *  @param {string} [mappedName] name to map too - optional, name used if not given
6667	 *  @memberof DataTable#oApi
6668	 */
6669	function _fnMap( ret, src, name, mappedName )
6670	{
6671		if ( Array.isArray( name ) ) {
6672			$.each( name, function (i, val) {
6673				if ( Array.isArray( val ) ) {
6674					_fnMap( ret, src, val[0], val[1] );
6675				}
6676				else {
6677					_fnMap( ret, src, val );
6678				}
6679			} );
6680
6681			return;
6682		}
6683
6684		if ( mappedName === undefined ) {
6685			mappedName = name;
6686		}
6687
6688		if ( src[name] !== undefined ) {
6689			ret[mappedName] = src[name];
6690		}
6691	}
6692
6693
6694	/**
6695	 * Extend objects - very similar to jQuery.extend, but deep copy objects, and
6696	 * shallow copy arrays. The reason we need to do this, is that we don't want to
6697	 * deep copy array init values (such as aaSorting) since the dev wouldn't be
6698	 * able to override them, but we do want to deep copy arrays.
6699	 *  @param {object} out Object to extend
6700	 *  @param {object} extender Object from which the properties will be applied to
6701	 *      out
6702	 *  @param {boolean} breakRefs If true, then arrays will be sliced to take an
6703	 *      independent copy with the exception of the `data` or `aaData` parameters
6704	 *      if they are present. This is so you can pass in a collection to
6705	 *      DataTables and have that used as your data source without breaking the
6706	 *      references
6707	 *  @returns {object} out Reference, just for convenience - out === the return.
6708	 *  @memberof DataTable#oApi
6709	 *  @todo This doesn't take account of arrays inside the deep copied objects.
6710	 */
6711	function _fnExtend( out, extender, breakRefs )
6712	{
6713		var val;
6714
6715		for ( var prop in extender ) {
6716			if ( extender.hasOwnProperty(prop) ) {
6717				val = extender[prop];
6718
6719				if ( $.isPlainObject( val ) ) {
6720					if ( ! $.isPlainObject( out[prop] ) ) {
6721						out[prop] = {};
6722					}
6723					$.extend( true, out[prop], val );
6724				}
6725				else if ( breakRefs && prop !== 'data' && prop !== 'aaData' && Array.isArray(val) ) {
6726					out[prop] = val.slice();
6727				}
6728				else {
6729					out[prop] = val;
6730				}
6731			}
6732		}
6733
6734		return out;
6735	}
6736
6737
6738	/**
6739	 * Bind an event handers to allow a click or return key to activate the callback.
6740	 * This is good for accessibility since a return on the keyboard will have the
6741	 * same effect as a click, if the element has focus.
6742	 *  @param {element} n Element to bind the action to
6743	 *  @param {object} oData Data object to pass to the triggered function
6744	 *  @param {function} fn Callback function for when the event is triggered
6745	 *  @memberof DataTable#oApi
6746	 */
6747	function _fnBindAction( n, oData, fn )
6748	{
6749		$(n)
6750			.on( 'click.DT', oData, function (e) {
6751					$(n).trigger('blur'); // Remove focus outline for mouse users
6752					fn(e);
6753				} )
6754			.on( 'keypress.DT', oData, function (e){
6755					if ( e.which === 13 ) {
6756						e.preventDefault();
6757						fn(e);
6758					}
6759				} )
6760			.on( 'selectstart.DT', function () {
6761					/* Take the brutal approach to cancelling text selection */
6762					return false;
6763				} );
6764	}
6765
6766
6767	/**
6768	 * Register a callback function. Easily allows a callback function to be added to
6769	 * an array store of callback functions that can then all be called together.
6770	 *  @param {object} oSettings dataTables settings object
6771	 *  @param {string} sStore Name of the array storage for the callbacks in oSettings
6772	 *  @param {function} fn Function to be called back
6773	 *  @param {string} sName Identifying name for the callback (i.e. a label)
6774	 *  @memberof DataTable#oApi
6775	 */
6776	function _fnCallbackReg( oSettings, sStore, fn, sName )
6777	{
6778		if ( fn )
6779		{
6780			oSettings[sStore].push( {
6781				"fn": fn,
6782				"sName": sName
6783			} );
6784		}
6785	}
6786
6787
6788	/**
6789	 * Fire callback functions and trigger events. Note that the loop over the
6790	 * callback array store is done backwards! Further note that you do not want to
6791	 * fire off triggers in time sensitive applications (for example cell creation)
6792	 * as its slow.
6793	 *  @param {object} settings dataTables settings object
6794	 *  @param {string} callbackArr Name of the array storage for the callbacks in
6795	 *      oSettings
6796	 *  @param {string} eventName Name of the jQuery custom event to trigger. If
6797	 *      null no trigger is fired
6798	 *  @param {array} args Array of arguments to pass to the callback function /
6799	 *      trigger
6800	 *  @memberof DataTable#oApi
6801	 */
6802	function _fnCallbackFire( settings, callbackArr, eventName, args )
6803	{
6804		var ret = [];
6805
6806		if ( callbackArr ) {
6807			ret = $.map( settings[callbackArr].slice().reverse(), function (val, i) {
6808				return val.fn.apply( settings.oInstance, args );
6809			} );
6810		}
6811
6812		if ( eventName !== null ) {
6813			var e = $.Event( eventName+'.dt' );
6814			var table = $(settings.nTable);
6815
6816			table.trigger( e, args );
6817
6818			// If not yet attached to the document, trigger the event
6819			// on the body directly to sort of simulate the bubble
6820			if (table.parents('body').length === 0) {
6821				$('body').trigger( e, args );
6822			}
6823
6824			ret.push( e.result );
6825		}
6826
6827		return ret;
6828	}
6829
6830
6831	function _fnLengthOverflow ( settings )
6832	{
6833		var
6834			start = settings._iDisplayStart,
6835			end = settings.fnDisplayEnd(),
6836			len = settings._iDisplayLength;
6837
6838		/* If we have space to show extra rows (backing up from the end point - then do so */
6839		if ( start >= end )
6840		{
6841			start = end - len;
6842		}
6843
6844		// Keep the start record on the current page
6845		start -= (start % len);
6846
6847		if ( len === -1 || start < 0 )
6848		{
6849			start = 0;
6850		}
6851
6852		settings._iDisplayStart = start;
6853	}
6854
6855
6856	function _fnRenderer( settings, type )
6857	{
6858		var renderer = settings.renderer;
6859		var host = DataTable.ext.renderer[type];
6860
6861		if ( $.isPlainObject( renderer ) && renderer[type] ) {
6862			// Specific renderer for this type. If available use it, otherwise use
6863			// the default.
6864			return host[renderer[type]] || host._;
6865		}
6866		else if ( typeof renderer === 'string' ) {
6867			// Common renderer - if there is one available for this type use it,
6868			// otherwise use the default
6869			return host[renderer] || host._;
6870		}
6871
6872		// Use the default
6873		return host._;
6874	}
6875
6876
6877	/**
6878	 * Detect the data source being used for the table. Used to simplify the code
6879	 * a little (ajax) and to make it compress a little smaller.
6880	 *
6881	 *  @param {object} settings dataTables settings object
6882	 *  @returns {string} Data source
6883	 *  @memberof DataTable#oApi
6884	 */
6885	function _fnDataSource ( settings )
6886	{
6887		if ( settings.oFeatures.bServerSide ) {
6888			return 'ssp';
6889		}
6890		else if ( settings.ajax || settings.sAjaxSource ) {
6891			return 'ajax';
6892		}
6893		return 'dom';
6894	}
6895
6896
6897
6898
6899	/**
6900	 * Computed structure of the DataTables API, defined by the options passed to
6901	 * `DataTable.Api.register()` when building the API.
6902	 *
6903	 * The structure is built in order to speed creation and extension of the Api
6904	 * objects since the extensions are effectively pre-parsed.
6905	 *
6906	 * The array is an array of objects with the following structure, where this
6907	 * base array represents the Api prototype base:
6908	 *
6909	 *     [
6910	 *       {
6911	 *         name:      'data'                -- string   - Property name
6912	 *         val:       function () {},       -- function - Api method (or undefined if just an object
6913	 *         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
6914	 *         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
6915	 *       },
6916	 *       {
6917	 *         name:     'row'
6918	 *         val:       {},
6919	 *         methodExt: [ ... ],
6920	 *         propExt:   [
6921	 *           {
6922	 *             name:      'data'
6923	 *             val:       function () {},
6924	 *             methodExt: [ ... ],
6925	 *             propExt:   [ ... ]
6926	 *           },
6927	 *           ...
6928	 *         ]
6929	 *       }
6930	 *     ]
6931	 *
6932	 * @type {Array}
6933	 * @ignore
6934	 */
6935	var __apiStruct = [];
6936
6937
6938	/**
6939	 * `Array.prototype` reference.
6940	 *
6941	 * @type object
6942	 * @ignore
6943	 */
6944	var __arrayProto = Array.prototype;
6945
6946
6947	/**
6948	 * Abstraction for `context` parameter of the `Api` constructor to allow it to
6949	 * take several different forms for ease of use.
6950	 *
6951	 * Each of the input parameter types will be converted to a DataTables settings
6952	 * object where possible.
6953	 *
6954	 * @param  {string|node|jQuery|object} mixed DataTable identifier. Can be one
6955	 *   of:
6956	 *
6957	 *   * `string` - jQuery selector. Any DataTables' matching the given selector
6958	 *     with be found and used.
6959	 *   * `node` - `TABLE` node which has already been formed into a DataTable.
6960	 *   * `jQuery` - A jQuery object of `TABLE` nodes.
6961	 *   * `object` - DataTables settings object
6962	 *   * `DataTables.Api` - API instance
6963	 * @return {array|null} Matching DataTables settings objects. `null` or
6964	 *   `undefined` is returned if no matching DataTable is found.
6965	 * @ignore
6966	 */
6967	var _toSettings = function ( mixed )
6968	{
6969		var idx, jq;
6970		var settings = DataTable.settings;
6971		var tables = $.map( settings, function (el, i) {
6972			return el.nTable;
6973		} );
6974
6975		if ( ! mixed ) {
6976			return [];
6977		}
6978		else if ( mixed.nTable && mixed.oApi ) {
6979			// DataTables settings object
6980			return [ mixed ];
6981		}
6982		else if ( mixed.nodeName && mixed.nodeName.toLowerCase() === 'table' ) {
6983			// Table node
6984			idx = $.inArray( mixed, tables );
6985			return idx !== -1 ? [ settings[idx] ] : null;
6986		}
6987		else if ( mixed && typeof mixed.settings === 'function' ) {
6988			return mixed.settings().toArray();
6989		}
6990		else if ( typeof mixed === 'string' ) {
6991			// jQuery selector
6992			jq = $(mixed);
6993		}
6994		else if ( mixed instanceof $ ) {
6995			// jQuery object (also DataTables instance)
6996			jq = mixed;
6997		}
6998
6999		if ( jq ) {
7000			return jq.map( function(i) {
7001				idx = $.inArray( this, tables );
7002				return idx !== -1 ? settings[idx] : null;
7003			} ).toArray();
7004		}
7005	};
7006
7007
7008	/**
7009	 * DataTables API class - used to control and interface with  one or more
7010	 * DataTables enhanced tables.
7011	 *
7012	 * The API class is heavily based on jQuery, presenting a chainable interface
7013	 * that you can use to interact with tables. Each instance of the API class has
7014	 * a "context" - i.e. the tables that it will operate on. This could be a single
7015	 * table, all tables on a page or a sub-set thereof.
7016	 *
7017	 * Additionally the API is designed to allow you to easily work with the data in
7018	 * the tables, retrieving and manipulating it as required. This is done by
7019	 * presenting the API class as an array like interface. The contents of the
7020	 * array depend upon the actions requested by each method (for example
7021	 * `rows().nodes()` will return an array of nodes, while `rows().data()` will
7022	 * return an array of objects or arrays depending upon your table's
7023	 * configuration). The API object has a number of array like methods (`push`,
7024	 * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`,
7025	 * `unique` etc) to assist your working with the data held in a table.
7026	 *
7027	 * Most methods (those which return an Api instance) are chainable, which means
7028	 * the return from a method call also has all of the methods available that the
7029	 * top level object had. For example, these two calls are equivalent:
7030	 *
7031	 *     // Not chained
7032	 *     api.row.add( {...} );
7033	 *     api.draw();
7034	 *
7035	 *     // Chained
7036	 *     api.row.add( {...} ).draw();
7037	 *
7038	 * @class DataTable.Api
7039	 * @param {array|object|string|jQuery} context DataTable identifier. This is
7040	 *   used to define which DataTables enhanced tables this API will operate on.
7041	 *   Can be one of:
7042	 *
7043	 *   * `string` - jQuery selector. Any DataTables' matching the given selector
7044	 *     with be found and used.
7045	 *   * `node` - `TABLE` node which has already been formed into a DataTable.
7046	 *   * `jQuery` - A jQuery object of `TABLE` nodes.
7047	 *   * `object` - DataTables settings object
7048	 * @param {array} [data] Data to initialise the Api instance with.
7049	 *
7050	 * @example
7051	 *   // Direct initialisation during DataTables construction
7052	 *   var api = $('#example').DataTable();
7053	 *
7054	 * @example
7055	 *   // Initialisation using a DataTables jQuery object
7056	 *   var api = $('#example').dataTable().api();
7057	 *
7058	 * @example
7059	 *   // Initialisation as a constructor
7060	 *   var api = new $.fn.DataTable.Api( 'table.dataTable' );
7061	 */
7062	_Api = function ( context, data )
7063	{
7064		if ( ! (this instanceof _Api) ) {
7065			return new _Api( context, data );
7066		}
7067
7068		var settings = [];
7069		var ctxSettings = function ( o ) {
7070			var a = _toSettings( o );
7071			if ( a ) {
7072				settings.push.apply( settings, a );
7073			}
7074		};
7075
7076		if ( Array.isArray( context ) ) {
7077			for ( var i=0, ien=context.length ; i<ien ; i++ ) {
7078				ctxSettings( context[i] );
7079			}
7080		}
7081		else {
7082			ctxSettings( context );
7083		}
7084
7085		// Remove duplicates
7086		this.context = _unique( settings );
7087
7088		// Initial data
7089		if ( data ) {
7090			$.merge( this, data );
7091		}
7092
7093		// selector
7094		this.selector = {
7095			rows: null,
7096			cols: null,
7097			opts: null
7098		};
7099
7100		_Api.extend( this, this, __apiStruct );
7101	};
7102
7103	DataTable.Api = _Api;
7104
7105	// Don't destroy the existing prototype, just extend it. Required for jQuery 2's
7106	// isPlainObject.
7107	$.extend( _Api.prototype, {
7108		any: function ()
7109		{
7110			return this.count() !== 0;
7111		},
7112
7113
7114		concat:  __arrayProto.concat,
7115
7116
7117		context: [], // array of table settings objects
7118
7119
7120		count: function ()
7121		{
7122			return this.flatten().length;
7123		},
7124
7125
7126		each: function ( fn )
7127		{
7128			for ( var i=0, ien=this.length ; i<ien; i++ ) {
7129				fn.call( this, this[i], i, this );
7130			}
7131
7132			return this;
7133		},
7134
7135
7136		eq: function ( idx )
7137		{
7138			var ctx = this.context;
7139
7140			return ctx.length > idx ?
7141				new _Api( ctx[idx], this[idx] ) :
7142				null;
7143		},
7144
7145
7146		filter: function ( fn )
7147		{
7148			var a = [];
7149
7150			if ( __arrayProto.filter ) {
7151				a = __arrayProto.filter.call( this, fn, this );
7152			}
7153			else {
7154				// Compatibility for browsers without EMCA-252-5 (JS 1.6)
7155				for ( var i=0, ien=this.length ; i<ien ; i++ ) {
7156					if ( fn.call( this, this[i], i, this ) ) {
7157						a.push( this[i] );
7158					}
7159				}
7160			}
7161
7162			return new _Api( this.context, a );
7163		},
7164
7165
7166		flatten: function ()
7167		{
7168			var a = [];
7169			return new _Api( this.context, a.concat.apply( a, this.toArray() ) );
7170		},
7171
7172
7173		join:    __arrayProto.join,
7174
7175
7176		indexOf: __arrayProto.indexOf || function (obj, start)
7177		{
7178			for ( var i=(start || 0), ien=this.length ; i<ien ; i++ ) {
7179				if ( this[i] === obj ) {
7180					return i;
7181				}
7182			}
7183			return -1;
7184		},
7185
7186		iterator: function ( flatten, type, fn, alwaysNew ) {
7187			var
7188				a = [], ret,
7189				i, ien, j, jen,
7190				context = this.context,
7191				rows, items, item,
7192				selector = this.selector;
7193
7194			// Argument shifting
7195			if ( typeof flatten === 'string' ) {
7196				alwaysNew = fn;
7197				fn = type;
7198				type = flatten;
7199				flatten = false;
7200			}
7201
7202			for ( i=0, ien=context.length ; i<ien ; i++ ) {
7203				var apiInst = new _Api( context[i] );
7204
7205				if ( type === 'table' ) {
7206					ret = fn.call( apiInst, context[i], i );
7207
7208					if ( ret !== undefined ) {
7209						a.push( ret );
7210					}
7211				}
7212				else if ( type === 'columns' || type === 'rows' ) {
7213					// this has same length as context - one entry for each table
7214					ret = fn.call( apiInst, context[i], this[i], i );
7215
7216					if ( ret !== undefined ) {
7217						a.push( ret );
7218					}
7219				}
7220				else if ( type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell' ) {
7221					// columns and rows share the same structure.
7222					// 'this' is an array of column indexes for each context
7223					items = this[i];
7224
7225					if ( type === 'column-rows' ) {
7226						rows = _selector_row_indexes( context[i], selector.opts );
7227					}
7228
7229					for ( j=0, jen=items.length ; j<jen ; j++ ) {
7230						item = items[j];
7231
7232						if ( type === 'cell' ) {
7233							ret = fn.call( apiInst, context[i], item.row, item.column, i, j );
7234						}
7235						else {
7236							ret = fn.call( apiInst, context[i], item, i, j, rows );
7237						}
7238
7239						if ( ret !== undefined ) {
7240							a.push( ret );
7241						}
7242					}
7243				}
7244			}
7245
7246			if ( a.length || alwaysNew ) {
7247				var api = new _Api( context, flatten ? a.concat.apply( [], a ) : a );
7248				var apiSelector = api.selector;
7249				apiSelector.rows = selector.rows;
7250				apiSelector.cols = selector.cols;
7251				apiSelector.opts = selector.opts;
7252				return api;
7253			}
7254			return this;
7255		},
7256
7257
7258		lastIndexOf: __arrayProto.lastIndexOf || function (obj, start)
7259		{
7260			// Bit cheeky...
7261			return this.indexOf.apply( this.toArray.reverse(), arguments );
7262		},
7263
7264
7265		length:  0,
7266
7267
7268		map: function ( fn )
7269		{
7270			var a = [];
7271
7272			if ( __arrayProto.map ) {
7273				a = __arrayProto.map.call( this, fn, this );
7274			}
7275			else {
7276				// Compatibility for browsers without EMCA-252-5 (JS 1.6)
7277				for ( var i=0, ien=this.length ; i<ien ; i++ ) {
7278					a.push( fn.call( this, this[i], i ) );
7279				}
7280			}
7281
7282			return new _Api( this.context, a );
7283		},
7284
7285
7286		pluck: function ( prop )
7287		{
7288			var fn = DataTable.util.get(prop);
7289
7290			return this.map( function ( el ) {
7291				return fn(el);
7292			} );
7293		},
7294
7295		pop:     __arrayProto.pop,
7296
7297
7298		push:    __arrayProto.push,
7299
7300
7301		// Does not return an API instance
7302		reduce: __arrayProto.reduce || function ( fn, init )
7303		{
7304			return _fnReduce( this, fn, init, 0, this.length, 1 );
7305		},
7306
7307
7308		reduceRight: __arrayProto.reduceRight || function ( fn, init )
7309		{
7310			return _fnReduce( this, fn, init, this.length-1, -1, -1 );
7311		},
7312
7313
7314		reverse: __arrayProto.reverse,
7315
7316
7317		// Object with rows, columns and opts
7318		selector: null,
7319
7320
7321		shift:   __arrayProto.shift,
7322
7323
7324		slice: function () {
7325			return new _Api( this.context, this );
7326		},
7327
7328
7329		sort:    __arrayProto.sort, // ? name - order?
7330
7331
7332		splice:  __arrayProto.splice,
7333
7334
7335		toArray: function ()
7336		{
7337			return __arrayProto.slice.call( this );
7338		},
7339
7340
7341		to$: function ()
7342		{
7343			return $( this );
7344		},
7345
7346
7347		toJQuery: function ()
7348		{
7349			return $( this );
7350		},
7351
7352
7353		unique: function ()
7354		{
7355			return new _Api( this.context, _unique(this) );
7356		},
7357
7358
7359		unshift: __arrayProto.unshift
7360	} );
7361
7362
7363	_Api.extend = function ( scope, obj, ext )
7364	{
7365		// Only extend API instances and static properties of the API
7366		if ( ! ext.length || ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) {
7367			return;
7368		}
7369
7370		var
7371			i, ien,
7372			struct,
7373			methodScoping = function ( scope, fn, struc ) {
7374				return function () {
7375					var ret = fn.apply( scope, arguments );
7376
7377					// Method extension
7378					_Api.extend( ret, ret, struc.methodExt );
7379					return ret;
7380				};
7381			};
7382
7383		for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7384			struct = ext[i];
7385
7386			// Value
7387			obj[ struct.name ] = struct.type === 'function' ?
7388				methodScoping( scope, struct.val, struct ) :
7389				struct.type === 'object' ?
7390					{} :
7391					struct.val;
7392
7393			obj[ struct.name ].__dt_wrapper = true;
7394
7395			// Property extension
7396			_Api.extend( scope, obj[ struct.name ], struct.propExt );
7397		}
7398	};
7399
7400
7401	// @todo - Is there need for an augment function?
7402	// _Api.augment = function ( inst, name )
7403	// {
7404	// 	// Find src object in the structure from the name
7405	// 	var parts = name.split('.');
7406
7407	// 	_Api.extend( inst, obj );
7408	// };
7409
7410
7411	//     [
7412	//       {
7413	//         name:      'data'                -- string   - Property name
7414	//         val:       function () {},       -- function - Api method (or undefined if just an object
7415	//         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
7416	//         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
7417	//       },
7418	//       {
7419	//         name:     'row'
7420	//         val:       {},
7421	//         methodExt: [ ... ],
7422	//         propExt:   [
7423	//           {
7424	//             name:      'data'
7425	//             val:       function () {},
7426	//             methodExt: [ ... ],
7427	//             propExt:   [ ... ]
7428	//           },
7429	//           ...
7430	//         ]
7431	//       }
7432	//     ]
7433
7434	_Api.register = _api_register = function ( name, val )
7435	{
7436		if ( Array.isArray( name ) ) {
7437			for ( var j=0, jen=name.length ; j<jen ; j++ ) {
7438				_Api.register( name[j], val );
7439			}
7440			return;
7441		}
7442
7443		var
7444			i, ien,
7445			heir = name.split('.'),
7446			struct = __apiStruct,
7447			key, method;
7448
7449		var find = function ( src, name ) {
7450			for ( var i=0, ien=src.length ; i<ien ; i++ ) {
7451				if ( src[i].name === name ) {
7452					return src[i];
7453				}
7454			}
7455			return null;
7456		};
7457
7458		for ( i=0, ien=heir.length ; i<ien ; i++ ) {
7459			method = heir[i].indexOf('()') !== -1;
7460			key = method ?
7461				heir[i].replace('()', '') :
7462				heir[i];
7463
7464			var src = find( struct, key );
7465			if ( ! src ) {
7466				src = {
7467					name:      key,
7468					val:       {},
7469					methodExt: [],
7470					propExt:   [],
7471					type:      'object'
7472				};
7473				struct.push( src );
7474			}
7475
7476			if ( i === ien-1 ) {
7477				src.val = val;
7478				src.type = typeof val === 'function' ?
7479					'function' :
7480					$.isPlainObject( val ) ?
7481						'object' :
7482						'other';
7483			}
7484			else {
7485				struct = method ?
7486					src.methodExt :
7487					src.propExt;
7488			}
7489		}
7490	};
7491
7492	_Api.registerPlural = _api_registerPlural = function ( pluralName, singularName, val ) {
7493		_Api.register( pluralName, val );
7494
7495		_Api.register( singularName, function () {
7496			var ret = val.apply( this, arguments );
7497
7498			if ( ret === this ) {
7499				// Returned item is the API instance that was passed in, return it
7500				return this;
7501			}
7502			else if ( ret instanceof _Api ) {
7503				// New API instance returned, want the value from the first item
7504				// in the returned array for the singular result.
7505				return ret.length ?
7506					Array.isArray( ret[0] ) ?
7507						new _Api( ret.context, ret[0] ) : // Array results are 'enhanced'
7508						ret[0] :
7509					undefined;
7510			}
7511
7512			// Non-API return - just fire it back
7513			return ret;
7514		} );
7515	};
7516
7517
7518	/**
7519	 * Selector for HTML tables. Apply the given selector to the give array of
7520	 * DataTables settings objects.
7521	 *
7522	 * @param {string|integer} [selector] jQuery selector string or integer
7523	 * @param  {array} Array of DataTables settings objects to be filtered
7524	 * @return {array}
7525	 * @ignore
7526	 */
7527	var __table_selector = function ( selector, a )
7528	{
7529		if ( Array.isArray(selector) ) {
7530			return $.map( selector, function (item) {
7531				return __table_selector(item, a);
7532			} );
7533		}
7534
7535		// Integer is used to pick out a table by index
7536		if ( typeof selector === 'number' ) {
7537			return [ a[ selector ] ];
7538		}
7539
7540		// Perform a jQuery selector on the table nodes
7541		var nodes = $.map( a, function (el, i) {
7542			return el.nTable;
7543		} );
7544
7545		return $(nodes)
7546			.filter( selector )
7547			.map( function (i) {
7548				// Need to translate back from the table node to the settings
7549				var idx = $.inArray( this, nodes );
7550				return a[ idx ];
7551			} )
7552			.toArray();
7553	};
7554
7555
7556
7557	/**
7558	 * Context selector for the API's context (i.e. the tables the API instance
7559	 * refers to.
7560	 *
7561	 * @name    DataTable.Api#tables
7562	 * @param {string|integer} [selector] Selector to pick which tables the iterator
7563	 *   should operate on. If not given, all tables in the current context are
7564	 *   used. This can be given as a jQuery selector (for example `':gt(0)'`) to
7565	 *   select multiple tables or as an integer to select a single table.
7566	 * @returns {DataTable.Api} Returns a new API instance if a selector is given.
7567	 */
7568	_api_register( 'tables()', function ( selector ) {
7569		// A new instance is created if there was a selector specified
7570		return selector !== undefined && selector !== null ?
7571			new _Api( __table_selector( selector, this.context ) ) :
7572			this;
7573	} );
7574
7575
7576	_api_register( 'table()', function ( selector ) {
7577		var tables = this.tables( selector );
7578		var ctx = tables.context;
7579
7580		// Truncate to the first matched table
7581		return ctx.length ?
7582			new _Api( ctx[0] ) :
7583			tables;
7584	} );
7585
7586
7587	_api_registerPlural( 'tables().nodes()', 'table().node()' , function () {
7588		return this.iterator( 'table', function ( ctx ) {
7589			return ctx.nTable;
7590		}, 1 );
7591	} );
7592
7593
7594	_api_registerPlural( 'tables().body()', 'table().body()' , function () {
7595		return this.iterator( 'table', function ( ctx ) {
7596			return ctx.nTBody;
7597		}, 1 );
7598	} );
7599
7600
7601	_api_registerPlural( 'tables().header()', 'table().header()' , function () {
7602		return this.iterator( 'table', function ( ctx ) {
7603			return ctx.nTHead;
7604		}, 1 );
7605	} );
7606
7607
7608	_api_registerPlural( 'tables().footer()', 'table().footer()' , function () {
7609		return this.iterator( 'table', function ( ctx ) {
7610			return ctx.nTFoot;
7611		}, 1 );
7612	} );
7613
7614
7615	_api_registerPlural( 'tables().containers()', 'table().container()' , function () {
7616		return this.iterator( 'table', function ( ctx ) {
7617			return ctx.nTableWrapper;
7618		}, 1 );
7619	} );
7620
7621
7622
7623	/**
7624	 * Redraw the tables in the current context.
7625	 */
7626	_api_register( 'draw()', function ( paging ) {
7627		return this.iterator( 'table', function ( settings ) {
7628			if ( paging === 'page' ) {
7629				_fnDraw( settings );
7630			}
7631			else {
7632				if ( typeof paging === 'string' ) {
7633					paging = paging === 'full-hold' ?
7634						false :
7635						true;
7636				}
7637
7638				_fnReDraw( settings, paging===false );
7639			}
7640		} );
7641	} );
7642
7643
7644
7645	/**
7646	 * Get the current page index.
7647	 *
7648	 * @return {integer} Current page index (zero based)
7649	 *//**
7650	 * Set the current page.
7651	 *
7652	 * Note that if you attempt to show a page which does not exist, DataTables will
7653	 * not throw an error, but rather reset the paging.
7654	 *
7655	 * @param {integer|string} action The paging action to take. This can be one of:
7656	 *  * `integer` - The page index to jump to
7657	 *  * `string` - An action to take:
7658	 *    * `first` - Jump to first page.
7659	 *    * `next` - Jump to the next page
7660	 *    * `previous` - Jump to previous page
7661	 *    * `last` - Jump to the last page.
7662	 * @returns {DataTables.Api} this
7663	 */
7664	_api_register( 'page()', function ( action ) {
7665		if ( action === undefined ) {
7666			return this.page.info().page; // not an expensive call
7667		}
7668
7669		// else, have an action to take on all tables
7670		return this.iterator( 'table', function ( settings ) {
7671			_fnPageChange( settings, action );
7672		} );
7673	} );
7674
7675
7676	/**
7677	 * Paging information for the first table in the current context.
7678	 *
7679	 * If you require paging information for another table, use the `table()` method
7680	 * with a suitable selector.
7681	 *
7682	 * @return {object} Object with the following properties set:
7683	 *  * `page` - Current page index (zero based - i.e. the first page is `0`)
7684	 *  * `pages` - Total number of pages
7685	 *  * `start` - Display index for the first record shown on the current page
7686	 *  * `end` - Display index for the last record shown on the current page
7687	 *  * `length` - Display length (number of records). Note that generally `start
7688	 *    + length = end`, but this is not always true, for example if there are
7689	 *    only 2 records to show on the final page, with a length of 10.
7690	 *  * `recordsTotal` - Full data set length
7691	 *  * `recordsDisplay` - Data set length once the current filtering criterion
7692	 *    are applied.
7693	 */
7694	_api_register( 'page.info()', function ( action ) {
7695		if ( this.context.length === 0 ) {
7696			return undefined;
7697		}
7698
7699		var
7700			settings   = this.context[0],
7701			start      = settings._iDisplayStart,
7702			len        = settings.oFeatures.bPaginate ? settings._iDisplayLength : -1,
7703			visRecords = settings.fnRecordsDisplay(),
7704			all        = len === -1;
7705
7706		return {
7707			"page":           all ? 0 : Math.floor( start / len ),
7708			"pages":          all ? 1 : Math.ceil( visRecords / len ),
7709			"start":          start,
7710			"end":            settings.fnDisplayEnd(),
7711			"length":         len,
7712			"recordsTotal":   settings.fnRecordsTotal(),
7713			"recordsDisplay": visRecords,
7714			"serverSide":     _fnDataSource( settings ) === 'ssp'
7715		};
7716	} );
7717
7718
7719	/**
7720	 * Get the current page length.
7721	 *
7722	 * @return {integer} Current page length. Note `-1` indicates that all records
7723	 *   are to be shown.
7724	 *//**
7725	 * Set the current page length.
7726	 *
7727	 * @param {integer} Page length to set. Use `-1` to show all records.
7728	 * @returns {DataTables.Api} this
7729	 */
7730	_api_register( 'page.len()', function ( len ) {
7731		// Note that we can't call this function 'length()' because `length`
7732		// is a Javascript property of functions which defines how many arguments
7733		// the function expects.
7734		if ( len === undefined ) {
7735			return this.context.length !== 0 ?
7736				this.context[0]._iDisplayLength :
7737				undefined;
7738		}
7739
7740		// else, set the page length
7741		return this.iterator( 'table', function ( settings ) {
7742			_fnLengthChange( settings, len );
7743		} );
7744	} );
7745
7746
7747
7748	var __reload = function ( settings, holdPosition, callback ) {
7749		// Use the draw event to trigger a callback
7750		if ( callback ) {
7751			var api = new _Api( settings );
7752
7753			api.one( 'draw', function () {
7754				callback( api.ajax.json() );
7755			} );
7756		}
7757
7758		if ( _fnDataSource( settings ) == 'ssp' ) {
7759			_fnReDraw( settings, holdPosition );
7760		}
7761		else {
7762			_fnProcessingDisplay( settings, true );
7763
7764			// Cancel an existing request
7765			var xhr = settings.jqXHR;
7766			if ( xhr && xhr.readyState !== 4 ) {
7767				xhr.abort();
7768			}
7769
7770			// Trigger xhr
7771			_fnBuildAjax( settings, [], function( json ) {
7772				_fnClearTable( settings );
7773
7774				var data = _fnAjaxDataSrc( settings, json );
7775				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7776					_fnAddData( settings, data[i] );
7777				}
7778
7779				_fnReDraw( settings, holdPosition );
7780				_fnProcessingDisplay( settings, false );
7781			} );
7782		}
7783	};
7784
7785
7786	/**
7787	 * Get the JSON response from the last Ajax request that DataTables made to the
7788	 * server. Note that this returns the JSON from the first table in the current
7789	 * context.
7790	 *
7791	 * @return {object} JSON received from the server.
7792	 */
7793	_api_register( 'ajax.json()', function () {
7794		var ctx = this.context;
7795
7796		if ( ctx.length > 0 ) {
7797			return ctx[0].json;
7798		}
7799
7800		// else return undefined;
7801	} );
7802
7803
7804	/**
7805	 * Get the data submitted in the last Ajax request
7806	 */
7807	_api_register( 'ajax.params()', function () {
7808		var ctx = this.context;
7809
7810		if ( ctx.length > 0 ) {
7811			return ctx[0].oAjaxData;
7812		}
7813
7814		// else return undefined;
7815	} );
7816
7817
7818	/**
7819	 * Reload tables from the Ajax data source. Note that this function will
7820	 * automatically re-draw the table when the remote data has been loaded.
7821	 *
7822	 * @param {boolean} [reset=true] Reset (default) or hold the current paging
7823	 *   position. A full re-sort and re-filter is performed when this method is
7824	 *   called, which is why the pagination reset is the default action.
7825	 * @returns {DataTables.Api} this
7826	 */
7827	_api_register( 'ajax.reload()', function ( callback, resetPaging ) {
7828		return this.iterator( 'table', function (settings) {
7829			__reload( settings, resetPaging===false, callback );
7830		} );
7831	} );
7832
7833
7834	/**
7835	 * Get the current Ajax URL. Note that this returns the URL from the first
7836	 * table in the current context.
7837	 *
7838	 * @return {string} Current Ajax source URL
7839	 *//**
7840	 * Set the Ajax URL. Note that this will set the URL for all tables in the
7841	 * current context.
7842	 *
7843	 * @param {string} url URL to set.
7844	 * @returns {DataTables.Api} this
7845	 */
7846	_api_register( 'ajax.url()', function ( url ) {
7847		var ctx = this.context;
7848
7849		if ( url === undefined ) {
7850			// get
7851			if ( ctx.length === 0 ) {
7852				return undefined;
7853			}
7854			ctx = ctx[0];
7855
7856			return ctx.ajax ?
7857				$.isPlainObject( ctx.ajax ) ?
7858					ctx.ajax.url :
7859					ctx.ajax :
7860				ctx.sAjaxSource;
7861		}
7862
7863		// set
7864		return this.iterator( 'table', function ( settings ) {
7865			if ( $.isPlainObject( settings.ajax ) ) {
7866				settings.ajax.url = url;
7867			}
7868			else {
7869				settings.ajax = url;
7870			}
7871			// No need to consider sAjaxSource here since DataTables gives priority
7872			// to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any
7873			// value of `sAjaxSource` redundant.
7874		} );
7875	} );
7876
7877
7878	/**
7879	 * Load data from the newly set Ajax URL. Note that this method is only
7880	 * available when `ajax.url()` is used to set a URL. Additionally, this method
7881	 * has the same effect as calling `ajax.reload()` but is provided for
7882	 * convenience when setting a new URL. Like `ajax.reload()` it will
7883	 * automatically redraw the table once the remote data has been loaded.
7884	 *
7885	 * @returns {DataTables.Api} this
7886	 */
7887	_api_register( 'ajax.url().load()', function ( callback, resetPaging ) {
7888		// Same as a reload, but makes sense to present it for easy access after a
7889		// url change
7890		return this.iterator( 'table', function ( ctx ) {
7891			__reload( ctx, resetPaging===false, callback );
7892		} );
7893	} );
7894
7895
7896
7897
7898	var _selector_run = function ( type, selector, selectFn, settings, opts )
7899	{
7900		var
7901			out = [], res,
7902			a, i, ien, j, jen,
7903			selectorType = typeof selector;
7904
7905		// Can't just check for isArray here, as an API or jQuery instance might be
7906		// given with their array like look
7907		if ( ! selector || selectorType === 'string' || selectorType === 'function' || selector.length === undefined ) {
7908			selector = [ selector ];
7909		}
7910
7911		for ( i=0, ien=selector.length ; i<ien ; i++ ) {
7912			// Only split on simple strings - complex expressions will be jQuery selectors
7913			a = selector[i] && selector[i].split && ! selector[i].match(/[\[\(:]/) ?
7914				selector[i].split(',') :
7915				[ selector[i] ];
7916
7917			for ( j=0, jen=a.length ; j<jen ; j++ ) {
7918				res = selectFn( typeof a[j] === 'string' ? (a[j]).trim() : a[j] );
7919
7920				if ( res && res.length ) {
7921					out = out.concat( res );
7922				}
7923			}
7924		}
7925
7926		// selector extensions
7927		var ext = _ext.selector[ type ];
7928		if ( ext.length ) {
7929			for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7930				out = ext[i]( settings, opts, out );
7931			}
7932		}
7933
7934		return _unique( out );
7935	};
7936
7937
7938	var _selector_opts = function ( opts )
7939	{
7940		if ( ! opts ) {
7941			opts = {};
7942		}
7943
7944		// Backwards compatibility for 1.9- which used the terminology filter rather
7945		// than search
7946		if ( opts.filter && opts.search === undefined ) {
7947			opts.search = opts.filter;
7948		}
7949
7950		return $.extend( {
7951			search: 'none',
7952			order: 'current',
7953			page: 'all'
7954		}, opts );
7955	};
7956
7957
7958	var _selector_first = function ( inst )
7959	{
7960		// Reduce the API instance to the first item found
7961		for ( var i=0, ien=inst.length ; i<ien ; i++ ) {
7962			if ( inst[i].length > 0 ) {
7963				// Assign the first element to the first item in the instance
7964				// and truncate the instance and context
7965				inst[0] = inst[i];
7966				inst[0].length = 1;
7967				inst.length = 1;
7968				inst.context = [ inst.context[i] ];
7969
7970				return inst;
7971			}
7972		}
7973
7974		// Not found - return an empty instance
7975		inst.length = 0;
7976		return inst;
7977	};
7978
7979
7980	var _selector_row_indexes = function ( settings, opts )
7981	{
7982		var
7983			i, ien, tmp, a=[],
7984			displayFiltered = settings.aiDisplay,
7985			displayMaster = settings.aiDisplayMaster;
7986
7987		var
7988			search = opts.search,  // none, applied, removed
7989			order  = opts.order,   // applied, current, index (original - compatibility with 1.9)
7990			page   = opts.page;    // all, current
7991
7992		if ( _fnDataSource( settings ) == 'ssp' ) {
7993			// In server-side processing mode, most options are irrelevant since
7994			// rows not shown don't exist and the index order is the applied order
7995			// Removed is a special case - for consistency just return an empty
7996			// array
7997			return search === 'removed' ?
7998				[] :
7999				_range( 0, displayMaster.length );
8000		}
8001		else if ( page == 'current' ) {
8002			// Current page implies that order=current and filter=applied, since it is
8003			// fairly senseless otherwise, regardless of what order and search actually
8004			// are
8005			for ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i<ien ; i++ ) {
8006				a.push( displayFiltered[i] );
8007			}
8008		}
8009		else if ( order == 'current' || order == 'applied' ) {
8010			if ( search == 'none') {
8011				a = displayMaster.slice();
8012			}
8013			else if ( search == 'applied' ) {
8014				a = displayFiltered.slice();
8015			}
8016			else if ( search == 'removed' ) {
8017				// O(n+m) solution by creating a hash map
8018				var displayFilteredMap = {};
8019
8020				for ( var i=0, ien=displayFiltered.length ; i<ien ; i++ ) {
8021					displayFilteredMap[displayFiltered[i]] = null;
8022				}
8023
8024				a = $.map( displayMaster, function (el) {
8025					return ! displayFilteredMap.hasOwnProperty(el) ?
8026						el :
8027						null;
8028				} );
8029			}
8030		}
8031		else if ( order == 'index' || order == 'original' ) {
8032			for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
8033				if ( search == 'none' ) {
8034					a.push( i );
8035				}
8036				else { // applied | removed
8037					tmp = $.inArray( i, displayFiltered );
8038
8039					if ((tmp === -1 && search == 'removed') ||
8040						(tmp >= 0   && search == 'applied') )
8041					{
8042						a.push( i );
8043					}
8044				}
8045			}
8046		}
8047
8048		return a;
8049	};
8050
8051
8052	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
8053	 * Rows
8054	 *
8055	 * {}          - no selector - use all available rows
8056	 * {integer}   - row aoData index
8057	 * {node}      - TR node
8058	 * {string}    - jQuery selector to apply to the TR elements
8059	 * {array}     - jQuery array of nodes, or simply an array of TR nodes
8060	 *
8061	 */
8062	var __row_selector = function ( settings, selector, opts )
8063	{
8064		var rows;
8065		var run = function ( sel ) {
8066			var selInt = _intVal( sel );
8067			var i, ien;
8068			var aoData = settings.aoData;
8069
8070			// Short cut - selector is a number and no options provided (default is
8071			// all records, so no need to check if the index is in there, since it
8072			// must be - dev error if the index doesn't exist).
8073			if ( selInt !== null && ! opts ) {
8074				return [ selInt ];
8075			}
8076
8077			if ( ! rows ) {
8078				rows = _selector_row_indexes( settings, opts );
8079			}
8080
8081			if ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) {
8082				// Selector - integer
8083				return [ selInt ];
8084			}
8085			else if ( sel === null || sel === undefined || sel === '' ) {
8086				// Selector - none
8087				return rows;
8088			}
8089
8090			// Selector - function
8091			if ( typeof sel === 'function' ) {
8092				return $.map( rows, function (idx) {
8093					var row = aoData[ idx ];
8094					return sel( idx, row._aData, row.nTr ) ? idx : null;
8095				} );
8096			}
8097
8098			// Selector - node
8099			if ( sel.nodeName ) {
8100				var rowIdx = sel._DT_RowIndex;  // Property added by DT for fast lookup
8101				var cellIdx = sel._DT_CellIndex;
8102
8103				if ( rowIdx !== undefined ) {
8104					// Make sure that the row is actually still present in the table
8105					return aoData[ rowIdx ] && aoData[ rowIdx ].nTr === sel ?
8106						[ rowIdx ] :
8107						[];
8108				}
8109				else if ( cellIdx ) {
8110					return aoData[ cellIdx.row ] && aoData[ cellIdx.row ].nTr === sel.parentNode ?
8111						[ cellIdx.row ] :
8112						[];
8113				}
8114				else {
8115					var host = $(sel).closest('*[data-dt-row]');
8116					return host.length ?
8117						[ host.data('dt-row') ] :
8118						[];
8119				}
8120			}
8121
8122			// ID selector. Want to always be able to select rows by id, regardless
8123			// of if the tr element has been created or not, so can't rely upon
8124			// jQuery here - hence a custom implementation. This does not match
8125			// Sizzle's fast selector or HTML4 - in HTML5 the ID can be anything,
8126			// but to select it using a CSS selector engine (like Sizzle or
8127			// querySelect) it would need to need to be escaped for some characters.
8128			// DataTables simplifies this for row selectors since you can select
8129			// only a row. A # indicates an id any anything that follows is the id -
8130			// unescaped.
8131			if ( typeof sel === 'string' && sel.charAt(0) === '#' ) {
8132				// get row index from id
8133				var rowObj = settings.aIds[ sel.replace( /^#/, '' ) ];
8134				if ( rowObj !== undefined ) {
8135					return [ rowObj.idx ];
8136				}
8137
8138				// need to fall through to jQuery in case there is DOM id that
8139				// matches
8140			}
8141
8142			// Get nodes in the order from the `rows` array with null values removed
8143			var nodes = _removeEmpty(
8144				_pluck_order( settings.aoData, rows, 'nTr' )
8145			);
8146
8147			// Selector - jQuery selector string, array of nodes or jQuery object/
8148			// As jQuery's .filter() allows jQuery objects to be passed in filter,
8149			// it also allows arrays, so this will cope with all three options
8150			return $(nodes)
8151				.filter( sel )
8152				.map( function () {
8153					return this._DT_RowIndex;
8154				} )
8155				.toArray();
8156		};
8157
8158		return _selector_run( 'row', selector, run, settings, opts );
8159	};
8160
8161
8162	_api_register( 'rows()', function ( selector, opts ) {
8163		// argument shifting
8164		if ( selector === undefined ) {
8165			selector = '';
8166		}
8167		else if ( $.isPlainObject( selector ) ) {
8168			opts = selector;
8169			selector = '';
8170		}
8171
8172		opts = _selector_opts( opts );
8173
8174		var inst = this.iterator( 'table', function ( settings ) {
8175			return __row_selector( settings, selector, opts );
8176		}, 1 );
8177
8178		// Want argument shifting here and in __row_selector?
8179		inst.selector.rows = selector;
8180		inst.selector.opts = opts;
8181
8182		return inst;
8183	} );
8184
8185	_api_register( 'rows().nodes()', function () {
8186		return this.iterator( 'row', function ( settings, row ) {
8187			return settings.aoData[ row ].nTr || undefined;
8188		}, 1 );
8189	} );
8190
8191	_api_register( 'rows().data()', function () {
8192		return this.iterator( true, 'rows', function ( settings, rows ) {
8193			return _pluck_order( settings.aoData, rows, '_aData' );
8194		}, 1 );
8195	} );
8196
8197	_api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) {
8198		return this.iterator( 'row', function ( settings, row ) {
8199			var r = settings.aoData[ row ];
8200			return type === 'search' ? r._aFilterData : r._aSortData;
8201		}, 1 );
8202	} );
8203
8204	_api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) {
8205		return this.iterator( 'row', function ( settings, row ) {
8206			_fnInvalidate( settings, row, src );
8207		} );
8208	} );
8209
8210	_api_registerPlural( 'rows().indexes()', 'row().index()', function () {
8211		return this.iterator( 'row', function ( settings, row ) {
8212			return row;
8213		}, 1 );
8214	} );
8215
8216	_api_registerPlural( 'rows().ids()', 'row().id()', function ( hash ) {
8217		var a = [];
8218		var context = this.context;
8219
8220		// `iterator` will drop undefined values, but in this case we want them
8221		for ( var i=0, ien=context.length ; i<ien ; i++ ) {
8222			for ( var j=0, jen=this[i].length ; j<jen ; j++ ) {
8223				var id = context[i].rowIdFn( context[i].aoData[ this[i][j] ]._aData );
8224				a.push( (hash === true ? '#' : '' )+ id );
8225			}
8226		}
8227
8228		return new _Api( context, a );
8229	} );
8230
8231	_api_registerPlural( 'rows().remove()', 'row().remove()', function () {
8232		var that = this;
8233
8234		this.iterator( 'row', function ( settings, row, thatIdx ) {
8235			var data = settings.aoData;
8236			var rowData = data[ row ];
8237			var i, ien, j, jen;
8238			var loopRow, loopCells;
8239
8240			data.splice( row, 1 );
8241
8242			// Update the cached indexes
8243			for ( i=0, ien=data.length ; i<ien ; i++ ) {
8244				loopRow = data[i];
8245				loopCells = loopRow.anCells;
8246
8247				// Rows
8248				if ( loopRow.nTr !== null ) {
8249					loopRow.nTr._DT_RowIndex = i;
8250				}
8251
8252				// Cells
8253				if ( loopCells !== null ) {
8254					for ( j=0, jen=loopCells.length ; j<jen ; j++ ) {
8255						loopCells[j]._DT_CellIndex.row = i;
8256					}
8257				}
8258			}
8259
8260			// Delete from the display arrays
8261			_fnDeleteIndex( settings.aiDisplayMaster, row );
8262			_fnDeleteIndex( settings.aiDisplay, row );
8263			_fnDeleteIndex( that[ thatIdx ], row, false ); // maintain local indexes
8264
8265			// For server-side processing tables - subtract the deleted row from the count
8266			if ( settings._iRecordsDisplay > 0 ) {
8267				settings._iRecordsDisplay--;
8268			}
8269
8270			// Check for an 'overflow' they case for displaying the table
8271			_fnLengthOverflow( settings );
8272
8273			// Remove the row's ID reference if there is one
8274			var id = settings.rowIdFn( rowData._aData );
8275			if ( id !== undefined ) {
8276				delete settings.aIds[ id ];
8277			}
8278		} );
8279
8280		this.iterator( 'table', function ( settings ) {
8281			for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
8282				settings.aoData[i].idx = i;
8283			}
8284		} );
8285
8286		return this;
8287	} );
8288
8289
8290	_api_register( 'rows.add()', function ( rows ) {
8291		var newRows = this.iterator( 'table', function ( settings ) {
8292				var row, i, ien;
8293				var out = [];
8294
8295				for ( i=0, ien=rows.length ; i<ien ; i++ ) {
8296					row = rows[i];
8297
8298					if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
8299						out.push( _fnAddTr( settings, row )[0] );
8300					}
8301					else {
8302						out.push( _fnAddData( settings, row ) );
8303					}
8304				}
8305
8306				return out;
8307			}, 1 );
8308
8309		// Return an Api.rows() extended instance, so rows().nodes() etc can be used
8310		var modRows = this.rows( -1 );
8311		modRows.pop();
8312		$.merge( modRows, newRows );
8313
8314		return modRows;
8315	} );
8316
8317
8318
8319
8320
8321	/**
8322	 *
8323	 */
8324	_api_register( 'row()', function ( selector, opts ) {
8325		return _selector_first( this.rows( selector, opts ) );
8326	} );
8327
8328
8329	_api_register( 'row().data()', function ( data ) {
8330		var ctx = this.context;
8331
8332		if ( data === undefined ) {
8333			// Get
8334			return ctx.length && this.length ?
8335				ctx[0].aoData[ this[0] ]._aData :
8336				undefined;
8337		}
8338
8339		// Set
8340		var row = ctx[0].aoData[ this[0] ];
8341		row._aData = data;
8342
8343		// If the DOM has an id, and the data source is an array
8344		if ( Array.isArray( data ) && row.nTr && row.nTr.id ) {
8345			_fnSetObjectDataFn( ctx[0].rowId )( data, row.nTr.id );
8346		}
8347
8348		// Automatically invalidate
8349		_fnInvalidate( ctx[0], this[0], 'data' );
8350
8351		return this;
8352	} );
8353
8354
8355	_api_register( 'row().node()', function () {
8356		var ctx = this.context;
8357
8358		return ctx.length && this.length ?
8359			ctx[0].aoData[ this[0] ].nTr || null :
8360			null;
8361	} );
8362
8363
8364	_api_register( 'row.add()', function ( row ) {
8365		// Allow a jQuery object to be passed in - only a single row is added from
8366		// it though - the first element in the set
8367		if ( row instanceof $ && row.length ) {
8368			row = row[0];
8369		}
8370
8371		var rows = this.iterator( 'table', function ( settings ) {
8372			if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
8373				return _fnAddTr( settings, row )[0];
8374			}
8375			return _fnAddData( settings, row );
8376		} );
8377
8378		// Return an Api.rows() extended instance, with the newly added row selected
8379		return this.row( rows[0] );
8380	} );
8381
8382
8383	$(document).on('plugin-init.dt', function (e, context) {
8384		var api = new _Api( context );
8385		var namespace = 'on-plugin-init';
8386		var stateSaveParamsEvent = 'stateSaveParams.' + namespace;
8387		var destroyEvent = 'destroy. ' + namespace;
8388
8389		api.on( stateSaveParamsEvent, function ( e, settings, d ) {
8390			// This could be more compact with the API, but it is a lot faster as a simple
8391			// internal loop
8392			var idFn = settings.rowIdFn;
8393			var data = settings.aoData;
8394			var ids = [];
8395
8396			for (var i=0 ; i<data.length ; i++) {
8397				if (data[i]._detailsShow) {
8398					ids.push( '#' + idFn(data[i]._aData) );
8399				}
8400			}
8401
8402			d.childRows = ids;
8403		});
8404
8405		api.on( destroyEvent, function () {
8406			api.off(stateSaveParamsEvent + ' ' + destroyEvent);
8407		});
8408
8409		var loaded = api.state.loaded();
8410
8411		if ( loaded && loaded.childRows ) {
8412			api
8413				.rows( $.map(loaded.childRows, function (id){
8414					return id.replace(/:/g, '\\:')
8415				}) )
8416				.every( function () {
8417					_fnCallbackFire( context, null, 'requestChild', [ this ] )
8418				});
8419		}
8420	});
8421
8422	var __details_add = function ( ctx, row, data, klass )
8423	{
8424		// Convert to array of TR elements
8425		var rows = [];
8426		var addRow = function ( r, k ) {
8427			// Recursion to allow for arrays of jQuery objects
8428			if ( Array.isArray( r ) || r instanceof $ ) {
8429				for ( var i=0, ien=r.length ; i<ien ; i++ ) {
8430					addRow( r[i], k );
8431				}
8432				return;
8433			}
8434
8435			// If we get a TR element, then just add it directly - up to the dev
8436			// to add the correct number of columns etc
8437			if ( r.nodeName && r.nodeName.toLowerCase() === 'tr' ) {
8438				rows.push( r );
8439			}
8440			else {
8441				// Otherwise create a row with a wrapper
8442				var created = $('<tr><td></td></tr>').addClass( k );
8443				$('td', created)
8444					.addClass( k )
8445					.html( r )
8446					[0].colSpan = _fnVisbleColumns( ctx );
8447
8448				rows.push( created[0] );
8449			}
8450		};
8451
8452		addRow( data, klass );
8453
8454		if ( row._details ) {
8455			row._details.detach();
8456		}
8457
8458		row._details = $(rows);
8459
8460		// If the children were already shown, that state should be retained
8461		if ( row._detailsShow ) {
8462			row._details.insertAfter( row.nTr );
8463		}
8464	};
8465
8466
8467	// Make state saving of child row details async to allow them to be batch processed
8468	var __details_state = DataTable.util.throttle(
8469		function (ctx) {
8470			_fnSaveState( ctx[0] )
8471		},
8472		500
8473	);
8474
8475
8476	var __details_remove = function ( api, idx )
8477	{
8478		var ctx = api.context;
8479
8480		if ( ctx.length ) {
8481			var row = ctx[0].aoData[ idx !== undefined ? idx : api[0] ];
8482
8483			if ( row && row._details ) {
8484				row._details.remove();
8485
8486				row._detailsShow = undefined;
8487				row._details = undefined;
8488				$( row.nTr ).removeClass( 'dt-hasChild' );
8489				__details_state( ctx );
8490			}
8491		}
8492	};
8493
8494
8495	var __details_display = function ( api, show ) {
8496		var ctx = api.context;
8497
8498		if ( ctx.length && api.length ) {
8499			var row = ctx[0].aoData[ api[0] ];
8500
8501			if ( row._details ) {
8502				row._detailsShow = show;
8503
8504				if ( show ) {
8505					row._details.insertAfter( row.nTr );
8506					$( row.nTr ).addClass( 'dt-hasChild' );
8507				}
8508				else {
8509					row._details.detach();
8510					$( row.nTr ).removeClass( 'dt-hasChild' );
8511				}
8512
8513				_fnCallbackFire( ctx[0], null, 'childRow', [ show, api.row( api[0] ) ] )
8514
8515				__details_events( ctx[0] );
8516				__details_state( ctx );
8517			}
8518		}
8519	};
8520
8521
8522	var __details_events = function ( settings )
8523	{
8524		var api = new _Api( settings );
8525		var namespace = '.dt.DT_details';
8526		var drawEvent = 'draw'+namespace;
8527		var colvisEvent = 'column-sizing'+namespace;
8528		var destroyEvent = 'destroy'+namespace;
8529		var data = settings.aoData;
8530
8531		api.off( drawEvent +' '+ colvisEvent +' '+ destroyEvent );
8532
8533		if ( _pluck( data, '_details' ).length > 0 ) {
8534			// On each draw, insert the required elements into the document
8535			api.on( drawEvent, function ( e, ctx ) {
8536				if ( settings !== ctx ) {
8537					return;
8538				}
8539
8540				api.rows( {page:'current'} ).eq(0).each( function (idx) {
8541					// Internal data grab
8542					var row = data[ idx ];
8543
8544					if ( row._detailsShow ) {
8545						row._details.insertAfter( row.nTr );
8546					}
8547				} );
8548			} );
8549
8550			// Column visibility change - update the colspan
8551			api.on( colvisEvent, function ( e, ctx, idx, vis ) {
8552				if ( settings !== ctx ) {
8553					return;
8554				}
8555
8556				// Update the colspan for the details rows (note, only if it already has
8557				// a colspan)
8558				var row, visible = _fnVisbleColumns( ctx );
8559
8560				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
8561					row = data[i];
8562
8563					if ( row._details ) {
8564						row._details.children('td[colspan]').attr('colspan', visible );
8565					}
8566				}
8567			} );
8568
8569			// Table destroyed - nuke any child rows
8570			api.on( destroyEvent, function ( e, ctx ) {
8571				if ( settings !== ctx ) {
8572					return;
8573				}
8574
8575				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
8576					if ( data[i]._details ) {
8577						__details_remove( api, i );
8578					}
8579				}
8580			} );
8581		}
8582	};
8583
8584	// Strings for the method names to help minification
8585	var _emp = '';
8586	var _child_obj = _emp+'row().child';
8587	var _child_mth = _child_obj+'()';
8588
8589	// data can be:
8590	//  tr
8591	//  string
8592	//  jQuery or array of any of the above
8593	_api_register( _child_mth, function ( data, klass ) {
8594		var ctx = this.context;
8595
8596		if ( data === undefined ) {
8597			// get
8598			return ctx.length && this.length ?
8599				ctx[0].aoData[ this[0] ]._details :
8600				undefined;
8601		}
8602		else if ( data === true ) {
8603			// show
8604			this.child.show();
8605		}
8606		else if ( data === false ) {
8607			// remove
8608			__details_remove( this );
8609		}
8610		else if ( ctx.length && this.length ) {
8611			// set
8612			__details_add( ctx[0], ctx[0].aoData[ this[0] ], data, klass );
8613		}
8614
8615		return this;
8616	} );
8617
8618
8619	_api_register( [
8620		_child_obj+'.show()',
8621		_child_mth+'.show()' // only when `child()` was called with parameters (without
8622	], function ( show ) {   // it returns an object and this method is not executed)
8623		__details_display( this, true );
8624		return this;
8625	} );
8626
8627
8628	_api_register( [
8629		_child_obj+'.hide()',
8630		_child_mth+'.hide()' // only when `child()` was called with parameters (without
8631	], function () {         // it returns an object and this method is not executed)
8632		__details_display( this, false );
8633		return this;
8634	} );
8635
8636
8637	_api_register( [
8638		_child_obj+'.remove()',
8639		_child_mth+'.remove()' // only when `child()` was called with parameters (without
8640	], function () {           // it returns an object and this method is not executed)
8641		__details_remove( this );
8642		return this;
8643	} );
8644
8645
8646	_api_register( _child_obj+'.isShown()', function () {
8647		var ctx = this.context;
8648
8649		if ( ctx.length && this.length ) {
8650			// _detailsShown as false or undefined will fall through to return false
8651			return ctx[0].aoData[ this[0] ]._detailsShow || false;
8652		}
8653		return false;
8654	} );
8655
8656
8657
8658	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
8659	 * Columns
8660	 *
8661	 * {integer}           - column index (>=0 count from left, <0 count from right)
8662	 * "{integer}:visIdx"  - visible column index (i.e. translate to column index)  (>=0 count from left, <0 count from right)
8663	 * "{integer}:visible" - alias for {integer}:visIdx  (>=0 count from left, <0 count from right)
8664	 * "{string}:name"     - column name
8665	 * "{string}"          - jQuery selector on column header nodes
8666	 *
8667	 */
8668
8669	// can be an array of these items, comma separated list, or an array of comma
8670	// separated lists
8671
8672	var __re_column_selector = /^([^:]+):(name|visIdx|visible)$/;
8673
8674
8675	// r1 and r2 are redundant - but it means that the parameters match for the
8676	// iterator callback in columns().data()
8677	var __columnData = function ( settings, column, r1, r2, rows ) {
8678		var a = [];
8679		for ( var row=0, ien=rows.length ; row<ien ; row++ ) {
8680			a.push( _fnGetCellData( settings, rows[row], column ) );
8681		}
8682		return a;
8683	};
8684
8685
8686	var __column_selector = function ( settings, selector, opts )
8687	{
8688		var
8689			columns = settings.aoColumns,
8690			names = _pluck( columns, 'sName' ),
8691			nodes = _pluck( columns, 'nTh' );
8692
8693		var run = function ( s ) {
8694			var selInt = _intVal( s );
8695
8696			// Selector - all
8697			if ( s === '' ) {
8698				return _range( columns.length );
8699			}
8700
8701			// Selector - index
8702			if ( selInt !== null ) {
8703				return [ selInt >= 0 ?
8704					selInt : // Count from left
8705					columns.length + selInt // Count from right (+ because its a negative value)
8706				];
8707			}
8708
8709			// Selector = function
8710			if ( typeof s === 'function' ) {
8711				var rows = _selector_row_indexes( settings, opts );
8712
8713				return $.map( columns, function (col, idx) {
8714					return s(
8715							idx,
8716							__columnData( settings, idx, 0, 0, rows ),
8717							nodes[ idx ]
8718						) ? idx : null;
8719				} );
8720			}
8721
8722			// jQuery or string selector
8723			var match = typeof s === 'string' ?
8724				s.match( __re_column_selector ) :
8725				'';
8726
8727			if ( match ) {
8728				switch( match[2] ) {
8729					case 'visIdx':
8730					case 'visible':
8731						var idx = parseInt( match[1], 10 );
8732						// Visible index given, convert to column index
8733						if ( idx < 0 ) {
8734							// Counting from the right
8735							var visColumns = $.map( columns, function (col,i) {
8736								return col.bVisible ? i : null;
8737							} );
8738							return [ visColumns[ visColumns.length + idx ] ];
8739						}
8740						// Counting from the left
8741						return [ _fnVisibleToColumnIndex( settings, idx ) ];
8742
8743					case 'name':
8744						// match by name. `names` is column index complete and in order
8745						return $.map( names, function (name, i) {
8746							return name === match[1] ? i : null;
8747						} );
8748
8749					default:
8750						return [];
8751				}
8752			}
8753
8754			// Cell in the table body
8755			if ( s.nodeName && s._DT_CellIndex ) {
8756				return [ s._DT_CellIndex.column ];
8757			}
8758
8759			// jQuery selector on the TH elements for the columns
8760			var jqResult = $( nodes )
8761				.filter( s )
8762				.map( function () {
8763					return $.inArray( this, nodes ); // `nodes` is column index complete and in order
8764				} )
8765				.toArray();
8766
8767			if ( jqResult.length || ! s.nodeName ) {
8768				return jqResult;
8769			}
8770
8771			// Otherwise a node which might have a `dt-column` data attribute, or be
8772			// a child or such an element
8773			var host = $(s).closest('*[data-dt-column]');
8774			return host.length ?
8775				[ host.data('dt-column') ] :
8776				[];
8777		};
8778
8779		return _selector_run( 'column', selector, run, settings, opts );
8780	};
8781
8782
8783	var __setColumnVis = function ( settings, column, vis ) {
8784		var
8785			cols = settings.aoColumns,
8786			col  = cols[ column ],
8787			data = settings.aoData,
8788			row, cells, i, ien, tr;
8789
8790		// Get
8791		if ( vis === undefined ) {
8792			return col.bVisible;
8793		}
8794
8795		// Set
8796		// No change
8797		if ( col.bVisible === vis ) {
8798			return;
8799		}
8800
8801		if ( vis ) {
8802			// Insert column
8803			// Need to decide if we should use appendChild or insertBefore
8804			var insertBefore = $.inArray( true, _pluck(cols, 'bVisible'), column+1 );
8805
8806			for ( i=0, ien=data.length ; i<ien ; i++ ) {
8807				tr = data[i].nTr;
8808				cells = data[i].anCells;
8809
8810				if ( tr ) {
8811					// insertBefore can act like appendChild if 2nd arg is null
8812					tr.insertBefore( cells[ column ], cells[ insertBefore ] || null );
8813				}
8814			}
8815		}
8816		else {
8817			// Remove column
8818			$( _pluck( settings.aoData, 'anCells', column ) ).detach();
8819		}
8820
8821		// Common actions
8822		col.bVisible = vis;
8823	};
8824
8825
8826	_api_register( 'columns()', function ( selector, opts ) {
8827		// argument shifting
8828		if ( selector === undefined ) {
8829			selector = '';
8830		}
8831		else if ( $.isPlainObject( selector ) ) {
8832			opts = selector;
8833			selector = '';
8834		}
8835
8836		opts = _selector_opts( opts );
8837
8838		var inst = this.iterator( 'table', function ( settings ) {
8839			return __column_selector( settings, selector, opts );
8840		}, 1 );
8841
8842		// Want argument shifting here and in _row_selector?
8843		inst.selector.cols = selector;
8844		inst.selector.opts = opts;
8845
8846		return inst;
8847	} );
8848
8849	_api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) {
8850		return this.iterator( 'column', function ( settings, column ) {
8851			return settings.aoColumns[column].nTh;
8852		}, 1 );
8853	} );
8854
8855	_api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) {
8856		return this.iterator( 'column', function ( settings, column ) {
8857			return settings.aoColumns[column].nTf;
8858		}, 1 );
8859	} );
8860
8861	_api_registerPlural( 'columns().data()', 'column().data()', function () {
8862		return this.iterator( 'column-rows', __columnData, 1 );
8863	} );
8864
8865	_api_registerPlural( 'columns().dataSrc()', 'column().dataSrc()', function () {
8866		return this.iterator( 'column', function ( settings, column ) {
8867			return settings.aoColumns[column].mData;
8868		}, 1 );
8869	} );
8870
8871	_api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) {
8872		return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8873			return _pluck_order( settings.aoData, rows,
8874				type === 'search' ? '_aFilterData' : '_aSortData', column
8875			);
8876		}, 1 );
8877	} );
8878
8879	_api_registerPlural( 'columns().nodes()', 'column().nodes()', function () {
8880		return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8881			return _pluck_order( settings.aoData, rows, 'anCells', column ) ;
8882		}, 1 );
8883	} );
8884
8885	_api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis, calc ) {
8886		var that = this;
8887		var ret = this.iterator( 'column', function ( settings, column ) {
8888			if ( vis === undefined ) {
8889				return settings.aoColumns[ column ].bVisible;
8890			} // else
8891			__setColumnVis( settings, column, vis );
8892		} );
8893
8894		// Group the column visibility changes
8895		if ( vis !== undefined ) {
8896			this.iterator( 'table', function ( settings ) {
8897				// Redraw the header after changes
8898				_fnDrawHead( settings, settings.aoHeader );
8899				_fnDrawHead( settings, settings.aoFooter );
8900
8901				// Update colspan for no records display. Child rows and extensions will use their own
8902				// listeners to do this - only need to update the empty table item here
8903				if ( ! settings.aiDisplay.length ) {
8904					$(settings.nTBody).find('td[colspan]').attr('colspan', _fnVisbleColumns(settings));
8905				}
8906
8907				_fnSaveState( settings );
8908
8909				// Second loop once the first is done for events
8910				that.iterator( 'column', function ( settings, column ) {
8911					_fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis, calc] );
8912				} );
8913
8914				if ( calc === undefined || calc ) {
8915					that.columns.adjust();
8916				}
8917			});
8918		}
8919
8920		return ret;
8921	} );
8922
8923	_api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) {
8924		return this.iterator( 'column', function ( settings, column ) {
8925			return type === 'visible' ?
8926				_fnColumnIndexToVisible( settings, column ) :
8927				column;
8928		}, 1 );
8929	} );
8930
8931	_api_register( 'columns.adjust()', function () {
8932		return this.iterator( 'table', function ( settings ) {
8933			_fnAdjustColumnSizing( settings );
8934		}, 1 );
8935	} );
8936
8937	_api_register( 'column.index()', function ( type, idx ) {
8938		if ( this.context.length !== 0 ) {
8939			var ctx = this.context[0];
8940
8941			if ( type === 'fromVisible' || type === 'toData' ) {
8942				return _fnVisibleToColumnIndex( ctx, idx );
8943			}
8944			else if ( type === 'fromData' || type === 'toVisible' ) {
8945				return _fnColumnIndexToVisible( ctx, idx );
8946			}
8947		}
8948	} );
8949
8950	_api_register( 'column()', function ( selector, opts ) {
8951		return _selector_first( this.columns( selector, opts ) );
8952	} );
8953
8954	var __cell_selector = function ( settings, selector, opts )
8955	{
8956		var data = settings.aoData;
8957		var rows = _selector_row_indexes( settings, opts );
8958		var cells = _removeEmpty( _pluck_order( data, rows, 'anCells' ) );
8959		var allCells = $(_flatten( [], cells ));
8960		var row;
8961		var columns = settings.aoColumns.length;
8962		var a, i, ien, j, o, host;
8963
8964		var run = function ( s ) {
8965			var fnSelector = typeof s === 'function';
8966
8967			if ( s === null || s === undefined || fnSelector ) {
8968				// All cells and function selectors
8969				a = [];
8970
8971				for ( i=0, ien=rows.length ; i<ien ; i++ ) {
8972					row = rows[i];
8973
8974					for ( j=0 ; j<columns ; j++ ) {
8975						o = {
8976							row: row,
8977							column: j
8978						};
8979
8980						if ( fnSelector ) {
8981							// Selector - function
8982							host = data[ row ];
8983
8984							if ( s( o, _fnGetCellData(settings, row, j), host.anCells ? host.anCells[j] : null ) ) {
8985								a.push( o );
8986							}
8987						}
8988						else {
8989							// Selector - all
8990							a.push( o );
8991						}
8992					}
8993				}
8994
8995				return a;
8996			}
8997
8998			// Selector - index
8999			if ( $.isPlainObject( s ) ) {
9000				// Valid cell index and its in the array of selectable rows
9001				return s.column !== undefined && s.row !== undefined && $.inArray( s.row, rows ) !== -1 ?
9002					[s] :
9003					[];
9004			}
9005
9006			// Selector - jQuery filtered cells
9007			var jqResult = allCells
9008				.filter( s )
9009				.map( function (i, el) {
9010					return { // use a new object, in case someone changes the values
9011						row:    el._DT_CellIndex.row,
9012						column: el._DT_CellIndex.column
9013	 				};
9014				} )
9015				.toArray();
9016
9017			if ( jqResult.length || ! s.nodeName ) {
9018				return jqResult;
9019			}
9020
9021			// Otherwise the selector is a node, and there is one last option - the
9022			// element might be a child of an element which has dt-row and dt-column
9023			// data attributes
9024			host = $(s).closest('*[data-dt-row]');
9025			return host.length ?
9026				[ {
9027					row: host.data('dt-row'),
9028					column: host.data('dt-column')
9029				} ] :
9030				[];
9031		};
9032
9033		return _selector_run( 'cell', selector, run, settings, opts );
9034	};
9035
9036
9037
9038
9039	_api_register( 'cells()', function ( rowSelector, columnSelector, opts ) {
9040		// Argument shifting
9041		if ( $.isPlainObject( rowSelector ) ) {
9042			// Indexes
9043			if ( rowSelector.row === undefined ) {
9044				// Selector options in first parameter
9045				opts = rowSelector;
9046				rowSelector = null;
9047			}
9048			else {
9049				// Cell index objects in first parameter
9050				opts = columnSelector;
9051				columnSelector = null;
9052			}
9053		}
9054		if ( $.isPlainObject( columnSelector ) ) {
9055			opts = columnSelector;
9056			columnSelector = null;
9057		}
9058
9059		// Cell selector
9060		if ( columnSelector === null || columnSelector === undefined ) {
9061			return this.iterator( 'table', function ( settings ) {
9062				return __cell_selector( settings, rowSelector, _selector_opts( opts ) );
9063			} );
9064		}
9065
9066		// The default built in options need to apply to row and columns
9067		var internalOpts = opts ? {
9068			page: opts.page,
9069			order: opts.order,
9070			search: opts.search
9071		} : {};
9072
9073		// Row + column selector
9074		var columns = this.columns( columnSelector, internalOpts );
9075		var rows = this.rows( rowSelector, internalOpts );
9076		var i, ien, j, jen;
9077
9078		var cellsNoOpts = this.iterator( 'table', function ( settings, idx ) {
9079			var a = [];
9080
9081			for ( i=0, ien=rows[idx].length ; i<ien ; i++ ) {
9082				for ( j=0, jen=columns[idx].length ; j<jen ; j++ ) {
9083					a.push( {
9084						row:    rows[idx][i],
9085						column: columns[idx][j]
9086					} );
9087				}
9088			}
9089
9090			return a;
9091		}, 1 );
9092
9093		// There is currently only one extension which uses a cell selector extension
9094		// It is a _major_ performance drag to run this if it isn't needed, so this is
9095		// an extension specific check at the moment
9096		var cells = opts && opts.selected ?
9097			this.cells( cellsNoOpts, opts ) :
9098			cellsNoOpts;
9099
9100		$.extend( cells.selector, {
9101			cols: columnSelector,
9102			rows: rowSelector,
9103			opts: opts
9104		} );
9105
9106		return cells;
9107	} );
9108
9109
9110	_api_registerPlural( 'cells().nodes()', 'cell().node()', function () {
9111		return this.iterator( 'cell', function ( settings, row, column ) {
9112			var data = settings.aoData[ row ];
9113
9114			return data && data.anCells ?
9115				data.anCells[ column ] :
9116				undefined;
9117		}, 1 );
9118	} );
9119
9120
9121	_api_register( 'cells().data()', function () {
9122		return this.iterator( 'cell', function ( settings, row, column ) {
9123			return _fnGetCellData( settings, row, column );
9124		}, 1 );
9125	} );
9126
9127
9128	_api_registerPlural( 'cells().cache()', 'cell().cache()', function ( type ) {
9129		type = type === 'search' ? '_aFilterData' : '_aSortData';
9130
9131		return this.iterator( 'cell', function ( settings, row, column ) {
9132			return settings.aoData[ row ][ type ][ column ];
9133		}, 1 );
9134	} );
9135
9136
9137	_api_registerPlural( 'cells().render()', 'cell().render()', function ( type ) {
9138		return this.iterator( 'cell', function ( settings, row, column ) {
9139			return _fnGetCellData( settings, row, column, type );
9140		}, 1 );
9141	} );
9142
9143
9144	_api_registerPlural( 'cells().indexes()', 'cell().index()', function () {
9145		return this.iterator( 'cell', function ( settings, row, column ) {
9146			return {
9147				row: row,
9148				column: column,
9149				columnVisible: _fnColumnIndexToVisible( settings, column )
9150			};
9151		}, 1 );
9152	} );
9153
9154
9155	_api_registerPlural( 'cells().invalidate()', 'cell().invalidate()', function ( src ) {
9156		return this.iterator( 'cell', function ( settings, row, column ) {
9157			_fnInvalidate( settings, row, src, column );
9158		} );
9159	} );
9160
9161
9162
9163	_api_register( 'cell()', function ( rowSelector, columnSelector, opts ) {
9164		return _selector_first( this.cells( rowSelector, columnSelector, opts ) );
9165	} );
9166
9167
9168	_api_register( 'cell().data()', function ( data ) {
9169		var ctx = this.context;
9170		var cell = this[0];
9171
9172		if ( data === undefined ) {
9173			// Get
9174			return ctx.length && cell.length ?
9175				_fnGetCellData( ctx[0], cell[0].row, cell[0].column ) :
9176				undefined;
9177		}
9178
9179		// Set
9180		_fnSetCellData( ctx[0], cell[0].row, cell[0].column, data );
9181		_fnInvalidate( ctx[0], cell[0].row, 'data', cell[0].column );
9182
9183		return this;
9184	} );
9185
9186
9187
9188	/**
9189	 * Get current ordering (sorting) that has been applied to the table.
9190	 *
9191	 * @returns {array} 2D array containing the sorting information for the first
9192	 *   table in the current context. Each element in the parent array represents
9193	 *   a column being sorted upon (i.e. multi-sorting with two columns would have
9194	 *   2 inner arrays). The inner arrays may have 2 or 3 elements. The first is
9195	 *   the column index that the sorting condition applies to, the second is the
9196	 *   direction of the sort (`desc` or `asc`) and, optionally, the third is the
9197	 *   index of the sorting order from the `column.sorting` initialisation array.
9198	 *//**
9199	 * Set the ordering for the table.
9200	 *
9201	 * @param {integer} order Column index to sort upon.
9202	 * @param {string} direction Direction of the sort to be applied (`asc` or `desc`)
9203	 * @returns {DataTables.Api} this
9204	 *//**
9205	 * Set the ordering for the table.
9206	 *
9207	 * @param {array} order 1D array of sorting information to be applied.
9208	 * @param {array} [...] Optional additional sorting conditions
9209	 * @returns {DataTables.Api} this
9210	 *//**
9211	 * Set the ordering for the table.
9212	 *
9213	 * @param {array} order 2D array of sorting information to be applied.
9214	 * @returns {DataTables.Api} this
9215	 */
9216	_api_register( 'order()', function ( order, dir ) {
9217		var ctx = this.context;
9218
9219		if ( order === undefined ) {
9220			// get
9221			return ctx.length !== 0 ?
9222				ctx[0].aaSorting :
9223				undefined;
9224		}
9225
9226		// set
9227		if ( typeof order === 'number' ) {
9228			// Simple column / direction passed in
9229			order = [ [ order, dir ] ];
9230		}
9231		else if ( order.length && ! Array.isArray( order[0] ) ) {
9232			// Arguments passed in (list of 1D arrays)
9233			order = Array.prototype.slice.call( arguments );
9234		}
9235		// otherwise a 2D array was passed in
9236
9237		return this.iterator( 'table', function ( settings ) {
9238			settings.aaSorting = order.slice();
9239		} );
9240	} );
9241
9242
9243	/**
9244	 * Attach a sort listener to an element for a given column
9245	 *
9246	 * @param {node|jQuery|string} node Identifier for the element(s) to attach the
9247	 *   listener to. This can take the form of a single DOM node, a jQuery
9248	 *   collection of nodes or a jQuery selector which will identify the node(s).
9249	 * @param {integer} column the column that a click on this node will sort on
9250	 * @param {function} [callback] callback function when sort is run
9251	 * @returns {DataTables.Api} this
9252	 */
9253	_api_register( 'order.listener()', function ( node, column, callback ) {
9254		return this.iterator( 'table', function ( settings ) {
9255			_fnSortAttachListener( settings, node, column, callback );
9256		} );
9257	} );
9258
9259
9260	_api_register( 'order.fixed()', function ( set ) {
9261		if ( ! set ) {
9262			var ctx = this.context;
9263			var fixed = ctx.length ?
9264				ctx[0].aaSortingFixed :
9265				undefined;
9266
9267			return Array.isArray( fixed ) ?
9268				{ pre: fixed } :
9269				fixed;
9270		}
9271
9272		return this.iterator( 'table', function ( settings ) {
9273			settings.aaSortingFixed = $.extend( true, {}, set );
9274		} );
9275	} );
9276
9277
9278	// Order by the selected column(s)
9279	_api_register( [
9280		'columns().order()',
9281		'column().order()'
9282	], function ( dir ) {
9283		var that = this;
9284
9285		return this.iterator( 'table', function ( settings, i ) {
9286			var sort = [];
9287
9288			$.each( that[i], function (j, col) {
9289				sort.push( [ col, dir ] );
9290			} );
9291
9292			settings.aaSorting = sort;
9293		} );
9294	} );
9295
9296
9297
9298	_api_register( 'search()', function ( input, regex, smart, caseInsen ) {
9299		var ctx = this.context;
9300
9301		if ( input === undefined ) {
9302			// get
9303			return ctx.length !== 0 ?
9304				ctx[0].oPreviousSearch.sSearch :
9305				undefined;
9306		}
9307
9308		// set
9309		return this.iterator( 'table', function ( settings ) {
9310			if ( ! settings.oFeatures.bFilter ) {
9311				return;
9312			}
9313
9314			_fnFilterComplete( settings, $.extend( {}, settings.oPreviousSearch, {
9315				"sSearch": input+"",
9316				"bRegex":  regex === null ? false : regex,
9317				"bSmart":  smart === null ? true  : smart,
9318				"bCaseInsensitive": caseInsen === null ? true : caseInsen
9319			} ), 1 );
9320		} );
9321	} );
9322
9323
9324	_api_registerPlural(
9325		'columns().search()',
9326		'column().search()',
9327		function ( input, regex, smart, caseInsen ) {
9328			return this.iterator( 'column', function ( settings, column ) {
9329				var preSearch = settings.aoPreSearchCols;
9330
9331				if ( input === undefined ) {
9332					// get
9333					return preSearch[ column ].sSearch;
9334				}
9335
9336				// set
9337				if ( ! settings.oFeatures.bFilter ) {
9338					return;
9339				}
9340
9341				$.extend( preSearch[ column ], {
9342					"sSearch": input+"",
9343					"bRegex":  regex === null ? false : regex,
9344					"bSmart":  smart === null ? true  : smart,
9345					"bCaseInsensitive": caseInsen === null ? true : caseInsen
9346				} );
9347
9348				_fnFilterComplete( settings, settings.oPreviousSearch, 1 );
9349			} );
9350		}
9351	);
9352
9353	/*
9354	 * State API methods
9355	 */
9356
9357	_api_register( 'state()', function () {
9358		return this.context.length ?
9359			this.context[0].oSavedState :
9360			null;
9361	} );
9362
9363
9364	_api_register( 'state.clear()', function () {
9365		return this.iterator( 'table', function ( settings ) {
9366			// Save an empty object
9367			settings.fnStateSaveCallback.call( settings.oInstance, settings, {} );
9368		} );
9369	} );
9370
9371
9372	_api_register( 'state.loaded()', function () {
9373		return this.context.length ?
9374			this.context[0].oLoadedState :
9375			null;
9376	} );
9377
9378
9379	_api_register( 'state.save()', function () {
9380		return this.iterator( 'table', function ( settings ) {
9381			_fnSaveState( settings );
9382		} );
9383	} );
9384
9385
9386
9387	/**
9388	 * Set the jQuery or window object to be used by DataTables
9389	 *
9390	 * @param {*} module Library / container object
9391	 * @param {string} [type] Library or container type `lib`, `win` or `datetime`.
9392	 *   If not provided, automatic detection is attempted.
9393	 */
9394	DataTable.use = function (module, type) {
9395		if (type === 'lib' || module.fn) {
9396			$ = module;
9397		}
9398		else if (type == 'win' || module.document) {
9399			window = module;
9400			document = module.document;
9401		}
9402		else if (type === 'datetime' || module.type === 'DateTime') {
9403			DataTable.DateTime = module;
9404		}
9405	}
9406
9407	/**
9408	 * CommonJS factory function pass through. This will check if the arguments
9409	 * given are a window object or a jQuery object. If so they are set
9410	 * accordingly.
9411	 * @param {*} root Window
9412	 * @param {*} jq jQUery
9413	 * @returns {boolean} Indicator
9414	 */
9415	DataTable.factory = function (root, jq) {
9416		var is = false;
9417
9418		// Test if the first parameter is a window object
9419		if (root && root.document) {
9420			window = root;
9421			document = root.document;
9422		}
9423
9424		// Test if the second parameter is a jQuery object
9425		if (jq && jq.fn && jq.fn.jquery) {
9426			$ = jq;
9427			is = true;
9428		}
9429
9430		return is;
9431	}
9432
9433	/**
9434	 * Provide a common method for plug-ins to check the version of DataTables being
9435	 * used, in order to ensure compatibility.
9436	 *
9437	 *  @param {string} version Version string to check for, in the format "X.Y.Z".
9438	 *    Note that the formats "X" and "X.Y" are also acceptable.
9439	 *  @returns {boolean} true if this version of DataTables is greater or equal to
9440	 *    the required version, or false if this version of DataTales is not
9441	 *    suitable
9442	 *  @static
9443	 *  @dtopt API-Static
9444	 *
9445	 *  @example
9446	 *    alert( $.fn.dataTable.versionCheck( '1.9.0' ) );
9447	 */
9448	DataTable.versionCheck = DataTable.fnVersionCheck = function( version )
9449	{
9450		var aThis = DataTable.version.split('.');
9451		var aThat = version.split('.');
9452		var iThis, iThat;
9453
9454		for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) {
9455			iThis = parseInt( aThis[i], 10 ) || 0;
9456			iThat = parseInt( aThat[i], 10 ) || 0;
9457
9458			// Parts are the same, keep comparing
9459			if (iThis === iThat) {
9460				continue;
9461			}
9462
9463			// Parts are different, return immediately
9464			return iThis > iThat;
9465		}
9466
9467		return true;
9468	};
9469
9470
9471	/**
9472	 * Check if a `<table>` node is a DataTable table already or not.
9473	 *
9474	 *  @param {node|jquery|string} table Table node, jQuery object or jQuery
9475	 *      selector for the table to test. Note that if more than more than one
9476	 *      table is passed on, only the first will be checked
9477	 *  @returns {boolean} true the table given is a DataTable, or false otherwise
9478	 *  @static
9479	 *  @dtopt API-Static
9480	 *
9481	 *  @example
9482	 *    if ( ! $.fn.DataTable.isDataTable( '#example' ) ) {
9483	 *      $('#example').dataTable();
9484	 *    }
9485	 */
9486	DataTable.isDataTable = DataTable.fnIsDataTable = function ( table )
9487	{
9488		var t = $(table).get(0);
9489		var is = false;
9490
9491		if ( table instanceof DataTable.Api ) {
9492			return true;
9493		}
9494
9495		$.each( DataTable.settings, function (i, o) {
9496			var head = o.nScrollHead ? $('table', o.nScrollHead)[0] : null;
9497			var foot = o.nScrollFoot ? $('table', o.nScrollFoot)[0] : null;
9498
9499			if ( o.nTable === t || head === t || foot === t ) {
9500				is = true;
9501			}
9502		} );
9503
9504		return is;
9505	};
9506
9507
9508	/**
9509	 * Get all DataTable tables that have been initialised - optionally you can
9510	 * select to get only currently visible tables.
9511	 *
9512	 *  @param {boolean} [visible=false] Flag to indicate if you want all (default)
9513	 *    or visible tables only.
9514	 *  @returns {array} Array of `table` nodes (not DataTable instances) which are
9515	 *    DataTables
9516	 *  @static
9517	 *  @dtopt API-Static
9518	 *
9519	 *  @example
9520	 *    $.each( $.fn.dataTable.tables(true), function () {
9521	 *      $(table).DataTable().columns.adjust();
9522	 *    } );
9523	 */
9524	DataTable.tables = DataTable.fnTables = function ( visible )
9525	{
9526		var api = false;
9527
9528		if ( $.isPlainObject( visible ) ) {
9529			api = visible.api;
9530			visible = visible.visible;
9531		}
9532
9533		var a = $.map( DataTable.settings, function (o) {
9534			if ( !visible || (visible && $(o.nTable).is(':visible')) ) {
9535				return o.nTable;
9536			}
9537		} );
9538
9539		return api ?
9540			new _Api( a ) :
9541			a;
9542	};
9543
9544
9545	/**
9546	 * Convert from camel case parameters to Hungarian notation. This is made public
9547	 * for the extensions to provide the same ability as DataTables core to accept
9548	 * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase
9549	 * parameters.
9550	 *
9551	 *  @param {object} src The model object which holds all parameters that can be
9552	 *    mapped.
9553	 *  @param {object} user The object to convert from camel case to Hungarian.
9554	 *  @param {boolean} force When set to `true`, properties which already have a
9555	 *    Hungarian value in the `user` object will be overwritten. Otherwise they
9556	 *    won't be.
9557	 */
9558	DataTable.camelToHungarian = _fnCamelToHungarian;
9559
9560
9561
9562	/**
9563	 *
9564	 */
9565	_api_register( '$()', function ( selector, opts ) {
9566		var
9567			rows   = this.rows( opts ).nodes(), // Get all rows
9568			jqRows = $(rows);
9569
9570		return $( [].concat(
9571			jqRows.filter( selector ).toArray(),
9572			jqRows.find( selector ).toArray()
9573		) );
9574	} );
9575
9576
9577	// jQuery functions to operate on the tables
9578	$.each( [ 'on', 'one', 'off' ], function (i, key) {
9579		_api_register( key+'()', function ( /* event, handler */ ) {
9580			var args = Array.prototype.slice.call(arguments);
9581
9582			// Add the `dt` namespace automatically if it isn't already present
9583			args[0] = $.map( args[0].split( /\s/ ), function ( e ) {
9584				return ! e.match(/\.dt\b/) ?
9585					e+'.dt' :
9586					e;
9587				} ).join( ' ' );
9588
9589			var inst = $( this.tables().nodes() );
9590			inst[key].apply( inst, args );
9591			return this;
9592		} );
9593	} );
9594
9595
9596	_api_register( 'clear()', function () {
9597		return this.iterator( 'table', function ( settings ) {
9598			_fnClearTable( settings );
9599		} );
9600	} );
9601
9602
9603	_api_register( 'settings()', function () {
9604		return new _Api( this.context, this.context );
9605	} );
9606
9607
9608	_api_register( 'init()', function () {
9609		var ctx = this.context;
9610		return ctx.length ? ctx[0].oInit : null;
9611	} );
9612
9613
9614	_api_register( 'data()', function () {
9615		return this.iterator( 'table', function ( settings ) {
9616			return _pluck( settings.aoData, '_aData' );
9617		} ).flatten();
9618	} );
9619
9620
9621	_api_register( 'destroy()', function ( remove ) {
9622		remove = remove || false;
9623
9624		return this.iterator( 'table', function ( settings ) {
9625			var classes   = settings.oClasses;
9626			var table     = settings.nTable;
9627			var tbody     = settings.nTBody;
9628			var thead     = settings.nTHead;
9629			var tfoot     = settings.nTFoot;
9630			var jqTable   = $(table);
9631			var jqTbody   = $(tbody);
9632			var jqWrapper = $(settings.nTableWrapper);
9633			var rows      = $.map( settings.aoData, function (r) { return r.nTr; } );
9634			var i, ien;
9635
9636			// Flag to note that the table is currently being destroyed - no action
9637			// should be taken
9638			settings.bDestroying = true;
9639
9640			// Fire off the destroy callbacks for plug-ins etc
9641			_fnCallbackFire( settings, "aoDestroyCallback", "destroy", [settings] );
9642
9643			// If not being removed from the document, make all columns visible
9644			if ( ! remove ) {
9645				new _Api( settings ).columns().visible( true );
9646			}
9647
9648			// Blitz all `DT` namespaced events (these are internal events, the
9649			// lowercase, `dt` events are user subscribed and they are responsible
9650			// for removing them
9651			jqWrapper.off('.DT').find(':not(tbody *)').off('.DT');
9652			$(window).off('.DT-'+settings.sInstance);
9653
9654			// When scrolling we had to break the table up - restore it
9655			if ( table != thead.parentNode ) {
9656				jqTable.children('thead').detach();
9657				jqTable.append( thead );
9658			}
9659
9660			if ( tfoot && table != tfoot.parentNode ) {
9661				jqTable.children('tfoot').detach();
9662				jqTable.append( tfoot );
9663			}
9664
9665			settings.aaSorting = [];
9666			settings.aaSortingFixed = [];
9667			_fnSortingClasses( settings );
9668
9669			$( rows ).removeClass( settings.asStripeClasses.join(' ') );
9670
9671			$('th, td', thead).removeClass( classes.sSortable+' '+
9672				classes.sSortableAsc+' '+classes.sSortableDesc+' '+classes.sSortableNone
9673			);
9674
9675			// Add the TR elements back into the table in their original order
9676			jqTbody.children().detach();
9677			jqTbody.append( rows );
9678
9679			var orig = settings.nTableWrapper.parentNode;
9680
9681			// Remove the DataTables generated nodes, events and classes
9682			var removedMethod = remove ? 'remove' : 'detach';
9683			jqTable[ removedMethod ]();
9684			jqWrapper[ removedMethod ]();
9685
9686			// If we need to reattach the table to the document
9687			if ( ! remove && orig ) {
9688				// insertBefore acts like appendChild if !arg[1]
9689				orig.insertBefore( table, settings.nTableReinsertBefore );
9690
9691				// Restore the width of the original table - was read from the style property,
9692				// so we can restore directly to that
9693				jqTable
9694					.css( 'width', settings.sDestroyWidth )
9695					.removeClass( classes.sTable );
9696
9697				// If the were originally stripe classes - then we add them back here.
9698				// Note this is not fool proof (for example if not all rows had stripe
9699				// classes - but it's a good effort without getting carried away
9700				ien = settings.asDestroyStripes.length;
9701
9702				if ( ien ) {
9703					jqTbody.children().each( function (i) {
9704						$(this).addClass( settings.asDestroyStripes[i % ien] );
9705					} );
9706				}
9707			}
9708
9709			/* Remove the settings object from the settings array */
9710			var idx = $.inArray( settings, DataTable.settings );
9711			if ( idx !== -1 ) {
9712				DataTable.settings.splice( idx, 1 );
9713			}
9714		} );
9715	} );
9716
9717
9718	// Add the `every()` method for rows, columns and cells in a compact form
9719	$.each( [ 'column', 'row', 'cell' ], function ( i, type ) {
9720		_api_register( type+'s().every()', function ( fn ) {
9721			var opts = this.selector.opts;
9722			var api = this;
9723
9724			return this.iterator( type, function ( settings, arg1, arg2, arg3, arg4 ) {
9725				// Rows and columns:
9726				//  arg1 - index
9727				//  arg2 - table counter
9728				//  arg3 - loop counter
9729				//  arg4 - undefined
9730				// Cells:
9731				//  arg1 - row index
9732				//  arg2 - column index
9733				//  arg3 - table counter
9734				//  arg4 - loop counter
9735				fn.call(
9736					api[ type ](
9737						arg1,
9738						type==='cell' ? arg2 : opts,
9739						type==='cell' ? opts : undefined
9740					),
9741					arg1, arg2, arg3, arg4
9742				);
9743			} );
9744		} );
9745	} );
9746
9747
9748	// i18n method for extensions to be able to use the language object from the
9749	// DataTable
9750	_api_register( 'i18n()', function ( token, def, plural ) {
9751		var ctx = this.context[0];
9752		var resolved = _fnGetObjectDataFn( token )( ctx.oLanguage );
9753
9754		if ( resolved === undefined ) {
9755			resolved = def;
9756		}
9757
9758		if ( plural !== undefined && $.isPlainObject( resolved ) ) {
9759			resolved = resolved[ plural ] !== undefined ?
9760				resolved[ plural ] :
9761				resolved._;
9762		}
9763
9764		return typeof resolved === 'string'
9765			? resolved.replace( '%d', plural ) // nb: plural might be undefined,
9766			: resolved;
9767	} );
9768	/**
9769	 * Version string for plug-ins to check compatibility. Allowed format is
9770	 * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used
9771	 * only for non-release builds. See http://semver.org/ for more information.
9772	 *  @member
9773	 *  @type string
9774	 *  @default Version number
9775	 */
9776	DataTable.version = "1.13.5";
9777
9778	/**
9779	 * Private data store, containing all of the settings objects that are
9780	 * created for the tables on a given page.
9781	 *
9782	 * Note that the `DataTable.settings` object is aliased to
9783	 * `jQuery.fn.dataTableExt` through which it may be accessed and
9784	 * manipulated, or `jQuery.fn.dataTable.settings`.
9785	 *  @member
9786	 *  @type array
9787	 *  @default []
9788	 *  @private
9789	 */
9790	DataTable.settings = [];
9791
9792	/**
9793	 * Object models container, for the various models that DataTables has
9794	 * available to it. These models define the objects that are used to hold
9795	 * the active state and configuration of the table.
9796	 *  @namespace
9797	 */
9798	DataTable.models = {};
9799
9800
9801
9802	/**
9803	 * Template object for the way in which DataTables holds information about
9804	 * search information for the global filter and individual column filters.
9805	 *  @namespace
9806	 */
9807	DataTable.models.oSearch = {
9808		/**
9809		 * Flag to indicate if the filtering should be case insensitive or not
9810		 *  @type boolean
9811		 *  @default true
9812		 */
9813		"bCaseInsensitive": true,
9814
9815		/**
9816		 * Applied search term
9817		 *  @type string
9818		 *  @default <i>Empty string</i>
9819		 */
9820		"sSearch": "",
9821
9822		/**
9823		 * Flag to indicate if the search term should be interpreted as a
9824		 * regular expression (true) or not (false) and therefore and special
9825		 * regex characters escaped.
9826		 *  @type boolean
9827		 *  @default false
9828		 */
9829		"bRegex": false,
9830
9831		/**
9832		 * Flag to indicate if DataTables is to use its smart filtering or not.
9833		 *  @type boolean
9834		 *  @default true
9835		 */
9836		"bSmart": true,
9837
9838		/**
9839		 * Flag to indicate if DataTables should only trigger a search when
9840		 * the return key is pressed.
9841		 *  @type boolean
9842		 *  @default false
9843		 */
9844		"return": false
9845	};
9846
9847
9848
9849
9850	/**
9851	 * Template object for the way in which DataTables holds information about
9852	 * each individual row. This is the object format used for the settings
9853	 * aoData array.
9854	 *  @namespace
9855	 */
9856	DataTable.models.oRow = {
9857		/**
9858		 * TR element for the row
9859		 *  @type node
9860		 *  @default null
9861		 */
9862		"nTr": null,
9863
9864		/**
9865		 * Array of TD elements for each row. This is null until the row has been
9866		 * created.
9867		 *  @type array nodes
9868		 *  @default []
9869		 */
9870		"anCells": null,
9871
9872		/**
9873		 * Data object from the original data source for the row. This is either
9874		 * an array if using the traditional form of DataTables, or an object if
9875		 * using mData options. The exact type will depend on the passed in
9876		 * data from the data source, or will be an array if using DOM a data
9877		 * source.
9878		 *  @type array|object
9879		 *  @default []
9880		 */
9881		"_aData": [],
9882
9883		/**
9884		 * Sorting data cache - this array is ostensibly the same length as the
9885		 * number of columns (although each index is generated only as it is
9886		 * needed), and holds the data that is used for sorting each column in the
9887		 * row. We do this cache generation at the start of the sort in order that
9888		 * the formatting of the sort data need be done only once for each cell
9889		 * per sort. This array should not be read from or written to by anything
9890		 * other than the master sorting methods.
9891		 *  @type array
9892		 *  @default null
9893		 *  @private
9894		 */
9895		"_aSortData": null,
9896
9897		/**
9898		 * Per cell filtering data cache. As per the sort data cache, used to
9899		 * increase the performance of the filtering in DataTables
9900		 *  @type array
9901		 *  @default null
9902		 *  @private
9903		 */
9904		"_aFilterData": null,
9905
9906		/**
9907		 * Filtering data cache. This is the same as the cell filtering cache, but
9908		 * in this case a string rather than an array. This is easily computed with
9909		 * a join on `_aFilterData`, but is provided as a cache so the join isn't
9910		 * needed on every search (memory traded for performance)
9911		 *  @type array
9912		 *  @default null
9913		 *  @private
9914		 */
9915		"_sFilterRow": null,
9916
9917		/**
9918		 * Cache of the class name that DataTables has applied to the row, so we
9919		 * can quickly look at this variable rather than needing to do a DOM check
9920		 * on className for the nTr property.
9921		 *  @type string
9922		 *  @default <i>Empty string</i>
9923		 *  @private
9924		 */
9925		"_sRowStripe": "",
9926
9927		/**
9928		 * Denote if the original data source was from the DOM, or the data source
9929		 * object. This is used for invalidating data, so DataTables can
9930		 * automatically read data from the original source, unless uninstructed
9931		 * otherwise.
9932		 *  @type string
9933		 *  @default null
9934		 *  @private
9935		 */
9936		"src": null,
9937
9938		/**
9939		 * Index in the aoData array. This saves an indexOf lookup when we have the
9940		 * object, but want to know the index
9941		 *  @type integer
9942		 *  @default -1
9943		 *  @private
9944		 */
9945		"idx": -1
9946	};
9947
9948
9949	/**
9950	 * Template object for the column information object in DataTables. This object
9951	 * is held in the settings aoColumns array and contains all the information that
9952	 * DataTables needs about each individual column.
9953	 *
9954	 * Note that this object is related to {@link DataTable.defaults.column}
9955	 * but this one is the internal data store for DataTables's cache of columns.
9956	 * It should NOT be manipulated outside of DataTables. Any configuration should
9957	 * be done through the initialisation options.
9958	 *  @namespace
9959	 */
9960	DataTable.models.oColumn = {
9961		/**
9962		 * Column index. This could be worked out on-the-fly with $.inArray, but it
9963		 * is faster to just hold it as a variable
9964		 *  @type integer
9965		 *  @default null
9966		 */
9967		"idx": null,
9968
9969		/**
9970		 * A list of the columns that sorting should occur on when this column
9971		 * is sorted. That this property is an array allows multi-column sorting
9972		 * to be defined for a column (for example first name / last name columns
9973		 * would benefit from this). The values are integers pointing to the
9974		 * columns to be sorted on (typically it will be a single integer pointing
9975		 * at itself, but that doesn't need to be the case).
9976		 *  @type array
9977		 */
9978		"aDataSort": null,
9979
9980		/**
9981		 * Define the sorting directions that are applied to the column, in sequence
9982		 * as the column is repeatedly sorted upon - i.e. the first value is used
9983		 * as the sorting direction when the column if first sorted (clicked on).
9984		 * Sort it again (click again) and it will move on to the next index.
9985		 * Repeat until loop.
9986		 *  @type array
9987		 */
9988		"asSorting": null,
9989
9990		/**
9991		 * Flag to indicate if the column is searchable, and thus should be included
9992		 * in the filtering or not.
9993		 *  @type boolean
9994		 */
9995		"bSearchable": null,
9996
9997		/**
9998		 * Flag to indicate if the column is sortable or not.
9999		 *  @type boolean
10000		 */
10001		"bSortable": null,
10002
10003		/**
10004		 * Flag to indicate if the column is currently visible in the table or not
10005		 *  @type boolean
10006		 */
10007		"bVisible": null,
10008
10009		/**
10010		 * Store for manual type assignment using the `column.type` option. This
10011		 * is held in store so we can manipulate the column's `sType` property.
10012		 *  @type string
10013		 *  @default null
10014		 *  @private
10015		 */
10016		"_sManualType": null,
10017
10018		/**
10019		 * Flag to indicate if HTML5 data attributes should be used as the data
10020		 * source for filtering or sorting. True is either are.
10021		 *  @type boolean
10022		 *  @default false
10023		 *  @private
10024		 */
10025		"_bAttrSrc": false,
10026
10027		/**
10028		 * Developer definable function that is called whenever a cell is created (Ajax source,
10029		 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
10030		 * allowing you to modify the DOM element (add background colour for example) when the
10031		 * element is available.
10032		 *  @type function
10033		 *  @param {element} nTd The TD node that has been created
10034		 *  @param {*} sData The Data for the cell
10035		 *  @param {array|object} oData The data for the whole row
10036		 *  @param {int} iRow The row index for the aoData data store
10037		 *  @default null
10038		 */
10039		"fnCreatedCell": null,
10040
10041		/**
10042		 * Function to get data from a cell in a column. You should <b>never</b>
10043		 * access data directly through _aData internally in DataTables - always use
10044		 * the method attached to this property. It allows mData to function as
10045		 * required. This function is automatically assigned by the column
10046		 * initialisation method
10047		 *  @type function
10048		 *  @param {array|object} oData The data array/object for the array
10049		 *    (i.e. aoData[]._aData)
10050		 *  @param {string} sSpecific The specific data type you want to get -
10051		 *    'display', 'type' 'filter' 'sort'
10052		 *  @returns {*} The data for the cell from the given row's data
10053		 *  @default null
10054		 */
10055		"fnGetData": null,
10056
10057		/**
10058		 * Function to set data for a cell in the column. You should <b>never</b>
10059		 * set the data directly to _aData internally in DataTables - always use
10060		 * this method. It allows mData to function as required. This function
10061		 * is automatically assigned by the column initialisation method
10062		 *  @type function
10063		 *  @param {array|object} oData The data array/object for the array
10064		 *    (i.e. aoData[]._aData)
10065		 *  @param {*} sValue Value to set
10066		 *  @default null
10067		 */
10068		"fnSetData": null,
10069
10070		/**
10071		 * Property to read the value for the cells in the column from the data
10072		 * source array / object. If null, then the default content is used, if a
10073		 * function is given then the return from the function is used.
10074		 *  @type function|int|string|null
10075		 *  @default null
10076		 */
10077		"mData": null,
10078
10079		/**
10080		 * Partner property to mData which is used (only when defined) to get
10081		 * the data - i.e. it is basically the same as mData, but without the
10082		 * 'set' option, and also the data fed to it is the result from mData.
10083		 * This is the rendering method to match the data method of mData.
10084		 *  @type function|int|string|null
10085		 *  @default null
10086		 */
10087		"mRender": null,
10088
10089		/**
10090		 * Unique header TH/TD element for this column - this is what the sorting
10091		 * listener is attached to (if sorting is enabled.)
10092		 *  @type node
10093		 *  @default null
10094		 */
10095		"nTh": null,
10096
10097		/**
10098		 * Unique footer TH/TD element for this column (if there is one). Not used
10099		 * in DataTables as such, but can be used for plug-ins to reference the
10100		 * footer for each column.
10101		 *  @type node
10102		 *  @default null
10103		 */
10104		"nTf": null,
10105
10106		/**
10107		 * The class to apply to all TD elements in the table's TBODY for the column
10108		 *  @type string
10109		 *  @default null
10110		 */
10111		"sClass": null,
10112
10113		/**
10114		 * When DataTables calculates the column widths to assign to each column,
10115		 * it finds the longest string in each column and then constructs a
10116		 * temporary table and reads the widths from that. The problem with this
10117		 * is that "mmm" is much wider then "iiii", but the latter is a longer
10118		 * string - thus the calculation can go wrong (doing it properly and putting
10119		 * it into an DOM object and measuring that is horribly(!) slow). Thus as
10120		 * a "work around" we provide this option. It will append its value to the
10121		 * text that is found to be the longest string for the column - i.e. padding.
10122		 *  @type string
10123		 */
10124		"sContentPadding": null,
10125
10126		/**
10127		 * Allows a default value to be given for a column's data, and will be used
10128		 * whenever a null data source is encountered (this can be because mData
10129		 * is set to null, or because the data source itself is null).
10130		 *  @type string
10131		 *  @default null
10132		 */
10133		"sDefaultContent": null,
10134
10135		/**
10136		 * Name for the column, allowing reference to the column by name as well as
10137		 * by index (needs a lookup to work by name).
10138		 *  @type string
10139		 */
10140		"sName": null,
10141
10142		/**
10143		 * Custom sorting data type - defines which of the available plug-ins in
10144		 * afnSortData the custom sorting will use - if any is defined.
10145		 *  @type string
10146		 *  @default std
10147		 */
10148		"sSortDataType": 'std',
10149
10150		/**
10151		 * Class to be applied to the header element when sorting on this column
10152		 *  @type string
10153		 *  @default null
10154		 */
10155		"sSortingClass": null,
10156
10157		/**
10158		 * Class to be applied to the header element when sorting on this column -
10159		 * when jQuery UI theming is used.
10160		 *  @type string
10161		 *  @default null
10162		 */
10163		"sSortingClassJUI": null,
10164
10165		/**
10166		 * Title of the column - what is seen in the TH element (nTh).
10167		 *  @type string
10168		 */
10169		"sTitle": null,
10170
10171		/**
10172		 * Column sorting and filtering type
10173		 *  @type string
10174		 *  @default null
10175		 */
10176		"sType": null,
10177
10178		/**
10179		 * Width of the column
10180		 *  @type string
10181		 *  @default null
10182		 */
10183		"sWidth": null,
10184
10185		/**
10186		 * Width of the column when it was first "encountered"
10187		 *  @type string
10188		 *  @default null
10189		 */
10190		"sWidthOrig": null
10191	};
10192
10193
10194	/*
10195	 * Developer note: The properties of the object below are given in Hungarian
10196	 * notation, that was used as the interface for DataTables prior to v1.10, however
10197	 * from v1.10 onwards the primary interface is camel case. In order to avoid
10198	 * breaking backwards compatibility utterly with this change, the Hungarian
10199	 * version is still, internally the primary interface, but is is not documented
10200	 * - hence the @name tags in each doc comment. This allows a Javascript function
10201	 * to create a map from Hungarian notation to camel case (going the other direction
10202	 * would require each property to be listed, which would add around 3K to the size
10203	 * of DataTables, while this method is about a 0.5K hit).
10204	 *
10205	 * Ultimately this does pave the way for Hungarian notation to be dropped
10206	 * completely, but that is a massive amount of work and will break current
10207	 * installs (therefore is on-hold until v2).
10208	 */
10209
10210	/**
10211	 * Initialisation options that can be given to DataTables at initialisation
10212	 * time.
10213	 *  @namespace
10214	 */
10215	DataTable.defaults = {
10216		/**
10217		 * An array of data to use for the table, passed in at initialisation which
10218		 * will be used in preference to any data which is already in the DOM. This is
10219		 * particularly useful for constructing tables purely in Javascript, for
10220		 * example with a custom Ajax call.
10221		 *  @type array
10222		 *  @default null
10223		 *
10224		 *  @dtopt Option
10225		 *  @name DataTable.defaults.data
10226		 *
10227		 *  @example
10228		 *    // Using a 2D array data source
10229		 *    $(document).ready( function () {
10230		 *      $('#example').dataTable( {
10231		 *        "data": [
10232		 *          ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
10233		 *          ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
10234		 *        ],
10235		 *        "columns": [
10236		 *          { "title": "Engine" },
10237		 *          { "title": "Browser" },
10238		 *          { "title": "Platform" },
10239		 *          { "title": "Version" },
10240		 *          { "title": "Grade" }
10241		 *        ]
10242		 *      } );
10243		 *    } );
10244		 *
10245		 *  @example
10246		 *    // Using an array of objects as a data source (`data`)
10247		 *    $(document).ready( function () {
10248		 *      $('#example').dataTable( {
10249		 *        "data": [
10250		 *          {
10251		 *            "engine":   "Trident",
10252		 *            "browser":  "Internet Explorer 4.0",
10253		 *            "platform": "Win 95+",
10254		 *            "version":  4,
10255		 *            "grade":    "X"
10256		 *          },
10257		 *          {
10258		 *            "engine":   "Trident",
10259		 *            "browser":  "Internet Explorer 5.0",
10260		 *            "platform": "Win 95+",
10261		 *            "version":  5,
10262		 *            "grade":    "C"
10263		 *          }
10264		 *        ],
10265		 *        "columns": [
10266		 *          { "title": "Engine",   "data": "engine" },
10267		 *          { "title": "Browser",  "data": "browser" },
10268		 *          { "title": "Platform", "data": "platform" },
10269		 *          { "title": "Version",  "data": "version" },
10270		 *          { "title": "Grade",    "data": "grade" }
10271		 *        ]
10272		 *      } );
10273		 *    } );
10274		 */
10275		"aaData": null,
10276
10277
10278		/**
10279		 * If ordering is enabled, then DataTables will perform a first pass sort on
10280		 * initialisation. You can define which column(s) the sort is performed
10281		 * upon, and the sorting direction, with this variable. The `sorting` array
10282		 * should contain an array for each column to be sorted initially containing
10283		 * the column's index and a direction string ('asc' or 'desc').
10284		 *  @type array
10285		 *  @default [[0,'asc']]
10286		 *
10287		 *  @dtopt Option
10288		 *  @name DataTable.defaults.order
10289		 *
10290		 *  @example
10291		 *    // Sort by 3rd column first, and then 4th column
10292		 *    $(document).ready( function() {
10293		 *      $('#example').dataTable( {
10294		 *        "order": [[2,'asc'], [3,'desc']]
10295		 *      } );
10296		 *    } );
10297		 *
10298		 *    // No initial sorting
10299		 *    $(document).ready( function() {
10300		 *      $('#example').dataTable( {
10301		 *        "order": []
10302		 *      } );
10303		 *    } );
10304		 */
10305		"aaSorting": [[0,'asc']],
10306
10307
10308		/**
10309		 * This parameter is basically identical to the `sorting` parameter, but
10310		 * cannot be overridden by user interaction with the table. What this means
10311		 * is that you could have a column (visible or hidden) which the sorting
10312		 * will always be forced on first - any sorting after that (from the user)
10313		 * will then be performed as required. This can be useful for grouping rows
10314		 * together.
10315		 *  @type array
10316		 *  @default null
10317		 *
10318		 *  @dtopt Option
10319		 *  @name DataTable.defaults.orderFixed
10320		 *
10321		 *  @example
10322		 *    $(document).ready( function() {
10323		 *      $('#example').dataTable( {
10324		 *        "orderFixed": [[0,'asc']]
10325		 *      } );
10326		 *    } )
10327		 */
10328		"aaSortingFixed": [],
10329
10330
10331		/**
10332		 * DataTables can be instructed to load data to display in the table from a
10333		 * Ajax source. This option defines how that Ajax call is made and where to.
10334		 *
10335		 * The `ajax` property has three different modes of operation, depending on
10336		 * how it is defined. These are:
10337		 *
10338		 * * `string` - Set the URL from where the data should be loaded from.
10339		 * * `object` - Define properties for `jQuery.ajax`.
10340		 * * `function` - Custom data get function
10341		 *
10342		 * `string`
10343		 * --------
10344		 *
10345		 * As a string, the `ajax` property simply defines the URL from which
10346		 * DataTables will load data.
10347		 *
10348		 * `object`
10349		 * --------
10350		 *
10351		 * As an object, the parameters in the object are passed to
10352		 * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control
10353		 * of the Ajax request. DataTables has a number of default parameters which
10354		 * you can override using this option. Please refer to the jQuery
10355		 * documentation for a full description of the options available, although
10356		 * the following parameters provide additional options in DataTables or
10357		 * require special consideration:
10358		 *
10359		 * * `data` - As with jQuery, `data` can be provided as an object, but it
10360		 *   can also be used as a function to manipulate the data DataTables sends
10361		 *   to the server. The function takes a single parameter, an object of
10362		 *   parameters with the values that DataTables has readied for sending. An
10363		 *   object may be returned which will be merged into the DataTables
10364		 *   defaults, or you can add the items to the object that was passed in and
10365		 *   not return anything from the function. This supersedes `fnServerParams`
10366		 *   from DataTables 1.9-.
10367		 *
10368		 * * `dataSrc` - By default DataTables will look for the property `data` (or
10369		 *   `aaData` for compatibility with DataTables 1.9-) when obtaining data
10370		 *   from an Ajax source or for server-side processing - this parameter
10371		 *   allows that property to be changed. You can use Javascript dotted
10372		 *   object notation to get a data source for multiple levels of nesting, or
10373		 *   it my be used as a function. As a function it takes a single parameter,
10374		 *   the JSON returned from the server, which can be manipulated as
10375		 *   required, with the returned value being that used by DataTables as the
10376		 *   data source for the table. This supersedes `sAjaxDataProp` from
10377		 *   DataTables 1.9-.
10378		 *
10379		 * * `success` - Should not be overridden it is used internally in
10380		 *   DataTables. To manipulate / transform the data returned by the server
10381		 *   use `ajax.dataSrc`, or use `ajax` as a function (see below).
10382		 *
10383		 * `function`
10384		 * ----------
10385		 *
10386		 * As a function, making the Ajax call is left up to yourself allowing
10387		 * complete control of the Ajax request. Indeed, if desired, a method other
10388		 * than Ajax could be used to obtain the required data, such as Web storage
10389		 * or an AIR database.
10390		 *
10391		 * The function is given four parameters and no return is required. The
10392		 * parameters are:
10393		 *
10394		 * 1. _object_ - Data to send to the server
10395		 * 2. _function_ - Callback function that must be executed when the required
10396		 *    data has been obtained. That data should be passed into the callback
10397		 *    as the only parameter
10398		 * 3. _object_ - DataTables settings object for the table
10399		 *
10400		 * Note that this supersedes `fnServerData` from DataTables 1.9-.
10401		 *
10402		 *  @type string|object|function
10403		 *  @default null
10404		 *
10405		 *  @dtopt Option
10406		 *  @name DataTable.defaults.ajax
10407		 *  @since 1.10.0
10408		 *
10409		 * @example
10410		 *   // Get JSON data from a file via Ajax.
10411		 *   // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default).
10412		 *   $('#example').dataTable( {
10413		 *     "ajax": "data.json"
10414		 *   } );
10415		 *
10416		 * @example
10417		 *   // Get JSON data from a file via Ajax, using `dataSrc` to change
10418		 *   // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`)
10419		 *   $('#example').dataTable( {
10420		 *     "ajax": {
10421		 *       "url": "data.json",
10422		 *       "dataSrc": "tableData"
10423		 *     }
10424		 *   } );
10425		 *
10426		 * @example
10427		 *   // Get JSON data from a file via Ajax, using `dataSrc` to read data
10428		 *   // from a plain array rather than an array in an object
10429		 *   $('#example').dataTable( {
10430		 *     "ajax": {
10431		 *       "url": "data.json",
10432		 *       "dataSrc": ""
10433		 *     }
10434		 *   } );
10435		 *
10436		 * @example
10437		 *   // Manipulate the data returned from the server - add a link to data
10438		 *   // (note this can, should, be done using `render` for the column - this
10439		 *   // is just a simple example of how the data can be manipulated).
10440		 *   $('#example').dataTable( {
10441		 *     "ajax": {
10442		 *       "url": "data.json",
10443		 *       "dataSrc": function ( json ) {
10444		 *         for ( var i=0, ien=json.length ; i<ien ; i++ ) {
10445		 *           json[i][0] = '<a href="/message/'+json[i][0]+'>View message</a>';
10446		 *         }
10447		 *         return json;
10448		 *       }
10449		 *     }
10450		 *   } );
10451		 *
10452		 * @example
10453		 *   // Add data to the request
10454		 *   $('#example').dataTable( {
10455		 *     "ajax": {
10456		 *       "url": "data.json",
10457		 *       "data": function ( d ) {
10458		 *         return {
10459		 *           "extra_search": $('#extra').val()
10460		 *         };
10461		 *       }
10462		 *     }
10463		 *   } );
10464		 *
10465		 * @example
10466		 *   // Send request as POST
10467		 *   $('#example').dataTable( {
10468		 *     "ajax": {
10469		 *       "url": "data.json",
10470		 *       "type": "POST"
10471		 *     }
10472		 *   } );
10473		 *
10474		 * @example
10475		 *   // Get the data from localStorage (could interface with a form for
10476		 *   // adding, editing and removing rows).
10477		 *   $('#example').dataTable( {
10478		 *     "ajax": function (data, callback, settings) {
10479		 *       callback(
10480		 *         JSON.parse( localStorage.getItem('dataTablesData') )
10481		 *       );
10482		 *     }
10483		 *   } );
10484		 */
10485		"ajax": null,
10486
10487
10488		/**
10489		 * This parameter allows you to readily specify the entries in the length drop
10490		 * down menu that DataTables shows when pagination is enabled. It can be
10491		 * either a 1D array of options which will be used for both the displayed
10492		 * option and the value, or a 2D array which will use the array in the first
10493		 * position as the value, and the array in the second position as the
10494		 * displayed options (useful for language strings such as 'All').
10495		 *
10496		 * Note that the `pageLength` property will be automatically set to the
10497		 * first value given in this array, unless `pageLength` is also provided.
10498		 *  @type array
10499		 *  @default [ 10, 25, 50, 100 ]
10500		 *
10501		 *  @dtopt Option
10502		 *  @name DataTable.defaults.lengthMenu
10503		 *
10504		 *  @example
10505		 *    $(document).ready( function() {
10506		 *      $('#example').dataTable( {
10507		 *        "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
10508		 *      } );
10509		 *    } );
10510		 */
10511		"aLengthMenu": [ 10, 25, 50, 100 ],
10512
10513
10514		/**
10515		 * The `columns` option in the initialisation parameter allows you to define
10516		 * details about the way individual columns behave. For a full list of
10517		 * column options that can be set, please see
10518		 * {@link DataTable.defaults.column}. Note that if you use `columns` to
10519		 * define your columns, you must have an entry in the array for every single
10520		 * column that you have in your table (these can be null if you don't which
10521		 * to specify any options).
10522		 *  @member
10523		 *
10524		 *  @name DataTable.defaults.column
10525		 */
10526		"aoColumns": null,
10527
10528		/**
10529		 * Very similar to `columns`, `columnDefs` allows you to target a specific
10530		 * column, multiple columns, or all columns, using the `targets` property of
10531		 * each object in the array. This allows great flexibility when creating
10532		 * tables, as the `columnDefs` arrays can be of any length, targeting the
10533		 * columns you specifically want. `columnDefs` may use any of the column
10534		 * options available: {@link DataTable.defaults.column}, but it _must_
10535		 * have `targets` defined in each object in the array. Values in the `targets`
10536		 * array may be:
10537		 *   <ul>
10538		 *     <li>a string - class name will be matched on the TH for the column</li>
10539		 *     <li>0 or a positive integer - column index counting from the left</li>
10540		 *     <li>a negative integer - column index counting from the right</li>
10541		 *     <li>the string "_all" - all columns (i.e. assign a default)</li>
10542		 *   </ul>
10543		 *  @member
10544		 *
10545		 *  @name DataTable.defaults.columnDefs
10546		 */
10547		"aoColumnDefs": null,
10548
10549
10550		/**
10551		 * Basically the same as `search`, this parameter defines the individual column
10552		 * filtering state at initialisation time. The array must be of the same size
10553		 * as the number of columns, and each element be an object with the parameters
10554		 * `search` and `escapeRegex` (the latter is optional). 'null' is also
10555		 * accepted and the default will be used.
10556		 *  @type array
10557		 *  @default []
10558		 *
10559		 *  @dtopt Option
10560		 *  @name DataTable.defaults.searchCols
10561		 *
10562		 *  @example
10563		 *    $(document).ready( function() {
10564		 *      $('#example').dataTable( {
10565		 *        "searchCols": [
10566		 *          null,
10567		 *          { "search": "My filter" },
10568		 *          null,
10569		 *          { "search": "^[0-9]", "escapeRegex": false }
10570		 *        ]
10571		 *      } );
10572		 *    } )
10573		 */
10574		"aoSearchCols": [],
10575
10576
10577		/**
10578		 * An array of CSS classes that should be applied to displayed rows. This
10579		 * array may be of any length, and DataTables will apply each class
10580		 * sequentially, looping when required.
10581		 *  @type array
10582		 *  @default null <i>Will take the values determined by the `oClasses.stripe*`
10583		 *    options</i>
10584		 *
10585		 *  @dtopt Option
10586		 *  @name DataTable.defaults.stripeClasses
10587		 *
10588		 *  @example
10589		 *    $(document).ready( function() {
10590		 *      $('#example').dataTable( {
10591		 *        "stripeClasses": [ 'strip1', 'strip2', 'strip3' ]
10592		 *      } );
10593		 *    } )
10594		 */
10595		"asStripeClasses": null,
10596
10597
10598		/**
10599		 * Enable or disable automatic column width calculation. This can be disabled
10600		 * as an optimisation (it takes some time to calculate the widths) if the
10601		 * tables widths are passed in using `columns`.
10602		 *  @type boolean
10603		 *  @default true
10604		 *
10605		 *  @dtopt Features
10606		 *  @name DataTable.defaults.autoWidth
10607		 *
10608		 *  @example
10609		 *    $(document).ready( function () {
10610		 *      $('#example').dataTable( {
10611		 *        "autoWidth": false
10612		 *      } );
10613		 *    } );
10614		 */
10615		"bAutoWidth": true,
10616
10617
10618		/**
10619		 * Deferred rendering can provide DataTables with a huge speed boost when you
10620		 * are using an Ajax or JS data source for the table. This option, when set to
10621		 * true, will cause DataTables to defer the creation of the table elements for
10622		 * each row until they are needed for a draw - saving a significant amount of
10623		 * time.
10624		 *  @type boolean
10625		 *  @default false
10626		 *
10627		 *  @dtopt Features
10628		 *  @name DataTable.defaults.deferRender
10629		 *
10630		 *  @example
10631		 *    $(document).ready( function() {
10632		 *      $('#example').dataTable( {
10633		 *        "ajax": "sources/arrays.txt",
10634		 *        "deferRender": true
10635		 *      } );
10636		 *    } );
10637		 */
10638		"bDeferRender": false,
10639
10640
10641		/**
10642		 * Replace a DataTable which matches the given selector and replace it with
10643		 * one which has the properties of the new initialisation object passed. If no
10644		 * table matches the selector, then the new DataTable will be constructed as
10645		 * per normal.
10646		 *  @type boolean
10647		 *  @default false
10648		 *
10649		 *  @dtopt Options
10650		 *  @name DataTable.defaults.destroy
10651		 *
10652		 *  @example
10653		 *    $(document).ready( function() {
10654		 *      $('#example').dataTable( {
10655		 *        "srollY": "200px",
10656		 *        "paginate": false
10657		 *      } );
10658		 *
10659		 *      // Some time later....
10660		 *      $('#example').dataTable( {
10661		 *        "filter": false,
10662		 *        "destroy": true
10663		 *      } );
10664		 *    } );
10665		 */
10666		"bDestroy": false,
10667
10668
10669		/**
10670		 * Enable or disable filtering of data. Filtering in DataTables is "smart" in
10671		 * that it allows the end user to input multiple words (space separated) and
10672		 * will match a row containing those words, even if not in the order that was
10673		 * specified (this allow matching across multiple columns). Note that if you
10674		 * wish to use filtering in DataTables this must remain 'true' - to remove the
10675		 * default filtering input box and retain filtering abilities, please use
10676		 * {@link DataTable.defaults.dom}.
10677		 *  @type boolean
10678		 *  @default true
10679		 *
10680		 *  @dtopt Features
10681		 *  @name DataTable.defaults.searching
10682		 *
10683		 *  @example
10684		 *    $(document).ready( function () {
10685		 *      $('#example').dataTable( {
10686		 *        "searching": false
10687		 *      } );
10688		 *    } );
10689		 */
10690		"bFilter": true,
10691
10692
10693		/**
10694		 * Enable or disable the table information display. This shows information
10695		 * about the data that is currently visible on the page, including information
10696		 * about filtered data if that action is being performed.
10697		 *  @type boolean
10698		 *  @default true
10699		 *
10700		 *  @dtopt Features
10701		 *  @name DataTable.defaults.info
10702		 *
10703		 *  @example
10704		 *    $(document).ready( function () {
10705		 *      $('#example').dataTable( {
10706		 *        "info": false
10707		 *      } );
10708		 *    } );
10709		 */
10710		"bInfo": true,
10711
10712
10713		/**
10714		 * Allows the end user to select the size of a formatted page from a select
10715		 * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`).
10716		 *  @type boolean
10717		 *  @default true
10718		 *
10719		 *  @dtopt Features
10720		 *  @name DataTable.defaults.lengthChange
10721		 *
10722		 *  @example
10723		 *    $(document).ready( function () {
10724		 *      $('#example').dataTable( {
10725		 *        "lengthChange": false
10726		 *      } );
10727		 *    } );
10728		 */
10729		"bLengthChange": true,
10730
10731
10732		/**
10733		 * Enable or disable pagination.
10734		 *  @type boolean
10735		 *  @default true
10736		 *
10737		 *  @dtopt Features
10738		 *  @name DataTable.defaults.paging
10739		 *
10740		 *  @example
10741		 *    $(document).ready( function () {
10742		 *      $('#example').dataTable( {
10743		 *        "paging": false
10744		 *      } );
10745		 *    } );
10746		 */
10747		"bPaginate": true,
10748
10749
10750		/**
10751		 * Enable or disable the display of a 'processing' indicator when the table is
10752		 * being processed (e.g. a sort). This is particularly useful for tables with
10753		 * large amounts of data where it can take a noticeable amount of time to sort
10754		 * the entries.
10755		 *  @type boolean
10756		 *  @default false
10757		 *
10758		 *  @dtopt Features
10759		 *  @name DataTable.defaults.processing
10760		 *
10761		 *  @example
10762		 *    $(document).ready( function () {
10763		 *      $('#example').dataTable( {
10764		 *        "processing": true
10765		 *      } );
10766		 *    } );
10767		 */
10768		"bProcessing": false,
10769
10770
10771		/**
10772		 * Retrieve the DataTables object for the given selector. Note that if the
10773		 * table has already been initialised, this parameter will cause DataTables
10774		 * to simply return the object that has already been set up - it will not take
10775		 * account of any changes you might have made to the initialisation object
10776		 * passed to DataTables (setting this parameter to true is an acknowledgement
10777		 * that you understand this). `destroy` can be used to reinitialise a table if
10778		 * you need.
10779		 *  @type boolean
10780		 *  @default false
10781		 *
10782		 *  @dtopt Options
10783		 *  @name DataTable.defaults.retrieve
10784		 *
10785		 *  @example
10786		 *    $(document).ready( function() {
10787		 *      initTable();
10788		 *      tableActions();
10789		 *    } );
10790		 *
10791		 *    function initTable ()
10792		 *    {
10793		 *      return $('#example').dataTable( {
10794		 *        "scrollY": "200px",
10795		 *        "paginate": false,
10796		 *        "retrieve": true
10797		 *      } );
10798		 *    }
10799		 *
10800		 *    function tableActions ()
10801		 *    {
10802		 *      var table = initTable();
10803		 *      // perform API operations with oTable
10804		 *    }
10805		 */
10806		"bRetrieve": false,
10807
10808
10809		/**
10810		 * When vertical (y) scrolling is enabled, DataTables will force the height of
10811		 * the table's viewport to the given height at all times (useful for layout).
10812		 * However, this can look odd when filtering data down to a small data set,
10813		 * and the footer is left "floating" further down. This parameter (when
10814		 * enabled) will cause DataTables to collapse the table's viewport down when
10815		 * the result set will fit within the given Y height.
10816		 *  @type boolean
10817		 *  @default false
10818		 *
10819		 *  @dtopt Options
10820		 *  @name DataTable.defaults.scrollCollapse
10821		 *
10822		 *  @example
10823		 *    $(document).ready( function() {
10824		 *      $('#example').dataTable( {
10825		 *        "scrollY": "200",
10826		 *        "scrollCollapse": true
10827		 *      } );
10828		 *    } );
10829		 */
10830		"bScrollCollapse": false,
10831
10832
10833		/**
10834		 * Configure DataTables to use server-side processing. Note that the
10835		 * `ajax` parameter must also be given in order to give DataTables a
10836		 * source to obtain the required data for each draw.
10837		 *  @type boolean
10838		 *  @default false
10839		 *
10840		 *  @dtopt Features
10841		 *  @dtopt Server-side
10842		 *  @name DataTable.defaults.serverSide
10843		 *
10844		 *  @example
10845		 *    $(document).ready( function () {
10846		 *      $('#example').dataTable( {
10847		 *        "serverSide": true,
10848		 *        "ajax": "xhr.php"
10849		 *      } );
10850		 *    } );
10851		 */
10852		"bServerSide": false,
10853
10854
10855		/**
10856		 * Enable or disable sorting of columns. Sorting of individual columns can be
10857		 * disabled by the `sortable` option for each column.
10858		 *  @type boolean
10859		 *  @default true
10860		 *
10861		 *  @dtopt Features
10862		 *  @name DataTable.defaults.ordering
10863		 *
10864		 *  @example
10865		 *    $(document).ready( function () {
10866		 *      $('#example').dataTable( {
10867		 *        "ordering": false
10868		 *      } );
10869		 *    } );
10870		 */
10871		"bSort": true,
10872
10873
10874		/**
10875		 * Enable or display DataTables' ability to sort multiple columns at the
10876		 * same time (activated by shift-click by the user).
10877		 *  @type boolean
10878		 *  @default true
10879		 *
10880		 *  @dtopt Options
10881		 *  @name DataTable.defaults.orderMulti
10882		 *
10883		 *  @example
10884		 *    // Disable multiple column sorting ability
10885		 *    $(document).ready( function () {
10886		 *      $('#example').dataTable( {
10887		 *        "orderMulti": false
10888		 *      } );
10889		 *    } );
10890		 */
10891		"bSortMulti": true,
10892
10893
10894		/**
10895		 * Allows control over whether DataTables should use the top (true) unique
10896		 * cell that is found for a single column, or the bottom (false - default).
10897		 * This is useful when using complex headers.
10898		 *  @type boolean
10899		 *  @default false
10900		 *
10901		 *  @dtopt Options
10902		 *  @name DataTable.defaults.orderCellsTop
10903		 *
10904		 *  @example
10905		 *    $(document).ready( function() {
10906		 *      $('#example').dataTable( {
10907		 *        "orderCellsTop": true
10908		 *      } );
10909		 *    } );
10910		 */
10911		"bSortCellsTop": false,
10912
10913
10914		/**
10915		 * Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and
10916		 * `sorting\_3` to the columns which are currently being sorted on. This is
10917		 * presented as a feature switch as it can increase processing time (while
10918		 * classes are removed and added) so for large data sets you might want to
10919		 * turn this off.
10920		 *  @type boolean
10921		 *  @default true
10922		 *
10923		 *  @dtopt Features
10924		 *  @name DataTable.defaults.orderClasses
10925		 *
10926		 *  @example
10927		 *    $(document).ready( function () {
10928		 *      $('#example').dataTable( {
10929		 *        "orderClasses": false
10930		 *      } );
10931		 *    } );
10932		 */
10933		"bSortClasses": true,
10934
10935
10936		/**
10937		 * Enable or disable state saving. When enabled HTML5 `localStorage` will be
10938		 * used to save table display information such as pagination information,
10939		 * display length, filtering and sorting. As such when the end user reloads
10940		 * the page the display display will match what thy had previously set up.
10941		 *
10942		 * Due to the use of `localStorage` the default state saving is not supported
10943		 * in IE6 or 7. If state saving is required in those browsers, use
10944		 * `stateSaveCallback` to provide a storage solution such as cookies.
10945		 *  @type boolean
10946		 *  @default false
10947		 *
10948		 *  @dtopt Features
10949		 *  @name DataTable.defaults.stateSave
10950		 *
10951		 *  @example
10952		 *    $(document).ready( function () {
10953		 *      $('#example').dataTable( {
10954		 *        "stateSave": true
10955		 *      } );
10956		 *    } );
10957		 */
10958		"bStateSave": false,
10959
10960
10961		/**
10962		 * This function is called when a TR element is created (and all TD child
10963		 * elements have been inserted), or registered if using a DOM source, allowing
10964		 * manipulation of the TR element (adding classes etc).
10965		 *  @type function
10966		 *  @param {node} row "TR" element for the current row
10967		 *  @param {array} data Raw data array for this row
10968		 *  @param {int} dataIndex The index of this row in the internal aoData array
10969		 *
10970		 *  @dtopt Callbacks
10971		 *  @name DataTable.defaults.createdRow
10972		 *
10973		 *  @example
10974		 *    $(document).ready( function() {
10975		 *      $('#example').dataTable( {
10976		 *        "createdRow": function( row, data, dataIndex ) {
10977		 *          // Bold the grade for all 'A' grade browsers
10978		 *          if ( data[4] == "A" )
10979		 *          {
10980		 *            $('td:eq(4)', row).html( '<b>A</b>' );
10981		 *          }
10982		 *        }
10983		 *      } );
10984		 *    } );
10985		 */
10986		"fnCreatedRow": null,
10987
10988
10989		/**
10990		 * This function is called on every 'draw' event, and allows you to
10991		 * dynamically modify any aspect you want about the created DOM.
10992		 *  @type function
10993		 *  @param {object} settings DataTables settings object
10994		 *
10995		 *  @dtopt Callbacks
10996		 *  @name DataTable.defaults.drawCallback
10997		 *
10998		 *  @example
10999		 *    $(document).ready( function() {
11000		 *      $('#example').dataTable( {
11001		 *        "drawCallback": function( settings ) {
11002		 *          alert( 'DataTables has redrawn the table' );
11003		 *        }
11004		 *      } );
11005		 *    } );
11006		 */
11007		"fnDrawCallback": null,
11008
11009
11010		/**
11011		 * Identical to fnHeaderCallback() but for the table footer this function
11012		 * allows you to modify the table footer on every 'draw' event.
11013		 *  @type function
11014		 *  @param {node} foot "TR" element for the footer
11015		 *  @param {array} data Full table data (as derived from the original HTML)
11016		 *  @param {int} start Index for the current display starting point in the
11017		 *    display array
11018		 *  @param {int} end Index for the current display ending point in the
11019		 *    display array
11020		 *  @param {array int} display Index array to translate the visual position
11021		 *    to the full data array
11022		 *
11023		 *  @dtopt Callbacks
11024		 *  @name DataTable.defaults.footerCallback
11025		 *
11026		 *  @example
11027		 *    $(document).ready( function() {
11028		 *      $('#example').dataTable( {
11029		 *        "footerCallback": function( tfoot, data, start, end, display ) {
11030		 *          tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start;
11031		 *        }
11032		 *      } );
11033		 *    } )
11034		 */
11035		"fnFooterCallback": null,
11036
11037
11038		/**
11039		 * When rendering large numbers in the information element for the table
11040		 * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
11041		 * to have a comma separator for the 'thousands' units (e.g. 1 million is
11042		 * rendered as "1,000,000") to help readability for the end user. This
11043		 * function will override the default method DataTables uses.
11044		 *  @type function
11045		 *  @member
11046		 *  @param {int} toFormat number to be formatted
11047		 *  @returns {string} formatted string for DataTables to show the number
11048		 *
11049		 *  @dtopt Callbacks
11050		 *  @name DataTable.defaults.formatNumber
11051		 *
11052		 *  @example
11053		 *    // Format a number using a single quote for the separator (note that
11054		 *    // this can also be done with the language.thousands option)
11055		 *    $(document).ready( function() {
11056		 *      $('#example').dataTable( {
11057		 *        "formatNumber": function ( toFormat ) {
11058		 *          return toFormat.toString().replace(
11059		 *            /\B(?=(\d{3})+(?!\d))/g, "'"
11060		 *          );
11061		 *        };
11062		 *      } );
11063		 *    } );
11064		 */
11065		"fnFormatNumber": function ( toFormat ) {
11066			return toFormat.toString().replace(
11067				/\B(?=(\d{3})+(?!\d))/g,
11068				this.oLanguage.sThousands
11069			);
11070		},
11071
11072
11073		/**
11074		 * This function is called on every 'draw' event, and allows you to
11075		 * dynamically modify the header row. This can be used to calculate and
11076		 * display useful information about the table.
11077		 *  @type function
11078		 *  @param {node} head "TR" element for the header
11079		 *  @param {array} data Full table data (as derived from the original HTML)
11080		 *  @param {int} start Index for the current display starting point in the
11081		 *    display array
11082		 *  @param {int} end Index for the current display ending point in the
11083		 *    display array
11084		 *  @param {array int} display Index array to translate the visual position
11085		 *    to the full data array
11086		 *
11087		 *  @dtopt Callbacks
11088		 *  @name DataTable.defaults.headerCallback
11089		 *
11090		 *  @example
11091		 *    $(document).ready( function() {
11092		 *      $('#example').dataTable( {
11093		 *        "fheaderCallback": function( head, data, start, end, display ) {
11094		 *          head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records";
11095		 *        }
11096		 *      } );
11097		 *    } )
11098		 */
11099		"fnHeaderCallback": null,
11100
11101
11102		/**
11103		 * The information element can be used to convey information about the current
11104		 * state of the table. Although the internationalisation options presented by
11105		 * DataTables are quite capable of dealing with most customisations, there may
11106		 * be times where you wish to customise the string further. This callback
11107		 * allows you to do exactly that.
11108		 *  @type function
11109		 *  @param {object} oSettings DataTables settings object
11110		 *  @param {int} start Starting position in data for the draw
11111		 *  @param {int} end End position in data for the draw
11112		 *  @param {int} max Total number of rows in the table (regardless of
11113		 *    filtering)
11114		 *  @param {int} total Total number of rows in the data set, after filtering
11115		 *  @param {string} pre The string that DataTables has formatted using it's
11116		 *    own rules
11117		 *  @returns {string} The string to be displayed in the information element.
11118		 *
11119		 *  @dtopt Callbacks
11120		 *  @name DataTable.defaults.infoCallback
11121		 *
11122		 *  @example
11123		 *    $('#example').dataTable( {
11124		 *      "infoCallback": function( settings, start, end, max, total, pre ) {
11125		 *        return start +" to "+ end;
11126		 *      }
11127		 *    } );
11128		 */
11129		"fnInfoCallback": null,
11130
11131
11132		/**
11133		 * Called when the table has been initialised. Normally DataTables will
11134		 * initialise sequentially and there will be no need for this function,
11135		 * however, this does not hold true when using external language information
11136		 * since that is obtained using an async XHR call.
11137		 *  @type function
11138		 *  @param {object} settings DataTables settings object
11139		 *  @param {object} json The JSON object request from the server - only
11140		 *    present if client-side Ajax sourced data is used
11141		 *
11142		 *  @dtopt Callbacks
11143		 *  @name DataTable.defaults.initComplete
11144		 *
11145		 *  @example
11146		 *    $(document).ready( function() {
11147		 *      $('#example').dataTable( {
11148		 *        "initComplete": function(settings, json) {
11149		 *          alert( 'DataTables has finished its initialisation.' );
11150		 *        }
11151		 *      } );
11152		 *    } )
11153		 */
11154		"fnInitComplete": null,
11155
11156
11157		/**
11158		 * Called at the very start of each table draw and can be used to cancel the
11159		 * draw by returning false, any other return (including undefined) results in
11160		 * the full draw occurring).
11161		 *  @type function
11162		 *  @param {object} settings DataTables settings object
11163		 *  @returns {boolean} False will cancel the draw, anything else (including no
11164		 *    return) will allow it to complete.
11165		 *
11166		 *  @dtopt Callbacks
11167		 *  @name DataTable.defaults.preDrawCallback
11168		 *
11169		 *  @example
11170		 *    $(document).ready( function() {
11171		 *      $('#example').dataTable( {
11172		 *        "preDrawCallback": function( settings ) {
11173		 *          if ( $('#test').val() == 1 ) {
11174		 *            return false;
11175		 *          }
11176		 *        }
11177		 *      } );
11178		 *    } );
11179		 */
11180		"fnPreDrawCallback": null,
11181
11182
11183		/**
11184		 * This function allows you to 'post process' each row after it have been
11185		 * generated for each table draw, but before it is rendered on screen. This
11186		 * function might be used for setting the row class name etc.
11187		 *  @type function
11188		 *  @param {node} row "TR" element for the current row
11189		 *  @param {array} data Raw data array for this row
11190		 *  @param {int} displayIndex The display index for the current table draw
11191		 *  @param {int} displayIndexFull The index of the data in the full list of
11192		 *    rows (after filtering)
11193		 *
11194		 *  @dtopt Callbacks
11195		 *  @name DataTable.defaults.rowCallback
11196		 *
11197		 *  @example
11198		 *    $(document).ready( function() {
11199		 *      $('#example').dataTable( {
11200		 *        "rowCallback": function( row, data, displayIndex, displayIndexFull ) {
11201		 *          // Bold the grade for all 'A' grade browsers
11202		 *          if ( data[4] == "A" ) {
11203		 *            $('td:eq(4)', row).html( '<b>A</b>' );
11204		 *          }
11205		 *        }
11206		 *      } );
11207		 *    } );
11208		 */
11209		"fnRowCallback": null,
11210
11211
11212		/**
11213		 * __Deprecated__ The functionality provided by this parameter has now been
11214		 * superseded by that provided through `ajax`, which should be used instead.
11215		 *
11216		 * This parameter allows you to override the default function which obtains
11217		 * the data from the server so something more suitable for your application.
11218		 * For example you could use POST data, or pull information from a Gears or
11219		 * AIR database.
11220		 *  @type function
11221		 *  @member
11222		 *  @param {string} source HTTP source to obtain the data from (`ajax`)
11223		 *  @param {array} data A key/value pair object containing the data to send
11224		 *    to the server
11225		 *  @param {function} callback to be called on completion of the data get
11226		 *    process that will draw the data on the page.
11227		 *  @param {object} settings DataTables settings object
11228		 *
11229		 *  @dtopt Callbacks
11230		 *  @dtopt Server-side
11231		 *  @name DataTable.defaults.serverData
11232		 *
11233		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11234		 */
11235		"fnServerData": null,
11236
11237
11238		/**
11239		 * __Deprecated__ The functionality provided by this parameter has now been
11240		 * superseded by that provided through `ajax`, which should be used instead.
11241		 *
11242		 *  It is often useful to send extra data to the server when making an Ajax
11243		 * request - for example custom filtering information, and this callback
11244		 * function makes it trivial to send extra information to the server. The
11245		 * passed in parameter is the data set that has been constructed by
11246		 * DataTables, and you can add to this or modify it as you require.
11247		 *  @type function
11248		 *  @param {array} data Data array (array of objects which are name/value
11249		 *    pairs) that has been constructed by DataTables and will be sent to the
11250		 *    server. In the case of Ajax sourced data with server-side processing
11251		 *    this will be an empty array, for server-side processing there will be a
11252		 *    significant number of parameters!
11253		 *  @returns {undefined} Ensure that you modify the data array passed in,
11254		 *    as this is passed by reference.
11255		 *
11256		 *  @dtopt Callbacks
11257		 *  @dtopt Server-side
11258		 *  @name DataTable.defaults.serverParams
11259		 *
11260		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11261		 */
11262		"fnServerParams": null,
11263
11264
11265		/**
11266		 * Load the table state. With this function you can define from where, and how, the
11267		 * state of a table is loaded. By default DataTables will load from `localStorage`
11268		 * but you might wish to use a server-side database or cookies.
11269		 *  @type function
11270		 *  @member
11271		 *  @param {object} settings DataTables settings object
11272		 *  @param {object} callback Callback that can be executed when done. It
11273		 *    should be passed the loaded state object.
11274		 *  @return {object} The DataTables state object to be loaded
11275		 *
11276		 *  @dtopt Callbacks
11277		 *  @name DataTable.defaults.stateLoadCallback
11278		 *
11279		 *  @example
11280		 *    $(document).ready( function() {
11281		 *      $('#example').dataTable( {
11282		 *        "stateSave": true,
11283		 *        "stateLoadCallback": function (settings, callback) {
11284		 *          $.ajax( {
11285		 *            "url": "/state_load",
11286		 *            "dataType": "json",
11287		 *            "success": function (json) {
11288		 *              callback( json );
11289		 *            }
11290		 *          } );
11291		 *        }
11292		 *      } );
11293		 *    } );
11294		 */
11295		"fnStateLoadCallback": function ( settings ) {
11296			try {
11297				return JSON.parse(
11298					(settings.iStateDuration === -1 ? sessionStorage : localStorage).getItem(
11299						'DataTables_'+settings.sInstance+'_'+location.pathname
11300					)
11301				);
11302			} catch (e) {
11303				return {};
11304			}
11305		},
11306
11307
11308		/**
11309		 * Callback which allows modification of the saved state prior to loading that state.
11310		 * This callback is called when the table is loading state from the stored data, but
11311		 * prior to the settings object being modified by the saved state. Note that for
11312		 * plug-in authors, you should use the `stateLoadParams` event to load parameters for
11313		 * a plug-in.
11314		 *  @type function
11315		 *  @param {object} settings DataTables settings object
11316		 *  @param {object} data The state object that is to be loaded
11317		 *
11318		 *  @dtopt Callbacks
11319		 *  @name DataTable.defaults.stateLoadParams
11320		 *
11321		 *  @example
11322		 *    // Remove a saved filter, so filtering is never loaded
11323		 *    $(document).ready( function() {
11324		 *      $('#example').dataTable( {
11325		 *        "stateSave": true,
11326		 *        "stateLoadParams": function (settings, data) {
11327		 *          data.oSearch.sSearch = "";
11328		 *        }
11329		 *      } );
11330		 *    } );
11331		 *
11332		 *  @example
11333		 *    // Disallow state loading by returning false
11334		 *    $(document).ready( function() {
11335		 *      $('#example').dataTable( {
11336		 *        "stateSave": true,
11337		 *        "stateLoadParams": function (settings, data) {
11338		 *          return false;
11339		 *        }
11340		 *      } );
11341		 *    } );
11342		 */
11343		"fnStateLoadParams": null,
11344
11345
11346		/**
11347		 * Callback that is called when the state has been loaded from the state saving method
11348		 * and the DataTables settings object has been modified as a result of the loaded state.
11349		 *  @type function
11350		 *  @param {object} settings DataTables settings object
11351		 *  @param {object} data The state object that was loaded
11352		 *
11353		 *  @dtopt Callbacks
11354		 *  @name DataTable.defaults.stateLoaded
11355		 *
11356		 *  @example
11357		 *    // Show an alert with the filtering value that was saved
11358		 *    $(document).ready( function() {
11359		 *      $('#example').dataTable( {
11360		 *        "stateSave": true,
11361		 *        "stateLoaded": function (settings, data) {
11362		 *          alert( 'Saved filter was: '+data.oSearch.sSearch );
11363		 *        }
11364		 *      } );
11365		 *    } );
11366		 */
11367		"fnStateLoaded": null,
11368
11369
11370		/**
11371		 * Save the table state. This function allows you to define where and how the state
11372		 * information for the table is stored By default DataTables will use `localStorage`
11373		 * but you might wish to use a server-side database or cookies.
11374		 *  @type function
11375		 *  @member
11376		 *  @param {object} settings DataTables settings object
11377		 *  @param {object} data The state object to be saved
11378		 *
11379		 *  @dtopt Callbacks
11380		 *  @name DataTable.defaults.stateSaveCallback
11381		 *
11382		 *  @example
11383		 *    $(document).ready( function() {
11384		 *      $('#example').dataTable( {
11385		 *        "stateSave": true,
11386		 *        "stateSaveCallback": function (settings, data) {
11387		 *          // Send an Ajax request to the server with the state object
11388		 *          $.ajax( {
11389		 *            "url": "/state_save",
11390		 *            "data": data,
11391		 *            "dataType": "json",
11392		 *            "method": "POST"
11393		 *            "success": function () {}
11394		 *          } );
11395		 *        }
11396		 *      } );
11397		 *    } );
11398		 */
11399		"fnStateSaveCallback": function ( settings, data ) {
11400			try {
11401				(settings.iStateDuration === -1 ? sessionStorage : localStorage).setItem(
11402					'DataTables_'+settings.sInstance+'_'+location.pathname,
11403					JSON.stringify( data )
11404				);
11405			} catch (e) {}
11406		},
11407
11408
11409		/**
11410		 * Callback which allows modification of the state to be saved. Called when the table
11411		 * has changed state a new state save is required. This method allows modification of
11412		 * the state saving object prior to actually doing the save, including addition or
11413		 * other state properties or modification. Note that for plug-in authors, you should
11414		 * use the `stateSaveParams` event to save parameters for a plug-in.
11415		 *  @type function
11416		 *  @param {object} settings DataTables settings object
11417		 *  @param {object} data The state object to be saved
11418		 *
11419		 *  @dtopt Callbacks
11420		 *  @name DataTable.defaults.stateSaveParams
11421		 *
11422		 *  @example
11423		 *    // Remove a saved filter, so filtering is never saved
11424		 *    $(document).ready( function() {
11425		 *      $('#example').dataTable( {
11426		 *        "stateSave": true,
11427		 *        "stateSaveParams": function (settings, data) {
11428		 *          data.oSearch.sSearch = "";
11429		 *        }
11430		 *      } );
11431		 *    } );
11432		 */
11433		"fnStateSaveParams": null,
11434
11435
11436		/**
11437		 * Duration for which the saved state information is considered valid. After this period
11438		 * has elapsed the state will be returned to the default.
11439		 * Value is given in seconds.
11440		 *  @type int
11441		 *  @default 7200 <i>(2 hours)</i>
11442		 *
11443		 *  @dtopt Options
11444		 *  @name DataTable.defaults.stateDuration
11445		 *
11446		 *  @example
11447		 *    $(document).ready( function() {
11448		 *      $('#example').dataTable( {
11449		 *        "stateDuration": 60*60*24; // 1 day
11450		 *      } );
11451		 *    } )
11452		 */
11453		"iStateDuration": 7200,
11454
11455
11456		/**
11457		 * When enabled DataTables will not make a request to the server for the first
11458		 * page draw - rather it will use the data already on the page (no sorting etc
11459		 * will be applied to it), thus saving on an XHR at load time. `deferLoading`
11460		 * is used to indicate that deferred loading is required, but it is also used
11461		 * to tell DataTables how many records there are in the full table (allowing
11462		 * the information element and pagination to be displayed correctly). In the case
11463		 * where a filtering is applied to the table on initial load, this can be
11464		 * indicated by giving the parameter as an array, where the first element is
11465		 * the number of records available after filtering and the second element is the
11466		 * number of records without filtering (allowing the table information element
11467		 * to be shown correctly).
11468		 *  @type int | array
11469		 *  @default null
11470		 *
11471		 *  @dtopt Options
11472		 *  @name DataTable.defaults.deferLoading
11473		 *
11474		 *  @example
11475		 *    // 57 records available in the table, no filtering applied
11476		 *    $(document).ready( function() {
11477		 *      $('#example').dataTable( {
11478		 *        "serverSide": true,
11479		 *        "ajax": "scripts/server_processing.php",
11480		 *        "deferLoading": 57
11481		 *      } );
11482		 *    } );
11483		 *
11484		 *  @example
11485		 *    // 57 records after filtering, 100 without filtering (an initial filter applied)
11486		 *    $(document).ready( function() {
11487		 *      $('#example').dataTable( {
11488		 *        "serverSide": true,
11489		 *        "ajax": "scripts/server_processing.php",
11490		 *        "deferLoading": [ 57, 100 ],
11491		 *        "search": {
11492		 *          "search": "my_filter"
11493		 *        }
11494		 *      } );
11495		 *    } );
11496		 */
11497		"iDeferLoading": null,
11498
11499
11500		/**
11501		 * Number of rows to display on a single page when using pagination. If
11502		 * feature enabled (`lengthChange`) then the end user will be able to override
11503		 * this to a custom setting using a pop-up menu.
11504		 *  @type int
11505		 *  @default 10
11506		 *
11507		 *  @dtopt Options
11508		 *  @name DataTable.defaults.pageLength
11509		 *
11510		 *  @example
11511		 *    $(document).ready( function() {
11512		 *      $('#example').dataTable( {
11513		 *        "pageLength": 50
11514		 *      } );
11515		 *    } )
11516		 */
11517		"iDisplayLength": 10,
11518
11519
11520		/**
11521		 * Define the starting point for data display when using DataTables with
11522		 * pagination. Note that this parameter is the number of records, rather than
11523		 * the page number, so if you have 10 records per page and want to start on
11524		 * the third page, it should be "20".
11525		 *  @type int
11526		 *  @default 0
11527		 *
11528		 *  @dtopt Options
11529		 *  @name DataTable.defaults.displayStart
11530		 *
11531		 *  @example
11532		 *    $(document).ready( function() {
11533		 *      $('#example').dataTable( {
11534		 *        "displayStart": 20
11535		 *      } );
11536		 *    } )
11537		 */
11538		"iDisplayStart": 0,
11539
11540
11541		/**
11542		 * By default DataTables allows keyboard navigation of the table (sorting, paging,
11543		 * and filtering) by adding a `tabindex` attribute to the required elements. This
11544		 * allows you to tab through the controls and press the enter key to activate them.
11545		 * The tabindex is default 0, meaning that the tab follows the flow of the document.
11546		 * You can overrule this using this parameter if you wish. Use a value of -1 to
11547		 * disable built-in keyboard navigation.
11548		 *  @type int
11549		 *  @default 0
11550		 *
11551		 *  @dtopt Options
11552		 *  @name DataTable.defaults.tabIndex
11553		 *
11554		 *  @example
11555		 *    $(document).ready( function() {
11556		 *      $('#example').dataTable( {
11557		 *        "tabIndex": 1
11558		 *      } );
11559		 *    } );
11560		 */
11561		"iTabIndex": 0,
11562
11563
11564		/**
11565		 * Classes that DataTables assigns to the various components and features
11566		 * that it adds to the HTML table. This allows classes to be configured
11567		 * during initialisation in addition to through the static
11568		 * {@link DataTable.ext.oStdClasses} object).
11569		 *  @namespace
11570		 *  @name DataTable.defaults.classes
11571		 */
11572		"oClasses": {},
11573
11574
11575		/**
11576		 * All strings that DataTables uses in the user interface that it creates
11577		 * are defined in this object, allowing you to modified them individually or
11578		 * completely replace them all as required.
11579		 *  @namespace
11580		 *  @name DataTable.defaults.language
11581		 */
11582		"oLanguage": {
11583			/**
11584			 * Strings that are used for WAI-ARIA labels and controls only (these are not
11585			 * actually visible on the page, but will be read by screenreaders, and thus
11586			 * must be internationalised as well).
11587			 *  @namespace
11588			 *  @name DataTable.defaults.language.aria
11589			 */
11590			"oAria": {
11591				/**
11592				 * ARIA label that is added to the table headers when the column may be
11593				 * sorted ascending by activing the column (click or return when focused).
11594				 * Note that the column header is prefixed to this string.
11595				 *  @type string
11596				 *  @default : activate to sort column ascending
11597				 *
11598				 *  @dtopt Language
11599				 *  @name DataTable.defaults.language.aria.sortAscending
11600				 *
11601				 *  @example
11602				 *    $(document).ready( function() {
11603				 *      $('#example').dataTable( {
11604				 *        "language": {
11605				 *          "aria": {
11606				 *            "sortAscending": " - click/return to sort ascending"
11607				 *          }
11608				 *        }
11609				 *      } );
11610				 *    } );
11611				 */
11612				"sSortAscending": ": activate to sort column ascending",
11613
11614				/**
11615				 * ARIA label that is added to the table headers when the column may be
11616				 * sorted descending by activing the column (click or return when focused).
11617				 * Note that the column header is prefixed to this string.
11618				 *  @type string
11619				 *  @default : activate to sort column ascending
11620				 *
11621				 *  @dtopt Language
11622				 *  @name DataTable.defaults.language.aria.sortDescending
11623				 *
11624				 *  @example
11625				 *    $(document).ready( function() {
11626				 *      $('#example').dataTable( {
11627				 *        "language": {
11628				 *          "aria": {
11629				 *            "sortDescending": " - click/return to sort descending"
11630				 *          }
11631				 *        }
11632				 *      } );
11633				 *    } );
11634				 */
11635				"sSortDescending": ": activate to sort column descending"
11636			},
11637
11638			/**
11639			 * Pagination string used by DataTables for the built-in pagination
11640			 * control types.
11641			 *  @namespace
11642			 *  @name DataTable.defaults.language.paginate
11643			 */
11644			"oPaginate": {
11645				/**
11646				 * Text to use when using the 'full_numbers' type of pagination for the
11647				 * button to take the user to the first page.
11648				 *  @type string
11649				 *  @default First
11650				 *
11651				 *  @dtopt Language
11652				 *  @name DataTable.defaults.language.paginate.first
11653				 *
11654				 *  @example
11655				 *    $(document).ready( function() {
11656				 *      $('#example').dataTable( {
11657				 *        "language": {
11658				 *          "paginate": {
11659				 *            "first": "First page"
11660				 *          }
11661				 *        }
11662				 *      } );
11663				 *    } );
11664				 */
11665				"sFirst": "First",
11666
11667
11668				/**
11669				 * Text to use when using the 'full_numbers' type of pagination for the
11670				 * button to take the user to the last page.
11671				 *  @type string
11672				 *  @default Last
11673				 *
11674				 *  @dtopt Language
11675				 *  @name DataTable.defaults.language.paginate.last
11676				 *
11677				 *  @example
11678				 *    $(document).ready( function() {
11679				 *      $('#example').dataTable( {
11680				 *        "language": {
11681				 *          "paginate": {
11682				 *            "last": "Last page"
11683				 *          }
11684				 *        }
11685				 *      } );
11686				 *    } );
11687				 */
11688				"sLast": "Last",
11689
11690
11691				/**
11692				 * Text to use for the 'next' pagination button (to take the user to the
11693				 * next page).
11694				 *  @type string
11695				 *  @default Next
11696				 *
11697				 *  @dtopt Language
11698				 *  @name DataTable.defaults.language.paginate.next
11699				 *
11700				 *  @example
11701				 *    $(document).ready( function() {
11702				 *      $('#example').dataTable( {
11703				 *        "language": {
11704				 *          "paginate": {
11705				 *            "next": "Next page"
11706				 *          }
11707				 *        }
11708				 *      } );
11709				 *    } );
11710				 */
11711				"sNext": "Next",
11712
11713
11714				/**
11715				 * Text to use for the 'previous' pagination button (to take the user to
11716				 * the previous page).
11717				 *  @type string
11718				 *  @default Previous
11719				 *
11720				 *  @dtopt Language
11721				 *  @name DataTable.defaults.language.paginate.previous
11722				 *
11723				 *  @example
11724				 *    $(document).ready( function() {
11725				 *      $('#example').dataTable( {
11726				 *        "language": {
11727				 *          "paginate": {
11728				 *            "previous": "Previous page"
11729				 *          }
11730				 *        }
11731				 *      } );
11732				 *    } );
11733				 */
11734				"sPrevious": "Previous"
11735			},
11736
11737			/**
11738			 * This string is shown in preference to `zeroRecords` when the table is
11739			 * empty of data (regardless of filtering). Note that this is an optional
11740			 * parameter - if it is not given, the value of `zeroRecords` will be used
11741			 * instead (either the default or given value).
11742			 *  @type string
11743			 *  @default No data available in table
11744			 *
11745			 *  @dtopt Language
11746			 *  @name DataTable.defaults.language.emptyTable
11747			 *
11748			 *  @example
11749			 *    $(document).ready( function() {
11750			 *      $('#example').dataTable( {
11751			 *        "language": {
11752			 *          "emptyTable": "No data available in table"
11753			 *        }
11754			 *      } );
11755			 *    } );
11756			 */
11757			"sEmptyTable": "No data available in table",
11758
11759
11760			/**
11761			 * This string gives information to the end user about the information
11762			 * that is current on display on the page. The following tokens can be
11763			 * used in the string and will be dynamically replaced as the table
11764			 * display updates. This tokens can be placed anywhere in the string, or
11765			 * removed as needed by the language requires:
11766			 *
11767			 * * `\_START\_` - Display index of the first record on the current page
11768			 * * `\_END\_` - Display index of the last record on the current page
11769			 * * `\_TOTAL\_` - Number of records in the table after filtering
11770			 * * `\_MAX\_` - Number of records in the table without filtering
11771			 * * `\_PAGE\_` - Current page number
11772			 * * `\_PAGES\_` - Total number of pages of data in the table
11773			 *
11774			 *  @type string
11775			 *  @default Showing _START_ to _END_ of _TOTAL_ entries
11776			 *
11777			 *  @dtopt Language
11778			 *  @name DataTable.defaults.language.info
11779			 *
11780			 *  @example
11781			 *    $(document).ready( function() {
11782			 *      $('#example').dataTable( {
11783			 *        "language": {
11784			 *          "info": "Showing page _PAGE_ of _PAGES_"
11785			 *        }
11786			 *      } );
11787			 *    } );
11788			 */
11789			"sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
11790
11791
11792			/**
11793			 * Display information string for when the table is empty. Typically the
11794			 * format of this string should match `info`.
11795			 *  @type string
11796			 *  @default Showing 0 to 0 of 0 entries
11797			 *
11798			 *  @dtopt Language
11799			 *  @name DataTable.defaults.language.infoEmpty
11800			 *
11801			 *  @example
11802			 *    $(document).ready( function() {
11803			 *      $('#example').dataTable( {
11804			 *        "language": {
11805			 *          "infoEmpty": "No entries to show"
11806			 *        }
11807			 *      } );
11808			 *    } );
11809			 */
11810			"sInfoEmpty": "Showing 0 to 0 of 0 entries",
11811
11812
11813			/**
11814			 * When a user filters the information in a table, this string is appended
11815			 * to the information (`info`) to give an idea of how strong the filtering
11816			 * is. The variable _MAX_ is dynamically updated.
11817			 *  @type string
11818			 *  @default (filtered from _MAX_ total entries)
11819			 *
11820			 *  @dtopt Language
11821			 *  @name DataTable.defaults.language.infoFiltered
11822			 *
11823			 *  @example
11824			 *    $(document).ready( function() {
11825			 *      $('#example').dataTable( {
11826			 *        "language": {
11827			 *          "infoFiltered": " - filtering from _MAX_ records"
11828			 *        }
11829			 *      } );
11830			 *    } );
11831			 */
11832			"sInfoFiltered": "(filtered from _MAX_ total entries)",
11833
11834
11835			/**
11836			 * If can be useful to append extra information to the info string at times,
11837			 * and this variable does exactly that. This information will be appended to
11838			 * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are
11839			 * being used) at all times.
11840			 *  @type string
11841			 *  @default <i>Empty string</i>
11842			 *
11843			 *  @dtopt Language
11844			 *  @name DataTable.defaults.language.infoPostFix
11845			 *
11846			 *  @example
11847			 *    $(document).ready( function() {
11848			 *      $('#example').dataTable( {
11849			 *        "language": {
11850			 *          "infoPostFix": "All records shown are derived from real information."
11851			 *        }
11852			 *      } );
11853			 *    } );
11854			 */
11855			"sInfoPostFix": "",
11856
11857
11858			/**
11859			 * This decimal place operator is a little different from the other
11860			 * language options since DataTables doesn't output floating point
11861			 * numbers, so it won't ever use this for display of a number. Rather,
11862			 * what this parameter does is modify the sort methods of the table so
11863			 * that numbers which are in a format which has a character other than
11864			 * a period (`.`) as a decimal place will be sorted numerically.
11865			 *
11866			 * Note that numbers with different decimal places cannot be shown in
11867			 * the same table and still be sortable, the table must be consistent.
11868			 * However, multiple different tables on the page can use different
11869			 * decimal place characters.
11870			 *  @type string
11871			 *  @default
11872			 *
11873			 *  @dtopt Language
11874			 *  @name DataTable.defaults.language.decimal
11875			 *
11876			 *  @example
11877			 *    $(document).ready( function() {
11878			 *      $('#example').dataTable( {
11879			 *        "language": {
11880			 *          "decimal": ","
11881			 *          "thousands": "."
11882			 *        }
11883			 *      } );
11884			 *    } );
11885			 */
11886			"sDecimal": "",
11887
11888
11889			/**
11890			 * DataTables has a build in number formatter (`formatNumber`) which is
11891			 * used to format large numbers that are used in the table information.
11892			 * By default a comma is used, but this can be trivially changed to any
11893			 * character you wish with this parameter.
11894			 *  @type string
11895			 *  @default ,
11896			 *
11897			 *  @dtopt Language
11898			 *  @name DataTable.defaults.language.thousands
11899			 *
11900			 *  @example
11901			 *    $(document).ready( function() {
11902			 *      $('#example').dataTable( {
11903			 *        "language": {
11904			 *          "thousands": "'"
11905			 *        }
11906			 *      } );
11907			 *    } );
11908			 */
11909			"sThousands": ",",
11910
11911
11912			/**
11913			 * Detail the action that will be taken when the drop down menu for the
11914			 * pagination length option is changed. The '_MENU_' variable is replaced
11915			 * with a default select list of 10, 25, 50 and 100, and can be replaced
11916			 * with a custom select box if required.
11917			 *  @type string
11918			 *  @default Show _MENU_ entries
11919			 *
11920			 *  @dtopt Language
11921			 *  @name DataTable.defaults.language.lengthMenu
11922			 *
11923			 *  @example
11924			 *    // Language change only
11925			 *    $(document).ready( function() {
11926			 *      $('#example').dataTable( {
11927			 *        "language": {
11928			 *          "lengthMenu": "Display _MENU_ records"
11929			 *        }
11930			 *      } );
11931			 *    } );
11932			 *
11933			 *  @example
11934			 *    // Language and options change
11935			 *    $(document).ready( function() {
11936			 *      $('#example').dataTable( {
11937			 *        "language": {
11938			 *          "lengthMenu": 'Display <select>'+
11939			 *            '<option value="10">10</option>'+
11940			 *            '<option value="20">20</option>'+
11941			 *            '<option value="30">30</option>'+
11942			 *            '<option value="40">40</option>'+
11943			 *            '<option value="50">50</option>'+
11944			 *            '<option value="-1">All</option>'+
11945			 *            '</select> records'
11946			 *        }
11947			 *      } );
11948			 *    } );
11949			 */
11950			"sLengthMenu": "Show _MENU_ entries",
11951
11952
11953			/**
11954			 * When using Ajax sourced data and during the first draw when DataTables is
11955			 * gathering the data, this message is shown in an empty row in the table to
11956			 * indicate to the end user the the data is being loaded. Note that this
11957			 * parameter is not used when loading data by server-side processing, just
11958			 * Ajax sourced data with client-side processing.
11959			 *  @type string
11960			 *  @default Loading...
11961			 *
11962			 *  @dtopt Language
11963			 *  @name DataTable.defaults.language.loadingRecords
11964			 *
11965			 *  @example
11966			 *    $(document).ready( function() {
11967			 *      $('#example').dataTable( {
11968			 *        "language": {
11969			 *          "loadingRecords": "Please wait - loading..."
11970			 *        }
11971			 *      } );
11972			 *    } );
11973			 */
11974			"sLoadingRecords": "Loading...",
11975
11976
11977			/**
11978			 * Text which is displayed when the table is processing a user action
11979			 * (usually a sort command or similar).
11980			 *  @type string
11981			 *
11982			 *  @dtopt Language
11983			 *  @name DataTable.defaults.language.processing
11984			 *
11985			 *  @example
11986			 *    $(document).ready( function() {
11987			 *      $('#example').dataTable( {
11988			 *        "language": {
11989			 *          "processing": "DataTables is currently busy"
11990			 *        }
11991			 *      } );
11992			 *    } );
11993			 */
11994			"sProcessing": "",
11995
11996
11997			/**
11998			 * Details the actions that will be taken when the user types into the
11999			 * filtering input text box. The variable "_INPUT_", if used in the string,
12000			 * is replaced with the HTML text box for the filtering input allowing
12001			 * control over where it appears in the string. If "_INPUT_" is not given
12002			 * then the input box is appended to the string automatically.
12003			 *  @type string
12004			 *  @default Search:
12005			 *
12006			 *  @dtopt Language
12007			 *  @name DataTable.defaults.language.search
12008			 *
12009			 *  @example
12010			 *    // Input text box will be appended at the end automatically
12011			 *    $(document).ready( function() {
12012			 *      $('#example').dataTable( {
12013			 *        "language": {
12014			 *          "search": "Filter records:"
12015			 *        }
12016			 *      } );
12017			 *    } );
12018			 *
12019			 *  @example
12020			 *    // Specify where the filter should appear
12021			 *    $(document).ready( function() {
12022			 *      $('#example').dataTable( {
12023			 *        "language": {
12024			 *          "search": "Apply filter _INPUT_ to table"
12025			 *        }
12026			 *      } );
12027			 *    } );
12028			 */
12029			"sSearch": "Search:",
12030
12031
12032			/**
12033			 * Assign a `placeholder` attribute to the search `input` element
12034			 *  @type string
12035			 *  @default
12036			 *
12037			 *  @dtopt Language
12038			 *  @name DataTable.defaults.language.searchPlaceholder
12039			 */
12040			"sSearchPlaceholder": "",
12041
12042
12043			/**
12044			 * All of the language information can be stored in a file on the
12045			 * server-side, which DataTables will look up if this parameter is passed.
12046			 * It must store the URL of the language file, which is in a JSON format,
12047			 * and the object has the same properties as the oLanguage object in the
12048			 * initialiser object (i.e. the above parameters). Please refer to one of
12049			 * the example language files to see how this works in action.
12050			 *  @type string
12051			 *  @default <i>Empty string - i.e. disabled</i>
12052			 *
12053			 *  @dtopt Language
12054			 *  @name DataTable.defaults.language.url
12055			 *
12056			 *  @example
12057			 *    $(document).ready( function() {
12058			 *      $('#example').dataTable( {
12059			 *        "language": {
12060			 *          "url": "http://www.sprymedia.co.uk/dataTables/lang.txt"
12061			 *        }
12062			 *      } );
12063			 *    } );
12064			 */
12065			"sUrl": "",
12066
12067
12068			/**
12069			 * Text shown inside the table records when the is no information to be
12070			 * displayed after filtering. `emptyTable` is shown when there is simply no
12071			 * information in the table at all (regardless of filtering).
12072			 *  @type string
12073			 *  @default No matching records found
12074			 *
12075			 *  @dtopt Language
12076			 *  @name DataTable.defaults.language.zeroRecords
12077			 *
12078			 *  @example
12079			 *    $(document).ready( function() {
12080			 *      $('#example').dataTable( {
12081			 *        "language": {
12082			 *          "zeroRecords": "No records to display"
12083			 *        }
12084			 *      } );
12085			 *    } );
12086			 */
12087			"sZeroRecords": "No matching records found"
12088		},
12089
12090
12091		/**
12092		 * This parameter allows you to have define the global filtering state at
12093		 * initialisation time. As an object the `search` parameter must be
12094		 * defined, but all other parameters are optional. When `regex` is true,
12095		 * the search string will be treated as a regular expression, when false
12096		 * (default) it will be treated as a straight string. When `smart`
12097		 * DataTables will use it's smart filtering methods (to word match at
12098		 * any point in the data), when false this will not be done.
12099		 *  @namespace
12100		 *  @extends DataTable.models.oSearch
12101		 *
12102		 *  @dtopt Options
12103		 *  @name DataTable.defaults.search
12104		 *
12105		 *  @example
12106		 *    $(document).ready( function() {
12107		 *      $('#example').dataTable( {
12108		 *        "search": {"search": "Initial search"}
12109		 *      } );
12110		 *    } )
12111		 */
12112		"oSearch": $.extend( {}, DataTable.models.oSearch ),
12113
12114
12115		/**
12116		 * __Deprecated__ The functionality provided by this parameter has now been
12117		 * superseded by that provided through `ajax`, which should be used instead.
12118		 *
12119		 * By default DataTables will look for the property `data` (or `aaData` for
12120		 * compatibility with DataTables 1.9-) when obtaining data from an Ajax
12121		 * source or for server-side processing - this parameter allows that
12122		 * property to be changed. You can use Javascript dotted object notation to
12123		 * get a data source for multiple levels of nesting.
12124		 *  @type string
12125		 *  @default data
12126		 *
12127		 *  @dtopt Options
12128		 *  @dtopt Server-side
12129		 *  @name DataTable.defaults.ajaxDataProp
12130		 *
12131		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
12132		 */
12133		"sAjaxDataProp": "data",
12134
12135
12136		/**
12137		 * __Deprecated__ The functionality provided by this parameter has now been
12138		 * superseded by that provided through `ajax`, which should be used instead.
12139		 *
12140		 * You can instruct DataTables to load data from an external
12141		 * source using this parameter (use aData if you want to pass data in you
12142		 * already have). Simply provide a url a JSON object can be obtained from.
12143		 *  @type string
12144		 *  @default null
12145		 *
12146		 *  @dtopt Options
12147		 *  @dtopt Server-side
12148		 *  @name DataTable.defaults.ajaxSource
12149		 *
12150		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
12151		 */
12152		"sAjaxSource": null,
12153
12154
12155		/**
12156		 * This initialisation variable allows you to specify exactly where in the
12157		 * DOM you want DataTables to inject the various controls it adds to the page
12158		 * (for example you might want the pagination controls at the top of the
12159		 * table). DIV elements (with or without a custom class) can also be added to
12160		 * aid styling. The follow syntax is used:
12161		 *   <ul>
12162		 *     <li>The following options are allowed:
12163		 *       <ul>
12164		 *         <li>'l' - Length changing</li>
12165		 *         <li>'f' - Filtering input</li>
12166		 *         <li>'t' - The table!</li>
12167		 *         <li>'i' - Information</li>
12168		 *         <li>'p' - Pagination</li>
12169		 *         <li>'r' - pRocessing</li>
12170		 *       </ul>
12171		 *     </li>
12172		 *     <li>The following constants are allowed:
12173		 *       <ul>
12174		 *         <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>
12175		 *         <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>
12176		 *       </ul>
12177		 *     </li>
12178		 *     <li>The following syntax is expected:
12179		 *       <ul>
12180		 *         <li>'&lt;' and '&gt;' - div elements</li>
12181		 *         <li>'&lt;"class" and '&gt;' - div with a class</li>
12182		 *         <li>'&lt;"#id" and '&gt;' - div with an ID</li>
12183		 *       </ul>
12184		 *     </li>
12185		 *     <li>Examples:
12186		 *       <ul>
12187		 *         <li>'&lt;"wrapper"flipt&gt;'</li>
12188		 *         <li>'&lt;lf&lt;t&gt;ip&gt;'</li>
12189		 *       </ul>
12190		 *     </li>
12191		 *   </ul>
12192		 *  @type string
12193		 *  @default lfrtip <i>(when `jQueryUI` is false)</i> <b>or</b>
12194		 *    <"H"lfr>t<"F"ip> <i>(when `jQueryUI` is true)</i>
12195		 *
12196		 *  @dtopt Options
12197		 *  @name DataTable.defaults.dom
12198		 *
12199		 *  @example
12200		 *    $(document).ready( function() {
12201		 *      $('#example').dataTable( {
12202		 *        "dom": '&lt;"top"i&gt;rt&lt;"bottom"flp&gt;&lt;"clear"&gt;'
12203		 *      } );
12204		 *    } );
12205		 */
12206		"sDom": "lfrtip",
12207
12208
12209		/**
12210		 * Search delay option. This will throttle full table searches that use the
12211		 * DataTables provided search input element (it does not effect calls to
12212		 * `dt-api search()`, providing a delay before the search is made.
12213		 *  @type integer
12214		 *  @default 0
12215		 *
12216		 *  @dtopt Options
12217		 *  @name DataTable.defaults.searchDelay
12218		 *
12219		 *  @example
12220		 *    $(document).ready( function() {
12221		 *      $('#example').dataTable( {
12222		 *        "searchDelay": 200
12223		 *      } );
12224		 *    } )
12225		 */
12226		"searchDelay": null,
12227
12228
12229		/**
12230		 * DataTables features six different built-in options for the buttons to
12231		 * display for pagination control:
12232		 *
12233		 * * `numbers` - Page number buttons only
12234		 * * `simple` - 'Previous' and 'Next' buttons only
12235		 * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers
12236		 * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons
12237		 * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus page numbers
12238		 * * `first_last_numbers` - 'First' and 'Last' buttons, plus page numbers
12239		 *
12240		 * Further methods can be added using {@link DataTable.ext.oPagination}.
12241		 *  @type string
12242		 *  @default simple_numbers
12243		 *
12244		 *  @dtopt Options
12245		 *  @name DataTable.defaults.pagingType
12246		 *
12247		 *  @example
12248		 *    $(document).ready( function() {
12249		 *      $('#example').dataTable( {
12250		 *        "pagingType": "full_numbers"
12251		 *      } );
12252		 *    } )
12253		 */
12254		"sPaginationType": "simple_numbers",
12255
12256
12257		/**
12258		 * Enable horizontal scrolling. When a table is too wide to fit into a
12259		 * certain layout, or you have a large number of columns in the table, you
12260		 * can enable x-scrolling to show the table in a viewport, which can be
12261		 * scrolled. This property can be `true` which will allow the table to
12262		 * scroll horizontally when needed, or any CSS unit, or a number (in which
12263		 * case it will be treated as a pixel measurement). Setting as simply `true`
12264		 * is recommended.
12265		 *  @type boolean|string
12266		 *  @default <i>blank string - i.e. disabled</i>
12267		 *
12268		 *  @dtopt Features
12269		 *  @name DataTable.defaults.scrollX
12270		 *
12271		 *  @example
12272		 *    $(document).ready( function() {
12273		 *      $('#example').dataTable( {
12274		 *        "scrollX": true,
12275		 *        "scrollCollapse": true
12276		 *      } );
12277		 *    } );
12278		 */
12279		"sScrollX": "",
12280
12281
12282		/**
12283		 * This property can be used to force a DataTable to use more width than it
12284		 * might otherwise do when x-scrolling is enabled. For example if you have a
12285		 * table which requires to be well spaced, this parameter is useful for
12286		 * "over-sizing" the table, and thus forcing scrolling. This property can by
12287		 * any CSS unit, or a number (in which case it will be treated as a pixel
12288		 * measurement).
12289		 *  @type string
12290		 *  @default <i>blank string - i.e. disabled</i>
12291		 *
12292		 *  @dtopt Options
12293		 *  @name DataTable.defaults.scrollXInner
12294		 *
12295		 *  @example
12296		 *    $(document).ready( function() {
12297		 *      $('#example').dataTable( {
12298		 *        "scrollX": "100%",
12299		 *        "scrollXInner": "110%"
12300		 *      } );
12301		 *    } );
12302		 */
12303		"sScrollXInner": "",
12304
12305
12306		/**
12307		 * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
12308		 * to the given height, and enable scrolling for any data which overflows the
12309		 * current viewport. This can be used as an alternative to paging to display
12310		 * a lot of data in a small area (although paging and scrolling can both be
12311		 * enabled at the same time). This property can be any CSS unit, or a number
12312		 * (in which case it will be treated as a pixel measurement).
12313		 *  @type string
12314		 *  @default <i>blank string - i.e. disabled</i>
12315		 *
12316		 *  @dtopt Features
12317		 *  @name DataTable.defaults.scrollY
12318		 *
12319		 *  @example
12320		 *    $(document).ready( function() {
12321		 *      $('#example').dataTable( {
12322		 *        "scrollY": "200px",
12323		 *        "paginate": false
12324		 *      } );
12325		 *    } );
12326		 */
12327		"sScrollY": "",
12328
12329
12330		/**
12331		 * __Deprecated__ The functionality provided by this parameter has now been
12332		 * superseded by that provided through `ajax`, which should be used instead.
12333		 *
12334		 * Set the HTTP method that is used to make the Ajax call for server-side
12335		 * processing or Ajax sourced data.
12336		 *  @type string
12337		 *  @default GET
12338		 *
12339		 *  @dtopt Options
12340		 *  @dtopt Server-side
12341		 *  @name DataTable.defaults.serverMethod
12342		 *
12343		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
12344		 */
12345		"sServerMethod": "GET",
12346
12347
12348		/**
12349		 * DataTables makes use of renderers when displaying HTML elements for
12350		 * a table. These renderers can be added or modified by plug-ins to
12351		 * generate suitable mark-up for a site. For example the Bootstrap
12352		 * integration plug-in for DataTables uses a paging button renderer to
12353		 * display pagination buttons in the mark-up required by Bootstrap.
12354		 *
12355		 * For further information about the renderers available see
12356		 * DataTable.ext.renderer
12357		 *  @type string|object
12358		 *  @default null
12359		 *
12360		 *  @name DataTable.defaults.renderer
12361		 *
12362		 */
12363		"renderer": null,
12364
12365
12366		/**
12367		 * Set the data property name that DataTables should use to get a row's id
12368		 * to set as the `id` property in the node.
12369		 *  @type string
12370		 *  @default DT_RowId
12371		 *
12372		 *  @name DataTable.defaults.rowId
12373		 */
12374		"rowId": "DT_RowId"
12375	};
12376
12377	_fnHungarianMap( DataTable.defaults );
12378
12379
12380
12381	/*
12382	 * Developer note - See note in model.defaults.js about the use of Hungarian
12383	 * notation and camel case.
12384	 */
12385
12386	/**
12387	 * Column options that can be given to DataTables at initialisation time.
12388	 *  @namespace
12389	 */
12390	DataTable.defaults.column = {
12391		/**
12392		 * Define which column(s) an order will occur on for this column. This
12393		 * allows a column's ordering to take multiple columns into account when
12394		 * doing a sort or use the data from a different column. For example first
12395		 * name / last name columns make sense to do a multi-column sort over the
12396		 * two columns.
12397		 *  @type array|int
12398		 *  @default null <i>Takes the value of the column index automatically</i>
12399		 *
12400		 *  @name DataTable.defaults.column.orderData
12401		 *  @dtopt Columns
12402		 *
12403		 *  @example
12404		 *    // Using `columnDefs`
12405		 *    $(document).ready( function() {
12406		 *      $('#example').dataTable( {
12407		 *        "columnDefs": [
12408		 *          { "orderData": [ 0, 1 ], "targets": [ 0 ] },
12409		 *          { "orderData": [ 1, 0 ], "targets": [ 1 ] },
12410		 *          { "orderData": 2, "targets": [ 2 ] }
12411		 *        ]
12412		 *      } );
12413		 *    } );
12414		 *
12415		 *  @example
12416		 *    // Using `columns`
12417		 *    $(document).ready( function() {
12418		 *      $('#example').dataTable( {
12419		 *        "columns": [
12420		 *          { "orderData": [ 0, 1 ] },
12421		 *          { "orderData": [ 1, 0 ] },
12422		 *          { "orderData": 2 },
12423		 *          null,
12424		 *          null
12425		 *        ]
12426		 *      } );
12427		 *    } );
12428		 */
12429		"aDataSort": null,
12430		"iDataSort": -1,
12431
12432
12433		/**
12434		 * You can control the default ordering direction, and even alter the
12435		 * behaviour of the sort handler (i.e. only allow ascending ordering etc)
12436		 * using this parameter.
12437		 *  @type array
12438		 *  @default [ 'asc', 'desc' ]
12439		 *
12440		 *  @name DataTable.defaults.column.orderSequence
12441		 *  @dtopt Columns
12442		 *
12443		 *  @example
12444		 *    // Using `columnDefs`
12445		 *    $(document).ready( function() {
12446		 *      $('#example').dataTable( {
12447		 *        "columnDefs": [
12448		 *          { "orderSequence": [ "asc" ], "targets": [ 1 ] },
12449		 *          { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] },
12450		 *          { "orderSequence": [ "desc" ], "targets": [ 3 ] }
12451		 *        ]
12452		 *      } );
12453		 *    } );
12454		 *
12455		 *  @example
12456		 *    // Using `columns`
12457		 *    $(document).ready( function() {
12458		 *      $('#example').dataTable( {
12459		 *        "columns": [
12460		 *          null,
12461		 *          { "orderSequence": [ "asc" ] },
12462		 *          { "orderSequence": [ "desc", "asc", "asc" ] },
12463		 *          { "orderSequence": [ "desc" ] },
12464		 *          null
12465		 *        ]
12466		 *      } );
12467		 *    } );
12468		 */
12469		"asSorting": [ 'asc', 'desc' ],
12470
12471
12472		/**
12473		 * Enable or disable filtering on the data in this column.
12474		 *  @type boolean
12475		 *  @default true
12476		 *
12477		 *  @name DataTable.defaults.column.searchable
12478		 *  @dtopt Columns
12479		 *
12480		 *  @example
12481		 *    // Using `columnDefs`
12482		 *    $(document).ready( function() {
12483		 *      $('#example').dataTable( {
12484		 *        "columnDefs": [
12485		 *          { "searchable": false, "targets": [ 0 ] }
12486		 *        ] } );
12487		 *    } );
12488		 *
12489		 *  @example
12490		 *    // Using `columns`
12491		 *    $(document).ready( function() {
12492		 *      $('#example').dataTable( {
12493		 *        "columns": [
12494		 *          { "searchable": false },
12495		 *          null,
12496		 *          null,
12497		 *          null,
12498		 *          null
12499		 *        ] } );
12500		 *    } );
12501		 */
12502		"bSearchable": true,
12503
12504
12505		/**
12506		 * Enable or disable ordering on this column.
12507		 *  @type boolean
12508		 *  @default true
12509		 *
12510		 *  @name DataTable.defaults.column.orderable
12511		 *  @dtopt Columns
12512		 *
12513		 *  @example
12514		 *    // Using `columnDefs`
12515		 *    $(document).ready( function() {
12516		 *      $('#example').dataTable( {
12517		 *        "columnDefs": [
12518		 *          { "orderable": false, "targets": [ 0 ] }
12519		 *        ] } );
12520		 *    } );
12521		 *
12522		 *  @example
12523		 *    // Using `columns`
12524		 *    $(document).ready( function() {
12525		 *      $('#example').dataTable( {
12526		 *        "columns": [
12527		 *          { "orderable": false },
12528		 *          null,
12529		 *          null,
12530		 *          null,
12531		 *          null
12532		 *        ] } );
12533		 *    } );
12534		 */
12535		"bSortable": true,
12536
12537
12538		/**
12539		 * Enable or disable the display of this column.
12540		 *  @type boolean
12541		 *  @default true
12542		 *
12543		 *  @name DataTable.defaults.column.visible
12544		 *  @dtopt Columns
12545		 *
12546		 *  @example
12547		 *    // Using `columnDefs`
12548		 *    $(document).ready( function() {
12549		 *      $('#example').dataTable( {
12550		 *        "columnDefs": [
12551		 *          { "visible": false, "targets": [ 0 ] }
12552		 *        ] } );
12553		 *    } );
12554		 *
12555		 *  @example
12556		 *    // Using `columns`
12557		 *    $(document).ready( function() {
12558		 *      $('#example').dataTable( {
12559		 *        "columns": [
12560		 *          { "visible": false },
12561		 *          null,
12562		 *          null,
12563		 *          null,
12564		 *          null
12565		 *        ] } );
12566		 *    } );
12567		 */
12568		"bVisible": true,
12569
12570
12571		/**
12572		 * Developer definable function that is called whenever a cell is created (Ajax source,
12573		 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
12574		 * allowing you to modify the DOM element (add background colour for example) when the
12575		 * element is available.
12576		 *  @type function
12577		 *  @param {element} td The TD node that has been created
12578		 *  @param {*} cellData The Data for the cell
12579		 *  @param {array|object} rowData The data for the whole row
12580		 *  @param {int} row The row index for the aoData data store
12581		 *  @param {int} col The column index for aoColumns
12582		 *
12583		 *  @name DataTable.defaults.column.createdCell
12584		 *  @dtopt Columns
12585		 *
12586		 *  @example
12587		 *    $(document).ready( function() {
12588		 *      $('#example').dataTable( {
12589		 *        "columnDefs": [ {
12590		 *          "targets": [3],
12591		 *          "createdCell": function (td, cellData, rowData, row, col) {
12592		 *            if ( cellData == "1.7" ) {
12593		 *              $(td).css('color', 'blue')
12594		 *            }
12595		 *          }
12596		 *        } ]
12597		 *      });
12598		 *    } );
12599		 */
12600		"fnCreatedCell": null,
12601
12602
12603		/**
12604		 * This parameter has been replaced by `data` in DataTables to ensure naming
12605		 * consistency. `dataProp` can still be used, as there is backwards
12606		 * compatibility in DataTables for this option, but it is strongly
12607		 * recommended that you use `data` in preference to `dataProp`.
12608		 *  @name DataTable.defaults.column.dataProp
12609		 */
12610
12611
12612		/**
12613		 * This property can be used to read data from any data source property,
12614		 * including deeply nested objects / properties. `data` can be given in a
12615		 * number of different ways which effect its behaviour:
12616		 *
12617		 * * `integer` - treated as an array index for the data source. This is the
12618		 *   default that DataTables uses (incrementally increased for each column).
12619		 * * `string` - read an object property from the data source. There are
12620		 *   three 'special' options that can be used in the string to alter how
12621		 *   DataTables reads the data from the source object:
12622		 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
12623		 *      Javascript to read from nested objects, so to can the options
12624		 *      specified in `data`. For example: `browser.version` or
12625		 *      `browser.name`. If your object parameter name contains a period, use
12626		 *      `\\` to escape it - i.e. `first\\.name`.
12627		 *    * `[]` - Array notation. DataTables can automatically combine data
12628		 *      from and array source, joining the data with the characters provided
12629		 *      between the two brackets. For example: `name[, ]` would provide a
12630		 *      comma-space separated list from the source array. If no characters
12631		 *      are provided between the brackets, the original array source is
12632		 *      returned.
12633		 *    * `()` - Function notation. Adding `()` to the end of a parameter will
12634		 *      execute a function of the name given. For example: `browser()` for a
12635		 *      simple function on the data source, `browser.version()` for a
12636		 *      function in a nested property or even `browser().version` to get an
12637		 *      object property if the function called returns an object. Note that
12638		 *      function notation is recommended for use in `render` rather than
12639		 *      `data` as it is much simpler to use as a renderer.
12640		 * * `null` - use the original data source for the row rather than plucking
12641		 *   data directly from it. This action has effects on two other
12642		 *   initialisation options:
12643		 *    * `defaultContent` - When null is given as the `data` option and
12644		 *      `defaultContent` is specified for the column, the value defined by
12645		 *      `defaultContent` will be used for the cell.
12646		 *    * `render` - When null is used for the `data` option and the `render`
12647		 *      option is specified for the column, the whole data source for the
12648		 *      row is used for the renderer.
12649		 * * `function` - the function given will be executed whenever DataTables
12650		 *   needs to set or get the data for a cell in the column. The function
12651		 *   takes three parameters:
12652		 *    * Parameters:
12653		 *      * `{array|object}` The data source for the row
12654		 *      * `{string}` The type call data requested - this will be 'set' when
12655		 *        setting data or 'filter', 'display', 'type', 'sort' or undefined
12656		 *        when gathering data. Note that when `undefined` is given for the
12657		 *        type DataTables expects to get the raw data for the object back<
12658		 *      * `{*}` Data to set when the second parameter is 'set'.
12659		 *    * Return:
12660		 *      * The return value from the function is not required when 'set' is
12661		 *        the type of call, but otherwise the return is what will be used
12662		 *        for the data requested.
12663		 *
12664		 * Note that `data` is a getter and setter option. If you just require
12665		 * formatting of data for output, you will likely want to use `render` which
12666		 * is simply a getter and thus simpler to use.
12667		 *
12668		 * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The
12669		 * name change reflects the flexibility of this property and is consistent
12670		 * with the naming of mRender. If 'mDataProp' is given, then it will still
12671		 * be used by DataTables, as it automatically maps the old name to the new
12672		 * if required.
12673		 *
12674		 *  @type string|int|function|null
12675		 *  @default null <i>Use automatically calculated column index</i>
12676		 *
12677		 *  @name DataTable.defaults.column.data
12678		 *  @dtopt Columns
12679		 *
12680		 *  @example
12681		 *    // Read table data from objects
12682		 *    // JSON structure for each row:
12683		 *    //   {
12684		 *    //      "engine": {value},
12685		 *    //      "browser": {value},
12686		 *    //      "platform": {value},
12687		 *    //      "version": {value},
12688		 *    //      "grade": {value}
12689		 *    //   }
12690		 *    $(document).ready( function() {
12691		 *      $('#example').dataTable( {
12692		 *        "ajaxSource": "sources/objects.txt",
12693		 *        "columns": [
12694		 *          { "data": "engine" },
12695		 *          { "data": "browser" },
12696		 *          { "data": "platform" },
12697		 *          { "data": "version" },
12698		 *          { "data": "grade" }
12699		 *        ]
12700		 *      } );
12701		 *    } );
12702		 *
12703		 *  @example
12704		 *    // Read information from deeply nested objects
12705		 *    // JSON structure for each row:
12706		 *    //   {
12707		 *    //      "engine": {value},
12708		 *    //      "browser": {value},
12709		 *    //      "platform": {
12710		 *    //         "inner": {value}
12711		 *    //      },
12712		 *    //      "details": [
12713		 *    //         {value}, {value}
12714		 *    //      ]
12715		 *    //   }
12716		 *    $(document).ready( function() {
12717		 *      $('#example').dataTable( {
12718		 *        "ajaxSource": "sources/deep.txt",
12719		 *        "columns": [
12720		 *          { "data": "engine" },
12721		 *          { "data": "browser" },
12722		 *          { "data": "platform.inner" },
12723		 *          { "data": "details.0" },
12724		 *          { "data": "details.1" }
12725		 *        ]
12726		 *      } );
12727		 *    } );
12728		 *
12729		 *  @example
12730		 *    // Using `data` as a function to provide different information for
12731		 *    // sorting, filtering and display. In this case, currency (price)
12732		 *    $(document).ready( function() {
12733		 *      $('#example').dataTable( {
12734		 *        "columnDefs": [ {
12735		 *          "targets": [ 0 ],
12736		 *          "data": function ( source, type, val ) {
12737		 *            if (type === 'set') {
12738		 *              source.price = val;
12739		 *              // Store the computed display and filter values for efficiency
12740		 *              source.price_display = val=="" ? "" : "$"+numberFormat(val);
12741		 *              source.price_filter  = val=="" ? "" : "$"+numberFormat(val)+" "+val;
12742		 *              return;
12743		 *            }
12744		 *            else if (type === 'display') {
12745		 *              return source.price_display;
12746		 *            }
12747		 *            else if (type === 'filter') {
12748		 *              return source.price_filter;
12749		 *            }
12750		 *            // 'sort', 'type' and undefined all just use the integer
12751		 *            return source.price;
12752		 *          }
12753		 *        } ]
12754		 *      } );
12755		 *    } );
12756		 *
12757		 *  @example
12758		 *    // Using default content
12759		 *    $(document).ready( function() {
12760		 *      $('#example').dataTable( {
12761		 *        "columnDefs": [ {
12762		 *          "targets": [ 0 ],
12763		 *          "data": null,
12764		 *          "defaultContent": "Click to edit"
12765		 *        } ]
12766		 *      } );
12767		 *    } );
12768		 *
12769		 *  @example
12770		 *    // Using array notation - outputting a list from an array
12771		 *    $(document).ready( function() {
12772		 *      $('#example').dataTable( {
12773		 *        "columnDefs": [ {
12774		 *          "targets": [ 0 ],
12775		 *          "data": "name[, ]"
12776		 *        } ]
12777		 *      } );
12778		 *    } );
12779		 *
12780		 */
12781		"mData": null,
12782
12783
12784		/**
12785		 * This property is the rendering partner to `data` and it is suggested that
12786		 * when you want to manipulate data for display (including filtering,
12787		 * sorting etc) without altering the underlying data for the table, use this
12788		 * property. `render` can be considered to be the the read only companion to
12789		 * `data` which is read / write (then as such more complex). Like `data`
12790		 * this option can be given in a number of different ways to effect its
12791		 * behaviour:
12792		 *
12793		 * * `integer` - treated as an array index for the data source. This is the
12794		 *   default that DataTables uses (incrementally increased for each column).
12795		 * * `string` - read an object property from the data source. There are
12796		 *   three 'special' options that can be used in the string to alter how
12797		 *   DataTables reads the data from the source object:
12798		 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
12799		 *      Javascript to read from nested objects, so to can the options
12800		 *      specified in `data`. For example: `browser.version` or
12801		 *      `browser.name`. If your object parameter name contains a period, use
12802		 *      `\\` to escape it - i.e. `first\\.name`.
12803		 *    * `[]` - Array notation. DataTables can automatically combine data
12804		 *      from and array source, joining the data with the characters provided
12805		 *      between the two brackets. For example: `name[, ]` would provide a
12806		 *      comma-space separated list from the source array. If no characters
12807		 *      are provided between the brackets, the original array source is
12808		 *      returned.
12809		 *    * `()` - Function notation. Adding `()` to the end of a parameter will
12810		 *      execute a function of the name given. For example: `browser()` for a
12811		 *      simple function on the data source, `browser.version()` for a
12812		 *      function in a nested property or even `browser().version` to get an
12813		 *      object property if the function called returns an object.
12814		 * * `object` - use different data for the different data types requested by
12815		 *   DataTables ('filter', 'display', 'type' or 'sort'). The property names
12816		 *   of the object is the data type the property refers to and the value can
12817		 *   defined using an integer, string or function using the same rules as
12818		 *   `render` normally does. Note that an `_` option _must_ be specified.
12819		 *   This is the default value to use if you haven't specified a value for
12820		 *   the data type requested by DataTables.
12821		 * * `function` - the function given will be executed whenever DataTables
12822		 *   needs to set or get the data for a cell in the column. The function
12823		 *   takes three parameters:
12824		 *    * Parameters:
12825		 *      * {array|object} The data source for the row (based on `data`)
12826		 *      * {string} The type call data requested - this will be 'filter',
12827		 *        'display', 'type' or 'sort'.
12828		 *      * {array|object} The full data source for the row (not based on
12829		 *        `data`)
12830		 *    * Return:
12831		 *      * The return value from the function is what will be used for the
12832		 *        data requested.
12833		 *
12834		 *  @type string|int|function|object|null
12835		 *  @default null Use the data source value.
12836		 *
12837		 *  @name DataTable.defaults.column.render
12838		 *  @dtopt Columns
12839		 *
12840		 *  @example
12841		 *    // Create a comma separated list from an array of objects
12842		 *    $(document).ready( function() {
12843		 *      $('#example').dataTable( {
12844		 *        "ajaxSource": "sources/deep.txt",
12845		 *        "columns": [
12846		 *          { "data": "engine" },
12847		 *          { "data": "browser" },
12848		 *          {
12849		 *            "data": "platform",
12850		 *            "render": "[, ].name"
12851		 *          }
12852		 *        ]
12853		 *      } );
12854		 *    } );
12855		 *
12856		 *  @example
12857		 *    // Execute a function to obtain data
12858		 *    $(document).ready( function() {
12859		 *      $('#example').dataTable( {
12860		 *        "columnDefs": [ {
12861		 *          "targets": [ 0 ],
12862		 *          "data": null, // Use the full data source object for the renderer's source
12863		 *          "render": "browserName()"
12864		 *        } ]
12865		 *      } );
12866		 *    } );
12867		 *
12868		 *  @example
12869		 *    // As an object, extracting different data for the different types
12870		 *    // This would be used with a data source such as:
12871		 *    //   { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" }
12872		 *    // Here the `phone` integer is used for sorting and type detection, while `phone_filter`
12873		 *    // (which has both forms) is used for filtering for if a user inputs either format, while
12874		 *    // the formatted phone number is the one that is shown in the table.
12875		 *    $(document).ready( function() {
12876		 *      $('#example').dataTable( {
12877		 *        "columnDefs": [ {
12878		 *          "targets": [ 0 ],
12879		 *          "data": null, // Use the full data source object for the renderer's source
12880		 *          "render": {
12881		 *            "_": "phone",
12882		 *            "filter": "phone_filter",
12883		 *            "display": "phone_display"
12884		 *          }
12885		 *        } ]
12886		 *      } );
12887		 *    } );
12888		 *
12889		 *  @example
12890		 *    // Use as a function to create a link from the data source
12891		 *    $(document).ready( function() {
12892		 *      $('#example').dataTable( {
12893		 *        "columnDefs": [ {
12894		 *          "targets": [ 0 ],
12895		 *          "data": "download_link",
12896		 *          "render": function ( data, type, full ) {
12897		 *            return '<a href="'+data+'">Download</a>';
12898		 *          }
12899		 *        } ]
12900		 *      } );
12901		 *    } );
12902		 */
12903		"mRender": null,
12904
12905
12906		/**
12907		 * Change the cell type created for the column - either TD cells or TH cells. This
12908		 * can be useful as TH cells have semantic meaning in the table body, allowing them
12909		 * to act as a header for a row (you may wish to add scope='row' to the TH elements).
12910		 *  @type string
12911		 *  @default td
12912		 *
12913		 *  @name DataTable.defaults.column.cellType
12914		 *  @dtopt Columns
12915		 *
12916		 *  @example
12917		 *    // Make the first column use TH cells
12918		 *    $(document).ready( function() {
12919		 *      $('#example').dataTable( {
12920		 *        "columnDefs": [ {
12921		 *          "targets": [ 0 ],
12922		 *          "cellType": "th"
12923		 *        } ]
12924		 *      } );
12925		 *    } );
12926		 */
12927		"sCellType": "td",
12928
12929
12930		/**
12931		 * Class to give to each cell in this column.
12932		 *  @type string
12933		 *  @default <i>Empty string</i>
12934		 *
12935		 *  @name DataTable.defaults.column.class
12936		 *  @dtopt Columns
12937		 *
12938		 *  @example
12939		 *    // Using `columnDefs`
12940		 *    $(document).ready( function() {
12941		 *      $('#example').dataTable( {
12942		 *        "columnDefs": [
12943		 *          { "class": "my_class", "targets": [ 0 ] }
12944		 *        ]
12945		 *      } );
12946		 *    } );
12947		 *
12948		 *  @example
12949		 *    // Using `columns`
12950		 *    $(document).ready( function() {
12951		 *      $('#example').dataTable( {
12952		 *        "columns": [
12953		 *          { "class": "my_class" },
12954		 *          null,
12955		 *          null,
12956		 *          null,
12957		 *          null
12958		 *        ]
12959		 *      } );
12960		 *    } );
12961		 */
12962		"sClass": "",
12963
12964		/**
12965		 * When DataTables calculates the column widths to assign to each column,
12966		 * it finds the longest string in each column and then constructs a
12967		 * temporary table and reads the widths from that. The problem with this
12968		 * is that "mmm" is much wider then "iiii", but the latter is a longer
12969		 * string - thus the calculation can go wrong (doing it properly and putting
12970		 * it into an DOM object and measuring that is horribly(!) slow). Thus as
12971		 * a "work around" we provide this option. It will append its value to the
12972		 * text that is found to be the longest string for the column - i.e. padding.
12973		 * Generally you shouldn't need this!
12974		 *  @type string
12975		 *  @default <i>Empty string<i>
12976		 *
12977		 *  @name DataTable.defaults.column.contentPadding
12978		 *  @dtopt Columns
12979		 *
12980		 *  @example
12981		 *    // Using `columns`
12982		 *    $(document).ready( function() {
12983		 *      $('#example').dataTable( {
12984		 *        "columns": [
12985		 *          null,
12986		 *          null,
12987		 *          null,
12988		 *          {
12989		 *            "contentPadding": "mmm"
12990		 *          }
12991		 *        ]
12992		 *      } );
12993		 *    } );
12994		 */
12995		"sContentPadding": "",
12996
12997
12998		/**
12999		 * Allows a default value to be given for a column's data, and will be used
13000		 * whenever a null data source is encountered (this can be because `data`
13001		 * is set to null, or because the data source itself is null).
13002		 *  @type string
13003		 *  @default null
13004		 *
13005		 *  @name DataTable.defaults.column.defaultContent
13006		 *  @dtopt Columns
13007		 *
13008		 *  @example
13009		 *    // Using `columnDefs`
13010		 *    $(document).ready( function() {
13011		 *      $('#example').dataTable( {
13012		 *        "columnDefs": [
13013		 *          {
13014		 *            "data": null,
13015		 *            "defaultContent": "Edit",
13016		 *            "targets": [ -1 ]
13017		 *          }
13018		 *        ]
13019		 *      } );
13020		 *    } );
13021		 *
13022		 *  @example
13023		 *    // Using `columns`
13024		 *    $(document).ready( function() {
13025		 *      $('#example').dataTable( {
13026		 *        "columns": [
13027		 *          null,
13028		 *          null,
13029		 *          null,
13030		 *          {
13031		 *            "data": null,
13032		 *            "defaultContent": "Edit"
13033		 *          }
13034		 *        ]
13035		 *      } );
13036		 *    } );
13037		 */
13038		"sDefaultContent": null,
13039
13040
13041		/**
13042		 * This parameter is only used in DataTables' server-side processing. It can
13043		 * be exceptionally useful to know what columns are being displayed on the
13044		 * client side, and to map these to database fields. When defined, the names
13045		 * also allow DataTables to reorder information from the server if it comes
13046		 * back in an unexpected order (i.e. if you switch your columns around on the
13047		 * client-side, your server-side code does not also need updating).
13048		 *  @type string
13049		 *  @default <i>Empty string</i>
13050		 *
13051		 *  @name DataTable.defaults.column.name
13052		 *  @dtopt Columns
13053		 *
13054		 *  @example
13055		 *    // Using `columnDefs`
13056		 *    $(document).ready( function() {
13057		 *      $('#example').dataTable( {
13058		 *        "columnDefs": [
13059		 *          { "name": "engine", "targets": [ 0 ] },
13060		 *          { "name": "browser", "targets": [ 1 ] },
13061		 *          { "name": "platform", "targets": [ 2 ] },
13062		 *          { "name": "version", "targets": [ 3 ] },
13063		 *          { "name": "grade", "targets": [ 4 ] }
13064		 *        ]
13065		 *      } );
13066		 *    } );
13067		 *
13068		 *  @example
13069		 *    // Using `columns`
13070		 *    $(document).ready( function() {
13071		 *      $('#example').dataTable( {
13072		 *        "columns": [
13073		 *          { "name": "engine" },
13074		 *          { "name": "browser" },
13075		 *          { "name": "platform" },
13076		 *          { "name": "version" },
13077		 *          { "name": "grade" }
13078		 *        ]
13079		 *      } );
13080		 *    } );
13081		 */
13082		"sName": "",
13083
13084
13085		/**
13086		 * Defines a data source type for the ordering which can be used to read
13087		 * real-time information from the table (updating the internally cached
13088		 * version) prior to ordering. This allows ordering to occur on user
13089		 * editable elements such as form inputs.
13090		 *  @type string
13091		 *  @default std
13092		 *
13093		 *  @name DataTable.defaults.column.orderDataType
13094		 *  @dtopt Columns
13095		 *
13096		 *  @example
13097		 *    // Using `columnDefs`
13098		 *    $(document).ready( function() {
13099		 *      $('#example').dataTable( {
13100		 *        "columnDefs": [
13101		 *          { "orderDataType": "dom-text", "targets": [ 2, 3 ] },
13102		 *          { "type": "numeric", "targets": [ 3 ] },
13103		 *          { "orderDataType": "dom-select", "targets": [ 4 ] },
13104		 *          { "orderDataType": "dom-checkbox", "targets": [ 5 ] }
13105		 *        ]
13106		 *      } );
13107		 *    } );
13108		 *
13109		 *  @example
13110		 *    // Using `columns`
13111		 *    $(document).ready( function() {
13112		 *      $('#example').dataTable( {
13113		 *        "columns": [
13114		 *          null,
13115		 *          null,
13116		 *          { "orderDataType": "dom-text" },
13117		 *          { "orderDataType": "dom-text", "type": "numeric" },
13118		 *          { "orderDataType": "dom-select" },
13119		 *          { "orderDataType": "dom-checkbox" }
13120		 *        ]
13121		 *      } );
13122		 *    } );
13123		 */
13124		"sSortDataType": "std",
13125
13126
13127		/**
13128		 * The title of this column.
13129		 *  @type string
13130		 *  @default null <i>Derived from the 'TH' value for this column in the
13131		 *    original HTML table.</i>
13132		 *
13133		 *  @name DataTable.defaults.column.title
13134		 *  @dtopt Columns
13135		 *
13136		 *  @example
13137		 *    // Using `columnDefs`
13138		 *    $(document).ready( function() {
13139		 *      $('#example').dataTable( {
13140		 *        "columnDefs": [
13141		 *          { "title": "My column title", "targets": [ 0 ] }
13142		 *        ]
13143		 *      } );
13144		 *    } );
13145		 *
13146		 *  @example
13147		 *    // Using `columns`
13148		 *    $(document).ready( function() {
13149		 *      $('#example').dataTable( {
13150		 *        "columns": [
13151		 *          { "title": "My column title" },
13152		 *          null,
13153		 *          null,
13154		 *          null,
13155		 *          null
13156		 *        ]
13157		 *      } );
13158		 *    } );
13159		 */
13160		"sTitle": null,
13161
13162
13163		/**
13164		 * The type allows you to specify how the data for this column will be
13165		 * ordered. Four types (string, numeric, date and html (which will strip
13166		 * HTML tags before ordering)) are currently available. Note that only date
13167		 * formats understood by Javascript's Date() object will be accepted as type
13168		 * date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string',
13169		 * 'numeric', 'date' or 'html' (by default). Further types can be adding
13170		 * through plug-ins.
13171		 *  @type string
13172		 *  @default null <i>Auto-detected from raw data</i>
13173		 *
13174		 *  @name DataTable.defaults.column.type
13175		 *  @dtopt Columns
13176		 *
13177		 *  @example
13178		 *    // Using `columnDefs`
13179		 *    $(document).ready( function() {
13180		 *      $('#example').dataTable( {
13181		 *        "columnDefs": [
13182		 *          { "type": "html", "targets": [ 0 ] }
13183		 *        ]
13184		 *      } );
13185		 *    } );
13186		 *
13187		 *  @example
13188		 *    // Using `columns`
13189		 *    $(document).ready( function() {
13190		 *      $('#example').dataTable( {
13191		 *        "columns": [
13192		 *          { "type": "html" },
13193		 *          null,
13194		 *          null,
13195		 *          null,
13196		 *          null
13197		 *        ]
13198		 *      } );
13199		 *    } );
13200		 */
13201		"sType": null,
13202
13203
13204		/**
13205		 * Defining the width of the column, this parameter may take any CSS value
13206		 * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not
13207		 * been given a specific width through this interface ensuring that the table
13208		 * remains readable.
13209		 *  @type string
13210		 *  @default null <i>Automatic</i>
13211		 *
13212		 *  @name DataTable.defaults.column.width
13213		 *  @dtopt Columns
13214		 *
13215		 *  @example
13216		 *    // Using `columnDefs`
13217		 *    $(document).ready( function() {
13218		 *      $('#example').dataTable( {
13219		 *        "columnDefs": [
13220		 *          { "width": "20%", "targets": [ 0 ] }
13221		 *        ]
13222		 *      } );
13223		 *    } );
13224		 *
13225		 *  @example
13226		 *    // Using `columns`
13227		 *    $(document).ready( function() {
13228		 *      $('#example').dataTable( {
13229		 *        "columns": [
13230		 *          { "width": "20%" },
13231		 *          null,
13232		 *          null,
13233		 *          null,
13234		 *          null
13235		 *        ]
13236		 *      } );
13237		 *    } );
13238		 */
13239		"sWidth": null
13240	};
13241
13242	_fnHungarianMap( DataTable.defaults.column );
13243
13244
13245
13246	/**
13247	 * DataTables settings object - this holds all the information needed for a
13248	 * given table, including configuration, data and current application of the
13249	 * table options. DataTables does not have a single instance for each DataTable
13250	 * with the settings attached to that instance, but rather instances of the
13251	 * DataTable "class" are created on-the-fly as needed (typically by a
13252	 * $().dataTable() call) and the settings object is then applied to that
13253	 * instance.
13254	 *
13255	 * Note that this object is related to {@link DataTable.defaults} but this
13256	 * one is the internal data store for DataTables's cache of columns. It should
13257	 * NOT be manipulated outside of DataTables. Any configuration should be done
13258	 * through the initialisation options.
13259	 *  @namespace
13260	 *  @todo Really should attach the settings object to individual instances so we
13261	 *    don't need to create new instances on each $().dataTable() call (if the
13262	 *    table already exists). It would also save passing oSettings around and
13263	 *    into every single function. However, this is a very significant
13264	 *    architecture change for DataTables and will almost certainly break
13265	 *    backwards compatibility with older installations. This is something that
13266	 *    will be done in 2.0.
13267	 */
13268	DataTable.models.oSettings = {
13269		/**
13270		 * Primary features of DataTables and their enablement state.
13271		 *  @namespace
13272		 */
13273		"oFeatures": {
13274
13275			/**
13276			 * Flag to say if DataTables should automatically try to calculate the
13277			 * optimum table and columns widths (true) or not (false).
13278			 * Note that this parameter will be set by the initialisation routine. To
13279			 * set a default use {@link DataTable.defaults}.
13280			 *  @type boolean
13281			 */
13282			"bAutoWidth": null,
13283
13284			/**
13285			 * Delay the creation of TR and TD elements until they are actually
13286			 * needed by a driven page draw. This can give a significant speed
13287			 * increase for Ajax source and Javascript source data, but makes no
13288			 * difference at all for DOM and server-side processing tables.
13289			 * Note that this parameter will be set by the initialisation routine. To
13290			 * set a default use {@link DataTable.defaults}.
13291			 *  @type boolean
13292			 */
13293			"bDeferRender": null,
13294
13295			/**
13296			 * Enable filtering on the table or not. Note that if this is disabled
13297			 * then there is no filtering at all on the table, including fnFilter.
13298			 * To just remove the filtering input use sDom and remove the 'f' option.
13299			 * Note that this parameter will be set by the initialisation routine. To
13300			 * set a default use {@link DataTable.defaults}.
13301			 *  @type boolean
13302			 */
13303			"bFilter": null,
13304
13305			/**
13306			 * Table information element (the 'Showing x of y records' div) enable
13307			 * flag.
13308			 * Note that this parameter will be set by the initialisation routine. To
13309			 * set a default use {@link DataTable.defaults}.
13310			 *  @type boolean
13311			 */
13312			"bInfo": null,
13313
13314			/**
13315			 * Present a user control allowing the end user to change the page size
13316			 * when pagination is enabled.
13317			 * Note that this parameter will be set by the initialisation routine. To
13318			 * set a default use {@link DataTable.defaults}.
13319			 *  @type boolean
13320			 */
13321			"bLengthChange": null,
13322
13323			/**
13324			 * Pagination enabled or not. Note that if this is disabled then length
13325			 * changing must also be disabled.
13326			 * Note that this parameter will be set by the initialisation routine. To
13327			 * set a default use {@link DataTable.defaults}.
13328			 *  @type boolean
13329			 */
13330			"bPaginate": null,
13331
13332			/**
13333			 * Processing indicator enable flag whenever DataTables is enacting a
13334			 * user request - typically an Ajax request for server-side processing.
13335			 * Note that this parameter will be set by the initialisation routine. To
13336			 * set a default use {@link DataTable.defaults}.
13337			 *  @type boolean
13338			 */
13339			"bProcessing": null,
13340
13341			/**
13342			 * Server-side processing enabled flag - when enabled DataTables will
13343			 * get all data from the server for every draw - there is no filtering,
13344			 * sorting or paging done on the client-side.
13345			 * Note that this parameter will be set by the initialisation routine. To
13346			 * set a default use {@link DataTable.defaults}.
13347			 *  @type boolean
13348			 */
13349			"bServerSide": null,
13350
13351			/**
13352			 * Sorting enablement flag.
13353			 * Note that this parameter will be set by the initialisation routine. To
13354			 * set a default use {@link DataTable.defaults}.
13355			 *  @type boolean
13356			 */
13357			"bSort": null,
13358
13359			/**
13360			 * Multi-column sorting
13361			 * Note that this parameter will be set by the initialisation routine. To
13362			 * set a default use {@link DataTable.defaults}.
13363			 *  @type boolean
13364			 */
13365			"bSortMulti": null,
13366
13367			/**
13368			 * Apply a class to the columns which are being sorted to provide a
13369			 * visual highlight or not. This can slow things down when enabled since
13370			 * there is a lot of DOM interaction.
13371			 * Note that this parameter will be set by the initialisation routine. To
13372			 * set a default use {@link DataTable.defaults}.
13373			 *  @type boolean
13374			 */
13375			"bSortClasses": null,
13376
13377			/**
13378			 * State saving enablement flag.
13379			 * Note that this parameter will be set by the initialisation routine. To
13380			 * set a default use {@link DataTable.defaults}.
13381			 *  @type boolean
13382			 */
13383			"bStateSave": null
13384		},
13385
13386
13387		/**
13388		 * Scrolling settings for a table.
13389		 *  @namespace
13390		 */
13391		"oScroll": {
13392			/**
13393			 * When the table is shorter in height than sScrollY, collapse the
13394			 * table container down to the height of the table (when true).
13395			 * Note that this parameter will be set by the initialisation routine. To
13396			 * set a default use {@link DataTable.defaults}.
13397			 *  @type boolean
13398			 */
13399			"bCollapse": null,
13400
13401			/**
13402			 * Width of the scrollbar for the web-browser's platform. Calculated
13403			 * during table initialisation.
13404			 *  @type int
13405			 *  @default 0
13406			 */
13407			"iBarWidth": 0,
13408
13409			/**
13410			 * Viewport width for horizontal scrolling. Horizontal scrolling is
13411			 * disabled if an empty string.
13412			 * Note that this parameter will be set by the initialisation routine. To
13413			 * set a default use {@link DataTable.defaults}.
13414			 *  @type string
13415			 */
13416			"sX": null,
13417
13418			/**
13419			 * Width to expand the table to when using x-scrolling. Typically you
13420			 * should not need to use this.
13421			 * Note that this parameter will be set by the initialisation routine. To
13422			 * set a default use {@link DataTable.defaults}.
13423			 *  @type string
13424			 *  @deprecated
13425			 */
13426			"sXInner": null,
13427
13428			/**
13429			 * Viewport height for vertical scrolling. Vertical scrolling is disabled
13430			 * if an empty string.
13431			 * Note that this parameter will be set by the initialisation routine. To
13432			 * set a default use {@link DataTable.defaults}.
13433			 *  @type string
13434			 */
13435			"sY": null
13436		},
13437
13438		/**
13439		 * Language information for the table.
13440		 *  @namespace
13441		 *  @extends DataTable.defaults.oLanguage
13442		 */
13443		"oLanguage": {
13444			/**
13445			 * Information callback function. See
13446			 * {@link DataTable.defaults.fnInfoCallback}
13447			 *  @type function
13448			 *  @default null
13449			 */
13450			"fnInfoCallback": null
13451		},
13452
13453		/**
13454		 * Browser support parameters
13455		 *  @namespace
13456		 */
13457		"oBrowser": {
13458			/**
13459			 * Indicate if the browser incorrectly calculates width:100% inside a
13460			 * scrolling element (IE6/7)
13461			 *  @type boolean
13462			 *  @default false
13463			 */
13464			"bScrollOversize": false,
13465
13466			/**
13467			 * Determine if the vertical scrollbar is on the right or left of the
13468			 * scrolling container - needed for rtl language layout, although not
13469			 * all browsers move the scrollbar (Safari).
13470			 *  @type boolean
13471			 *  @default false
13472			 */
13473			"bScrollbarLeft": false,
13474
13475			/**
13476			 * Flag for if `getBoundingClientRect` is fully supported or not
13477			 *  @type boolean
13478			 *  @default false
13479			 */
13480			"bBounding": false,
13481
13482			/**
13483			 * Browser scrollbar width
13484			 *  @type integer
13485			 *  @default 0
13486			 */
13487			"barWidth": 0
13488		},
13489
13490
13491		"ajax": null,
13492
13493
13494		/**
13495		 * Array referencing the nodes which are used for the features. The
13496		 * parameters of this object match what is allowed by sDom - i.e.
13497		 *   <ul>
13498		 *     <li>'l' - Length changing</li>
13499		 *     <li>'f' - Filtering input</li>
13500		 *     <li>'t' - The table!</li>
13501		 *     <li>'i' - Information</li>
13502		 *     <li>'p' - Pagination</li>
13503		 *     <li>'r' - pRocessing</li>
13504		 *   </ul>
13505		 *  @type array
13506		 *  @default []
13507		 */
13508		"aanFeatures": [],
13509
13510		/**
13511		 * Store data information - see {@link DataTable.models.oRow} for detailed
13512		 * information.
13513		 *  @type array
13514		 *  @default []
13515		 */
13516		"aoData": [],
13517
13518		/**
13519		 * Array of indexes which are in the current display (after filtering etc)
13520		 *  @type array
13521		 *  @default []
13522		 */
13523		"aiDisplay": [],
13524
13525		/**
13526		 * Array of indexes for display - no filtering
13527		 *  @type array
13528		 *  @default []
13529		 */
13530		"aiDisplayMaster": [],
13531
13532		/**
13533		 * Map of row ids to data indexes
13534		 *  @type object
13535		 *  @default {}
13536		 */
13537		"aIds": {},
13538
13539		/**
13540		 * Store information about each column that is in use
13541		 *  @type array
13542		 *  @default []
13543		 */
13544		"aoColumns": [],
13545
13546		/**
13547		 * Store information about the table's header
13548		 *  @type array
13549		 *  @default []
13550		 */
13551		"aoHeader": [],
13552
13553		/**
13554		 * Store information about the table's footer
13555		 *  @type array
13556		 *  @default []
13557		 */
13558		"aoFooter": [],
13559
13560		/**
13561		 * Store the applied global search information in case we want to force a
13562		 * research or compare the old search to a new one.
13563		 * Note that this parameter will be set by the initialisation routine. To
13564		 * set a default use {@link DataTable.defaults}.
13565		 *  @namespace
13566		 *  @extends DataTable.models.oSearch
13567		 */
13568		"oPreviousSearch": {},
13569
13570		/**
13571		 * Store the applied search for each column - see
13572		 * {@link DataTable.models.oSearch} for the format that is used for the
13573		 * filtering information for each column.
13574		 *  @type array
13575		 *  @default []
13576		 */
13577		"aoPreSearchCols": [],
13578
13579		/**
13580		 * Sorting that is applied to the table. Note that the inner arrays are
13581		 * used in the following manner:
13582		 * <ul>
13583		 *   <li>Index 0 - column number</li>
13584		 *   <li>Index 1 - current sorting direction</li>
13585		 * </ul>
13586		 * Note that this parameter will be set by the initialisation routine. To
13587		 * set a default use {@link DataTable.defaults}.
13588		 *  @type array
13589		 *  @todo These inner arrays should really be objects
13590		 */
13591		"aaSorting": null,
13592
13593		/**
13594		 * Sorting that is always applied to the table (i.e. prefixed in front of
13595		 * aaSorting).
13596		 * Note that this parameter will be set by the initialisation routine. To
13597		 * set a default use {@link DataTable.defaults}.
13598		 *  @type array
13599		 *  @default []
13600		 */
13601		"aaSortingFixed": [],
13602
13603		/**
13604		 * Classes to use for the striping of a table.
13605		 * Note that this parameter will be set by the initialisation routine. To
13606		 * set a default use {@link DataTable.defaults}.
13607		 *  @type array
13608		 *  @default []
13609		 */
13610		"asStripeClasses": null,
13611
13612		/**
13613		 * If restoring a table - we should restore its striping classes as well
13614		 *  @type array
13615		 *  @default []
13616		 */
13617		"asDestroyStripes": [],
13618
13619		/**
13620		 * If restoring a table - we should restore its width
13621		 *  @type int
13622		 *  @default 0
13623		 */
13624		"sDestroyWidth": 0,
13625
13626		/**
13627		 * Callback functions array for every time a row is inserted (i.e. on a draw).
13628		 *  @type array
13629		 *  @default []
13630		 */
13631		"aoRowCallback": [],
13632
13633		/**
13634		 * Callback functions for the header on each draw.
13635		 *  @type array
13636		 *  @default []
13637		 */
13638		"aoHeaderCallback": [],
13639
13640		/**
13641		 * Callback function for the footer on each draw.
13642		 *  @type array
13643		 *  @default []
13644		 */
13645		"aoFooterCallback": [],
13646
13647		/**
13648		 * Array of callback functions for draw callback functions
13649		 *  @type array
13650		 *  @default []
13651		 */
13652		"aoDrawCallback": [],
13653
13654		/**
13655		 * Array of callback functions for row created function
13656		 *  @type array
13657		 *  @default []
13658		 */
13659		"aoRowCreatedCallback": [],
13660
13661		/**
13662		 * Callback functions for just before the table is redrawn. A return of
13663		 * false will be used to cancel the draw.
13664		 *  @type array
13665		 *  @default []
13666		 */
13667		"aoPreDrawCallback": [],
13668
13669		/**
13670		 * Callback functions for when the table has been initialised.
13671		 *  @type array
13672		 *  @default []
13673		 */
13674		"aoInitComplete": [],
13675
13676
13677		/**
13678		 * Callbacks for modifying the settings to be stored for state saving, prior to
13679		 * saving state.
13680		 *  @type array
13681		 *  @default []
13682		 */
13683		"aoStateSaveParams": [],
13684
13685		/**
13686		 * Callbacks for modifying the settings that have been stored for state saving
13687		 * prior to using the stored values to restore the state.
13688		 *  @type array
13689		 *  @default []
13690		 */
13691		"aoStateLoadParams": [],
13692
13693		/**
13694		 * Callbacks for operating on the settings object once the saved state has been
13695		 * loaded
13696		 *  @type array
13697		 *  @default []
13698		 */
13699		"aoStateLoaded": [],
13700
13701		/**
13702		 * Cache the table ID for quick access
13703		 *  @type string
13704		 *  @default <i>Empty string</i>
13705		 */
13706		"sTableId": "",
13707
13708		/**
13709		 * The TABLE node for the main table
13710		 *  @type node
13711		 *  @default null
13712		 */
13713		"nTable": null,
13714
13715		/**
13716		 * Permanent ref to the thead element
13717		 *  @type node
13718		 *  @default null
13719		 */
13720		"nTHead": null,
13721
13722		/**
13723		 * Permanent ref to the tfoot element - if it exists
13724		 *  @type node
13725		 *  @default null
13726		 */
13727		"nTFoot": null,
13728
13729		/**
13730		 * Permanent ref to the tbody element
13731		 *  @type node
13732		 *  @default null
13733		 */
13734		"nTBody": null,
13735
13736		/**
13737		 * Cache the wrapper node (contains all DataTables controlled elements)
13738		 *  @type node
13739		 *  @default null
13740		 */
13741		"nTableWrapper": null,
13742
13743		/**
13744		 * Indicate if when using server-side processing the loading of data
13745		 * should be deferred until the second draw.
13746		 * Note that this parameter will be set by the initialisation routine. To
13747		 * set a default use {@link DataTable.defaults}.
13748		 *  @type boolean
13749		 *  @default false
13750		 */
13751		"bDeferLoading": false,
13752
13753		/**
13754		 * Indicate if all required information has been read in
13755		 *  @type boolean
13756		 *  @default false
13757		 */
13758		"bInitialised": false,
13759
13760		/**
13761		 * Information about open rows. Each object in the array has the parameters
13762		 * 'nTr' and 'nParent'
13763		 *  @type array
13764		 *  @default []
13765		 */
13766		"aoOpenRows": [],
13767
13768		/**
13769		 * Dictate the positioning of DataTables' control elements - see
13770		 * {@link DataTable.model.oInit.sDom}.
13771		 * Note that this parameter will be set by the initialisation routine. To
13772		 * set a default use {@link DataTable.defaults}.
13773		 *  @type string
13774		 *  @default null
13775		 */
13776		"sDom": null,
13777
13778		/**
13779		 * Search delay (in mS)
13780		 *  @type integer
13781		 *  @default null
13782		 */
13783		"searchDelay": null,
13784
13785		/**
13786		 * Which type of pagination should be used.
13787		 * Note that this parameter will be set by the initialisation routine. To
13788		 * set a default use {@link DataTable.defaults}.
13789		 *  @type string
13790		 *  @default two_button
13791		 */
13792		"sPaginationType": "two_button",
13793
13794		/**
13795		 * The state duration (for `stateSave`) in seconds.
13796		 * Note that this parameter will be set by the initialisation routine. To
13797		 * set a default use {@link DataTable.defaults}.
13798		 *  @type int
13799		 *  @default 0
13800		 */
13801		"iStateDuration": 0,
13802
13803		/**
13804		 * Array of callback functions for state saving. Each array element is an
13805		 * object with the following parameters:
13806		 *   <ul>
13807		 *     <li>function:fn - function to call. Takes two parameters, oSettings
13808		 *       and the JSON string to save that has been thus far created. Returns
13809		 *       a JSON string to be inserted into a json object
13810		 *       (i.e. '"param": [ 0, 1, 2]')</li>
13811		 *     <li>string:sName - name of callback</li>
13812		 *   </ul>
13813		 *  @type array
13814		 *  @default []
13815		 */
13816		"aoStateSave": [],
13817
13818		/**
13819		 * Array of callback functions for state loading. Each array element is an
13820		 * object with the following parameters:
13821		 *   <ul>
13822		 *     <li>function:fn - function to call. Takes two parameters, oSettings
13823		 *       and the object stored. May return false to cancel state loading</li>
13824		 *     <li>string:sName - name of callback</li>
13825		 *   </ul>
13826		 *  @type array
13827		 *  @default []
13828		 */
13829		"aoStateLoad": [],
13830
13831		/**
13832		 * State that was saved. Useful for back reference
13833		 *  @type object
13834		 *  @default null
13835		 */
13836		"oSavedState": null,
13837
13838		/**
13839		 * State that was loaded. Useful for back reference
13840		 *  @type object
13841		 *  @default null
13842		 */
13843		"oLoadedState": null,
13844
13845		/**
13846		 * Source url for AJAX data for the table.
13847		 * Note that this parameter will be set by the initialisation routine. To
13848		 * set a default use {@link DataTable.defaults}.
13849		 *  @type string
13850		 *  @default null
13851		 */
13852		"sAjaxSource": null,
13853
13854		/**
13855		 * Property from a given object from which to read the table data from. This
13856		 * can be an empty string (when not server-side processing), in which case
13857		 * it is  assumed an an array is given directly.
13858		 * Note that this parameter will be set by the initialisation routine. To
13859		 * set a default use {@link DataTable.defaults}.
13860		 *  @type string
13861		 */
13862		"sAjaxDataProp": null,
13863
13864		/**
13865		 * The last jQuery XHR object that was used for server-side data gathering.
13866		 * This can be used for working with the XHR information in one of the
13867		 * callbacks
13868		 *  @type object
13869		 *  @default null
13870		 */
13871		"jqXHR": null,
13872
13873		/**
13874		 * JSON returned from the server in the last Ajax request
13875		 *  @type object
13876		 *  @default undefined
13877		 */
13878		"json": undefined,
13879
13880		/**
13881		 * Data submitted as part of the last Ajax request
13882		 *  @type object
13883		 *  @default undefined
13884		 */
13885		"oAjaxData": undefined,
13886
13887		/**
13888		 * Function to get the server-side data.
13889		 * Note that this parameter will be set by the initialisation routine. To
13890		 * set a default use {@link DataTable.defaults}.
13891		 *  @type function
13892		 */
13893		"fnServerData": null,
13894
13895		/**
13896		 * Functions which are called prior to sending an Ajax request so extra
13897		 * parameters can easily be sent to the server
13898		 *  @type array
13899		 *  @default []
13900		 */
13901		"aoServerParams": [],
13902
13903		/**
13904		 * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
13905		 * required).
13906		 * Note that this parameter will be set by the initialisation routine. To
13907		 * set a default use {@link DataTable.defaults}.
13908		 *  @type string
13909		 */
13910		"sServerMethod": null,
13911
13912		/**
13913		 * Format numbers for display.
13914		 * Note that this parameter will be set by the initialisation routine. To
13915		 * set a default use {@link DataTable.defaults}.
13916		 *  @type function
13917		 */
13918		"fnFormatNumber": null,
13919
13920		/**
13921		 * List of options that can be used for the user selectable length menu.
13922		 * Note that this parameter will be set by the initialisation routine. To
13923		 * set a default use {@link DataTable.defaults}.
13924		 *  @type array
13925		 *  @default []
13926		 */
13927		"aLengthMenu": null,
13928
13929		/**
13930		 * Counter for the draws that the table does. Also used as a tracker for
13931		 * server-side processing
13932		 *  @type int
13933		 *  @default 0
13934		 */
13935		"iDraw": 0,
13936
13937		/**
13938		 * Indicate if a redraw is being done - useful for Ajax
13939		 *  @type boolean
13940		 *  @default false
13941		 */
13942		"bDrawing": false,
13943
13944		/**
13945		 * Draw index (iDraw) of the last error when parsing the returned data
13946		 *  @type int
13947		 *  @default -1
13948		 */
13949		"iDrawError": -1,
13950
13951		/**
13952		 * Paging display length
13953		 *  @type int
13954		 *  @default 10
13955		 */
13956		"_iDisplayLength": 10,
13957
13958		/**
13959		 * Paging start point - aiDisplay index
13960		 *  @type int
13961		 *  @default 0
13962		 */
13963		"_iDisplayStart": 0,
13964
13965		/**
13966		 * Server-side processing - number of records in the result set
13967		 * (i.e. before filtering), Use fnRecordsTotal rather than
13968		 * this property to get the value of the number of records, regardless of
13969		 * the server-side processing setting.
13970		 *  @type int
13971		 *  @default 0
13972		 *  @private
13973		 */
13974		"_iRecordsTotal": 0,
13975
13976		/**
13977		 * Server-side processing - number of records in the current display set
13978		 * (i.e. after filtering). Use fnRecordsDisplay rather than
13979		 * this property to get the value of the number of records, regardless of
13980		 * the server-side processing setting.
13981		 *  @type boolean
13982		 *  @default 0
13983		 *  @private
13984		 */
13985		"_iRecordsDisplay": 0,
13986
13987		/**
13988		 * The classes to use for the table
13989		 *  @type object
13990		 *  @default {}
13991		 */
13992		"oClasses": {},
13993
13994		/**
13995		 * Flag attached to the settings object so you can check in the draw
13996		 * callback if filtering has been done in the draw. Deprecated in favour of
13997		 * events.
13998		 *  @type boolean
13999		 *  @default false
14000		 *  @deprecated
14001		 */
14002		"bFiltered": false,
14003
14004		/**
14005		 * Flag attached to the settings object so you can check in the draw
14006		 * callback if sorting has been done in the draw. Deprecated in favour of
14007		 * events.
14008		 *  @type boolean
14009		 *  @default false
14010		 *  @deprecated
14011		 */
14012		"bSorted": false,
14013
14014		/**
14015		 * Indicate that if multiple rows are in the header and there is more than
14016		 * one unique cell per column, if the top one (true) or bottom one (false)
14017		 * should be used for sorting / title by DataTables.
14018		 * Note that this parameter will be set by the initialisation routine. To
14019		 * set a default use {@link DataTable.defaults}.
14020		 *  @type boolean
14021		 */
14022		"bSortCellsTop": null,
14023
14024		/**
14025		 * Initialisation object that is used for the table
14026		 *  @type object
14027		 *  @default null
14028		 */
14029		"oInit": null,
14030
14031		/**
14032		 * Destroy callback functions - for plug-ins to attach themselves to the
14033		 * destroy so they can clean up markup and events.
14034		 *  @type array
14035		 *  @default []
14036		 */
14037		"aoDestroyCallback": [],
14038
14039
14040		/**
14041		 * Get the number of records in the current record set, before filtering
14042		 *  @type function
14043		 */
14044		"fnRecordsTotal": function ()
14045		{
14046			return _fnDataSource( this ) == 'ssp' ?
14047				this._iRecordsTotal * 1 :
14048				this.aiDisplayMaster.length;
14049		},
14050
14051		/**
14052		 * Get the number of records in the current record set, after filtering
14053		 *  @type function
14054		 */
14055		"fnRecordsDisplay": function ()
14056		{
14057			return _fnDataSource( this ) == 'ssp' ?
14058				this._iRecordsDisplay * 1 :
14059				this.aiDisplay.length;
14060		},
14061
14062		/**
14063		 * Get the display end point - aiDisplay index
14064		 *  @type function
14065		 */
14066		"fnDisplayEnd": function ()
14067		{
14068			var
14069				len      = this._iDisplayLength,
14070				start    = this._iDisplayStart,
14071				calc     = start + len,
14072				records  = this.aiDisplay.length,
14073				features = this.oFeatures,
14074				paginate = features.bPaginate;
14075
14076			if ( features.bServerSide ) {
14077				return paginate === false || len === -1 ?
14078					start + records :
14079					Math.min( start+len, this._iRecordsDisplay );
14080			}
14081			else {
14082				return ! paginate || calc>records || len===-1 ?
14083					records :
14084					calc;
14085			}
14086		},
14087
14088		/**
14089		 * The DataTables object for this table
14090		 *  @type object
14091		 *  @default null
14092		 */
14093		"oInstance": null,
14094
14095		/**
14096		 * Unique identifier for each instance of the DataTables object. If there
14097		 * is an ID on the table node, then it takes that value, otherwise an
14098		 * incrementing internal counter is used.
14099		 *  @type string
14100		 *  @default null
14101		 */
14102		"sInstance": null,
14103
14104		/**
14105		 * tabindex attribute value that is added to DataTables control elements, allowing
14106		 * keyboard navigation of the table and its controls.
14107		 */
14108		"iTabIndex": 0,
14109
14110		/**
14111		 * DIV container for the footer scrolling table if scrolling
14112		 */
14113		"nScrollHead": null,
14114
14115		/**
14116		 * DIV container for the footer scrolling table if scrolling
14117		 */
14118		"nScrollFoot": null,
14119
14120		/**
14121		 * Last applied sort
14122		 *  @type array
14123		 *  @default []
14124		 */
14125		"aLastSort": [],
14126
14127		/**
14128		 * Stored plug-in instances
14129		 *  @type object
14130		 *  @default {}
14131		 */
14132		"oPlugins": {},
14133
14134		/**
14135		 * Function used to get a row's id from the row's data
14136		 *  @type function
14137		 *  @default null
14138		 */
14139		"rowIdFn": null,
14140
14141		/**
14142		 * Data location where to store a row's id
14143		 *  @type string
14144		 *  @default null
14145		 */
14146		"rowId": null
14147	};
14148
14149	/**
14150	 * Extension object for DataTables that is used to provide all extension
14151	 * options.
14152	 *
14153	 * Note that the `DataTable.ext` object is available through
14154	 * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is
14155	 * also aliased to `jQuery.fn.dataTableExt` for historic reasons.
14156	 *  @namespace
14157	 *  @extends DataTable.models.ext
14158	 */
14159
14160
14161	/**
14162	 * DataTables extensions
14163	 *
14164	 * This namespace acts as a collection area for plug-ins that can be used to
14165	 * extend DataTables capabilities. Indeed many of the build in methods
14166	 * use this method to provide their own capabilities (sorting methods for
14167	 * example).
14168	 *
14169	 * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy
14170	 * reasons
14171	 *
14172	 *  @namespace
14173	 */
14174	DataTable.ext = _ext = {
14175		/**
14176		 * Buttons. For use with the Buttons extension for DataTables. This is
14177		 * defined here so other extensions can define buttons regardless of load
14178		 * order. It is _not_ used by DataTables core.
14179		 *
14180		 *  @type object
14181		 *  @default {}
14182		 */
14183		buttons: {},
14184
14185
14186		/**
14187		 * Element class names
14188		 *
14189		 *  @type object
14190		 *  @default {}
14191		 */
14192		classes: {},
14193
14194
14195		/**
14196		 * DataTables build type (expanded by the download builder)
14197		 *
14198		 *  @type string
14199		 */
14200		builder: "-source-",
14201
14202
14203		/**
14204		 * Error reporting.
14205		 *
14206		 * How should DataTables report an error. Can take the value 'alert',
14207		 * 'throw', 'none' or a function.
14208		 *
14209		 *  @type string|function
14210		 *  @default alert
14211		 */
14212		errMode: "alert",
14213
14214
14215		/**
14216		 * Feature plug-ins.
14217		 *
14218		 * This is an array of objects which describe the feature plug-ins that are
14219		 * available to DataTables. These feature plug-ins are then available for
14220		 * use through the `dom` initialisation option.
14221		 *
14222		 * Each feature plug-in is described by an object which must have the
14223		 * following properties:
14224		 *
14225		 * * `fnInit` - function that is used to initialise the plug-in,
14226		 * * `cFeature` - a character so the feature can be enabled by the `dom`
14227		 *   instillation option. This is case sensitive.
14228		 *
14229		 * The `fnInit` function has the following input parameters:
14230		 *
14231		 * 1. `{object}` DataTables settings object: see
14232		 *    {@link DataTable.models.oSettings}
14233		 *
14234		 * And the following return is expected:
14235		 *
14236		 * * {node|null} The element which contains your feature. Note that the
14237		 *   return may also be void if your plug-in does not require to inject any
14238		 *   DOM elements into DataTables control (`dom`) - for example this might
14239		 *   be useful when developing a plug-in which allows table control via
14240		 *   keyboard entry
14241		 *
14242		 *  @type array
14243		 *
14244		 *  @example
14245		 *    $.fn.dataTable.ext.features.push( {
14246		 *      "fnInit": function( oSettings ) {
14247		 *        return new TableTools( { "oDTSettings": oSettings } );
14248		 *      },
14249		 *      "cFeature": "T"
14250		 *    } );
14251		 */
14252		feature: [],
14253
14254
14255		/**
14256		 * Row searching.
14257		 *
14258		 * This method of searching is complimentary to the default type based
14259		 * searching, and a lot more comprehensive as it allows you complete control
14260		 * over the searching logic. Each element in this array is a function
14261		 * (parameters described below) that is called for every row in the table,
14262		 * and your logic decides if it should be included in the searching data set
14263		 * or not.
14264		 *
14265		 * Searching functions have the following input parameters:
14266		 *
14267		 * 1. `{object}` DataTables settings object: see
14268		 *    {@link DataTable.models.oSettings}
14269		 * 2. `{array|object}` Data for the row to be processed (same as the
14270		 *    original format that was passed in as the data source, or an array
14271		 *    from a DOM data source
14272		 * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which
14273		 *    can be useful to retrieve the `TR` element if you need DOM interaction.
14274		 *
14275		 * And the following return is expected:
14276		 *
14277		 * * {boolean} Include the row in the searched result set (true) or not
14278		 *   (false)
14279		 *
14280		 * Note that as with the main search ability in DataTables, technically this
14281		 * is "filtering", since it is subtractive. However, for consistency in
14282		 * naming we call it searching here.
14283		 *
14284		 *  @type array
14285		 *  @default []
14286		 *
14287		 *  @example
14288		 *    // The following example shows custom search being applied to the
14289		 *    // fourth column (i.e. the data[3] index) based on two input values
14290		 *    // from the end-user, matching the data in a certain range.
14291		 *    $.fn.dataTable.ext.search.push(
14292		 *      function( settings, data, dataIndex ) {
14293		 *        var min = document.getElementById('min').value * 1;
14294		 *        var max = document.getElementById('max').value * 1;
14295		 *        var version = data[3] == "-" ? 0 : data[3]*1;
14296		 *
14297		 *        if ( min == "" && max == "" ) {
14298		 *          return true;
14299		 *        }
14300		 *        else if ( min == "" && version < max ) {
14301		 *          return true;
14302		 *        }
14303		 *        else if ( min < version && "" == max ) {
14304		 *          return true;
14305		 *        }
14306		 *        else if ( min < version && version < max ) {
14307		 *          return true;
14308		 *        }
14309		 *        return false;
14310		 *      }
14311		 *    );
14312		 */
14313		search: [],
14314
14315
14316		/**
14317		 * Selector extensions
14318		 *
14319		 * The `selector` option can be used to extend the options available for the
14320		 * selector modifier options (`selector-modifier` object data type) that
14321		 * each of the three built in selector types offer (row, column and cell +
14322		 * their plural counterparts). For example the Select extension uses this
14323		 * mechanism to provide an option to select only rows, columns and cells
14324		 * that have been marked as selected by the end user (`{selected: true}`),
14325		 * which can be used in conjunction with the existing built in selector
14326		 * options.
14327		 *
14328		 * Each property is an array to which functions can be pushed. The functions
14329		 * take three attributes:
14330		 *
14331		 * * Settings object for the host table
14332		 * * Options object (`selector-modifier` object type)
14333		 * * Array of selected item indexes
14334		 *
14335		 * The return is an array of the resulting item indexes after the custom
14336		 * selector has been applied.
14337		 *
14338		 *  @type object
14339		 */
14340		selector: {
14341			cell: [],
14342			column: [],
14343			row: []
14344		},
14345
14346
14347		/**
14348		 * Internal functions, exposed for used in plug-ins.
14349		 *
14350		 * Please note that you should not need to use the internal methods for
14351		 * anything other than a plug-in (and even then, try to avoid if possible).
14352		 * The internal function may change between releases.
14353		 *
14354		 *  @type object
14355		 *  @default {}
14356		 */
14357		internal: {},
14358
14359
14360		/**
14361		 * Legacy configuration options. Enable and disable legacy options that
14362		 * are available in DataTables.
14363		 *
14364		 *  @type object
14365		 */
14366		legacy: {
14367			/**
14368			 * Enable / disable DataTables 1.9 compatible server-side processing
14369			 * requests
14370			 *
14371			 *  @type boolean
14372			 *  @default null
14373			 */
14374			ajax: null
14375		},
14376
14377
14378		/**
14379		 * Pagination plug-in methods.
14380		 *
14381		 * Each entry in this object is a function and defines which buttons should
14382		 * be shown by the pagination rendering method that is used for the table:
14383		 * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the
14384		 * buttons are displayed in the document, while the functions here tell it
14385		 * what buttons to display. This is done by returning an array of button
14386		 * descriptions (what each button will do).
14387		 *
14388		 * Pagination types (the four built in options and any additional plug-in
14389		 * options defined here) can be used through the `paginationType`
14390		 * initialisation parameter.
14391		 *
14392		 * The functions defined take two parameters:
14393		 *
14394		 * 1. `{int} page` The current page index
14395		 * 2. `{int} pages` The number of pages in the table
14396		 *
14397		 * Each function is expected to return an array where each element of the
14398		 * array can be one of:
14399		 *
14400		 * * `first` - Jump to first page when activated
14401		 * * `last` - Jump to last page when activated
14402		 * * `previous` - Show previous page when activated
14403		 * * `next` - Show next page when activated
14404		 * * `{int}` - Show page of the index given
14405		 * * `{array}` - A nested array containing the above elements to add a
14406		 *   containing 'DIV' element (might be useful for styling).
14407		 *
14408		 * Note that DataTables v1.9- used this object slightly differently whereby
14409		 * an object with two functions would be defined for each plug-in. That
14410		 * ability is still supported by DataTables 1.10+ to provide backwards
14411		 * compatibility, but this option of use is now decremented and no longer
14412		 * documented in DataTables 1.10+.
14413		 *
14414		 *  @type object
14415		 *  @default {}
14416		 *
14417		 *  @example
14418		 *    // Show previous, next and current page buttons only
14419		 *    $.fn.dataTableExt.oPagination.current = function ( page, pages ) {
14420		 *      return [ 'previous', page, 'next' ];
14421		 *    };
14422		 */
14423		pager: {},
14424
14425
14426		renderer: {
14427			pageButton: {},
14428			header: {}
14429		},
14430
14431
14432		/**
14433		 * Ordering plug-ins - custom data source
14434		 *
14435		 * The extension options for ordering of data available here is complimentary
14436		 * to the default type based ordering that DataTables typically uses. It
14437		 * allows much greater control over the the data that is being used to
14438		 * order a column, but is necessarily therefore more complex.
14439		 *
14440		 * This type of ordering is useful if you want to do ordering based on data
14441		 * live from the DOM (for example the contents of an 'input' element) rather
14442		 * than just the static string that DataTables knows of.
14443		 *
14444		 * The way these plug-ins work is that you create an array of the values you
14445		 * wish to be ordering for the column in question and then return that
14446		 * array. The data in the array much be in the index order of the rows in
14447		 * the table (not the currently ordering order!). Which order data gathering
14448		 * function is run here depends on the `dt-init columns.orderDataType`
14449		 * parameter that is used for the column (if any).
14450		 *
14451		 * The functions defined take two parameters:
14452		 *
14453		 * 1. `{object}` DataTables settings object: see
14454		 *    {@link DataTable.models.oSettings}
14455		 * 2. `{int}` Target column index
14456		 *
14457		 * Each function is expected to return an array:
14458		 *
14459		 * * `{array}` Data for the column to be ordering upon
14460		 *
14461		 *  @type array
14462		 *
14463		 *  @example
14464		 *    // Ordering using `input` node values
14465		 *    $.fn.dataTable.ext.order['dom-text'] = function  ( settings, col )
14466		 *    {
14467		 *      return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
14468		 *        return $('input', td).val();
14469		 *      } );
14470		 *    }
14471		 */
14472		order: {},
14473
14474
14475		/**
14476		 * Type based plug-ins.
14477		 *
14478		 * Each column in DataTables has a type assigned to it, either by automatic
14479		 * detection or by direct assignment using the `type` option for the column.
14480		 * The type of a column will effect how it is ordering and search (plug-ins
14481		 * can also make use of the column type if required).
14482		 *
14483		 * @namespace
14484		 */
14485		type: {
14486			/**
14487			 * Type detection functions.
14488			 *
14489			 * The functions defined in this object are used to automatically detect
14490			 * a column's type, making initialisation of DataTables super easy, even
14491			 * when complex data is in the table.
14492			 *
14493			 * The functions defined take two parameters:
14494			 *
14495		     *  1. `{*}` Data from the column cell to be analysed
14496		     *  2. `{settings}` DataTables settings object. This can be used to
14497		     *     perform context specific type detection - for example detection
14498		     *     based on language settings such as using a comma for a decimal
14499		     *     place. Generally speaking the options from the settings will not
14500		     *     be required
14501			 *
14502			 * Each function is expected to return:
14503			 *
14504			 * * `{string|null}` Data type detected, or null if unknown (and thus
14505			 *   pass it on to the other type detection functions.
14506			 *
14507			 *  @type array
14508			 *
14509			 *  @example
14510			 *    // Currency type detection plug-in:
14511			 *    $.fn.dataTable.ext.type.detect.push(
14512			 *      function ( data, settings ) {
14513			 *        // Check the numeric part
14514			 *        if ( ! data.substring(1).match(/[0-9]/) ) {
14515			 *          return null;
14516			 *        }
14517			 *
14518			 *        // Check prefixed by currency
14519			 *        if ( data.charAt(0) == '$' || data.charAt(0) == '&pound;' ) {
14520			 *          return 'currency';
14521			 *        }
14522			 *        return null;
14523			 *      }
14524			 *    );
14525			 */
14526			detect: [],
14527
14528
14529			/**
14530			 * Type based search formatting.
14531			 *
14532			 * The type based searching functions can be used to pre-format the
14533			 * data to be search on. For example, it can be used to strip HTML
14534			 * tags or to de-format telephone numbers for numeric only searching.
14535			 *
14536			 * Note that is a search is not defined for a column of a given type,
14537			 * no search formatting will be performed.
14538			 *
14539			 * Pre-processing of searching data plug-ins - When you assign the sType
14540			 * for a column (or have it automatically detected for you by DataTables
14541			 * or a type detection plug-in), you will typically be using this for
14542			 * custom sorting, but it can also be used to provide custom searching
14543			 * by allowing you to pre-processing the data and returning the data in
14544			 * the format that should be searched upon. This is done by adding
14545			 * functions this object with a parameter name which matches the sType
14546			 * for that target column. This is the corollary of <i>afnSortData</i>
14547			 * for searching data.
14548			 *
14549			 * The functions defined take a single parameter:
14550			 *
14551		     *  1. `{*}` Data from the column cell to be prepared for searching
14552			 *
14553			 * Each function is expected to return:
14554			 *
14555			 * * `{string|null}` Formatted string that will be used for the searching.
14556			 *
14557			 *  @type object
14558			 *  @default {}
14559			 *
14560			 *  @example
14561			 *    $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) {
14562			 *      return d.replace(/\n/g," ").replace( /<.*?>/g, "" );
14563			 *    }
14564			 */
14565			search: {},
14566
14567
14568			/**
14569			 * Type based ordering.
14570			 *
14571			 * The column type tells DataTables what ordering to apply to the table
14572			 * when a column is sorted upon. The order for each type that is defined,
14573			 * is defined by the functions available in this object.
14574			 *
14575			 * Each ordering option can be described by three properties added to
14576			 * this object:
14577			 *
14578			 * * `{type}-pre` - Pre-formatting function
14579			 * * `{type}-asc` - Ascending order function
14580			 * * `{type}-desc` - Descending order function
14581			 *
14582			 * All three can be used together, only `{type}-pre` or only
14583			 * `{type}-asc` and `{type}-desc` together. It is generally recommended
14584			 * that only `{type}-pre` is used, as this provides the optimal
14585			 * implementation in terms of speed, although the others are provided
14586			 * for compatibility with existing Javascript sort functions.
14587			 *
14588			 * `{type}-pre`: Functions defined take a single parameter:
14589			 *
14590		     *  1. `{*}` Data from the column cell to be prepared for ordering
14591			 *
14592			 * And return:
14593			 *
14594			 * * `{*}` Data to be sorted upon
14595			 *
14596			 * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort
14597			 * functions, taking two parameters:
14598			 *
14599		     *  1. `{*}` Data to compare to the second parameter
14600		     *  2. `{*}` Data to compare to the first parameter
14601			 *
14602			 * And returning:
14603			 *
14604			 * * `{*}` Ordering match: <0 if first parameter should be sorted lower
14605			 *   than the second parameter, ===0 if the two parameters are equal and
14606			 *   >0 if the first parameter should be sorted height than the second
14607			 *   parameter.
14608			 *
14609			 *  @type object
14610			 *  @default {}
14611			 *
14612			 *  @example
14613			 *    // Numeric ordering of formatted numbers with a pre-formatter
14614			 *    $.extend( $.fn.dataTable.ext.type.order, {
14615			 *      "string-pre": function(x) {
14616			 *        a = (a === "-" || a === "") ? 0 : a.replace( /[^\d\-\.]/g, "" );
14617			 *        return parseFloat( a );
14618			 *      }
14619			 *    } );
14620			 *
14621			 *  @example
14622			 *    // Case-sensitive string ordering, with no pre-formatting method
14623			 *    $.extend( $.fn.dataTable.ext.order, {
14624			 *      "string-case-asc": function(x,y) {
14625			 *        return ((x < y) ? -1 : ((x > y) ? 1 : 0));
14626			 *      },
14627			 *      "string-case-desc": function(x,y) {
14628			 *        return ((x < y) ? 1 : ((x > y) ? -1 : 0));
14629			 *      }
14630			 *    } );
14631			 */
14632			order: {}
14633		},
14634
14635		/**
14636		 * Unique DataTables instance counter
14637		 *
14638		 * @type int
14639		 * @private
14640		 */
14641		_unique: 0,
14642
14643
14644		//
14645		// Depreciated
14646		// The following properties are retained for backwards compatibility only.
14647		// The should not be used in new projects and will be removed in a future
14648		// version
14649		//
14650
14651		/**
14652		 * Version check function.
14653		 *  @type function
14654		 *  @depreciated Since 1.10
14655		 */
14656		fnVersionCheck: DataTable.fnVersionCheck,
14657
14658
14659		/**
14660		 * Index for what 'this' index API functions should use
14661		 *  @type int
14662		 *  @deprecated Since v1.10
14663		 */
14664		iApiIndex: 0,
14665
14666
14667		/**
14668		 * jQuery UI class container
14669		 *  @type object
14670		 *  @deprecated Since v1.10
14671		 */
14672		oJUIClasses: {},
14673
14674
14675		/**
14676		 * Software version
14677		 *  @type string
14678		 *  @deprecated Since v1.10
14679		 */
14680		sVersion: DataTable.version
14681	};
14682
14683
14684	//
14685	// Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts
14686	//
14687	$.extend( _ext, {
14688		afnFiltering: _ext.search,
14689		aTypes:       _ext.type.detect,
14690		ofnSearch:    _ext.type.search,
14691		oSort:        _ext.type.order,
14692		afnSortData:  _ext.order,
14693		aoFeatures:   _ext.feature,
14694		oApi:         _ext.internal,
14695		oStdClasses:  _ext.classes,
14696		oPagination:  _ext.pager
14697	} );
14698
14699
14700	$.extend( DataTable.ext.classes, {
14701		"sTable": "dataTable",
14702		"sNoFooter": "no-footer",
14703
14704		/* Paging buttons */
14705		"sPageButton": "paginate_button",
14706		"sPageButtonActive": "current",
14707		"sPageButtonDisabled": "disabled",
14708
14709		/* Striping classes */
14710		"sStripeOdd": "odd",
14711		"sStripeEven": "even",
14712
14713		/* Empty row */
14714		"sRowEmpty": "dataTables_empty",
14715
14716		/* Features */
14717		"sWrapper": "dataTables_wrapper",
14718		"sFilter": "dataTables_filter",
14719		"sInfo": "dataTables_info",
14720		"sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
14721		"sLength": "dataTables_length",
14722		"sProcessing": "dataTables_processing",
14723
14724		/* Sorting */
14725		"sSortAsc": "sorting_asc",
14726		"sSortDesc": "sorting_desc",
14727		"sSortable": "sorting", /* Sortable in both directions */
14728		"sSortableAsc": "sorting_desc_disabled",
14729		"sSortableDesc": "sorting_asc_disabled",
14730		"sSortableNone": "sorting_disabled",
14731		"sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
14732
14733		/* Filtering */
14734		"sFilterInput": "",
14735
14736		/* Page length */
14737		"sLengthSelect": "",
14738
14739		/* Scrolling */
14740		"sScrollWrapper": "dataTables_scroll",
14741		"sScrollHead": "dataTables_scrollHead",
14742		"sScrollHeadInner": "dataTables_scrollHeadInner",
14743		"sScrollBody": "dataTables_scrollBody",
14744		"sScrollFoot": "dataTables_scrollFoot",
14745		"sScrollFootInner": "dataTables_scrollFootInner",
14746
14747		/* Misc */
14748		"sHeaderTH": "",
14749		"sFooterTH": "",
14750
14751		// Deprecated
14752		"sSortJUIAsc": "",
14753		"sSortJUIDesc": "",
14754		"sSortJUI": "",
14755		"sSortJUIAscAllowed": "",
14756		"sSortJUIDescAllowed": "",
14757		"sSortJUIWrapper": "",
14758		"sSortIcon": "",
14759		"sJUIHeader": "",
14760		"sJUIFooter": ""
14761	} );
14762
14763
14764	var extPagination = DataTable.ext.pager;
14765
14766	function _numbers ( page, pages ) {
14767		var
14768			numbers = [],
14769			buttons = extPagination.numbers_length,
14770			half = Math.floor( buttons / 2 ),
14771			i = 1;
14772
14773		if ( pages <= buttons ) {
14774			numbers = _range( 0, pages );
14775		}
14776		else if ( page <= half ) {
14777			numbers = _range( 0, buttons-2 );
14778			numbers.push( 'ellipsis' );
14779			numbers.push( pages-1 );
14780		}
14781		else if ( page >= pages - 1 - half ) {
14782			numbers = _range( pages-(buttons-2), pages );
14783			numbers.splice( 0, 0, 'ellipsis' ); // no unshift in ie6
14784			numbers.splice( 0, 0, 0 );
14785		}
14786		else {
14787			numbers = _range( page-half+2, page+half-1 );
14788			numbers.push( 'ellipsis' );
14789			numbers.push( pages-1 );
14790			numbers.splice( 0, 0, 'ellipsis' );
14791			numbers.splice( 0, 0, 0 );
14792		}
14793
14794		numbers.DT_el = 'span';
14795		return numbers;
14796	}
14797
14798
14799	$.extend( extPagination, {
14800		simple: function ( page, pages ) {
14801			return [ 'previous', 'next' ];
14802		},
14803
14804		full: function ( page, pages ) {
14805			return [  'first', 'previous', 'next', 'last' ];
14806		},
14807
14808		numbers: function ( page, pages ) {
14809			return [ _numbers(page, pages) ];
14810		},
14811
14812		simple_numbers: function ( page, pages ) {
14813			return [ 'previous', _numbers(page, pages), 'next' ];
14814		},
14815
14816		full_numbers: function ( page, pages ) {
14817			return [ 'first', 'previous', _numbers(page, pages), 'next', 'last' ];
14818		},
14819
14820		first_last_numbers: function (page, pages) {
14821	 		return ['first', _numbers(page, pages), 'last'];
14822	 	},
14823
14824		// For testing and plug-ins to use
14825		_numbers: _numbers,
14826
14827		// Number of number buttons (including ellipsis) to show. _Must be odd!_
14828		numbers_length: 7
14829	} );
14830
14831
14832	$.extend( true, DataTable.ext.renderer, {
14833		pageButton: {
14834			_: function ( settings, host, idx, buttons, page, pages ) {
14835				var classes = settings.oClasses;
14836				var lang = settings.oLanguage.oPaginate;
14837				var aria = settings.oLanguage.oAria.paginate || {};
14838				var btnDisplay, btnClass;
14839
14840				var attach = function( container, buttons ) {
14841					var i, ien, node, button, tabIndex;
14842					var disabledClass = classes.sPageButtonDisabled;
14843					var clickHandler = function ( e ) {
14844						_fnPageChange( settings, e.data.action, true );
14845					};
14846
14847					for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
14848						button = buttons[i];
14849
14850						if ( Array.isArray( button ) ) {
14851							var inner = $( '<'+(button.DT_el || 'div')+'/>' )
14852								.appendTo( container );
14853							attach( inner, button );
14854						}
14855						else {
14856							btnDisplay = null;
14857							btnClass = button;
14858							tabIndex = settings.iTabIndex;
14859
14860							switch ( button ) {
14861								case 'ellipsis':
14862									container.append('<span class="ellipsis">&#x2026;</span>');
14863									break;
14864
14865								case 'first':
14866									btnDisplay = lang.sFirst;
14867
14868									if ( page === 0 ) {
14869										tabIndex = -1;
14870										btnClass += ' ' + disabledClass;
14871									}
14872									break;
14873
14874								case 'previous':
14875									btnDisplay = lang.sPrevious;
14876
14877									if ( page === 0 ) {
14878										tabIndex = -1;
14879										btnClass += ' ' + disabledClass;
14880									}
14881									break;
14882
14883								case 'next':
14884									btnDisplay = lang.sNext;
14885
14886									if ( pages === 0 || page === pages-1 ) {
14887										tabIndex = -1;
14888										btnClass += ' ' + disabledClass;
14889									}
14890									break;
14891
14892								case 'last':
14893									btnDisplay = lang.sLast;
14894
14895									if ( pages === 0 || page === pages-1 ) {
14896										tabIndex = -1;
14897										btnClass += ' ' + disabledClass;
14898									}
14899									break;
14900
14901								default:
14902									btnDisplay = settings.fnFormatNumber( button + 1 );
14903									btnClass = page === button ?
14904										classes.sPageButtonActive : '';
14905									break;
14906							}
14907
14908							if ( btnDisplay !== null ) {
14909								var tag = settings.oInit.pagingTag || 'a';
14910								var disabled = btnClass.indexOf(disabledClass) !== -1;
14911
14912
14913								node = $('<'+tag+'>', {
14914										'class': classes.sPageButton+' '+btnClass,
14915										'aria-controls': settings.sTableId,
14916										'aria-disabled': disabled ? 'true' : null,
14917										'aria-label': aria[ button ],
14918										'role': 'link',
14919										'aria-current': btnClass === classes.sPageButtonActive ? 'page' : null,
14920										'data-dt-idx': button,
14921										'tabindex': tabIndex,
14922										'id': idx === 0 && typeof button === 'string' ?
14923											settings.sTableId +'_'+ button :
14924											null
14925									} )
14926									.html( btnDisplay )
14927									.appendTo( container );
14928
14929								_fnBindAction(
14930									node, {action: button}, clickHandler
14931								);
14932							}
14933						}
14934					}
14935				};
14936
14937				// IE9 throws an 'unknown error' if document.activeElement is used
14938				// inside an iframe or frame. Try / catch the error. Not good for
14939				// accessibility, but neither are frames.
14940				var activeEl;
14941
14942				try {
14943					// Because this approach is destroying and recreating the paging
14944					// elements, focus is lost on the select button which is bad for
14945					// accessibility. So we want to restore focus once the draw has
14946					// completed
14947					activeEl = $(host).find(document.activeElement).data('dt-idx');
14948				}
14949				catch (e) {}
14950
14951				attach( $(host).empty(), buttons );
14952
14953				if ( activeEl !== undefined ) {
14954					$(host).find( '[data-dt-idx='+activeEl+']' ).trigger('focus');
14955				}
14956			}
14957		}
14958	} );
14959
14960
14961
14962	// Built in type detection. See model.ext.aTypes for information about
14963	// what is required from this methods.
14964	$.extend( DataTable.ext.type.detect, [
14965		// Plain numbers - first since V8 detects some plain numbers as dates
14966		// e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...).
14967		function ( d, settings )
14968		{
14969			var decimal = settings.oLanguage.sDecimal;
14970			return _isNumber( d, decimal ) ? 'num'+decimal : null;
14971		},
14972
14973		// Dates (only those recognised by the browser's Date.parse)
14974		function ( d, settings )
14975		{
14976			// V8 tries _very_ hard to make a string passed into `Date.parse()`
14977			// valid, so we need to use a regex to restrict date formats. Use a
14978			// plug-in for anything other than ISO8601 style strings
14979			if ( d && !(d instanceof Date) && ! _re_date.test(d) ) {
14980				return null;
14981			}
14982			var parsed = Date.parse(d);
14983			return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null;
14984		},
14985
14986		// Formatted numbers
14987		function ( d, settings )
14988		{
14989			var decimal = settings.oLanguage.sDecimal;
14990			return _isNumber( d, decimal, true ) ? 'num-fmt'+decimal : null;
14991		},
14992
14993		// HTML numeric
14994		function ( d, settings )
14995		{
14996			var decimal = settings.oLanguage.sDecimal;
14997			return _htmlNumeric( d, decimal ) ? 'html-num'+decimal : null;
14998		},
14999
15000		// HTML numeric, formatted
15001		function ( d, settings )
15002		{
15003			var decimal = settings.oLanguage.sDecimal;
15004			return _htmlNumeric( d, decimal, true ) ? 'html-num-fmt'+decimal : null;
15005		},
15006
15007		// HTML (this is strict checking - there must be html)
15008		function ( d, settings )
15009		{
15010			return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ?
15011				'html' : null;
15012		}
15013	] );
15014
15015
15016
15017	// Filter formatting functions. See model.ext.ofnSearch for information about
15018	// what is required from these methods.
15019	//
15020	// Note that additional search methods are added for the html numbers and
15021	// html formatted numbers by `_addNumericSort()` when we know what the decimal
15022	// place is
15023
15024
15025	$.extend( DataTable.ext.type.search, {
15026		html: function ( data ) {
15027			return _empty(data) ?
15028				data :
15029				typeof data === 'string' ?
15030					data
15031						.replace( _re_new_lines, " " )
15032						.replace( _re_html, "" ) :
15033					'';
15034		},
15035
15036		string: function ( data ) {
15037			return _empty(data) ?
15038				data :
15039				typeof data === 'string' ?
15040					data.replace( _re_new_lines, " " ) :
15041					data;
15042		}
15043	} );
15044
15045
15046
15047	var __numericReplace = function ( d, decimalPlace, re1, re2 ) {
15048		if ( d !== 0 && (!d || d === '-') ) {
15049			return -Infinity;
15050		}
15051
15052		var type = typeof d;
15053
15054		if (type === 'number' || type === 'bigint') {
15055			return d;
15056		}
15057
15058		// If a decimal place other than `.` is used, it needs to be given to the
15059		// function so we can detect it and replace with a `.` which is the only
15060		// decimal place Javascript recognises - it is not locale aware.
15061		if ( decimalPlace ) {
15062			d = _numToDecimal( d, decimalPlace );
15063		}
15064
15065		if ( d.replace ) {
15066			if ( re1 ) {
15067				d = d.replace( re1, '' );
15068			}
15069
15070			if ( re2 ) {
15071				d = d.replace( re2, '' );
15072			}
15073		}
15074
15075		return d * 1;
15076	};
15077
15078
15079	// Add the numeric 'deformatting' functions for sorting and search. This is done
15080	// in a function to provide an easy ability for the language options to add
15081	// additional methods if a non-period decimal place is used.
15082	function _addNumericSort ( decimalPlace ) {
15083		$.each(
15084			{
15085				// Plain numbers
15086				"num": function ( d ) {
15087					return __numericReplace( d, decimalPlace );
15088				},
15089
15090				// Formatted numbers
15091				"num-fmt": function ( d ) {
15092					return __numericReplace( d, decimalPlace, _re_formatted_numeric );
15093				},
15094
15095				// HTML numeric
15096				"html-num": function ( d ) {
15097					return __numericReplace( d, decimalPlace, _re_html );
15098				},
15099
15100				// HTML numeric, formatted
15101				"html-num-fmt": function ( d ) {
15102					return __numericReplace( d, decimalPlace, _re_html, _re_formatted_numeric );
15103				}
15104			},
15105			function ( key, fn ) {
15106				// Add the ordering method
15107				_ext.type.order[ key+decimalPlace+'-pre' ] = fn;
15108
15109				// For HTML types add a search formatter that will strip the HTML
15110				if ( key.match(/^html\-/) ) {
15111					_ext.type.search[ key+decimalPlace ] = _ext.type.search.html;
15112				}
15113			}
15114		);
15115	}
15116
15117
15118	// Default sort methods
15119	$.extend( _ext.type.order, {
15120		// Dates
15121		"date-pre": function ( d ) {
15122			var ts = Date.parse( d );
15123			return isNaN(ts) ? -Infinity : ts;
15124		},
15125
15126		// html
15127		"html-pre": function ( a ) {
15128			return _empty(a) ?
15129				'' :
15130				a.replace ?
15131					a.replace( /<.*?>/g, "" ).toLowerCase() :
15132					a+'';
15133		},
15134
15135		// string
15136		"string-pre": function ( a ) {
15137			// This is a little complex, but faster than always calling toString,
15138			// http://jsperf.com/tostring-v-check
15139			return _empty(a) ?
15140				'' :
15141				typeof a === 'string' ?
15142					a.toLowerCase() :
15143					! a.toString ?
15144						'' :
15145						a.toString();
15146		},
15147
15148		// string-asc and -desc are retained only for compatibility with the old
15149		// sort methods
15150		"string-asc": function ( x, y ) {
15151			return ((x < y) ? -1 : ((x > y) ? 1 : 0));
15152		},
15153
15154		"string-desc": function ( x, y ) {
15155			return ((x < y) ? 1 : ((x > y) ? -1 : 0));
15156		}
15157	} );
15158
15159
15160	// Numeric sorting types - order doesn't matter here
15161	_addNumericSort( '' );
15162
15163
15164	$.extend( true, DataTable.ext.renderer, {
15165		header: {
15166			_: function ( settings, cell, column, classes ) {
15167				// No additional mark-up required
15168				// Attach a sort listener to update on sort - note that using the
15169				// `DT` namespace will allow the event to be removed automatically
15170				// on destroy, while the `dt` namespaced event is the one we are
15171				// listening for
15172				$(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
15173					if ( settings !== ctx ) { // need to check this this is the host
15174						return;               // table, not a nested one
15175					}
15176
15177					var colIdx = column.idx;
15178
15179					cell
15180						.removeClass(
15181							classes.sSortAsc +' '+
15182							classes.sSortDesc
15183						)
15184						.addClass( columns[ colIdx ] == 'asc' ?
15185							classes.sSortAsc : columns[ colIdx ] == 'desc' ?
15186								classes.sSortDesc :
15187								column.sSortingClass
15188						);
15189				} );
15190			},
15191
15192			jqueryui: function ( settings, cell, column, classes ) {
15193				$('<div/>')
15194					.addClass( classes.sSortJUIWrapper )
15195					.append( cell.contents() )
15196					.append( $('<span/>')
15197						.addClass( classes.sSortIcon+' '+column.sSortingClassJUI )
15198					)
15199					.appendTo( cell );
15200
15201				// Attach a sort listener to update on sort
15202				$(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
15203					if ( settings !== ctx ) {
15204						return;
15205					}
15206
15207					var colIdx = column.idx;
15208
15209					cell
15210						.removeClass( classes.sSortAsc +" "+classes.sSortDesc )
15211						.addClass( columns[ colIdx ] == 'asc' ?
15212							classes.sSortAsc : columns[ colIdx ] == 'desc' ?
15213								classes.sSortDesc :
15214								column.sSortingClass
15215						);
15216
15217					cell
15218						.find( 'span.'+classes.sSortIcon )
15219						.removeClass(
15220							classes.sSortJUIAsc +" "+
15221							classes.sSortJUIDesc +" "+
15222							classes.sSortJUI +" "+
15223							classes.sSortJUIAscAllowed +" "+
15224							classes.sSortJUIDescAllowed
15225						)
15226						.addClass( columns[ colIdx ] == 'asc' ?
15227							classes.sSortJUIAsc : columns[ colIdx ] == 'desc' ?
15228								classes.sSortJUIDesc :
15229								column.sSortingClassJUI
15230						);
15231				} );
15232			}
15233		}
15234	} );
15235
15236	/*
15237	 * Public helper functions. These aren't used internally by DataTables, or
15238	 * called by any of the options passed into DataTables, but they can be used
15239	 * externally by developers working with DataTables. They are helper functions
15240	 * to make working with DataTables a little bit easier.
15241	 */
15242
15243	var __htmlEscapeEntities = function ( d ) {
15244		if (Array.isArray(d)) {
15245			d = d.join(',');
15246		}
15247
15248		return typeof d === 'string' ?
15249			d
15250				.replace(/&/g, '&amp;')
15251				.replace(/</g, '&lt;')
15252				.replace(/>/g, '&gt;')
15253				.replace(/"/g, '&quot;') :
15254			d;
15255	};
15256
15257	// Common logic for moment, luxon or a date action
15258	function __mld( dt, momentFn, luxonFn, dateFn, arg1 ) {
15259		if (window.moment) {
15260			return dt[momentFn]( arg1 );
15261		}
15262		else if (window.luxon) {
15263			return dt[luxonFn]( arg1 );
15264		}
15265
15266		return dateFn ? dt[dateFn]( arg1 ) : dt;
15267	}
15268
15269
15270	var __mlWarning = false;
15271	function __mldObj (d, format, locale) {
15272		var dt;
15273
15274		if (window.moment) {
15275			dt = window.moment.utc( d, format, locale, true );
15276
15277			if (! dt.isValid()) {
15278				return null;
15279			}
15280		}
15281		else if (window.luxon) {
15282			dt = format && typeof d === 'string'
15283				? window.luxon.DateTime.fromFormat( d, format )
15284				: window.luxon.DateTime.fromISO( d );
15285
15286			if (! dt.isValid) {
15287				return null;
15288			}
15289
15290			dt.setLocale(locale);
15291		}
15292		else if (! format) {
15293			// No format given, must be ISO
15294			dt = new Date(d);
15295		}
15296		else {
15297			if (! __mlWarning) {
15298				alert('DataTables warning: Formatted date without Moment.js or Luxon - https://datatables.net/tn/17');
15299			}
15300
15301			__mlWarning = true;
15302		}
15303
15304		return dt;
15305	}
15306
15307	// Wrapper for date, datetime and time which all operate the same way with the exception of
15308	// the output string for auto locale support
15309	function __mlHelper (localeString) {
15310		return function ( from, to, locale, def ) {
15311			// Luxon and Moment support
15312			// Argument shifting
15313			if ( arguments.length === 0 ) {
15314				locale = 'en';
15315				to = null; // means toLocaleString
15316				from = null; // means iso8601
15317			}
15318			else if ( arguments.length === 1 ) {
15319				locale = 'en';
15320				to = from;
15321				from = null;
15322			}
15323			else if ( arguments.length === 2 ) {
15324				locale = to;
15325				to = from;
15326				from = null;
15327			}
15328
15329			var typeName = 'datetime-' + to;
15330
15331			// Add type detection and sorting specific to this date format - we need to be able to identify
15332			// date type columns as such, rather than as numbers in extensions. Hence the need for this.
15333			if (! DataTable.ext.type.order[typeName]) {
15334				// The renderer will give the value to type detect as the type!
15335				DataTable.ext.type.detect.unshift(function (d) {
15336					return d === typeName ? typeName : false;
15337				});
15338
15339				// The renderer gives us Moment, Luxon or Date obects for the sorting, all of which have a
15340				// `valueOf` which gives milliseconds epoch
15341				DataTable.ext.type.order[typeName + '-asc'] = function (a, b) {
15342					var x = a.valueOf();
15343					var y = b.valueOf();
15344
15345					return x === y
15346						? 0
15347						: x < y
15348							? -1
15349							: 1;
15350				}
15351
15352				DataTable.ext.type.order[typeName + '-desc'] = function (a, b) {
15353					var x = a.valueOf();
15354					var y = b.valueOf();
15355
15356					return x === y
15357						? 0
15358						: x > y
15359							? -1
15360							: 1;
15361				}
15362			}
15363
15364			return function ( d, type ) {
15365				// Allow for a default value
15366				if (d === null || d === undefined) {
15367					if (def === '--now') {
15368						// We treat everything as UTC further down, so no changes are
15369						// made, as such need to get the local date / time as if it were
15370						// UTC
15371						var local = new Date();
15372						d = new Date( Date.UTC(
15373							local.getFullYear(), local.getMonth(), local.getDate(),
15374							local.getHours(), local.getMinutes(), local.getSeconds()
15375						) );
15376					}
15377					else {
15378						d = '';
15379					}
15380				}
15381
15382				if (type === 'type') {
15383					// Typing uses the type name for fast matching
15384					return typeName;
15385				}
15386
15387				if (d === '') {
15388					return type !== 'sort'
15389						? ''
15390						: __mldObj('0000-01-01 00:00:00', null, locale);
15391				}
15392
15393				// Shortcut. If `from` and `to` are the same, we are using the renderer to
15394				// format for ordering, not display - its already in the display format.
15395				if ( to !== null && from === to && type !== 'sort' && type !== 'type' && ! (d instanceof Date) ) {
15396					return d;
15397				}
15398
15399				var dt = __mldObj(d, from, locale);
15400
15401				if (dt === null) {
15402					return d;
15403				}
15404
15405				if (type === 'sort') {
15406					return dt;
15407				}
15408
15409				var formatted = to === null
15410					? __mld(dt, 'toDate', 'toJSDate', '')[localeString]()
15411					: __mld(dt, 'format', 'toFormat', 'toISOString', to);
15412
15413				// XSS protection
15414				return type === 'display' ?
15415					__htmlEscapeEntities( formatted ) :
15416					formatted;
15417			};
15418		}
15419	}
15420
15421	// Based on locale, determine standard number formatting
15422	// Fallback for legacy browsers is US English
15423	var __thousands = ',';
15424	var __decimal = '.';
15425
15426	if (window.Intl !== undefined) {
15427		try {
15428			var num = new Intl.NumberFormat().formatToParts(100000.1);
15429
15430			for (var i=0 ; i<num.length ; i++) {
15431				if (num[i].type === 'group') {
15432					__thousands = num[i].value;
15433				}
15434				else if (num[i].type === 'decimal') {
15435					__decimal = num[i].value;
15436				}
15437			}
15438		}
15439		catch (e) {
15440			// noop
15441		}
15442	}
15443
15444	// Formatted date time detection - use by declaring the formats you are going to use
15445	DataTable.datetime = function ( format, locale ) {
15446		var typeName = 'datetime-detect-' + format;
15447
15448		if (! locale) {
15449			locale = 'en';
15450		}
15451
15452		if (! DataTable.ext.type.order[typeName]) {
15453			DataTable.ext.type.detect.unshift(function (d) {
15454				var dt = __mldObj(d, format, locale);
15455				return d === '' || dt ? typeName : false;
15456			});
15457
15458			DataTable.ext.type.order[typeName + '-pre'] = function (d) {
15459				return __mldObj(d, format, locale) || 0;
15460			}
15461		}
15462	}
15463
15464	/**
15465	 * Helpers for `columns.render`.
15466	 *
15467	 * The options defined here can be used with the `columns.render` initialisation
15468	 * option to provide a display renderer. The following functions are defined:
15469	 *
15470	 * * `number` - Will format numeric data (defined by `columns.data`) for
15471	 *   display, retaining the original unformatted data for sorting and filtering.
15472	 *   It takes 5 parameters:
15473	 *   * `string` - Thousands grouping separator
15474	 *   * `string` - Decimal point indicator
15475	 *   * `integer` - Number of decimal points to show
15476	 *   * `string` (optional) - Prefix.
15477	 *   * `string` (optional) - Postfix (/suffix).
15478	 * * `text` - Escape HTML to help prevent XSS attacks. It has no optional
15479	 *   parameters.
15480	 *
15481	 * @example
15482	 *   // Column definition using the number renderer
15483	 *   {
15484	 *     data: "salary",
15485	 *     render: $.fn.dataTable.render.number( '\'', '.', 0, '$' )
15486	 *   }
15487	 *
15488	 * @namespace
15489	 */
15490	DataTable.render = {
15491		date: __mlHelper('toLocaleDateString'),
15492		datetime: __mlHelper('toLocaleString'),
15493		time: __mlHelper('toLocaleTimeString'),
15494		number: function ( thousands, decimal, precision, prefix, postfix ) {
15495			// Auto locale detection
15496			if (thousands === null || thousands === undefined) {
15497				thousands = __thousands;
15498			}
15499
15500			if (decimal === null || decimal === undefined) {
15501				decimal = __decimal;
15502			}
15503
15504			return {
15505				display: function ( d ) {
15506					if ( typeof d !== 'number' && typeof d !== 'string' ) {
15507						return d;
15508					}
15509
15510					if (d === '' || d === null) {
15511						return d;
15512					}
15513
15514					var negative = d < 0 ? '-' : '';
15515					var flo = parseFloat( d );
15516
15517					// If NaN then there isn't much formatting that we can do - just
15518					// return immediately, escaping any HTML (this was supposed to
15519					// be a number after all)
15520					if ( isNaN( flo ) ) {
15521						return __htmlEscapeEntities( d );
15522					}
15523
15524					flo = flo.toFixed( precision );
15525					d = Math.abs( flo );
15526
15527					var intPart = parseInt( d, 10 );
15528					var floatPart = precision ?
15529						decimal+(d - intPart).toFixed( precision ).substring( 2 ):
15530						'';
15531
15532					// If zero, then can't have a negative prefix
15533					if (intPart === 0 && parseFloat(floatPart) === 0) {
15534						negative = '';
15535					}
15536
15537					return negative + (prefix||'') +
15538						intPart.toString().replace(
15539							/\B(?=(\d{3})+(?!\d))/g, thousands
15540						) +
15541						floatPart +
15542						(postfix||'');
15543				}
15544			};
15545		},
15546
15547		text: function () {
15548			return {
15549				display: __htmlEscapeEntities,
15550				filter: __htmlEscapeEntities
15551			};
15552		}
15553	};
15554
15555
15556	/*
15557	 * This is really a good bit rubbish this method of exposing the internal methods
15558	 * publicly... - To be fixed in 2.0 using methods on the prototype
15559	 */
15560
15561
15562	/**
15563	 * Create a wrapper function for exporting an internal functions to an external API.
15564	 *  @param {string} fn API function name
15565	 *  @returns {function} wrapped function
15566	 *  @memberof DataTable#internal
15567	 */
15568	function _fnExternApiFunc (fn)
15569	{
15570		return function() {
15571			var args = [_fnSettingsFromNode( this[DataTable.ext.iApiIndex] )].concat(
15572				Array.prototype.slice.call(arguments)
15573			);
15574			return DataTable.ext.internal[fn].apply( this, args );
15575		};
15576	}
15577
15578
15579	/**
15580	 * Reference to internal functions for use by plug-in developers. Note that
15581	 * these methods are references to internal functions and are considered to be
15582	 * private. If you use these methods, be aware that they are liable to change
15583	 * between versions.
15584	 *  @namespace
15585	 */
15586	$.extend( DataTable.ext.internal, {
15587		_fnExternApiFunc: _fnExternApiFunc,
15588		_fnBuildAjax: _fnBuildAjax,
15589		_fnAjaxUpdate: _fnAjaxUpdate,
15590		_fnAjaxParameters: _fnAjaxParameters,
15591		_fnAjaxUpdateDraw: _fnAjaxUpdateDraw,
15592		_fnAjaxDataSrc: _fnAjaxDataSrc,
15593		_fnAddColumn: _fnAddColumn,
15594		_fnColumnOptions: _fnColumnOptions,
15595		_fnAdjustColumnSizing: _fnAdjustColumnSizing,
15596		_fnVisibleToColumnIndex: _fnVisibleToColumnIndex,
15597		_fnColumnIndexToVisible: _fnColumnIndexToVisible,
15598		_fnVisbleColumns: _fnVisbleColumns,
15599		_fnGetColumns: _fnGetColumns,
15600		_fnColumnTypes: _fnColumnTypes,
15601		_fnApplyColumnDefs: _fnApplyColumnDefs,
15602		_fnHungarianMap: _fnHungarianMap,
15603		_fnCamelToHungarian: _fnCamelToHungarian,
15604		_fnLanguageCompat: _fnLanguageCompat,
15605		_fnBrowserDetect: _fnBrowserDetect,
15606		_fnAddData: _fnAddData,
15607		_fnAddTr: _fnAddTr,
15608		_fnNodeToDataIndex: _fnNodeToDataIndex,
15609		_fnNodeToColumnIndex: _fnNodeToColumnIndex,
15610		_fnGetCellData: _fnGetCellData,
15611		_fnSetCellData: _fnSetCellData,
15612		_fnSplitObjNotation: _fnSplitObjNotation,
15613		_fnGetObjectDataFn: _fnGetObjectDataFn,
15614		_fnSetObjectDataFn: _fnSetObjectDataFn,
15615		_fnGetDataMaster: _fnGetDataMaster,
15616		_fnClearTable: _fnClearTable,
15617		_fnDeleteIndex: _fnDeleteIndex,
15618		_fnInvalidate: _fnInvalidate,
15619		_fnGetRowElements: _fnGetRowElements,
15620		_fnCreateTr: _fnCreateTr,
15621		_fnBuildHead: _fnBuildHead,
15622		_fnDrawHead: _fnDrawHead,
15623		_fnDraw: _fnDraw,
15624		_fnReDraw: _fnReDraw,
15625		_fnAddOptionsHtml: _fnAddOptionsHtml,
15626		_fnDetectHeader: _fnDetectHeader,
15627		_fnGetUniqueThs: _fnGetUniqueThs,
15628		_fnFeatureHtmlFilter: _fnFeatureHtmlFilter,
15629		_fnFilterComplete: _fnFilterComplete,
15630		_fnFilterCustom: _fnFilterCustom,
15631		_fnFilterColumn: _fnFilterColumn,
15632		_fnFilter: _fnFilter,
15633		_fnFilterCreateSearch: _fnFilterCreateSearch,
15634		_fnEscapeRegex: _fnEscapeRegex,
15635		_fnFilterData: _fnFilterData,
15636		_fnFeatureHtmlInfo: _fnFeatureHtmlInfo,
15637		_fnUpdateInfo: _fnUpdateInfo,
15638		_fnInfoMacros: _fnInfoMacros,
15639		_fnInitialise: _fnInitialise,
15640		_fnInitComplete: _fnInitComplete,
15641		_fnLengthChange: _fnLengthChange,
15642		_fnFeatureHtmlLength: _fnFeatureHtmlLength,
15643		_fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate,
15644		_fnPageChange: _fnPageChange,
15645		_fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing,
15646		_fnProcessingDisplay: _fnProcessingDisplay,
15647		_fnFeatureHtmlTable: _fnFeatureHtmlTable,
15648		_fnScrollDraw: _fnScrollDraw,
15649		_fnApplyToChildren: _fnApplyToChildren,
15650		_fnCalculateColumnWidths: _fnCalculateColumnWidths,
15651		_fnThrottle: _fnThrottle,
15652		_fnConvertToWidth: _fnConvertToWidth,
15653		_fnGetWidestNode: _fnGetWidestNode,
15654		_fnGetMaxLenString: _fnGetMaxLenString,
15655		_fnStringToCss: _fnStringToCss,
15656		_fnSortFlatten: _fnSortFlatten,
15657		_fnSort: _fnSort,
15658		_fnSortAria: _fnSortAria,
15659		_fnSortListener: _fnSortListener,
15660		_fnSortAttachListener: _fnSortAttachListener,
15661		_fnSortingClasses: _fnSortingClasses,
15662		_fnSortData: _fnSortData,
15663		_fnSaveState: _fnSaveState,
15664		_fnLoadState: _fnLoadState,
15665		_fnImplementState: _fnImplementState,
15666		_fnSettingsFromNode: _fnSettingsFromNode,
15667		_fnLog: _fnLog,
15668		_fnMap: _fnMap,
15669		_fnBindAction: _fnBindAction,
15670		_fnCallbackReg: _fnCallbackReg,
15671		_fnCallbackFire: _fnCallbackFire,
15672		_fnLengthOverflow: _fnLengthOverflow,
15673		_fnRenderer: _fnRenderer,
15674		_fnDataSource: _fnDataSource,
15675		_fnRowAttributes: _fnRowAttributes,
15676		_fnExtend: _fnExtend,
15677		_fnCalculateEnd: function () {} // Used by a lot of plug-ins, but redundant
15678		                                // in 1.10, so this dead-end function is
15679		                                // added to prevent errors
15680	} );
15681
15682
15683	// jQuery access
15684	$.fn.dataTable = DataTable;
15685
15686	// Provide access to the host jQuery object (circular reference)
15687	DataTable.$ = $;
15688
15689	// Legacy aliases
15690	$.fn.dataTableSettings = DataTable.settings;
15691	$.fn.dataTableExt = DataTable.ext;
15692
15693	// With a capital `D` we return a DataTables API instance rather than a
15694	// jQuery object
15695	$.fn.DataTable = function ( opts ) {
15696		return $(this).dataTable( opts ).api();
15697	};
15698
15699	// All properties that are available to $.fn.dataTable should also be
15700	// available on $.fn.DataTable
15701	$.each( DataTable, function ( prop, val ) {
15702		$.fn.DataTable[ prop ] = val;
15703	} );
15704
15705	return DataTable;
15706}));
15707