PageSourceSearch

https://tec.mx/libraries/datatables.net/js/jquery.dataTables.js?tmme9z

js tec.mx collected 2026-10-10 00:08:48 UTC 457,711 bytes, 15,733 lines download raw bytes

1/*! DataTables 1.13.11
2 * ©2008-2024 SpryMedia Ltd - datatables.net/license
3 */
4
5/**
6 * @summary     DataTables
7 * @description Paginate, search and order HTML tables
8 * @version     1.13.11
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 - https://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: https://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			module.exports =
vendor: 41,972 bytes, lines 57-1348
57 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
1348s
vendor: 27,673 bytes, lines 1348-2347
1348://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	
2347
2348			// Fall back to the aria-label attribute on the table header if no ariaTitle is
2349			// provided.
2350			if (! oCol.ariaTitle) {
2351				oCol.ariaTitle = th.attr("aria-label");
2352			}
vendor: 54,944 bytes, lines 2352-4316
2352
2353		}
2354	
2355		/* Cache the data get and set functions for speed */
2356		var mDataSrc = oCol.mData;
2357		var mData = _fnGetObjectDataFn( mDataSrc );
2358		var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null;
2359	
2360		var attrTest = function( src ) {
2361			return typeof src === 'string' && src.indexOf('@') !== -1;
2362		};
2363		oCol._bAttrSrc = $.isPlainObject( mDataSrc ) && (
2364			attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter)
2365		);
2366		oCol._setter = null;
2367	
2368		oCol.fnGetData = function (rowData, type, meta) {
2369			var innerData = mData( rowData, type, undefined, meta );
2370	
2371			return mRender && type ?
2372				mRender( innerData, type, rowData, meta ) :
2373				innerData;
2374		};
2375		oCol.fnSetData = function ( rowData, val, meta ) {
2376			return _fnSetObjectDataFn( mDataSrc )( rowData, val, meta );
2377		};
2378	
2379		// Indicate if DataTables should read DOM data as an object or array
2380		// Used in _fnGetRowElements
2381		if ( typeof mDataSrc !== 'number' && ! oCol._isArrayHost ) {
2382			oSettings._rowReadObject = true;
2383		}
2384	
2385		/* Feature sorting overrides column specific when off */
2386		if ( !oSettings.oFeatures.bSort )
2387		{
2388			oCol.bSortable = false;
2389			th.addClass( oClasses.sSortableNone ); // Have to add class here as order event isn't called
2390		}
2391	
2392		/* Check that the class assignment is correct for sorting */
2393		var bAsc = $.inArray('asc', oCol.asSorting) !== -1;
2394		var bDesc = $.inArray('desc', oCol.asSorting) !== -1;
2395		if ( !oCol.bSortable || (!bAsc && !bDesc) )
2396		{
2397			oCol.sSortingClass = oClasses.sSortableNone;
2398			oCol.sSortingClassJUI = "";
2399		}
2400		else if ( bAsc && !bDesc )
2401		{
2402			oCol.sSortingClass = oClasses.sSortableAsc;
2403			oCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed;
2404		}
2405		else if ( !bAsc && bDesc )
2406		{
2407			oCol.sSortingClass = oClasses.sSortableDesc;
2408			oCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed;
2409		}
2410		else
2411		{
2412			oCol.sSortingClass = oClasses.sSortable;
2413			oCol.sSortingClassJUI = oClasses.sSortJUI;
2414		}
2415	}
2416	
2417	
2418	/**
2419	 * Adjust the table column widths for new data. Note: you would probably want to
2420	 * do a redraw after calling this function!
2421	 *  @param {object} settings dataTables settings object
2422	 *  @memberof DataTable#oApi
2423	 */
2424	function _fnAdjustColumnSizing ( settings )
2425	{
2426		/* Not interested in doing column width calculation if auto-width is disabled */
2427		if ( settings.oFeatures.bAutoWidth !== false )
2428		{
2429			var columns = settings.aoColumns;
2430	
2431			_fnCalculateColumnWidths( settings );
2432			for ( var i=0 , iLen=columns.length ; i<iLen ; i++ )
2433			{
2434				columns[i].nTh.style.width = columns[i].sWidth;
2435			}
2436		}
2437	
2438		var scroll = settings.oScroll;
2439		if ( scroll.sY !== '' || scroll.sX !== '')
2440		{
2441			_fnScrollDraw( settings );
2442		}
2443	
2444		_fnCallbackFire( settings, null, 'column-sizing', [settings] );
2445	}
2446	
2447	
2448	/**
2449	 * Convert the index of a visible column to the index in the data array (take account
2450	 * of hidden columns)
2451	 *  @param {object} oSettings dataTables settings object
2452	 *  @param {int} iMatch Visible column index to lookup
2453	 *  @returns {int} i the data index
2454	 *  @memberof DataTable#oApi
2455	 */
2456	function _fnVisibleToColumnIndex( oSettings, iMatch )
2457	{
2458		var aiVis = _fnGetColumns( oSettings, 'bVisible' );
2459	
2460		return typeof aiVis[iMatch] === 'number' ?
2461			aiVis[iMatch] :
2462			null;
2463	}
2464	
2465	
2466	/**
2467	 * Convert the index of an index in the data array and convert it to the visible
2468	 *   column index (take account of hidden columns)
2469	 *  @param {int} iMatch Column index to lookup
2470	 *  @param {object} oSettings dataTables settings object
2471	 *  @returns {int} i the data index
2472	 *  @memberof DataTable#oApi
2473	 */
2474	function _fnColumnIndexToVisible( oSettings, iMatch )
2475	{
2476		var aiVis = _fnGetColumns( oSettings, 'bVisible' );
2477		var iPos = $.inArray( iMatch, aiVis );
2478	
2479		return iPos !== -1 ? iPos : null;
2480	}
2481	
2482	
2483	/**
2484	 * Get the number of visible columns
2485	 *  @param {object} oSettings dataTables settings object
2486	 *  @returns {int} i the number of visible columns
2487	 *  @memberof DataTable#oApi
2488	 */
2489	function _fnVisbleColumns( oSettings )
2490	{
2491		var vis = 0;
2492	
2493		// No reduce in IE8, use a loop for now
2494		$.each( oSettings.aoColumns, function ( i, col ) {
2495			if ( col.bVisible && $(col.nTh).css('display') !== 'none' ) {
2496				vis++;
2497			}
2498		} );
2499	
2500		return vis;
2501	}
2502	
2503	
2504	/**
2505	 * Get an array of column indexes that match a given property
2506	 *  @param {object} oSettings dataTables settings object
2507	 *  @param {string} sParam Parameter in aoColumns to look for - typically
2508	 *    bVisible or bSearchable
2509	 *  @returns {array} Array of indexes with matched properties
2510	 *  @memberof DataTable#oApi
2511	 */
2512	function _fnGetColumns( oSettings, sParam )
2513	{
2514		var a = [];
2515	
2516		$.map( oSettings.aoColumns, function(val, i) {
2517			if ( val[sParam] ) {
2518				a.push( i );
2519			}
2520		} );
2521	
2522		return a;
2523	}
2524	
2525	
2526	/**
2527	 * Calculate the 'type' of a column
2528	 *  @param {object} settings dataTables settings object
2529	 *  @memberof DataTable#oApi
2530	 */
2531	function _fnColumnTypes ( settings )
2532	{
2533		var columns = settings.aoColumns;
2534		var data = settings.aoData;
2535		var types = DataTable.ext.type.detect;
2536		var i, ien, j, jen, k, ken;
2537		var col, cell, detectedType, cache;
2538	
2539		// For each column, spin over the 
2540		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
2541			col = columns[i];
2542			cache = [];
2543	
2544			if ( ! col.sType && col._sManualType ) {
2545				col.sType = col._sManualType;
2546			}
2547			else if ( ! col.sType ) {
2548				for ( j=0, jen=types.length ; j<jen ; j++ ) {
2549					for ( k=0, ken=data.length ; k<ken ; k++ ) {
2550						// Use a cache array so we only need to get the type data
2551						// from the formatter once (when using multiple detectors)
2552						if ( cache[k] === undefined ) {
2553							cache[k] = _fnGetCellData( settings, k, i, 'type' );
2554						}
2555	
2556						detectedType = types[j]( cache[k], settings );
2557	
2558						// If null, then this type can't apply to this column, so
2559						// rather than testing all cells, break out. There is an
2560						// exception for the last type which is `html`. We need to
2561						// scan all rows since it is possible to mix string and HTML
2562						// types
2563						if ( ! detectedType && j !== types.length-1 ) {
2564							break;
2565						}
2566	
2567						// Only a single match is needed for html type since it is
2568						// bottom of the pile and very similar to string - but it
2569						// must not be empty
2570						if ( detectedType === 'html' && ! _empty(cache[k]) ) {
2571							break;
2572						}
2573					}
2574	
2575					// Type is valid for all data points in the column - use this
2576					// type
2577					if ( detectedType ) {
2578						col.sType = detectedType;
2579						break;
2580					}
2581				}
2582	
2583				// Fall back - if no type was detected, always use string
2584				if ( ! col.sType ) {
2585					col.sType = 'string';
2586				}
2587			}
2588		}
2589	}
2590	
2591	
2592	/**
2593	 * Take the column definitions and static columns arrays and calculate how
2594	 * they relate to column indexes. The callback function will then apply the
2595	 * definition found for a column to a suitable configuration object.
2596	 *  @param {object} oSettings dataTables settings object
2597	 *  @param {array} aoColDefs The aoColumnDefs array that is to be applied
2598	 *  @param {array} aoCols The aoColumns array that defines columns individually
2599	 *  @param {function} fn Callback function - takes two parameters, the calculated
2600	 *    column index and the definition for that column.
2601	 *  @memberof DataTable#oApi
2602	 */
2603	function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )
2604	{
2605		var i, iLen, j, jLen, k, kLen, def;
2606		var columns = oSettings.aoColumns;
2607	
2608		// Column definitions with aTargets
2609		if ( aoColDefs )
2610		{
2611			/* Loop over the definitions array - loop in reverse so first instance has priority */
2612			for ( i=aoColDefs.length-1 ; i>=0 ; i-- )
2613			{
2614				def = aoColDefs[i];
2615	
2616				/* Each definition can target multiple columns, as it is an array */
2617				var aTargets = def.target !== undefined
2618					? def.target
2619					: def.targets !== undefined
2620						? def.targets
2621						: def.aTargets;
2622	
2623				if ( ! Array.isArray( aTargets ) )
2624				{
2625					aTargets = [ aTargets ];
2626				}
2627	
2628				for ( j=0, jLen=aTargets.length ; j<jLen ; j++ )
2629				{
2630					if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 )
2631					{
2632						/* Add columns that we don't yet know about */
2633						while( columns.length <= aTargets[j] )
2634						{
2635							_fnAddColumn( oSettings );
2636						}
2637	
2638						/* Integer, basic index */
2639						fn( aTargets[j], def );
2640					}
2641					else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 )
2642					{
2643						/* Negative integer, right to left column counting */
2644						fn( columns.length+aTargets[j], def );
2645					}
2646					else if ( typeof aTargets[j] === 'string' )
2647					{
2648						/* Class name matching on TH element */
2649						for ( k=0, kLen=columns.length ; k<kLen ; k++ )
2650						{
2651							if ( aTargets[j] == "_all" ||
2652							     $(columns[k].nTh).hasClass( aTargets[j] ) )
2653							{
2654								fn( k, def );
2655							}
2656						}
2657					}
2658				}
2659			}
2660		}
2661	
2662		// Statically defined columns array
2663		if ( aoCols )
2664		{
2665			for ( i=0, iLen=aoCols.length ; i<iLen ; i++ )
2666			{
2667				fn( i, aoCols[i] );
2668			}
2669		}
2670	}
2671	
2672	/**
2673	 * Add a data array to the table, creating DOM node etc. This is the parallel to
2674	 * _fnGatherData, but for adding rows from a Javascript source, rather than a
2675	 * DOM source.
2676	 *  @param {object} oSettings dataTables settings object
2677	 *  @param {array} aData data array to be added
2678	 *  @param {node} [nTr] TR element to add to the table - optional. If not given,
2679	 *    DataTables will create a row automatically
2680	 *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
2681	 *    if nTr is.
2682	 *  @returns {int} >=0 if successful (index of new aoData entry), -1 if failed
2683	 *  @memberof DataTable#oApi
2684	 */
2685	function _fnAddData ( oSettings, aDataIn, nTr, anTds )
2686	{
2687		/* Create the object for storing information about this new row */
2688		var iRow = oSettings.aoData.length;
2689		var oData = $.extend( true, {}, DataTable.models.oRow, {
2690			src: nTr ? 'dom' : 'data',
2691			idx: iRow
2692		} );
2693	
2694		oData._aData = aDataIn;
2695		oSettings.aoData.push( oData );
2696	
2697		/* Create the cells */
2698		var nTd, sThisType;
2699		var columns = oSettings.aoColumns;
2700	
2701		// Invalidate the column types as the new data needs to be revalidated
2702		for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
2703		{
2704			columns[i].sType = null;
2705		}
2706	
2707		/* Add to the display array */
2708		oSettings.aiDisplayMaster.push( iRow );
2709	
2710		var id = oSettings.rowIdFn( aDataIn );
2711		if ( id !== undefined ) {
2712			oSettings.aIds[ id ] = oData;
2713		}
2714	
2715		/* Create the DOM information, or register it if already present */
2716		if ( nTr || ! oSettings.oFeatures.bDeferRender )
2717		{
2718			_fnCreateTr( oSettings, iRow, nTr, anTds );
2719		}
2720	
2721		return iRow;
2722	}
2723	
2724	
2725	/**
2726	 * Add one or more TR elements to the table. Generally we'd expect to
2727	 * use this for reading data from a DOM sourced table, but it could be
2728	 * used for an TR element. Note that if a TR is given, it is used (i.e.
2729	 * it is not cloned).
2730	 *  @param {object} settings dataTables settings object
2731	 *  @param {array|node|jQuery} trs The TR element(s) to add to the table
2732	 *  @returns {array} Array of indexes for the added rows
2733	 *  @memberof DataTable#oApi
2734	 */
2735	function _fnAddTr( settings, trs )
2736	{
2737		var row;
2738	
2739		// Allow an individual node to be passed in
2740		if ( ! (trs instanceof $) ) {
2741			trs = $(trs);
2742		}
2743	
2744		return trs.map( function (i, el) {
2745			row = _fnGetRowElements( settings, el );
2746			return _fnAddData( settings, row.data, el, row.cells );
2747		} );
2748	}
2749	
2750	
2751	/**
2752	 * Take a TR element and convert it to an index in aoData
2753	 *  @param {object} oSettings dataTables settings object
2754	 *  @param {node} n the TR element to find
2755	 *  @returns {int} index if the node is found, null if not
2756	 *  @memberof DataTable#oApi
2757	 */
2758	function _fnNodeToDataIndex( oSettings, n )
2759	{
2760		return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null;
2761	}
2762	
2763	
2764	/**
2765	 * Take a TD element and convert it into a column data index (not the visible index)
2766	 *  @param {object} oSettings dataTables settings object
2767	 *  @param {int} iRow The row number the TD/TH can be found in
2768	 *  @param {node} n The TD/TH element to find
2769	 *  @returns {int} index if the node is found, -1 if not
2770	 *  @memberof DataTable#oApi
2771	 */
2772	function _fnNodeToColumnIndex( oSettings, iRow, n )
2773	{
2774		return $.inArray( n, oSettings.aoData[ iRow ].anCells );
2775	}
2776	
2777	
2778	/**
2779	 * Get the data for a given cell from the internal cache, taking into account data mapping
2780	 *  @param {object} settings dataTables settings object
2781	 *  @param {int} rowIdx aoData row id
2782	 *  @param {int} colIdx Column index
2783	 *  @param {string} type data get type ('display', 'type' 'filter|search' 'sort|order')
2784	 *  @returns {*} Cell data
2785	 *  @memberof DataTable#oApi
2786	 */
2787	function _fnGetCellData( settings, rowIdx, colIdx, type )
2788	{
2789		if (type === 'search') {
2790			type = 'filter';
2791		}
2792		else if (type === 'order') {
2793			type = 'sort';
2794		}
2795	
2796		var draw           = settings.iDraw;
2797		var col            = settings.aoColumns[colIdx];
2798		var rowData        = settings.aoData[rowIdx]._aData;
2799		var defaultContent = col.sDefaultContent;
2800		var cellData       = col.fnGetData( rowData, type, {
2801			settings: settings,
2802			row:      rowIdx,
2803			col:      colIdx
2804		} );
2805	
2806		if ( cellData === undefined ) {
2807			if ( settings.iDrawError != draw && defaultContent === null ) {
2808				_fnLog( settings, 0, "Requested unknown parameter "+
2809					(typeof col.mData=='function' ? '{function}' : "'"+col.mData+"'")+
2810					" for row "+rowIdx+", column "+colIdx, 4 );
2811				settings.iDrawError = draw;
2812			}
2813			return defaultContent;
2814		}
2815	
2816		// When the data source is null and a specific data type is requested (i.e.
2817		// not the original data), we can use default column data
2818		if ( (cellData === rowData || cellData === null) && defaultContent !== null && type !== undefined ) {
2819			cellData = defaultContent;
2820		}
2821		else if ( typeof cellData === 'function' ) {
2822			// If the data source is a function, then we run it and use the return,
2823			// executing in the scope of the data object (for instances)
2824			return cellData.call( rowData );
2825		}
2826	
2827		if ( cellData === null && type === 'display' ) {
2828			return '';
2829		}
2830	
2831		if ( type === 'filter' ) {
2832			var fomatters = DataTable.ext.type.search;
2833	
2834			if ( fomatters[ col.sType ] ) {
2835				cellData = fomatters[ col.sType ]( cellData );
2836			}
2837		}
2838	
2839		return cellData;
2840	}
2841	
2842	
2843	/**
2844	 * Set the value for a specific cell, into the internal data cache
2845	 *  @param {object} settings dataTables settings object
2846	 *  @param {int} rowIdx aoData row id
2847	 *  @param {int} colIdx Column index
2848	 *  @param {*} val Value to set
2849	 *  @memberof DataTable#oApi
2850	 */
2851	function _fnSetCellData( settings, rowIdx, colIdx, val )
2852	{
2853		var col     = settings.aoColumns[colIdx];
2854		var rowData = settings.aoData[rowIdx]._aData;
2855	
2856		col.fnSetData( rowData, val, {
2857			settings: settings,
2858			row:      rowIdx,
2859			col:      colIdx
2860		}  );
2861	}
2862	
2863	
2864	// Private variable that is used to match action syntax in the data property object
2865	var __reArray = /\[.*?\]$/;
2866	var __reFn = /\(\)$/;
2867	
2868	/**
2869	 * Split string on periods, taking into account escaped periods
2870	 * @param  {string} str String to split
2871	 * @return {array} Split string
2872	 */
2873	function _fnSplitObjNotation( str )
2874	{
2875		return $.map( str.match(/(\\.|[^\.])+/g) || [''], function ( s ) {
2876			return s.replace(/\\\./g, '.');
2877		} );
2878	}
2879	
2880	
2881	/**
2882	 * Return a function that can be used to get data from a source object, taking
2883	 * into account the ability to use nested objects as a source
2884	 *  @param {string|int|function} mSource The data source for the object
2885	 *  @returns {function} Data get function
2886	 *  @memberof DataTable#oApi
2887	 */
2888	var _fnGetObjectDataFn = DataTable.util.get;
2889	
2890	
2891	/**
2892	 * Return a function that can be used to set data from a source object, taking
2893	 * into account the ability to use nested objects as a source
2894	 *  @param {string|int|function} mSource The data source for the object
2895	 *  @returns {function} Data set function
2896	 *  @memberof DataTable#oApi
2897	 */
2898	var _fnSetObjectDataFn = DataTable.util.set;
2899	
2900	
2901	/**
2902	 * Return an array with the full table data
2903	 *  @param {object} oSettings dataTables settings object
2904	 *  @returns array {array} aData Master data array
2905	 *  @memberof DataTable#oApi
2906	 */
2907	function _fnGetDataMaster ( settings )
2908	{
2909		return _pluck( settings.aoData, '_aData' );
2910	}
2911	
2912	
2913	/**
2914	 * Nuke the table
2915	 *  @param {object} oSettings dataTables settings object
2916	 *  @memberof DataTable#oApi
2917	 */
2918	function _fnClearTable( settings )
2919	{
2920		settings.aoData.length = 0;
2921		settings.aiDisplayMaster.length = 0;
2922		settings.aiDisplay.length = 0;
2923		settings.aIds = {};
2924	}
2925	
2926	
2927	 /**
2928	 * Take an array of integers (index array) and remove a target integer (value - not
2929	 * the key!)
2930	 *  @param {array} a Index array to target
2931	 *  @param {int} iTarget value to find
2932	 *  @memberof DataTable#oApi
2933	 */
2934	function _fnDeleteIndex( a, iTarget, splice )
2935	{
2936		var iTargetIndex = -1;
2937	
2938		for ( var i=0, iLen=a.length ; i<iLen ; i++ )
2939		{
2940			if ( a[i] == iTarget )
2941			{
2942				iTargetIndex = i;
2943			}
2944			else if ( a[i] > iTarget )
2945			{
2946				a[i]--;
2947			}
2948		}
2949	
2950		if ( iTargetIndex != -1 && splice === undefined )
2951		{
2952			a.splice( iTargetIndex, 1 );
2953		}
2954	}
2955	
2956	
2957	/**
2958	 * Mark cached data as invalid such that a re-read of the data will occur when
2959	 * the cached data is next requested. Also update from the data source object.
2960	 *
2961	 * @param {object} settings DataTables settings object
2962	 * @param {int}    rowIdx   Row index to invalidate
2963	 * @param {string} [src]    Source to invalidate from: undefined, 'auto', 'dom'
2964	 *     or 'data'
2965	 * @param {int}    [colIdx] Column index to invalidate. If undefined the whole
2966	 *     row will be invalidated
2967	 * @memberof DataTable#oApi
2968	 *
2969	 * @todo For the modularisation of v1.11 this will need to become a callback, so
2970	 *   the sort and filter methods can subscribe to it. That will required
2971	 *   initialisation options for sorting, which is why it is not already baked in
2972	 */
2973	function _fnInvalidate( settings, rowIdx, src, colIdx )
2974	{
2975		var row = settings.aoData[ rowIdx ];
2976		var i, ien;
2977		var cellWrite = function ( cell, col ) {
2978			// This is very frustrating, but in IE if you just write directly
2979			// to innerHTML, and elements that are overwritten are GC'ed,
2980			// even if there is a reference to them elsewhere
2981			while ( cell.childNodes.length ) {
2982				cell.removeChild( cell.firstChild );
2983			}
2984	
2985			cell.innerHTML = _fnGetCellData( settings, rowIdx, col, 'display' );
2986		};
2987	
2988		// Are we reading last data from DOM or the data object?
2989		if ( src === 'dom' || ((! src || src === 'auto') && row.src === 'dom') ) {
2990			// Read the data from the DOM
2991			row._aData = _fnGetRowElements(
2992					settings, row, colIdx, colIdx === undefined ? undefined : row._aData
2993				)
2994				.data;
2995		}
2996		else {
2997			// Reading from data object, update the DOM
2998			var cells = row.anCells;
2999	
3000			if ( cells ) {
3001				if ( colIdx !== undefined ) {
3002					cellWrite( cells[colIdx], colIdx );
3003				}
3004				else {
3005					for ( i=0, ien=cells.length ; i<ien ; i++ ) {
3006						cellWrite( cells[i], i );
3007					}
3008				}
3009			}
3010		}
3011	
3012		// For both row and cell invalidation, the cached data for sorting and
3013		// filtering is nulled out
3014		row._aSortData = null;
3015		row._aFilterData = null;
3016	
3017		// Invalidate the type for a specific column (if given) or all columns since
3018		// the data might have changed
3019		var cols = settings.aoColumns;
3020		if ( colIdx !== undefined ) {
3021			cols[ colIdx ].sType = null;
3022		}
3023		else {
3024			for ( i=0, ien=cols.length ; i<ien ; i++ ) {
3025				cols[i].sType = null;
3026			}
3027	
3028			// Update DataTables special `DT_*` attributes for the row
3029			_fnRowAttributes( settings, row );
3030		}
3031	}
3032	
3033	
3034	/**
3035	 * Build a data source object from an HTML row, reading the contents of the
3036	 * cells that are in the row.
3037	 *
3038	 * @param {object} settings DataTables settings object
3039	 * @param {node|object} TR element from which to read data or existing row
3040	 *   object from which to re-read the data from the cells
3041	 * @param {int} [colIdx] Optional column index
3042	 * @param {array|object} [d] Data source object. If `colIdx` is given then this
3043	 *   parameter should also be given and will be used to write the data into.
3044	 *   Only the column in question will be written
3045	 * @returns {object} Object with two parameters: `data` the data read, in
3046	 *   document order, and `cells` and array of nodes (they can be useful to the
3047	 *   caller, so rather than needing a second traversal to get them, just return
3048	 *   them from here).
3049	 * @memberof DataTable#oApi
3050	 */
3051	function _fnGetRowElements( settings, row, colIdx, d )
3052	{
3053		var
3054			tds = [],
3055			td = row.firstChild,
3056			name, col, o, i=0, contents,
3057			columns = settings.aoColumns,
3058			objectRead = settings._rowReadObject;
3059	
3060		// Allow the data object to be passed in, or construct
3061		d = d !== undefined ?
3062			d :
3063			objectRead ?
3064				{} :
3065				[];
3066	
3067		var attr = function ( str, td  ) {
3068			if ( typeof str === 'string' ) {
3069				var idx = str.indexOf('@');
3070	
3071				if ( idx !== -1 ) {
3072					var attr = str.substring( idx+1 );
3073					var setter = _fnSetObjectDataFn( str );
3074					setter( d, td.getAttribute( attr ) );
3075				}
3076			}
3077		};
3078	
3079		// Read data from a cell and store into the data object
3080		var cellProcess = function ( cell ) {
3081			if ( colIdx === undefined || colIdx === i ) {
3082				col = columns[i];
3083				contents = (cell.innerHTML).trim();
3084	
3085				if ( col && col._bAttrSrc ) {
3086					var setter = _fnSetObjectDataFn( col.mData._ );
3087					setter( d, contents );
3088	
3089					attr( col.mData.sort, cell );
3090					attr( col.mData.type, cell );
3091					attr( col.mData.filter, cell );
3092				}
3093				else {
3094					// Depending on the `data` option for the columns the data can
3095					// be read to either an object or an array.
3096					if ( objectRead ) {
3097						if ( ! col._setter ) {
3098							// Cache the setter function
3099							col._setter = _fnSetObjectDataFn( col.mData );
3100						}
3101						col._setter( d, contents );
3102					}
3103					else {
3104						d[i] = contents;
3105					}
3106				}
3107			}
3108	
3109			i++;
3110		};
3111	
3112		if ( td ) {
3113			// `tr` element was passed in
3114			while ( td ) {
3115				name = td.nodeName.toUpperCase();
3116	
3117				if ( name == "TD" || name == "TH" ) {
3118					cellProcess( td );
3119					tds.push( td );
3120				}
3121	
3122				td = td.nextSibling;
3123			}
3124		}
3125		else {
3126			// Existing row object passed in
3127			tds = row.anCells;
3128	
3129			for ( var j=0, jen=tds.length ; j<jen ; j++ ) {
3130				cellProcess( tds[j] );
3131			}
3132		}
3133	
3134		// Read the ID from the DOM if present
3135		var rowNode = row.firstChild ? row : row.nTr;
3136	
3137		if ( rowNode ) {
3138			var id = rowNode.getAttribute( 'id' );
3139	
3140			if ( id ) {
3141				_fnSetObjectDataFn( settings.rowId )( d, id );
3142			}
3143		}
3144	
3145		return {
3146			data: d,
3147			cells: tds
3148		};
3149	}
3150	/**
3151	 * Create a new TR element (and it's TD children) for a row
3152	 *  @param {object} oSettings dataTables settings object
3153	 *  @param {int} iRow Row to consider
3154	 *  @param {node} [nTrIn] TR element to add to the table - optional. If not given,
3155	 *    DataTables will create a row automatically
3156	 *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
3157	 *    if nTr is.
3158	 *  @memberof DataTable#oApi
3159	 */
3160	function _fnCreateTr ( oSettings, iRow, nTrIn, anTds )
3161	{
3162		var
3163			row = oSettings.aoData[iRow],
3164			rowData = row._aData,
3165			cells = [],
3166			nTr, nTd, oCol,
3167			i, iLen, create;
3168	
3169		if ( row.nTr === null )
3170		{
3171			nTr = nTrIn || document.createElement('tr');
3172	
3173			row.nTr = nTr;
3174			row.anCells = cells;
3175	
3176			/* Use a private property on the node to allow reserve mapping from the node
3177			 * to the aoData array for fast look up
3178			 */
3179			nTr._DT_RowIndex = iRow;
3180	
3181			/* Special parameters can be given by the data source to be used on the row */
3182			_fnRowAttributes( oSettings, row );
3183	
3184			/* Process each column */
3185			for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
3186			{
3187				oCol = oSettings.aoColumns[i];
3188				create = nTrIn ? false : true;
3189	
3190				nTd = create ? document.createElement( oCol.sCellType ) : anTds[i];
3191	
3192				if (! nTd) {
3193					_fnLog( oSettings, 0, 'Incorrect column count', 18 );
3194				}
3195	
3196				nTd._DT_CellIndex = {
3197					row: iRow,
3198					column: i
3199				};
3200				
3201				cells.push( nTd );
3202	
3203				// Need to create the HTML if new, or if a rendering function is defined
3204				if ( create || ((oCol.mRender || oCol.mData !== i) &&
3205					 (!$.isPlainObject(oCol.mData) || oCol.mData._ !== i+'.display')
3206				)) {
3207					nTd.innerHTML = _fnGetCellData( oSettings, iRow, i, 'display' );
3208				}
3209	
3210				/* Add user defined class */
3211				if ( oCol.sClass )
3212				{
3213					nTd.className += ' '+oCol.sClass;
3214				}
3215	
3216				// Visibility - add or remove as required
3217				if ( oCol.bVisible && ! nTrIn )
3218				{
3219					nTr.appendChild( nTd );
3220				}
3221				else if ( ! oCol.bVisible && nTrIn )
3222				{
3223					nTd.parentNode.removeChild( nTd );
3224				}
3225	
3226				if ( oCol.fnCreatedCell )
3227				{
3228					oCol.fnCreatedCell.call( oSettings.oInstance,
3229						nTd, _fnGetCellData( oSettings, iRow, i ), rowData, iRow, i
3230					);
3231				}
3232			}
3233	
3234			_fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow, cells] );
3235		}
3236	}
3237	
3238	
3239	/**
3240	 * Add attributes to a row based on the special `DT_*` parameters in a data
3241	 * source object.
3242	 *  @param {object} settings DataTables settings object
3243	 *  @param {object} DataTables row object for the row to be modified
3244	 *  @memberof DataTable#oApi
3245	 */
3246	function _fnRowAttributes( settings, row )
3247	{
3248		var tr = row.nTr;
3249		var data = row._aData;
3250	
3251		if ( tr ) {
3252			var id = settings.rowIdFn( data );
3253	
3254			if ( id ) {
3255				tr.id = id;
3256			}
3257	
3258			if ( data.DT_RowClass ) {
3259				// Remove any classes added by DT_RowClass before
3260				var a = data.DT_RowClass.split(' ');
3261				row.__rowc = row.__rowc ?
3262					_unique( row.__rowc.concat( a ) ) :
3263					a;
3264	
3265				$(tr)
3266					.removeClass( row.__rowc.join(' ') )
3267					.addClass( data.DT_RowClass );
3268			}
3269	
3270			if ( data.DT_RowAttr ) {
3271				$(tr).attr( data.DT_RowAttr );
3272			}
3273	
3274			if ( data.DT_RowData ) {
3275				$(tr).data( data.DT_RowData );
3276			}
3277		}
3278	}
3279	
3280	
3281	/**
3282	 * Create the HTML header for the table
3283	 *  @param {object} oSettings dataTables settings object
3284	 *  @memberof DataTable#oApi
3285	 */
3286	function _fnBuildHead( oSettings )
3287	{
3288		var i, ien, cell, row, column;
3289		var thead = oSettings.nTHead;
3290		var tfoot = oSettings.nTFoot;
3291		var createHeader = $('th, td', thead).length === 0;
3292		var classes = oSettings.oClasses;
3293		var columns = oSettings.aoColumns;
3294	
3295		if ( createHeader ) {
3296			row = $('<tr/>').appendTo( thead );
3297		}
3298	
3299		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
3300			column = columns[i];
3301			cell = $( column.nTh ).addClass( column.sClass );
3302	
3303			if ( createHeader ) {
3304				cell.appendTo( row );
3305			}
3306	
3307			// 1.11 move into sorting
3308			if ( oSettings.oFeatures.bSort ) {
3309				cell.addClass( column.sSortingClass );
3310	
3311				if ( column.bSortable !== false ) {
3312					cell
3313						.attr( 'tabindex', oSettings.iTabIndex )
3314						.attr( 'aria-controls', oSettings.sTableId );
3315	
3316					_fnSortAttachListener( oSettings, column.nTh, i );
3317				}
3318			}
3319	
3320			if ( column.sTitle != cell[0].innerHTML ) {
3321				cell.html( column.sTitle );
3322			}
3323	
3324			_fnRenderer( oSettings, 'header' )(
3325				oSettings, cell, column, classes
3326			);
3327		}
3328	
3329		if ( createHeader ) {
3330			_fnDetectHeader( oSettings.aoHeader, thead );
3331		}
3332	
3333		/* Deal with the footer - add classes if required */
3334		$(thead).children('tr').children('th, td').addClass( classes.sHeaderTH );
3335		$(tfoot).children('tr').children('th, td').addClass( classes.sFooterTH );
3336	
3337		// Cache the footer cells. Note that we only take the cells from the first
3338		// row in the footer. If there is more than one row the user wants to
3339		// interact with, they need to use the table().foot() method. Note also this
3340		// allows cells to be used for multiple columns using colspan
3341		if ( tfoot !== null ) {
3342			var cells = oSettings.aoFooter[0];
3343	
3344			for ( i=0, ien=cells.length ; i<ien ; i++ ) {
3345				column = columns[i];
3346	
3347				if (column) {
3348					column.nTf = cells[i].cell;
3349		
3350					if ( column.sClass ) {
3351						$(column.nTf).addClass( column.sClass );
3352					}
3353				}
3354				else {
3355					_fnLog( oSettings, 0, 'Incorrect column count', 18 );
3356				}
3357			}
3358		}
3359	}
3360	
3361	
3362	/**
3363	 * Draw the header (or footer) element based on the column visibility states. The
3364	 * methodology here is to use the layout array from _fnDetectHeader, modified for
3365	 * the instantaneous column visibility, to construct the new layout. The grid is
3366	 * traversed over cell at a time in a rows x columns grid fashion, although each
3367	 * cell insert can cover multiple elements in the grid - which is tracks using the
3368	 * aApplied array. Cell inserts in the grid will only occur where there isn't
3369	 * already a cell in that position.
3370	 *  @param {object} oSettings dataTables settings object
3371	 *  @param array {objects} aoSource Layout array from _fnDetectHeader
3372	 *  @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,
3373	 *  @memberof DataTable#oApi
3374	 */
3375	function _fnDrawHead( oSettings, aoSource, bIncludeHidden )
3376	{
3377		var i, iLen, j, jLen, k, kLen, n, nLocalTr;
3378		var aoLocal = [];
3379		var aApplied = [];
3380		var iColumns = oSettings.aoColumns.length;
3381		var iRowspan, iColspan;
3382	
3383		if ( ! aoSource )
3384		{
3385			return;
3386		}
3387	
3388		if (  bIncludeHidden === undefined )
3389		{
3390			bIncludeHidden = false;
3391		}
3392	
3393		/* Make a copy of the master layout array, but without the visible columns in it */
3394		for ( i=0, iLen=aoSource.length ; i<iLen ; i++ )
3395		{
3396			aoLocal[i] = aoSource[i].slice();
3397			aoLocal[i].nTr = aoSource[i].nTr;
3398	
3399			/* Remove any columns which are currently hidden */
3400			for ( j=iColumns-1 ; j>=0 ; j-- )
3401			{
3402				if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden )
3403				{
3404					aoLocal[i].splice( j, 1 );
3405				}
3406			}
3407	
3408			/* Prep the applied array - it needs an element for each row */
3409			aApplied.push( [] );
3410		}
3411	
3412		for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ )
3413		{
3414			nLocalTr = aoLocal[i].nTr;
3415	
3416			/* All cells are going to be replaced, so empty out the row */
3417			if ( nLocalTr )
3418			{
3419				while( (n = nLocalTr.firstChild) )
3420				{
3421					nLocalTr.removeChild( n );
3422				}
3423			}
3424	
3425			for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ )
3426			{
3427				iRowspan = 1;
3428				iColspan = 1;
3429	
3430				/* Check to see if there is already a cell (row/colspan) covering our target
3431				 * insert point. If there is, then there is nothing to do.
3432				 */
3433				if ( aApplied[i][j] === undefined )
3434				{
3435					nLocalTr.appendChild( aoLocal[i][j].cell );
3436					aApplied[i][j] = 1;
3437	
3438					/* Expand the cell to cover as many rows as needed */
3439					while ( aoLocal[i+iRowspan] !== undefined &&
3440					        aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell )
3441					{
3442						aApplied[i+iRowspan][j] = 1;
3443						iRowspan++;
3444					}
3445	
3446					/* Expand the cell to cover as many columns as needed */
3447					while ( aoLocal[i][j+iColspan] !== undefined &&
3448					        aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell )
3449					{
3450						/* Must update the applied array over the rows for the columns */
3451						for ( k=0 ; k<iRowspan ; k++ )
3452						{
3453							aApplied[i+k][j+iColspan] = 1;
3454						}
3455						iColspan++;
3456					}
3457	
3458					/* Do the actual expansion in the DOM */
3459					$(aoLocal[i][j].cell)
3460						.attr('rowspan', iRowspan)
3461						.attr('colspan', iColspan);
3462				}
3463			}
3464		}
3465	}
3466	
3467	
3468	/**
3469	 * Insert the required TR nodes into the table for display
3470	 *  @param {object} oSettings dataTables settings object
3471	 *  @param ajaxComplete true after ajax call to complete rendering
3472	 *  @memberof DataTable#oApi
3473	 */
3474	function _fnDraw( oSettings, ajaxComplete )
3475	{
3476		// Allow for state saving and a custom start position
3477		_fnStart( oSettings );
3478	
3479		/* Provide a pre-callback function which can be used to cancel the draw is false is returned */
3480		var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] );
3481		if ( $.inArray( false, aPreDraw ) !== -1 )
3482		{
3483			_fnProcessingDisplay( oSettings, false );
3484			return;
3485		}
3486	
3487		var anRows = [];
3488		var iRowCount = 0;
3489		var asStripeClasses = oSettings.asStripeClasses;
3490		var iStripes = asStripeClasses.length;
3491		var oLang = oSettings.oLanguage;
3492		var bServerSide = _fnDataSource( oSettings ) == 'ssp';
3493		var aiDisplay = oSettings.aiDisplay;
3494		var iDisplayStart = oSettings._iDisplayStart;
3495		var iDisplayEnd = oSettings.fnDisplayEnd();
3496	
3497		oSettings.bDrawing = true;
3498	
3499		/* Server-side processing draw intercept */
3500		if ( oSettings.bDeferLoading )
3501		{
3502			oSettings.bDeferLoading = false;
3503			oSettings.iDraw++;
3504			_fnProcessingDisplay( oSettings, false );
3505		}
3506		else if ( !bServerSide )
3507		{
3508			oSettings.iDraw++;
3509		}
3510		else if ( !oSettings.bDestroying && !ajaxComplete)
3511		{
3512			_fnAjaxUpdate( oSettings );
3513			return;
3514		}
3515	
3516		if ( aiDisplay.length !== 0 )
3517		{
3518			var iStart = bServerSide ? 0 : iDisplayStart;
3519			var iEnd = bServerSide ? oSettings.aoData.length : iDisplayEnd;
3520	
3521			for ( var j=iStart ; j<iEnd ; j++ )
3522			{
3523				var iDataIndex = aiDisplay[j];
3524				var aoData = oSettings.aoData[ iDataIndex ];
3525				if ( aoData.nTr === null )
3526				{
3527					_fnCreateTr( oSettings, iDataIndex );
3528				}
3529	
3530				var nRow = aoData.nTr;
3531	
3532				/* Remove the old striping classes and then add the new one */
3533				if ( iStripes !== 0 )
3534				{
3535					var sStripe = asStripeClasses[ iRowCount % iStripes ];
3536					if ( aoData._sRowStripe != sStripe )
3537					{
3538						$(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe );
3539						aoData._sRowStripe = sStripe;
3540					}
3541				}
3542	
3543				// Row callback functions - might want to manipulate the row
3544				// iRowCount and j are not currently documented. Are they at all
3545				// useful?
3546				_fnCallbackFire( oSettings, 'aoRowCallback', null,
3547					[nRow, aoData._aData, iRowCount, j, iDataIndex] );
3548	
3549				anRows.push( nRow );
3550				iRowCount++;
3551			}
3552		}
3553		else
3554		{
3555			/* Table is empty - create a row with an empty message in it */
3556			var sZero = oLang.sZeroRecords;
3557			if ( oSettings.iDraw == 1 &&  _fnDataSource( oSettings ) == 'ajax' )
3558			{
3559				sZero = oLang.sLoadingRecords;
3560			}
3561			else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 )
3562			{
3563				sZero = oLang.sEmptyTable;
3564			}
3565	
3566			anRows[ 0 ] = $( '<tr/>', { 'class': iStripes ? asStripeClasses[0] : '' } )
3567				.append( $('<td />', {
3568					'valign':  'top',
3569					'colSpan': _fnVisbleColumns( oSettings ),
3570					'class':   oSettings.oClasses.sRowEmpty
3571				} ).html( sZero ) )[0];
3572		}
3573	
3574		/* Header and footer callbacks */
3575		_fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0],
3576			_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
3577	
3578		_fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0],
3579			_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
3580	
3581		var body = $(oSettings.nTBody);
3582	
3583		body.children().detach();
3584		body.append( $(anRows) );
3585	
3586		/* Call all required callback functions for the end of a draw */
3587		_fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] );
3588	
3589		/* Draw is complete, sorting and filtering must be as well */
3590		oSettings.bSorted = false;
3591		oSettings.bFiltered = false;
3592		oSettings.bDrawing = false;
3593	}
3594	
3595	
3596	/**
3597	 * Redraw the table - taking account of the various features which are enabled
3598	 *  @param {object} oSettings dataTables settings object
3599	 *  @param {boolean} [holdPosition] Keep the current paging position. By default
3600	 *    the paging is reset to the first page
3601	 *  @memberof DataTable#oApi
3602	 */
3603	function _fnReDraw( settings, holdPosition )
3604	{
3605		var
3606			features = settings.oFeatures,
3607			sort     = features.bSort,
3608			filter   = features.bFilter;
3609	
3610		if ( sort ) {
3611			_fnSort( settings );
3612		}
3613	
3614		if ( filter ) {
3615			_fnFilterComplete( settings, settings.oPreviousSearch );
3616		}
3617		else {
3618			// No filtering, so we want to just use the display master
3619			settings.aiDisplay = settings.aiDisplayMaster.slice();
3620		}
3621	
3622		if ( holdPosition !== true ) {
3623			settings._iDisplayStart = 0;
3624		}
3625	
3626		// Let any modules know about the draw hold position state (used by
3627		// scrolling internally)
3628		settings._drawHold = holdPosition;
3629	
3630		_fnDraw( settings );
3631	
3632		settings._drawHold = false;
3633	}
3634	
3635	
3636	/**
3637	 * Add the options to the page HTML for the table
3638	 *  @param {object} oSettings dataTables settings object
3639	 *  @memberof DataTable#oApi
3640	 */
3641	function _fnAddOptionsHtml ( oSettings )
3642	{
3643		var classes = oSettings.oClasses;
3644		var table = $(oSettings.nTable);
3645		var holding = $('<div/>').insertBefore( table ); // Holding element for speed
3646		var features = oSettings.oFeatures;
3647	
3648		// All DataTables are wrapped in a div
3649		var insert = $('<div/>', {
3650			id:      oSettings.sTableId+'_wrapper',
3651			'class': classes.sWrapper + (oSettings.nTFoot ? '' : ' '+classes.sNoFooter)
3652		} );
3653	
3654		oSettings.nHolding = holding[0];
3655		oSettings.nTableWrapper = insert[0];
3656		oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;
3657	
3658		/* Loop over the user set positioning and place the elements as needed */
3659		var aDom = oSettings.sDom.split('');
3660		var featureNode, cOption, nNewNode, cNext, sAttr, j;
3661		for ( var i=0 ; i<aDom.length ; i++ )
3662		{
3663			featureNode = null;
3664			cOption = aDom[i];
3665	
3666			if ( cOption == '<' )
3667			{
3668				/* New container div */
3669				nNewNode = $('<div/>')[0];
3670	
3671				/* Check to see if we should append an id and/or a class name to the container */
3672				cNext = aDom[i+1];
3673				if ( cNext == "'" || cNext == '"' )
3674				{
3675					sAttr = "";
3676					j = 2;
3677					while ( aDom[i+j] != cNext )
3678					{
3679						sAttr += aDom[i+j];
3680						j++;
3681					}
3682	
3683					/* Replace jQuery UI constants @todo depreciated */
3684					if ( sAttr == "H" )
3685					{
3686						sAttr = classes.sJUIHeader;
3687					}
3688					else if ( sAttr == "F" )
3689					{
3690						sAttr = classes.sJUIFooter;
3691					}
3692	
3693					/* The attribute can be in the format of "#id.class", "#id" or "class" This logic
3694					 * breaks the string into parts and applies them as needed
3695					 */
3696					if ( sAttr.indexOf('.') != -1 )
3697					{
3698						var aSplit = sAttr.split('.');
3699						nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);
3700						nNewNode.className = aSplit[1];
3701					}
3702					else if ( sAttr.charAt(0) == "#" )
3703					{
3704						nNewNode.id = sAttr.substr(1, sAttr.length-1);
3705					}
3706					else
3707					{
3708						nNewNode.className = sAttr;
3709					}
3710	
3711					i += j; /* Move along the position array */
3712				}
3713	
3714				insert.append( nNewNode );
3715				insert = $(nNewNode);
3716			}
3717			else if ( cOption == '>' )
3718			{
3719				/* End container div */
3720				insert = insert.parent();
3721			}
3722			// @todo Move options into their own plugins?
3723			else if ( cOption == 'l' && features.bPaginate && features.bLengthChange )
3724			{
3725				/* Length */
3726				featureNode = _fnFeatureHtmlLength( oSettings );
3727			}
3728			else if ( cOption == 'f' && features.bFilter )
3729			{
3730				/* Filter */
3731				featureNode = _fnFeatureHtmlFilter( oSettings );
3732			}
3733			else if ( cOption == 'r' && features.bProcessing )
3734			{
3735				/* pRocessing */
3736				featureNode = _fnFeatureHtmlProcessing( oSettings );
3737			}
3738			else if ( cOption == 't' )
3739			{
3740				/* Table */
3741				featureNode = _fnFeatureHtmlTable( oSettings );
3742			}
3743			else if ( cOption ==  'i' && features.bInfo )
3744			{
3745				/* Info */
3746				featureNode = _fnFeatureHtmlInfo( oSettings );
3747			}
3748			else if ( cOption == 'p' && features.bPaginate )
3749			{
3750				/* Pagination */
3751				featureNode = _fnFeatureHtmlPaginate( oSettings );
3752			}
3753			else if ( DataTable.ext.feature.length !== 0 )
3754			{
3755				/* Plug-in features */
3756				var aoFeatures = DataTable.ext.feature;
3757				for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )
3758				{
3759					if ( cOption == aoFeatures[k].cFeature )
3760					{
3761						featureNode = aoFeatures[k].fnInit( oSettings );
3762						break;
3763					}
3764				}
3765			}
3766	
3767			/* Add to the 2D features array */
3768			if ( featureNode )
3769			{
3770				var aanFeatures = oSettings.aanFeatures;
3771	
3772				if ( ! aanFeatures[cOption] )
3773				{
3774					aanFeatures[cOption] = [];
3775				}
3776	
3777				aanFeatures[cOption].push( featureNode );
3778				insert.append( featureNode );
3779			}
3780		}
3781	
3782		/* Built our DOM structure - replace the holding div with what we want */
3783		holding.replaceWith( insert );
3784		oSettings.nHolding = null;
3785	}
3786	
3787	
3788	/**
3789	 * Use the DOM source to create up an array of header cells. The idea here is to
3790	 * create a layout grid (array) of rows x columns, which contains a reference
3791	 * to the cell that that point in the grid (regardless of col/rowspan), such that
3792	 * any column / row could be removed and the new grid constructed
3793	 *  @param array {object} aLayout Array to store the calculated layout in
3794	 *  @param {node} nThead The header/footer element for the table
3795	 *  @memberof DataTable#oApi
3796	 */
3797	function _fnDetectHeader ( aLayout, nThead )
3798	{
3799		var nTrs = $(nThead).children('tr');
3800		var nTr, nCell;
3801		var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan;
3802		var bUnique;
3803		var fnShiftCol = function ( a, i, j ) {
3804			var k = a[i];
3805	                while ( k[j] ) {
3806				j++;
3807			}
3808			return j;
3809		};
3810	
3811		aLayout.splice( 0, aLayout.length );
3812	
3813		/* We know how many rows there are in the layout - so prep it */
3814		for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
3815		{
3816			aLayout.push( [] );
3817		}
3818	
3819		/* Calculate a layout array */
3820		for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
3821		{
3822			nTr = nTrs[i];
3823			iColumn = 0;
3824	
3825			/* For every cell in the row... */
3826			nCell = nTr.firstChild;
3827			while ( nCell ) {
3828				if ( nCell.nodeName.toUpperCase() == "TD" ||
3829				     nCell.nodeName.toUpperCase() == "TH" )
3830				{
3831					/* Get the col and rowspan attributes from the DOM and sanitise them */
3832					iColspan = nCell.getAttribute('colspan') * 1;
3833					iRowspan = nCell.getAttribute('rowspan') * 1;
3834					iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan;
3835					iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan;
3836	
3837					/* There might be colspan cells already in this row, so shift our target
3838					 * accordingly
3839					 */
3840					iColShifted = fnShiftCol( aLayout, i, iColumn );
3841	
3842					/* Cache calculation for unique columns */
3843					bUnique = iColspan === 1 ? true : false;
3844	
3845					/* If there is col / rowspan, copy the information into the layout grid */
3846					for ( l=0 ; l<iColspan ; l++ )
3847					{
3848						for ( k=0 ; k<iRowspan ; k++ )
3849						{
3850							aLayout[i+k][iColShifted+l] = {
3851								"cell": nCell,
3852								"unique": bUnique
3853							};
3854							aLayout[i+k].nTr = nTr;
3855						}
3856					}
3857				}
3858				nCell = nCell.nextSibling;
3859			}
3860		}
3861	}
3862	
3863	
3864	/**
3865	 * Get an array of unique th elements, one for each column
3866	 *  @param {object} oSettings dataTables settings object
3867	 *  @param {node} nHeader automatically detect the layout from this node - optional
3868	 *  @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional
3869	 *  @returns array {node} aReturn list of unique th's
3870	 *  @memberof DataTable#oApi
3871	 */
3872	function _fnGetUniqueThs ( oSettings, nHeader, aLayout )
3873	{
3874		var aReturn = [];
3875		if ( !aLayout )
3876		{
3877			aLayout = oSettings.aoHeader;
3878			if ( nHeader )
3879			{
3880				aLayout = [];
3881				_fnDetectHeader( aLayout, nHeader );
3882			}
3883		}
3884	
3885		for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ )
3886		{
3887			for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ )
3888			{
3889				if ( aLayout[i][j].unique &&
3890					 (!aReturn[j] || !oSettings.bSortCellsTop) )
3891				{
3892					aReturn[j] = aLayout[i][j].cell;
3893				}
3894			}
3895		}
3896	
3897		return aReturn;
3898	}
3899	
3900	/**
3901	 * Set the start position for draw
3902	 *  @param {object} oSettings dataTables settings object
3903	 */
3904	function _fnStart( oSettings )
3905	{
3906		var bServerSide = _fnDataSource( oSettings ) == 'ssp';
3907		var iInitDisplayStart = oSettings.iInitDisplayStart;
3908	
3909		// Check and see if we have an initial draw position from state saving
3910		if ( iInitDisplayStart !== undefined && iInitDisplayStart !== -1 )
3911		{
3912			oSettings._iDisplayStart = bServerSide ?
3913				iInitDisplayStart :
3914				iInitDisplayStart >= oSettings.fnRecordsDisplay() ?
3915					0 :
3916					iInitDisplayStart;
3917	
3918			oSettings.iInitDisplayStart = -1;
3919		}
3920	}
3921	
3922	/**
3923	 * Create an Ajax call based on the table's settings, taking into account that
3924	 * parameters can have multiple forms, and backwards compatibility.
3925	 *
3926	 * @param {object} oSettings dataTables settings object
3927	 * @param {array} data Data to send to the server, required by
3928	 *     DataTables - may be augmented by developer callbacks
3929	 * @param {function} fn Callback function to run when data is obtained
3930	 */
3931	function _fnBuildAjax( oSettings, data, fn )
3932	{
3933		// Compatibility with 1.9-, allow fnServerData and event to manipulate
3934		_fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [data] );
3935	
3936		// Convert to object based for 1.10+ if using the old array scheme which can
3937		// come from server-side processing or serverParams
3938		if ( data && Array.isArray(data) ) {
3939			var tmp = {};
3940			var rbracket = /(.*?)\[\]$/;
3941	
3942			$.each( data, function (key, val) {
3943				var match = val.name.match(rbracket);
3944	
3945				if ( match ) {
3946					// Support for arrays
3947					var name = match[0];
3948	
3949					if ( ! tmp[ name ] ) {
3950						tmp[ name ] = [];
3951					}
3952					tmp[ name ].push( val.value );
3953				}
3954				else {
3955					tmp[val.name] = val.value;
3956				}
3957			} );
3958			data = tmp;
3959		}
3960	
3961		var ajaxData;
3962		var ajax = oSettings.ajax;
3963		var instance = oSettings.oInstance;
3964		var callback = function ( json ) {
3965			var status = oSettings.jqXHR
3966				? oSettings.jqXHR.status
3967				: null;
3968	
3969			if ( json === null || (typeof status === 'number' && status == 204 ) ) {
3970				json = {};
3971				_fnAjaxDataSrc( oSettings, json, [] );
3972			}
3973	
3974			var error = json.error || json.sError;
3975			if ( error ) {
3976				_fnLog( oSettings, 0, error );
3977			}
3978	
3979			oSettings.json = json;
3980	
3981			_fnCallbackFire( oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR] );
3982			fn( json );
3983		};
3984	
3985		if ( $.isPlainObject( ajax ) && ajax.data )
3986		{
3987			ajaxData = ajax.data;
3988	
3989			var newData = typeof ajaxData === 'function' ?
3990				ajaxData( data, oSettings ) :  // fn can manipulate data or return
3991				ajaxData;                      // an object object or array to merge
3992	
3993			// If the function returned something, use that alone
3994			data = typeof ajaxData === 'function' && newData ?
3995				newData :
3996				$.extend( true, data, newData );
3997	
3998			// Remove the data property as we've resolved it already and don't want
3999			// jQuery to do it again (it is restored at the end of the function)
4000			delete ajax.data;
4001		}
4002	
4003		var baseAjax = {
4004			"data": data,
4005			"success": callback,
4006			"dataType": "json",
4007			"cache": false,
4008			"type": oSettings.sServerMethod,
4009			"error": function (xhr, error, thrown) {
4010				var ret = _fnCallbackFire( oSettings, null, 'xhr', [oSettings, null, oSettings.jqXHR] );
4011	
4012				if ( $.inArray( true, ret ) === -1 ) {
4013					if ( error == "parsererror" ) {
4014						_fnLog( oSettings, 0, 'Invalid JSON response', 1 );
4015					}
4016					else if ( xhr.readyState === 4 ) {
4017						_fnLog( oSettings, 0, 'Ajax error', 7 );
4018					}
4019				}
4020	
4021				_fnProcessingDisplay( oSettings, false );
4022			}
4023		};
4024	
4025		// Store the data submitted for the API
4026		oSettings.oAjaxData = data;
4027	
4028		// Allow plug-ins and external processes to modify the data
4029		_fnCallbackFire( oSettings, null, 'preXhr', [oSettings, data] );
4030	
4031		if ( oSettings.fnServerData )
4032		{
4033			// DataTables 1.9- compatibility
4034			oSettings.fnServerData.call( instance,
4035				oSettings.sAjaxSource,
4036				$.map( data, function (val, key) { // Need to convert back to 1.9 trad format
4037					return { name: key, value: val };
4038				} ),
4039				callback,
4040				oSettings
4041			);
4042		}
4043		else if ( oSettings.sAjaxSource || typeof ajax === 'string' )
4044		{
4045			// DataTables 1.9- compatibility
4046			oSettings.jqXHR = $.ajax( $.extend( baseAjax, {
4047				url: ajax || oSettings.sAjaxSource
4048			} ) );
4049		}
4050		else if ( typeof ajax === 'function' )
4051		{
4052			// Is a function - let the caller define what needs to be done
4053			oSettings.jqXHR = ajax.call( instance, data, callback, oSettings );
4054		}
4055		else
4056		{
4057			// Object to extend the base settings
4058			oSettings.jqXHR = $.ajax( $.extend( baseAjax, ajax ) );
4059	
4060			// Restore for next time around
4061			ajax.data = ajaxData;
4062		}
4063	}
4064	
4065	
4066	/**
4067	 * Update the table using an Ajax call
4068	 *  @param {object} settings dataTables settings object
4069	 *  @returns {boolean} Block the table drawing or not
4070	 *  @memberof DataTable#oApi
4071	 */
4072	function _fnAjaxUpdate( settings )
4073	{
4074		settings.iDraw++;
4075		_fnProcessingDisplay( settings, true );
4076	
4077		// Keep track of drawHold state to handle scrolling after the Ajax call
4078		var drawHold = settings._drawHold;
4079	
4080		_fnBuildAjax(
4081			settings,
4082			_fnAjaxParameters( settings ),
4083			function(json) {
4084				settings._drawHold = drawHold;
4085				_fnAjaxUpdateDraw( settings, json );
4086				settings._drawHold = false;
4087			}
4088		);
4089	}
4090	
4091	
4092	/**
4093	 * Build up the parameters in an object needed for a server-side processing
4094	 * request. Note that this is basically done twice, is different ways - a modern
4095	 * method which is used by default in DataTables 1.10 which uses objects and
4096	 * arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if
4097	 * the sAjaxSource option is used in the initialisation, or the legacyAjax
4098	 * option is set.
4099	 *  @param {object} oSettings dataTables settings object
4100	 *  @returns {bool} block the table drawing or not
4101	 *  @memberof DataTable#oApi
4102	 */
4103	function _fnAjaxParameters( settings )
4104	{
4105		var
4106			columns = settings.aoColumns,
4107			columnCount = columns.length,
4108			features = settings.oFeatures,
4109			preSearch = settings.oPreviousSearch,
4110			preColSearch = settings.aoPreSearchCols,
4111			i, data = [], dataProp, column, columnSearch,
4112			sort = _fnSortFlatten( settings ),
4113			displayStart = settings._iDisplayStart,
4114			displayLength = features.bPaginate !== false ?
4115				settings._iDisplayLength :
4116				-1;
4117	
4118		var param = function ( name, value ) {
4119			data.push( { 'name': name, 'value': value } );
4120		};
4121	
4122		// DataTables 1.9- compatible method
4123		param( 'sEcho',          settings.iDraw );
4124		param( 'iColumns',       columnCount );
4125		param( 'sColumns',       _pluck( columns, 'sName' ).join(',') );
4126		param( 'iDisplayStart',  displayStart );
4127		param( 'iDisplayLength', displayLength );
4128	
4129		// DataTables 1.10+ method
4130		var d = {
4131			draw:    settings.iDraw,
4132			columns: [],
4133			order:   [],
4134			start:   displayStart,
4135			length:  displayLength,
4136			search:  {
4137				value: preSearch.sSearch,
4138				regex: preSearch.bRegex
4139			}
4140		};
4141	
4142		for ( i=0 ; i<columnCount ; i++ ) {
4143			column = columns[i];
4144			columnSearch = preColSearch[i];
4145			dataProp = typeof column.mData=="function" ? 'function' : column.mData ;
4146	
4147			d.columns.push( {
4148				data:       dataProp,
4149				name:       column.sName,
4150				searchable: column.bSearchable,
4151				orderable:  column.bSortable,
4152				search:     {
4153					value: columnSearch.sSearch,
4154					regex: columnSearch.bRegex
4155				}
4156			} );
4157	
4158			param( "mDataProp_"+i, dataProp );
4159	
4160			if ( features.bFilter ) {
4161				param( 'sSearch_'+i,     columnSearch.sSearch );
4162				param( 'bRegex_'+i,      columnSearch.bRegex );
4163				param( 'bSearchable_'+i, column.bSearchable );
4164			}
4165	
4166			if ( features.bSort ) {
4167				param( 'bSortable_'+i, column.bSortable );
4168			}
4169		}
4170	
4171		if ( features.bFilter ) {
4172			param( 'sSearch', preSearch.sSearch );
4173			param( 'bRegex', preSearch.bRegex );
4174		}
4175	
4176		if ( features.bSort ) {
4177			$.each( sort, function ( i, val ) {
4178				d.order.push( { column: val.col, dir: val.dir } );
4179	
4180				param( 'iSortCol_'+i, val.col );
4181				param( 'sSortDir_'+i, val.dir );
4182			} );
4183	
4184			param( 'iSortingCols', sort.length );
4185		}
4186	
4187		// If the legacy.ajax parameter is null, then we automatically decide which
4188		// form to use, based on sAjaxSource
4189		var legacy = DataTable.ext.legacy.ajax;
4190		if ( legacy === null ) {
4191			return settings.sAjaxSource ? data : d;
4192		}
4193	
4194		// Otherwise, if legacy has been specified then we use that to decide on the
4195		// form
4196		return legacy ? data : d;
4197	}
4198	
4199	
4200	/**
4201	 * Data the data from the server (nuking the old) and redraw the table
4202	 *  @param {object} oSettings dataTables settings object
4203	 *  @param {object} json json data return from the server.
4204	 *  @param {string} json.sEcho Tracking flag for DataTables to match requests
4205	 *  @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering
4206	 *  @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering
4207	 *  @param {array} json.aaData The data to display on this page
4208	 *  @param {string} [json.sColumns] Column ordering (sName, comma separated)
4209	 *  @memberof DataTable#oApi
4210	 */
4211	function _fnAjaxUpdateDraw ( settings, json )
4212	{
4213		// v1.10 uses camelCase variables, while 1.9 uses Hungarian notation.
4214		// Support both
4215		var compat = function ( old, modern ) {
4216			return json[old] !== undefined ? json[old] : json[modern];
4217		};
4218	
4219		var data = _fnAjaxDataSrc( settings, json );
4220		var draw            = compat( 'sEcho',                'draw' );
4221		var recordsTotal    = compat( 'iTotalRecords',        'recordsTotal' );
4222		var recordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' );
4223	
4224		if ( draw !== undefined ) {
4225			// Protect against out of sequence returns
4226			if ( draw*1 < settings.iDraw ) {
4227				return;
4228			}
4229			settings.iDraw = draw * 1;
4230		}
4231	
4232		// No data in returned object, so rather than an array, we show an empty table
4233		if ( ! data ) {
4234			data = [];
4235		}
4236	
4237		_fnClearTable( settings );
4238		settings._iRecordsTotal   = parseInt(recordsTotal, 10);
4239		settings._iRecordsDisplay = parseInt(recordsFiltered, 10);
4240	
4241		for ( var i=0, ien=data.length ; i<ien ; i++ ) {
4242			_fnAddData( settings, data[i] );
4243		}
4244		settings.aiDisplay = settings.aiDisplayMaster.slice();
4245	
4246		_fnDraw( settings, true );
4247	
4248		if ( ! settings._bInitComplete ) {
4249			_fnInitComplete( settings, json );
4250		}
4251	
4252		_fnProcessingDisplay( settings, false );
4253	}
4254	
4255	
4256	/**
4257	 * Get the data from the JSON data source to use for drawing a table. Using
4258	 * `_fnGetObjectDataFn` allows the data to be sourced from a property of the
4259	 * source object, or from a processing function.
4260	 *  @param {object} oSettings dataTables settings object
4261	 *  @param  {object} json Data source object / array from the server
4262	 *  @return {array} Array of data to use
4263	 */
4264	 function _fnAjaxDataSrc ( oSettings, json, write )
4265	 {
4266		var dataSrc = $.isPlainObject( oSettings.ajax ) && oSettings.ajax.dataSrc !== undefined ?
4267			oSettings.ajax.dataSrc :
4268			oSettings.sAjaxDataProp; // Compatibility with 1.9-.
4269	
4270		if ( ! write ) {
4271			if ( dataSrc === 'data' ) {
4272				// If the default, then we still want to support the old style, and safely ignore
4273				// it if possible
4274				return json.aaData || json[dataSrc];
4275			}
4276	
4277			return dataSrc !== "" ?
4278				_fnGetObjectDataFn( dataSrc )( json ) :
4279				json;
4280		}
4281	
4282		// set
4283		_fnSetObjectDataFn( dataSrc )( json, write );
4284	}
4285	
4286	/**
4287	 * Generate the node required for filtering text
4288	 *  @returns {node} Filter control element
4289	 *  @param {object} oSettings dataTables settings object
4290	 *  @memberof DataTable#oApi
4291	 */
4292	function _fnFeatureHtmlFilter ( settings )
4293	{
4294		var classes = settings.oClasses;
4295		var tableId = settings.sTableId;
4296		var language = settings.oLanguage;
4297		var previousSearch = settings.oPreviousSearch;
4298		var features = settings.aanFeatures;
4299		var input = '<input type="search" class="'+classes.sFilterInput+'"/>';
4300	
4301		var str = language.sSearch;
4302		str = str.match(/_INPUT_/) ?
4303			str.replace('_INPUT_', input) :
4304			str+input;
4305	
4306		var filter = $('<div/>', {
4307				'id': ! features.f ? tableId+'_filter' : null,
4308				'class': classes.sFilter
4309			} )
4310			.append( $('<label/>' ).append( str ) );
4311	
4312		var searchFn = function(event) {
4313			/* Update all other filter input elements for the new display */
4314			var n = features.f;
4315			var val = !this.value ? "" : this.value; // mental IE8 fix :-(
4316			if(previousSearch
vendor: 10,320 bytes, lines 4316-4653
4316['return'] && event.key !== "Enter") {
4317				return;
4318			}
4319			/* Now do the filter */
4320			if ( val != previousSearch.sSearch ) {
4321				_fnFilterComplete( settings, {
4322					"sSearch": val,
4323					"bRegex": previousSearch.bRegex,
4324					"bSmart": previousSearch.bSmart ,
4325					"bCaseInsensitive": previousSearch.bCaseInsensitive,
4326					"return": previousSearch['return']
4327				} );
4328	
4329				// Need to redraw, without resorting
4330				settings._iDisplayStart = 0;
4331				_fnDraw( settings );
4332			}
4333		};
4334	
4335		var searchDelay = settings.searchDelay !== null ?
4336			settings.searchDelay :
4337			_fnDataSource( settings ) === 'ssp' ?
4338				400 :
4339				0;
4340	
4341		var jqFilter = $('input', filter)
4342			.val( previousSearch.sSearch )
4343			.attr( 'placeholder', language.sSearchPlaceholder )
4344			.on(
4345				'keyup.DT search.DT input.DT paste.DT cut.DT',
4346				searchDelay ?
4347					_fnThrottle( searchFn, searchDelay ) :
4348					searchFn
4349			)
4350			.on( 'mouseup.DT', function(e) {
4351				// Edge fix! Edge 17 does not trigger anything other than mouse events when clicking
4352				// on the clear icon (Edge bug 17584515). This is safe in other browsers as `searchFn`
4353				// checks the value to see if it has changed. In other browsers it won't have.
4354				setTimeout( function () {
4355					searchFn.call(jqFilter[0], e);
4356				}, 10);
4357			} )
4358			.on( 'keypress.DT', function(e) {
4359				/* Prevent form submission */
4360				if ( e.keyCode == 13 ) {
4361					return false;
4362				}
4363			} )
4364			.attr('aria-controls', tableId);
4365	
4366		// Update the input elements whenever the table is filtered
4367		$(settings.nTable).on( 'search.dt.DT', function ( ev, s ) {
4368			if ( settings === s ) {
4369				// IE9 throws an 'unknown error' if document.activeElement is used
4370				// inside an iframe or frame...
4371				try {
4372					if ( jqFilter[0] !== document.activeElement ) {
4373						jqFilter.val( previousSearch.sSearch );
4374					}
4375				}
4376				catch ( e ) {}
4377			}
4378		} );
4379	
4380		return filter[0];
4381	}
4382	
4383	
4384	/**
4385	 * Filter the table using both the global filter and column based filtering
4386	 *  @param {object} oSettings dataTables settings object
4387	 *  @param {object} oSearch search information
4388	 *  @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)
4389	 *  @memberof DataTable#oApi
4390	 */
4391	function _fnFilterComplete ( oSettings, oInput, iForce )
4392	{
4393		var oPrevSearch = oSettings.oPreviousSearch;
4394		var aoPrevSearch = oSettings.aoPreSearchCols;
4395		var fnSaveFilter = function ( oFilter ) {
4396			/* Save the filtering values */
4397			oPrevSearch.sSearch = oFilter.sSearch;
4398			oPrevSearch.bRegex = oFilter.bRegex;
4399			oPrevSearch.bSmart = oFilter.bSmart;
4400			oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive;
4401			oPrevSearch['return'] = oFilter['return'];
4402		};
4403		var fnRegex = function ( o ) {
4404			// Backwards compatibility with the bEscapeRegex option
4405			return o.bEscapeRegex !== undefined ? !o.bEscapeRegex : o.bRegex;
4406		};
4407	
4408		// Resolve any column types that are unknown due to addition or invalidation
4409		// @todo As per sort - can this be moved into an event handler?
4410		_fnColumnTypes( oSettings );
4411	
4412		/* In server-side processing all filtering is done by the server, so no point hanging around here */
4413		if ( _fnDataSource( oSettings ) != 'ssp' )
4414		{
4415			/* Global filter */
4416			_fnFilter( oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive );
4417			fnSaveFilter( oInput );
4418	
4419			/* Now do the individual column filter */
4420			for ( var i=0 ; i<aoPrevSearch.length ; i++ )
4421			{
4422				_fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, fnRegex(aoPrevSearch[i]),
4423					aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive );
4424			}
4425	
4426			/* Custom filtering */
4427			_fnFilterCustom( oSettings );
4428		}
4429		else
4430		{
4431			fnSaveFilter( oInput );
4432		}
4433	
4434		/* Tell the draw function we have been filtering */
4435		oSettings.bFiltered = true;
4436		_fnCallbackFire( oSettings, null, 'search', [oSettings] );
4437	}
4438	
4439	
4440	/**
4441	 * Apply custom filtering functions
4442	 *  @param {object} oSettings dataTables settings object
4443	 *  @memberof DataTable#oApi
4444	 */
4445	function _fnFilterCustom( settings )
4446	{
4447		var filters = DataTable.ext.search;
4448		var displayRows = settings.aiDisplay;
4449		var row, rowIdx;
4450	
4451		for ( var i=0, ien=filters.length ; i<ien ; i++ ) {
4452			var rows = [];
4453	
4454			// Loop over each row and see if it should be included
4455			for ( var j=0, jen=displayRows.length ; j<jen ; j++ ) {
4456				rowIdx = displayRows[ j ];
4457				row = settings.aoData[ rowIdx ];
4458	
4459				if ( filters[i]( settings, row._aFilterData, rowIdx, row._aData, j ) ) {
4460					rows.push( rowIdx );
4461				}
4462			}
4463	
4464			// So the array reference doesn't break set the results into the
4465			// existing array
4466			displayRows.length = 0;
4467			$.merge( displayRows, rows );
4468		}
4469	}
4470	
4471	
4472	/**
4473	 * Filter the table on a per-column basis
4474	 *  @param {object} oSettings dataTables settings object
4475	 *  @param {string} sInput string to filter on
4476	 *  @param {int} iColumn column to filter
4477	 *  @param {bool} bRegex treat search string as a regular expression or not
4478	 *  @param {bool} bSmart use smart filtering or not
4479	 *  @param {bool} bCaseInsensitive Do case insensitive matching or not
4480	 *  @memberof DataTable#oApi
4481	 */
4482	function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, caseInsensitive )
4483	{
4484		if ( searchStr === '' ) {
4485			return;
4486		}
4487	
4488		var data;
4489		var out = [];
4490		var display = settings.aiDisplay;
4491		var rpSearch = _fnFilterCreateSearch( searchStr, regex, smart, caseInsensitive );
4492	
4493		for ( var i=0 ; i<display.length ; i++ ) {
4494			data = settings.aoData[ display[i] ]._aFilterData[ colIdx ];
4495	
4496			if ( rpSearch.test( data ) ) {
4497				out.push( display[i] );
4498			}
4499		}
4500	
4501		settings.aiDisplay = out;
4502	}
4503	
4504	
4505	/**
4506	 * Filter the data table based on user input and draw the table
4507	 *  @param {object} settings dataTables settings object
4508	 *  @param {string} input string to filter on
4509	 *  @param {int} force optional - force a research of the master array (1) or not (undefined or 0)
4510	 *  @param {bool} regex treat as a regular expression or not
4511	 *  @param {bool} smart perform smart filtering or not
4512	 *  @param {bool} caseInsensitive Do case insensitive matching or not
4513	 *  @memberof DataTable#oApi
4514	 */
4515	function _fnFilter( settings, input, force, regex, smart, caseInsensitive )
4516	{
4517		var rpSearch = _fnFilterCreateSearch( input, regex, smart, caseInsensitive );
4518		var prevSearch = settings.oPreviousSearch.sSearch;
4519		var displayMaster = settings.aiDisplayMaster;
4520		var display, invalidated, i;
4521		var filtered = [];
4522	
4523		// Need to take account of custom filtering functions - always filter
4524		if ( DataTable.ext.search.length !== 0 ) {
4525			force = true;
4526		}
4527	
4528		// Check if any of the rows were invalidated
4529		invalidated = _fnFilterData( settings );
4530	
4531		// If the input is blank - we just want the full data set
4532		if ( input.length <= 0 ) {
4533			settings.aiDisplay = displayMaster.slice();
4534		}
4535		else {
4536			// New search - start from the master array
4537			if ( invalidated ||
4538				 force ||
4539				 regex ||
4540				 prevSearch.length > input.length ||
4541				 input.indexOf(prevSearch) !== 0 ||
4542				 settings.bSorted // On resort, the display master needs to be
4543				                  // re-filtered since indexes will have changed
4544			) {
4545				settings.aiDisplay = displayMaster.slice();
4546			}
4547	
4548			// Search the display array
4549			display = settings.aiDisplay;
4550	
4551			for ( i=0 ; i<display.length ; i++ ) {
4552				if ( rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) {
4553					filtered.push( display[i] );
4554				}
4555			}
4556	
4557			settings.aiDisplay = filtered;
4558		}
4559	}
4560	
4561	
4562	/**
4563	 * Build a regular expression object suitable for searching a table
4564	 *  @param {string} sSearch string to search for
4565	 *  @param {bool} bRegex treat as a regular expression or not
4566	 *  @param {bool} bSmart perform smart filtering or not
4567	 *  @param {bool} bCaseInsensitive Do case insensitive matching or not
4568	 *  @returns {RegExp} constructed object
4569	 *  @memberof DataTable#oApi
4570	 */
4571	function _fnFilterCreateSearch( search, regex, smart, caseInsensitive )
4572	{
4573		search = regex ?
4574			search :
4575			_fnEscapeRegex( search );
4576		
4577		if ( smart ) {
4578			/* For smart filtering we want to allow the search to work regardless of
4579			 * word order. We also want double quoted text to be preserved, so word
4580			 * order is important - a la google. So this is what we want to
4581			 * generate:
4582			 * 
4583			 * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$
4584			 */
4585			var a = $.map( search.match( /["\u201C][^"\u201D]+["\u201D]|[^ ]+/g ) || [''], function ( word ) {
4586				if ( word.charAt(0) === '"' ) {
4587					var m = word.match( /^"(.*)"$/ );
4588					word = m ? m[1] : word;
4589				}
4590				else if ( word.charAt(0) === '\u201C' ) {
4591					var m = word.match( /^\u201C(.*)\u201D$/ );
4592					word = m ? m[1] : word;
4593				}
4594	
4595				return word.replace('"', '');
4596			} );
4597	
4598			search = '^(?=.*?'+a.join( ')(?=.*?' )+').*$';
4599		}
4600	
4601		return new RegExp( search, caseInsensitive ? 'i' : '' );
4602	}
4603	
4604	
4605	/**
4606	 * Escape a string such that it can be used in a regular expression
4607	 *  @param {string} sVal string to escape
4608	 *  @returns {string} escaped string
4609	 *  @memberof DataTable#oApi
4610	 */
4611	var _fnEscapeRegex = DataTable.util.escapeRegex;
4612	
4613	var __filter_div = $('<div>')[0];
4614	var __filter_div_textContent = __filter_div.textContent !== undefined;
4615	
4616	// Update the filtering data for each row if needed (by invalidation or first run)
4617	function _fnFilterData ( settings )
4618	{
4619		var columns = settings.aoColumns;
4620		var column;
4621		var i, j, ien, jen, filterData, cellData, row;
4622		var wasInvalidated = false;
4623	
4624		for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
4625			row = settings.aoData[i];
4626	
4627			if ( ! row._aFilterData ) {
4628				filterData = [];
4629	
4630				for ( j=0, jen=columns.length ; j<jen ; j++ ) {
4631					column = columns[j];
4632	
4633					if ( column.bSearchable ) {
4634						cellData = _fnGetCellData( settings, i, j, 'filter' );
4635	
4636						// Search in DataTables 1.10 is string based. In 1.11 this
4637						// should be altered to also allow strict type checking.
4638						if ( cellData === null ) {
4639							cellData = '';
4640						}
4641	
4642						if ( typeof cellData !== 'string' && cellData.toString ) {
4643							cellData = cellData.toString();
4644						}
4645					}
4646					else {
4647						cellData = '';
4648					}
4649	
4650					// If it looks like there is an HTML entity in the string,
4651					// attempt to decode it so sorting works as expected. Note that
4652					// we could use a single line of jQuery to do this, but the DOM
4653					// method used here is much faster https
vendor: 28,961 bytes, lines 4653-5678
4653://jsperf.com/html-decode
4654					if ( cellData.indexOf && cellData.indexOf('&') !== -1 ) {
4655						__filter_div.innerHTML = cellData;
4656						cellData = __filter_div_textContent ?
4657							__filter_div.textContent :
4658							__filter_div.innerText;
4659					}
4660	
4661					if ( cellData.replace ) {
4662						cellData = cellData.replace(/[\r\n\u2028]/g, '');
4663					}
4664	
4665					filterData.push( cellData );
4666				}
4667	
4668				row._aFilterData = filterData;
4669				row._sFilterRow = filterData.join('  ');
4670				wasInvalidated = true;
4671			}
4672		}
4673	
4674		return wasInvalidated;
4675	}
4676	
4677	
4678	/**
4679	 * Convert from the internal Hungarian notation to camelCase for external
4680	 * interaction
4681	 *  @param {object} obj Object to convert
4682	 *  @returns {object} Inverted object
4683	 *  @memberof DataTable#oApi
4684	 */
4685	function _fnSearchToCamel ( obj )
4686	{
4687		return {
4688			search:          obj.sSearch,
4689			smart:           obj.bSmart,
4690			regex:           obj.bRegex,
4691			caseInsensitive: obj.bCaseInsensitive
4692		};
4693	}
4694	
4695	
4696	
4697	/**
4698	 * Convert from camelCase notation to the internal Hungarian. We could use the
4699	 * Hungarian convert function here, but this is cleaner
4700	 *  @param {object} obj Object to convert
4701	 *  @returns {object} Inverted object
4702	 *  @memberof DataTable#oApi
4703	 */
4704	function _fnSearchToHung ( obj )
4705	{
4706		return {
4707			sSearch:          obj.search,
4708			bSmart:           obj.smart,
4709			bRegex:           obj.regex,
4710			bCaseInsensitive: obj.caseInsensitive
4711		};
4712	}
4713	
4714	/**
4715	 * Generate the node required for the info display
4716	 *  @param {object} oSettings dataTables settings object
4717	 *  @returns {node} Information element
4718	 *  @memberof DataTable#oApi
4719	 */
4720	function _fnFeatureHtmlInfo ( settings )
4721	{
4722		var
4723			tid = settings.sTableId,
4724			nodes = settings.aanFeatures.i,
4725			n = $('<div/>', {
4726				'class': settings.oClasses.sInfo,
4727				'id': ! nodes ? tid+'_info' : null
4728			} );
4729	
4730		if ( ! nodes ) {
4731			// Update display on each draw
4732			settings.aoDrawCallback.push( {
4733				"fn": _fnUpdateInfo,
4734				"sName": "information"
4735			} );
4736	
4737			n
4738				.attr( 'role', 'status' )
4739				.attr( 'aria-live', 'polite' );
4740	
4741			// Table is described by our info div
4742			$(settings.nTable).attr( 'aria-describedby', tid+'_info' );
4743		}
4744	
4745		return n[0];
4746	}
4747	
4748	
4749	/**
4750	 * Update the information elements in the display
4751	 *  @param {object} settings dataTables settings object
4752	 *  @memberof DataTable#oApi
4753	 */
4754	function _fnUpdateInfo ( settings )
4755	{
4756		/* Show information about the table */
4757		var nodes = settings.aanFeatures.i;
4758		if ( nodes.length === 0 ) {
4759			return;
4760		}
4761	
4762		var
4763			lang  = settings.oLanguage,
4764			start = settings._iDisplayStart+1,
4765			end   = settings.fnDisplayEnd(),
4766			max   = settings.fnRecordsTotal(),
4767			total = settings.fnRecordsDisplay(),
4768			out   = total ?
4769				lang.sInfo :
4770				lang.sInfoEmpty;
4771	
4772		if ( total !== max ) {
4773			/* Record set after filtering */
4774			out += ' ' + lang.sInfoFiltered;
4775		}
4776	
4777		// Convert the macros
4778		out += lang.sInfoPostFix;
4779		out = _fnInfoMacros( settings, out );
4780	
4781		var callback = lang.fnInfoCallback;
4782		if ( callback !== null ) {
4783			out = callback.call( settings.oInstance,
4784				settings, start, end, max, total, out
4785			);
4786		}
4787	
4788		$(nodes).html( out );
4789	}
4790	
4791	
4792	function _fnInfoMacros ( settings, str )
4793	{
4794		// When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
4795		// internally
4796		var
4797			formatter  = settings.fnFormatNumber,
4798			start      = settings._iDisplayStart+1,
4799			len        = settings._iDisplayLength,
4800			vis        = settings.fnRecordsDisplay(),
4801			all        = len === -1;
4802	
4803		return str.
4804			replace(/_START_/g, formatter.call( settings, start ) ).
4805			replace(/_END_/g,   formatter.call( settings, settings.fnDisplayEnd() ) ).
4806			replace(/_MAX_/g,   formatter.call( settings, settings.fnRecordsTotal() ) ).
4807			replace(/_TOTAL_/g, formatter.call( settings, vis ) ).
4808			replace(/_PAGE_/g,  formatter.call( settings, all ? 1 : Math.ceil( start / len ) ) ).
4809			replace(/_PAGES_/g, formatter.call( settings, all ? 1 : Math.ceil( vis / len ) ) );
4810	}
4811	
4812	
4813	
4814	/**
4815	 * Draw the table for the first time, adding all required features
4816	 *  @param {object} settings dataTables settings object
4817	 *  @memberof DataTable#oApi
4818	 */
4819	function _fnInitialise ( settings )
4820	{
4821		var i, iLen, iAjaxStart=settings.iInitDisplayStart;
4822		var columns = settings.aoColumns, column;
4823		var features = settings.oFeatures;
4824		var deferLoading = settings.bDeferLoading; // value modified by the draw
4825	
4826		/* Ensure that the table data is fully initialised */
4827		if ( ! settings.bInitialised ) {
4828			setTimeout( function(){ _fnInitialise( settings ); }, 200 );
4829			return;
4830		}
4831	
4832		/* Show the display HTML options */
4833		_fnAddOptionsHtml( settings );
4834	
4835		/* Build and draw the header / footer for the table */
4836		_fnBuildHead( settings );
4837		_fnDrawHead( settings, settings.aoHeader );
4838		_fnDrawHead( settings, settings.aoFooter );
4839	
4840		/* Okay to show that something is going on now */
4841		_fnProcessingDisplay( settings, true );
4842	
4843		/* Calculate sizes for columns */
4844		if ( features.bAutoWidth ) {
4845			_fnCalculateColumnWidths( settings );
4846		}
4847	
4848		for ( i=0, iLen=columns.length ; i<iLen ; i++ ) {
4849			column = columns[i];
4850	
4851			if ( column.sWidth ) {
4852				column.nTh.style.width = _fnStringToCss( column.sWidth );
4853			}
4854		}
4855	
4856		_fnCallbackFire( settings, null, 'preInit', [settings] );
4857	
4858		// If there is default sorting required - let's do it. The sort function
4859		// will do the drawing for us. Otherwise we draw the table regardless of the
4860		// Ajax source - this allows the table to look initialised for Ajax sourcing
4861		// data (show 'loading' message possibly)
4862		_fnReDraw( settings );
4863	
4864		// Server-side processing init complete is done by _fnAjaxUpdateDraw
4865		var dataSrc = _fnDataSource( settings );
4866		if ( dataSrc != 'ssp' || deferLoading ) {
4867			// if there is an ajax source load the data
4868			if ( dataSrc == 'ajax' ) {
4869				_fnBuildAjax( settings, [], function(json) {
4870					var aData = _fnAjaxDataSrc( settings, json );
4871	
4872					// Got the data - add it to the table
4873					for ( i=0 ; i<aData.length ; i++ ) {
4874						_fnAddData( settings, aData[i] );
4875					}
4876	
4877					// Reset the init display for cookie saving. We've already done
4878					// a filter, and therefore cleared it before. So we need to make
4879					// it appear 'fresh'
4880					settings.iInitDisplayStart = iAjaxStart;
4881	
4882					_fnReDraw( settings );
4883	
4884					_fnProcessingDisplay( settings, false );
4885					_fnInitComplete( settings, json );
4886				}, settings );
4887			}
4888			else {
4889				_fnProcessingDisplay( settings, false );
4890				_fnInitComplete( settings );
4891			}
4892		}
4893	}
4894	
4895	
4896	/**
4897	 * Draw the table for the first time, adding all required features
4898	 *  @param {object} oSettings dataTables settings object
4899	 *  @param {object} [json] JSON from the server that completed the table, if using Ajax source
4900	 *    with client-side processing (optional)
4901	 *  @memberof DataTable#oApi
4902	 */
4903	function _fnInitComplete ( settings, json )
4904	{
4905		settings._bInitComplete = true;
4906	
4907		// When data was added after the initialisation (data or Ajax) we need to
4908		// calculate the column sizing
4909		if ( json || settings.oInit.aaData ) {
4910			_fnAdjustColumnSizing( settings );
4911		}
4912	
4913		_fnCallbackFire( settings, null, 'plugin-init', [settings, json] );
4914		_fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] );
4915	}
4916	
4917	
4918	function _fnLengthChange ( settings, val )
4919	{
4920		var len = parseInt( val, 10 );
4921		settings._iDisplayLength = len;
4922	
4923		_fnLengthOverflow( settings );
4924	
4925		// Fire length change event
4926		_fnCallbackFire( settings, null, 'length', [settings, len] );
4927	}
4928	
4929	
4930	/**
4931	 * Generate the node required for user display length changing
4932	 *  @param {object} settings dataTables settings object
4933	 *  @returns {node} Display length feature node
4934	 *  @memberof DataTable#oApi
4935	 */
4936	function _fnFeatureHtmlLength ( settings )
4937	{
4938		var
4939			classes  = settings.oClasses,
4940			tableId  = settings.sTableId,
4941			menu     = settings.aLengthMenu,
4942			d2       = Array.isArray( menu[0] ),
4943			lengths  = d2 ? menu[0] : menu,
4944			language = d2 ? menu[1] : menu;
4945	
4946		var select = $('<select/>', {
4947			'name':          tableId+'_length',
4948			'aria-controls': tableId,
4949			'class':         classes.sLengthSelect
4950		} );
4951	
4952		for ( var i=0, ien=lengths.length ; i<ien ; i++ ) {
4953			select[0][ i ] = new Option(
4954				typeof language[i] === 'number' ?
4955					settings.fnFormatNumber( language[i] ) :
4956					language[i],
4957				lengths[i]
4958			);
4959		}
4960	
4961		var div = $('<div><label/></div>').addClass( classes.sLength );
4962		if ( ! settings.aanFeatures.l ) {
4963			div[0].id = tableId+'_length';
4964		}
4965	
4966		div.children().append(
4967			settings.oLanguage.sLengthMenu.replace( '_MENU_', select[0].outerHTML )
4968		);
4969	
4970		// Can't use `select` variable as user might provide their own and the
4971		// reference is broken by the use of outerHTML
4972		$('select', div)
4973			.val( settings._iDisplayLength )
4974			.on( 'change.DT', function(e) {
4975				_fnLengthChange( settings, $(this).val() );
4976				_fnDraw( settings );
4977			} );
4978	
4979		// Update node value whenever anything changes the table's length
4980		$(settings.nTable).on( 'length.dt.DT', function (e, s, len) {
4981			if ( settings === s ) {
4982				$('select', div).val( len );
4983			}
4984		} );
4985	
4986		return div[0];
4987	}
4988	
4989	
4990	
4991	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
4992	 * Note that most of the paging logic is done in
4993	 * DataTable.ext.pager
4994	 */
4995	
4996	/**
4997	 * Generate the node required for default pagination
4998	 *  @param {object} oSettings dataTables settings object
4999	 *  @returns {node} Pagination feature node
5000	 *  @memberof DataTable#oApi
5001	 */
5002	function _fnFeatureHtmlPaginate ( settings )
5003	{
5004		var
5005			type   = settings.sPaginationType,
5006			plugin = DataTable.ext.pager[ type ],
5007			modern = typeof plugin === 'function',
5008			redraw = function( settings ) {
5009				_fnDraw( settings );
5010			},
5011			node = $('<div/>').addClass( settings.oClasses.sPaging + type )[0],
5012			features = settings.aanFeatures;
5013	
5014		if ( ! modern ) {
5015			plugin.fnInit( settings, node, redraw );
5016		}
5017	
5018		/* Add a draw callback for the pagination on first instance, to update the paging display */
5019		if ( ! features.p )
5020		{
5021			node.id = settings.sTableId+'_paginate';
5022	
5023			settings.aoDrawCallback.push( {
5024				"fn": function( settings ) {
5025					if ( modern ) {
5026						var
5027							start      = settings._iDisplayStart,
5028							len        = settings._iDisplayLength,
5029							visRecords = settings.fnRecordsDisplay(),
5030							all        = len === -1,
5031							page = all ? 0 : Math.ceil( start / len ),
5032							pages = all ? 1 : Math.ceil( visRecords / len ),
5033							buttons = plugin(page, pages),
5034							i, ien;
5035	
5036						for ( i=0, ien=features.p.length ; i<ien ; i++ ) {
5037							_fnRenderer( settings, 'pageButton' )(
5038								settings, features.p[i], i, buttons, page, pages
5039							);
5040						}
5041					}
5042					else {
5043						plugin.fnUpdate( settings, redraw );
5044					}
5045				},
5046				"sName": "pagination"
5047			} );
5048		}
5049	
5050		return node;
5051	}
5052	
5053	
5054	/**
5055	 * Alter the display settings to change the page
5056	 *  @param {object} settings DataTables settings object
5057	 *  @param {string|int} action Paging action to take: "first", "previous",
5058	 *    "next" or "last" or page number to jump to (integer)
5059	 *  @param [bool] redraw Automatically draw the update or not
5060	 *  @returns {bool} true page has changed, false - no change
5061	 *  @memberof DataTable#oApi
5062	 */
5063	function _fnPageChange ( settings, action, redraw )
5064	{
5065		var
5066			start     = settings._iDisplayStart,
5067			len       = settings._iDisplayLength,
5068			records   = settings.fnRecordsDisplay();
5069	
5070		if ( records === 0 || len === -1 )
5071		{
5072			start = 0;
5073		}
5074		else if ( typeof action === "number" )
5075		{
5076			start = action * len;
5077	
5078			if ( start > records )
5079			{
5080				start = 0;
5081			}
5082		}
5083		else if ( action == "first" )
5084		{
5085			start = 0;
5086		}
5087		else if ( action == "previous" )
5088		{
5089			start = len >= 0 ?
5090				start - len :
5091				0;
5092	
5093			if ( start < 0 )
5094			{
5095			  start = 0;
5096			}
5097		}
5098		else if ( action == "next" )
5099		{
5100			if ( start + len < records )
5101			{
5102				start += len;
5103			}
5104		}
5105		else if ( action == "last" )
5106		{
5107			start = Math.floor( (records-1) / len) * len;
5108		}
5109		else
5110		{
5111			_fnLog( settings, 0, "Unknown paging action: "+action, 5 );
5112		}
5113	
5114		var changed = settings._iDisplayStart !== start;
5115		settings._iDisplayStart = start;
5116	
5117		if ( changed ) {
5118			_fnCallbackFire( settings, null, 'page', [settings] );
5119	
5120			if ( redraw ) {
5121				_fnDraw( settings );
5122			}
5123		}
5124		else {
5125			// No change event - paging was called, but no change
5126			_fnCallbackFire( settings, null, 'page-nc', [settings] );
5127		}
5128	
5129		return changed;
5130	}
5131	
5132	
5133	
5134	/**
5135	 * Generate the node required for the processing node
5136	 *  @param {object} settings dataTables settings object
5137	 *  @returns {node} Processing element
5138	 *  @memberof DataTable#oApi
5139	 */
5140	function _fnFeatureHtmlProcessing ( settings )
5141	{
5142		return $('<div/>', {
5143				'id': ! settings.aanFeatures.r ? settings.sTableId+'_processing' : null,
5144				'class': settings.oClasses.sProcessing,
5145				'role': 'status'
5146			} )
5147			.html( settings.oLanguage.sProcessing )
5148			.append('<div><div></div><div></div><div></div><div></div></div>')
5149			.insertBefore( settings.nTable )[0];
5150	}
5151	
5152	
5153	/**
5154	 * Display or hide the processing indicator
5155	 *  @param {object} settings dataTables settings object
5156	 *  @param {bool} show Show the processing indicator (true) or not (false)
5157	 *  @memberof DataTable#oApi
5158	 */
5159	function _fnProcessingDisplay ( settings, show )
5160	{
5161		if ( settings.oFeatures.bProcessing ) {
5162			$(settings.aanFeatures.r).css( 'display', show ? 'block' : 'none' );
5163		}
5164	
5165		_fnCallbackFire( settings, null, 'processing', [settings, show] );
5166	}
5167	
5168	/**
5169	 * Add any control elements for the table - specifically scrolling
5170	 *  @param {object} settings dataTables settings object
5171	 *  @returns {node} Node to add to the DOM
5172	 *  @memberof DataTable#oApi
5173	 */
5174	function _fnFeatureHtmlTable ( settings )
5175	{
5176		var table = $(settings.nTable);
5177	
5178		// Scrolling from here on in
5179		var scroll = settings.oScroll;
5180	
5181		if ( scroll.sX === '' && scroll.sY === '' ) {
5182			return settings.nTable;
5183		}
5184	
5185		var scrollX = scroll.sX;
5186		var scrollY = scroll.sY;
5187		var classes = settings.oClasses;
5188		var caption = table.children('caption');
5189		var captionSide = caption.length ? caption[0]._captionSide : null;
5190		var headerClone = $( table[0].cloneNode(false) );
5191		var footerClone = $( table[0].cloneNode(false) );
5192		var footer = table.children('tfoot');
5193		var _div = '<div/>';
5194		var size = function ( s ) {
5195			return !s ? null : _fnStringToCss( s );
5196		};
5197	
5198		if ( ! footer.length ) {
5199			footer = null;
5200		}
5201	
5202		/*
5203		 * The HTML structure that we want to generate in this function is:
5204		 *  div - scroller
5205		 *    div - scroll head
5206		 *      div - scroll head inner
5207		 *        table - scroll head table
5208		 *          thead - thead
5209		 *    div - scroll body
5210		 *      table - table (master table)
5211		 *        thead - thead clone for sizing
5212		 *        tbody - tbody
5213		 *    div - scroll foot
5214		 *      div - scroll foot inner
5215		 *        table - scroll foot table
5216		 *          tfoot - tfoot
5217		 */
5218		var scroller = $( _div, { 'class': classes.sScrollWrapper } )
5219			.append(
5220				$(_div, { 'class': classes.sScrollHead } )
5221					.css( {
5222						overflow: 'hidden',
5223						position: 'relative',
5224						border: 0,
5225						width: scrollX ? size(scrollX) : '100%'
5226					} )
5227					.append(
5228						$(_div, { 'class': classes.sScrollHeadInner } )
5229							.css( {
5230								'box-sizing': 'content-box',
5231								width: scroll.sXInner || '100%'
5232							} )
5233							.append(
5234								headerClone
5235									.removeAttr('id')
5236									.css( 'margin-left', 0 )
5237									.append( captionSide === 'top' ? caption : null )
5238									.append(
5239										table.children('thead')
5240									)
5241							)
5242					)
5243			)
5244			.append(
5245				$(_div, { 'class': classes.sScrollBody } )
5246					.css( {
5247						position: 'relative',
5248						overflow: 'auto',
5249						width: size( scrollX )
5250					} )
5251					.append( table )
5252			);
5253	
5254		if ( footer ) {
5255			scroller.append(
5256				$(_div, { 'class': classes.sScrollFoot } )
5257					.css( {
5258						overflow: 'hidden',
5259						border: 0,
5260						width: scrollX ? size(scrollX) : '100%'
5261					} )
5262					.append(
5263						$(_div, { 'class': classes.sScrollFootInner } )
5264							.append(
5265								footerClone
5266									.removeAttr('id')
5267									.css( 'margin-left', 0 )
5268									.append( captionSide === 'bottom' ? caption : null )
5269									.append(
5270										table.children('tfoot')
5271									)
5272							)
5273					)
5274			);
5275		}
5276	
5277		var children = scroller.children();
5278		var scrollHead = children[0];
5279		var scrollBody = children[1];
5280		var scrollFoot = footer ? children[2] : null;
5281	
5282		// When the body is scrolled, then we also want to scroll the headers
5283		if ( scrollX ) {
5284			$(scrollBody).on( 'scroll.DT', function (e) {
5285				var scrollLeft = this.scrollLeft;
5286	
5287				scrollHead.scrollLeft = scrollLeft;
5288	
5289				if ( footer ) {
5290					scrollFoot.scrollLeft = scrollLeft;
5291				}
5292			} );
5293		}
5294	
5295		$(scrollBody).css('max-height', scrollY);
5296		if (! scroll.bCollapse) {
5297			$(scrollBody).css('height', scrollY);
5298		}
5299	
5300		settings.nScrollHead = scrollHead;
5301		settings.nScrollBody = scrollBody;
5302		settings.nScrollFoot = scrollFoot;
5303	
5304		// On redraw - align columns
5305		settings.aoDrawCallback.push( {
5306			"fn": _fnScrollDraw,
5307			"sName": "scrolling"
5308		} );
5309	
5310		return scroller[0];
5311	}
5312	
5313	
5314	
5315	/**
5316	 * Update the header, footer and body tables for resizing - i.e. column
5317	 * alignment.
5318	 *
5319	 * Welcome to the most horrible function DataTables. The process that this
5320	 * function follows is basically:
5321	 *   1. Re-create the table inside the scrolling div
5322	 *   2. Take live measurements from the DOM
5323	 *   3. Apply the measurements to align the columns
5324	 *   4. Clean up
5325	 *
5326	 *  @param {object} settings dataTables settings object
5327	 *  @memberof DataTable#oApi
5328	 */
5329	function _fnScrollDraw ( settings )
5330	{
5331		// Given that this is such a monster function, a lot of variables are use
5332		// to try and keep the minimised size as small as possible
5333		var
5334			scroll         = settings.oScroll,
5335			scrollX        = scroll.sX,
5336			scrollXInner   = scroll.sXInner,
5337			scrollY        = scroll.sY,
5338			barWidth       = scroll.iBarWidth,
5339			divHeader      = $(settings.nScrollHead),
5340			divHeaderStyle = divHeader[0].style,
5341			divHeaderInner = divHeader.children('div'),
5342			divHeaderInnerStyle = divHeaderInner[0].style,
5343			divHeaderTable = divHeaderInner.children('table'),
5344			divBodyEl      = settings.nScrollBody,
5345			divBody        = $(divBodyEl),
5346			divBodyStyle   = divBodyEl.style,
5347			divFooter      = $(settings.nScrollFoot),
5348			divFooterInner = divFooter.children('div'),
5349			divFooterTable = divFooterInner.children('table'),
5350			header         = $(settings.nTHead),
5351			table          = $(settings.nTable),
5352			tableEl        = table[0],
5353			tableStyle     = tableEl.style,
5354			footer         = settings.nTFoot ? $(settings.nTFoot) : null,
5355			browser        = settings.oBrowser,
5356			ie67           = browser.bScrollOversize,
5357			dtHeaderCells  = _pluck( settings.aoColumns, 'nTh' ),
5358			headerTrgEls, footerTrgEls,
5359			headerSrcEls, footerSrcEls,
5360			headerCopy, footerCopy,
5361			headerWidths=[], footerWidths=[],
5362			headerContent=[], footerContent=[],
5363			idx, correction, sanityWidth,
5364			zeroOut = function(nSizer) {
5365				var style = nSizer.style;
5366				style.paddingTop = "0";
5367				style.paddingBottom = "0";
5368				style.borderTopWidth = "0";
5369				style.borderBottomWidth = "0";
5370				style.height = 0;
5371			};
5372	
5373		// If the scrollbar visibility has changed from the last draw, we need to
5374		// adjust the column sizes as the table width will have changed to account
5375		// for the scrollbar
5376		var scrollBarVis = divBodyEl.scrollHeight > divBodyEl.clientHeight;
5377		
5378		if ( settings.scrollBarVis !== scrollBarVis && settings.scrollBarVis !== undefined ) {
5379			settings.scrollBarVis = scrollBarVis;
5380			_fnAdjustColumnSizing( settings );
5381			return; // adjust column sizing will call this function again
5382		}
5383		else {
5384			settings.scrollBarVis = scrollBarVis;
5385		}
5386	
5387		/*
5388		 * 1. Re-create the table inside the scrolling div
5389		 */
5390	
5391		// Remove the old minimised thead and tfoot elements in the inner table
5392		table.children('thead, tfoot').remove();
5393	
5394		if ( footer ) {
5395			footerCopy = footer.clone().prependTo( table );
5396			footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized
5397			footerSrcEls = footerCopy.find('tr');
5398			footerCopy.find('[id]').removeAttr('id');
5399		}
5400	
5401		// Clone the current header and footer elements and then place it into the inner table
5402		headerCopy = header.clone().prependTo( table );
5403		headerTrgEls = header.find('tr'); // original header is in its own table
5404		headerSrcEls = headerCopy.find('tr');
5405		headerCopy.find('th, td').removeAttr('tabindex');
5406		headerCopy.find('[id]').removeAttr('id');
5407	
5408	
5409		/*
5410		 * 2. Take live measurements from the DOM - do not alter the DOM itself!
5411		 */
5412	
5413		// Remove old sizing and apply the calculated column widths
5414		// Get the unique column headers in the newly created (cloned) header. We want to apply the
5415		// calculated sizes to this header
5416		if ( ! scrollX )
5417		{
5418			divBodyStyle.width = '100%';
5419			divHeader[0].style.width = '100%';
5420		}
5421	
5422		$.each( _fnGetUniqueThs( settings, headerCopy ), function ( i, el ) {
5423			idx = _fnVisibleToColumnIndex( settings, i );
5424			el.style.width = settings.aoColumns[idx].sWidth;
5425		} );
5426	
5427		if ( footer ) {
5428			_fnApplyToChildren( function(n) {
5429				n.style.width = "";
5430			}, footerSrcEls );
5431		}
5432	
5433		// Size the table as a whole
5434		sanityWidth = table.outerWidth();
5435		if ( scrollX === "" ) {
5436			// No x scrolling
5437			tableStyle.width = "100%";
5438	
5439			// IE7 will make the width of the table when 100% include the scrollbar
5440			// - which is shouldn't. When there is a scrollbar we need to take this
5441			// into account.
5442			if ( ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight ||
5443				divBody.css('overflow-y') == "scroll")
5444			) {
5445				tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth);
5446			}
5447	
5448			// Recalculate the sanity width
5449			sanityWidth = table.outerWidth();
5450		}
5451		else if ( scrollXInner !== "" ) {
5452			// legacy x scroll inner has been given - use it
5453			tableStyle.width = _fnStringToCss(scrollXInner);
5454	
5455			// Recalculate the sanity width
5456			sanityWidth = table.outerWidth();
5457		}
5458	
5459		// Hidden header should have zero height, so remove padding and borders. Then
5460		// set the width based on the real headers
5461	
5462		// Apply all styles in one pass
5463		_fnApplyToChildren( zeroOut, headerSrcEls );
5464	
5465		// Read all widths in next pass
5466		_fnApplyToChildren( function(nSizer) {
5467			var style = window.getComputedStyle ?
5468				window.getComputedStyle(nSizer).width :
5469				_fnStringToCss( $(nSizer).width() );
5470	
5471			headerContent.push( nSizer.innerHTML );
5472			headerWidths.push( style );
5473		}, headerSrcEls );
5474	
5475		// Apply all widths in final pass
5476		_fnApplyToChildren( function(nToSize, i) {
5477			nToSize.style.width = headerWidths[i];
5478		}, headerTrgEls );
5479	
5480		$(headerSrcEls).css('height', 0);
5481	
5482		/* Same again with the footer if we have one */
5483		if ( footer )
5484		{
5485			_fnApplyToChildren( zeroOut, footerSrcEls );
5486	
5487			_fnApplyToChildren( function(nSizer) {
5488				footerContent.push( nSizer.innerHTML );
5489				footerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
5490			}, footerSrcEls );
5491	
5492			_fnApplyToChildren( function(nToSize, i) {
5493				nToSize.style.width = footerWidths[i];
5494			}, footerTrgEls );
5495	
5496			$(footerSrcEls).height(0);
5497		}
5498	
5499	
5500		/*
5501		 * 3. Apply the measurements
5502		 */
5503	
5504		// "Hide" the header and footer that we used for the sizing. We need to keep
5505		// the content of the cell so that the width applied to the header and body
5506		// both match, but we want to hide it completely. We want to also fix their
5507		// width to what they currently are
5508		_fnApplyToChildren( function(nSizer, i) {
5509			nSizer.innerHTML = '<div class="dataTables_sizing">'+headerContent[i]+'</div>';
5510			nSizer.childNodes[0].style.height = "0";
5511			nSizer.childNodes[0].style.overflow = "hidden";
5512			nSizer.style.width = headerWidths[i];
5513		}, headerSrcEls );
5514	
5515		if ( footer )
5516		{
5517			_fnApplyToChildren( function(nSizer, i) {
5518				nSizer.innerHTML = '<div class="dataTables_sizing">'+footerContent[i]+'</div>';
5519				nSizer.childNodes[0].style.height = "0";
5520				nSizer.childNodes[0].style.overflow = "hidden";
5521				nSizer.style.width = footerWidths[i];
5522			}, footerSrcEls );
5523		}
5524	
5525		// Sanity check that the table is of a sensible width. If not then we are going to get
5526		// misalignment - try to prevent this by not allowing the table to shrink below its min width
5527		if ( Math.round(table.outerWidth()) < Math.round(sanityWidth) )
5528		{
5529			// The min width depends upon if we have a vertical scrollbar visible or not */
5530			correction = ((divBodyEl.scrollHeight > divBodyEl.offsetHeight ||
5531				divBody.css('overflow-y') == "scroll")) ?
5532					sanityWidth+barWidth :
5533					sanityWidth;
5534	
5535			// IE6/7 are a law unto themselves...
5536			if ( ie67 && (divBodyEl.scrollHeight >
5537				divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll")
5538			) {
5539				tableStyle.width = _fnStringToCss( correction-barWidth );
5540			}
5541	
5542			// And give the user a warning that we've stopped the table getting too small
5543			if ( scrollX === "" || scrollXInner !== "" ) {
5544				_fnLog( settings, 1, 'Possible column misalignment', 6 );
5545			}
5546		}
5547		else
5548		{
5549			correction = '100%';
5550		}
5551	
5552		// Apply to the container elements
5553		divBodyStyle.width = _fnStringToCss( correction );
5554		divHeaderStyle.width = _fnStringToCss( correction );
5555	
5556		if ( footer ) {
5557			settings.nScrollFoot.style.width = _fnStringToCss( correction );
5558		}
5559	
5560	
5561		/*
5562		 * 4. Clean up
5563		 */
5564		if ( ! scrollY ) {
5565			/* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
5566			 * the scrollbar height from the visible display, rather than adding it on. We need to
5567			 * set the height in order to sort this. Don't want to do it in any other browsers.
5568			 */
5569			if ( ie67 ) {
5570				divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+barWidth );
5571			}
5572		}
5573	
5574		/* Finally set the width's of the header and footer tables */
5575		var iOuterWidth = table.outerWidth();
5576		divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth );
5577		divHeaderInnerStyle.width = _fnStringToCss( iOuterWidth );
5578	
5579		// Figure out if there are scrollbar present - if so then we need a the header and footer to
5580		// provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
5581		var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll";
5582		var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' );
5583		divHeaderInnerStyle[ padding ] = bScrolling ? barWidth+"px" : "0px";
5584	
5585		if ( footer ) {
5586			divFooterTable[0].style.width = _fnStringToCss( iOuterWidth );
5587			divFooterInner[0].style.width = _fnStringToCss( iOuterWidth );
5588			divFooterInner[0].style[padding] = bScrolling ? barWidth+"px" : "0px";
5589		}
5590	
5591		// Correct DOM ordering for colgroup - comes before the thead
5592		table.children('colgroup').insertBefore( table.children('thead') );
5593	
5594		/* Adjust the position of the header in case we loose the y-scrollbar */
5595		divBody.trigger('scroll');
5596	
5597		// If sorting or filtering has occurred, jump the scrolling back to the top
5598		// only if we aren't holding the position
5599		if ( (settings.bSorted || settings.bFiltered) && ! settings._drawHold ) {
5600			divBodyEl.scrollTop = 0;
5601		}
5602	}
5603	
5604	
5605	
5606	/**
5607	 * Apply a given function to the display child nodes of an element array (typically
5608	 * TD children of TR rows
5609	 *  @param {function} fn Method to apply to the objects
5610	 *  @param array {nodes} an1 List of elements to look through for display children
5611	 *  @param array {nodes} an2 Another list (identical structure to the first) - optional
5612	 *  @memberof DataTable#oApi
5613	 */
5614	function _fnApplyToChildren( fn, an1, an2 )
5615	{
5616		var index=0, i=0, iLen=an1.length;
5617		var nNode1, nNode2;
5618	
5619		while ( i < iLen ) {
5620			nNode1 = an1[i].firstChild;
5621			nNode2 = an2 ? an2[i].firstChild : null;
5622	
5623			while ( nNode1 ) {
5624				if ( nNode1.nodeType === 1 ) {
5625					if ( an2 ) {
5626						fn( nNode1, nNode2, index );
5627					}
5628					else {
5629						fn( nNode1, index );
5630					}
5631	
5632					index++;
5633				}
5634	
5635				nNode1 = nNode1.nextSibling;
5636				nNode2 = an2 ? nNode2.nextSibling : null;
5637			}
5638	
5639			i++;
5640		}
5641	}
5642	
5643	
5644	
5645	var __re_html_remove = /<.*?>/g;
5646	
5647	
5648	/**
5649	 * Calculate the width of columns for the table
5650	 *  @param {object} oSettings dataTables settings object
5651	 *  @memberof DataTable#oApi
5652	 */
5653	function _fnCalculateColumnWidths ( oSettings )
5654	{
5655		var
5656			table = oSettings.nTable,
5657			columns = oSettings.aoColumns,
5658			scroll = oSettings.oScroll,
5659			scrollY = scroll.sY,
5660			scrollX = scroll.sX,
5661			scrollXInner = scroll.sXInner,
5662			columnCount = columns.length,
5663			visibleColumns = _fnGetColumns( oSettings, 'bVisible' ),
5664			headerCells = $('th', oSettings.nTHead),
5665			tableWidthAttr = table.getAttribute('width'), // from DOM element
5666			tableContainer = table.parentNode,
5667			userInputs = false,
5668			i, column, columnIdx, width, outerWidth,
5669			browser = oSettings.oBrowser,
5670			ie67 = browser.bScrollOversize;
5671	
5672		var styleWidth = table.style.width;
5673		if ( styleWidth && styleWidth.indexOf('%') !== -1 ) {
5674			tableWidthAttr = styleWidth;
5675		}
5676	
5677		/* Convert any user input sizes into pixel sizes */
5678		
5678var sizes = _fnConvertToWidth(_pluck(columns, 'sWidthOrig'), tableContainer);
5679	
5680		for ( i=0 ; i<visibleColumns.length ; i++ ) {
5681			column = columns[ visibleColumns[i] ];
5682	
5683			if ( column.sWidth !== null ) {
5684				column.sWidth = sizes[i]
vendor: 6,819 bytes, lines 5684-5887
5684;
5685	
5686				userInputs = true;
5687			}
5688		}
5689	
5690		/* If the number of columns in the DOM equals the number that we have to
5691		 * process in DataTables, then we can use the offsets that are created by
5692		 * the web- browser. No custom sizes can be set in order for this to happen,
5693		 * nor scrolling used
5694		 */
5695		if ( ie67 || ! userInputs && ! scrollX && ! scrollY &&
5696		     columnCount == _fnVisbleColumns( oSettings ) &&
5697		     columnCount == headerCells.length
5698		) {
5699			for ( i=0 ; i<columnCount ; i++ ) {
5700				var colIdx = _fnVisibleToColumnIndex( oSettings, i );
5701	
5702				if ( colIdx !== null ) {
5703					columns[ colIdx ].sWidth = _fnStringToCss( headerCells.eq(i).width() );
5704				}
5705			}
5706		}
5707		else
5708		{
5709			// Otherwise construct a single row, worst case, table with the widest
5710			// node in the data, assign any user defined widths, then insert it into
5711			// the DOM and allow the browser to do all the hard work of calculating
5712			// table widths
5713			var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table
5714				.css( 'visibility', 'hidden' )
5715				.removeAttr( 'id' );
5716	
5717			// Clean up the table body
5718			tmpTable.find('tbody tr').remove();
5719			var tr = $('<tr/>').appendTo( tmpTable.find('tbody') );
5720	
5721			// Clone the table header and footer - we can't use the header / footer
5722			// from the cloned table, since if scrolling is active, the table's
5723			// real header and footer are contained in different table tags
5724			tmpTable.find('thead, tfoot').remove();
5725			tmpTable
5726				.append( $(oSettings.nTHead).clone() )
5727				.append( $(oSettings.nTFoot).clone() );
5728	
5729			// Remove any assigned widths from the footer (from scrolling)
5730			tmpTable.find('tfoot th, tfoot td').css('width', '');
5731	
5732			// Apply custom sizing to the cloned header
5733			headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] );
5734	
5735			for ( i=0 ; i<visibleColumns.length ; i++ ) {
5736				column = columns[ visibleColumns[i] ];
5737	
5738				headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ?
5739					_fnStringToCss( column.sWidthOrig ) :
5740					'';
5741	
5742				// For scrollX we need to force the column width otherwise the
5743				// browser will collapse it. If this width is smaller than the
5744				// width the column requires, then it will have no effect
5745				if ( column.sWidthOrig && scrollX ) {
5746					$( headerCells[i] ).append( $('<div/>').css( {
5747						width: column.sWidthOrig,
5748						margin: 0,
5749						padding: 0,
5750						border: 0,
5751						height: 1
5752					} ) );
5753				}
5754			}
5755	
5756			// Find the widest cell for each column and put it into the table
5757			if ( oSettings.aoData.length ) {
5758				for ( i=0 ; i<visibleColumns.length ; i++ ) {
5759					columnIdx = visibleColumns[i];
5760					column = columns[ columnIdx ];
5761	
5762					$( _fnGetWidestNode( oSettings, columnIdx ) )
5763						.clone( false )
5764						.append( column.sContentPadding )
5765						.appendTo( tr );
5766				}
5767			}
5768	
5769			// Tidy the temporary table - remove name attributes so there aren't
5770			// duplicated in the dom (radio elements for example)
5771			$('[name]', tmpTable).removeAttr('name');
5772	
5773			// Table has been built, attach to the document so we can work with it.
5774			// A holding element is used, positioned at the top of the container
5775			// with minimal height, so it has no effect on if the container scrolls
5776			// or not. Otherwise it might trigger scrolling when it actually isn't
5777			// needed
5778			var holder = $('<div/>').css( scrollX || scrollY ?
5779					{
5780						position: 'absolute',
5781						top: 0,
5782						left: 0,
5783						height: 1,
5784						right: 0,
5785						overflow: 'hidden'
5786					} :
5787					{}
5788				)
5789				.append( tmpTable )
5790				.appendTo( tableContainer );
5791	
5792			// When scrolling (X or Y) we want to set the width of the table as 
5793			// appropriate. However, when not scrolling leave the table width as it
5794			// is. This results in slightly different, but I think correct behaviour
5795			if ( scrollX && scrollXInner ) {
5796				tmpTable.width( scrollXInner );
5797			}
5798			else if ( scrollX ) {
5799				tmpTable.css( 'width', 'auto' );
5800				tmpTable.removeAttr('width');
5801	
5802				// If there is no width attribute or style, then allow the table to
5803				// collapse
5804				if ( tmpTable.width() < tableContainer.clientWidth && tableWidthAttr ) {
5805					tmpTable.width( tableContainer.clientWidth );
5806				}
5807			}
5808			else if ( scrollY ) {
5809				tmpTable.width( tableContainer.clientWidth );
5810			}
5811			else if ( tableWidthAttr ) {
5812				tmpTable.width( tableWidthAttr );
5813			}
5814	
5815			// Get the width of each column in the constructed table - we need to
5816			// know the inner width (so it can be assigned to the other table's
5817			// cells) and the outer width so we can calculate the full width of the
5818			// table. This is safe since DataTables requires a unique cell for each
5819			// column, but if ever a header can span multiple columns, this will
5820			// need to be modified.
5821			var total = 0;
5822			for ( i=0 ; i<visibleColumns.length ; i++ ) {
5823				var cell = $(headerCells[i]);
5824				var border = cell.outerWidth() - cell.width();
5825	
5826				// Use getBounding... where possible (not IE8-) because it can give
5827				// sub-pixel accuracy, which we then want to round up!
5828				var bounding = browser.bBounding ?
5829					Math.ceil( headerCells[i].getBoundingClientRect().width ) :
5830					cell.outerWidth();
5831	
5832				// Total is tracked to remove any sub-pixel errors as the outerWidth
5833				// of the table might not equal the total given here (IE!).
5834				total += bounding;
5835	
5836				// Width for each column to use
5837				columns[ visibleColumns[i] ].sWidth = _fnStringToCss( bounding - border );
5838			}
5839	
5840			table.style.width = _fnStringToCss( total );
5841	
5842			// Finished with the table - ditch it
5843			holder.remove();
5844		}
5845	
5846		// If there is a width attr, we want to attach an event listener which
5847		// allows the table sizing to automatically adjust when the window is
5848		// resized. Use the width attr rather than CSS, since we can't know if the
5849		// CSS is a relative value or absolute - DOM read is always px.
5850		if ( tableWidthAttr ) {
5851			table.style.width = _fnStringToCss( tableWidthAttr );
5852		}
5853	
5854		if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) {
5855			var bindResize = function () {
5856				$(window).on('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {
5857					_fnAdjustColumnSizing( oSettings );
5858				} ) );
5859			};
5860	
5861			// IE6/7 will crash if we bind a resize event handler on page load.
5862			// To be removed in 1.11 which drops IE6/7 support
5863			if ( ie67 ) {
5864				setTimeout( bindResize, 1000 );
5865			}
5866			else {
5867				bindResize();
5868			}
5869	
5870			oSettings._reszEvt = true;
5871		}
5872	}
5873	
5874	
5875	/**
5876	 * Throttle the calls to a function. Arguments and context are maintained for
5877	 * the throttled function
5878	 *  @param {function} fn Function to be called
5879	 *  @param {int} [freq=200] call frequency in mS
5880	 *  @returns {function} wrapped function
5881	 *  @memberof DataTable#oApi
5882	 */
5883	var _fnThrottle = DataTable.util.throttle;
5884	
5885	
5886	/**
5887	 * Convert a 
5887set of CSS units width to pixels (e.g. 2em)
5888	 *  @param {string[]} widths widths to be converted
5889	 *  @param {node} parent parent to get the with for (required for relative widths) - optional
5890	 *  @returns {int[]} widths in pixels
5891	 *  @memberof DataTable#oApi
5892	 */
5893	function _fnConvertToWidth ( widths, parent )
5894	{
5895		var els = [];
5896		var results = [];
5897	
5898		// Add the elements in a single loop so we only need to reflow once
5899		for (var i=0 ; i<widths.length ; i++) {
5900			if (widths[i]) {
5901				els.push(
5902					$('<div/>')
5903						.css( 'width', _fnStringToCss( widths[i] ) )
5904						.appendTo( parent || document.body )
5905				)
5906			}
5907			else {
5908				els.push(null);
5909			}
5910		}
5911	
5912		// Get the sizes (will reflow once)
5913		for (var i=0 ; i<widths.length ; i++) {
5914			results.push(els[i] ? els[i][0].offsetWidth : null);
5915		}
5916	
5917		// Tidy
5918		$(els).remove();
5919	
5920		return results
vendor: 19,949 bytes, lines 5920-6655
5920;
5921	}
5922	
5923	
5924	/**
5925	 * Get the widest node
5926	 *  @param {object} settings dataTables settings object
5927	 *  @param {int} colIdx column of interest
5928	 *  @returns {node} widest table node
5929	 *  @memberof DataTable#oApi
5930	 */
5931	function _fnGetWidestNode( settings, colIdx )
5932	{
5933		var idx = _fnGetMaxLenString( settings, colIdx );
5934		if ( idx < 0 ) {
5935			return null;
5936		}
5937	
5938		var data = settings.aoData[ idx ];
5939		return ! data.nTr ? // Might not have been created when deferred rendering
5940			$('<td/>').html( _fnGetCellData( settings, idx, colIdx, 'display' ) )[0] :
5941			data.anCells[ colIdx ];
5942	}
5943	
5944	
5945	/**
5946	 * Get the maximum strlen for each data column
5947	 *  @param {object} settings dataTables settings object
5948	 *  @param {int} colIdx column of interest
5949	 *  @returns {string} max string length for each column
5950	 *  @memberof DataTable#oApi
5951	 */
5952	function _fnGetMaxLenString( settings, colIdx )
5953	{
5954		var s, max=-1, maxIdx = -1;
5955	
5956		for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
5957			s = _fnGetCellData( settings, i, colIdx, 'display' )+'';
5958			s = s.replace( __re_html_remove, '' );
5959			s = s.replace( /&nbsp;/g, ' ' );
5960	
5961			if ( s.length > max ) {
5962				max = s.length;
5963				maxIdx = i;
5964			}
5965		}
5966	
5967		return maxIdx;
5968	}
5969	
5970	
5971	/**
5972	 * Append a CSS unit (only if required) to a string
5973	 *  @param {string} value to css-ify
5974	 *  @returns {string} value with css unit
5975	 *  @memberof DataTable#oApi
5976	 */
5977	function _fnStringToCss( s )
5978	{
5979		if ( s === null ) {
5980			return '0px';
5981		}
5982	
5983		if ( typeof s == 'number' ) {
5984			return s < 0 ?
5985				'0px' :
5986				s+'px';
5987		}
5988	
5989		// Check it has a unit character already
5990		return s.match(/\d$/) ?
5991			s+'px' :
5992			s;
5993	}
5994	
5995	
5996	
5997	function _fnSortFlatten ( settings )
5998	{
5999		var
6000			i, iLen, k, kLen,
6001			aSort = [],
6002			aiOrig = [],
6003			aoColumns = settings.aoColumns,
6004			aDataSort, iCol, sType, srcCol,
6005			fixed = settings.aaSortingFixed,
6006			fixedObj = $.isPlainObject( fixed ),
6007			nestedSort = [],
6008			add = function ( a ) {
6009				if ( a.length && ! Array.isArray( a[0] ) ) {
6010					// 1D array
6011					nestedSort.push( a );
6012				}
6013				else {
6014					// 2D array
6015					$.merge( nestedSort, a );
6016				}
6017			};
6018	
6019		// Build the sort array, with pre-fix and post-fix options if they have been
6020		// specified
6021		if ( Array.isArray( fixed ) ) {
6022			add( fixed );
6023		}
6024	
6025		if ( fixedObj && fixed.pre ) {
6026			add( fixed.pre );
6027		}
6028	
6029		add( settings.aaSorting );
6030	
6031		if (fixedObj && fixed.post ) {
6032			add( fixed.post );
6033		}
6034	
6035		for ( i=0 ; i<nestedSort.length ; i++ )
6036		{
6037			srcCol = nestedSort[i][0];
6038			aDataSort = aoColumns[ srcCol ].aDataSort;
6039	
6040			for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ )
6041			{
6042				iCol = aDataSort[k];
6043				sType = aoColumns[ iCol ].sType || 'string';
6044	
6045				if ( nestedSort[i]._idx === undefined ) {
6046					nestedSort[i]._idx = $.inArray( nestedSort[i][1], aoColumns[iCol].asSorting );
6047				}
6048	
6049				aSort.push( {
6050					src:       srcCol,
6051					col:       iCol,
6052					dir:       nestedSort[i][1],
6053					index:     nestedSort[i]._idx,
6054					type:      sType,
6055					formatter: DataTable.ext.type.order[ sType+"-pre" ]
6056				} );
6057			}
6058		}
6059	
6060		return aSort;
6061	}
6062	
6063	/**
6064	 * Change the order of the table
6065	 *  @param {object} oSettings dataTables settings object
6066	 *  @memberof DataTable#oApi
6067	 *  @todo This really needs split up!
6068	 */
6069	function _fnSort ( oSettings )
6070	{
6071		var
6072			i, ien, iLen, j, jLen, k, kLen,
6073			sDataType, nTh,
6074			aiOrig = [],
6075			oExtSort = DataTable.ext.type.order,
6076			aoData = oSettings.aoData,
6077			aoColumns = oSettings.aoColumns,
6078			aDataSort, data, iCol, sType, oSort,
6079			formatters = 0,
6080			sortCol,
6081			displayMaster = oSettings.aiDisplayMaster,
6082			aSort;
6083	
6084		// Resolve any column types that are unknown due to addition or invalidation
6085		// @todo Can this be moved into a 'data-ready' handler which is called when
6086		//   data is going to be used in the table?
6087		_fnColumnTypes( oSettings );
6088	
6089		aSort = _fnSortFlatten( oSettings );
6090	
6091		for ( i=0, ien=aSort.length ; i<ien ; i++ ) {
6092			sortCol = aSort[i];
6093	
6094			// Track if we can use the fast sort algorithm
6095			if ( sortCol.formatter ) {
6096				formatters++;
6097			}
6098	
6099			// Load the data needed for the sort, for each cell
6100			_fnSortData( oSettings, sortCol.col );
6101		}
6102	
6103		/* No sorting required if server-side or no sorting array */
6104		if ( _fnDataSource( oSettings ) != 'ssp' && aSort.length !== 0 )
6105		{
6106			// Create a value - key array of the current row positions such that we can use their
6107			// current position during the sort, if values match, in order to perform stable sorting
6108			for ( i=0, iLen=displayMaster.length ; i<iLen ; i++ ) {
6109				aiOrig[ displayMaster[i] ] = i;
6110			}
6111	
6112			/* Do the sort - here we want multi-column sorting based on a given data source (column)
6113			 * and sorting function (from oSort) in a certain direction. It's reasonably complex to
6114			 * follow on it's own, but this is what we want (example two column sorting):
6115			 *  fnLocalSorting = function(a,b){
6116			 *    var iTest;
6117			 *    iTest = oSort['string-asc']('data11', 'data12');
6118			 *      if (iTest !== 0)
6119			 *        return iTest;
6120			 *    iTest = oSort['numeric-desc']('data21', 'data22');
6121			 *    if (iTest !== 0)
6122			 *      return iTest;
6123			 *    return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
6124			 *  }
6125			 * Basically we have a test for each sorting column, if the data in that column is equal,
6126			 * test the next column. If all columns match, then we use a numeric sort on the row
6127			 * positions in the original data array to provide a stable sort.
6128			 *
6129			 * Note - I know it seems excessive to have two sorting methods, but the first is around
6130			 * 15% faster, so the second is only maintained for backwards compatibility with sorting
6131			 * methods which do not have a pre-sort formatting function.
6132			 */
6133			if ( formatters === aSort.length ) {
6134				// All sort types have formatting functions
6135				displayMaster.sort( function ( a, b ) {
6136					var
6137						x, y, k, test, sort,
6138						len=aSort.length,
6139						dataA = aoData[a]._aSortData,
6140						dataB = aoData[b]._aSortData;
6141	
6142					for ( k=0 ; k<len ; k++ ) {
6143						sort = aSort[k];
6144	
6145						x = dataA[ sort.col ];
6146						y = dataB[ sort.col ];
6147	
6148						test = x<y ? -1 : x>y ? 1 : 0;
6149						if ( test !== 0 ) {
6150							return sort.dir === 'asc' ? test : -test;
6151						}
6152					}
6153	
6154					x = aiOrig[a];
6155					y = aiOrig[b];
6156					return x<y ? -1 : x>y ? 1 : 0;
6157				} );
6158			}
6159			else {
6160				// Depreciated - remove in 1.11 (providing a plug-in option)
6161				// Not all sort types have formatting methods, so we have to call their sorting
6162				// methods.
6163				displayMaster.sort( function ( a, b ) {
6164					var
6165						x, y, k, l, test, sort, fn,
6166						len=aSort.length,
6167						dataA = aoData[a]._aSortData,
6168						dataB = aoData[b]._aSortData;
6169	
6170					for ( k=0 ; k<len ; k++ ) {
6171						sort = aSort[k];
6172	
6173						x = dataA[ sort.col ];
6174						y = dataB[ sort.col ];
6175	
6176						fn = oExtSort[ sort.type+"-"+sort.dir ] || oExtSort[ "string-"+sort.dir ];
6177						test = fn( x, y );
6178						if ( test !== 0 ) {
6179							return test;
6180						}
6181					}
6182	
6183					x = aiOrig[a];
6184					y = aiOrig[b];
6185					return x<y ? -1 : x>y ? 1 : 0;
6186				} );
6187			}
6188		}
6189	
6190		/* Tell the draw function that we have sorted the data */
6191		oSettings.bSorted = true;
6192	}
6193	
6194	
6195	function _fnSortAria ( settings )
6196	{
6197		var label;
6198		var nextSort;
6199		var columns = settings.aoColumns;
6200		var aSort = _fnSortFlatten( settings );
6201		var oAria = settings.oLanguage.oAria;
6202	
6203		// ARIA attributes - need to loop all columns, to update all (removing old
6204		// attributes as needed)
6205		for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
6206		{
6207			var col = columns[i];
6208			var asSorting = col.asSorting;
6209			var sTitle = col.ariaTitle || col.sTitle.replace( /<.*?>/g, "" );
6210			var th = col.nTh;
6211	
6212			// IE7 is throwing an error when setting these properties with jQuery's
6213			// attr() and removeAttr() methods...
6214			th.removeAttribute('aria-sort');
6215	
6216			/* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
6217			if ( col.bSortable ) {
6218				if ( aSort.length > 0 && aSort[0].col == i ) {
6219					th.setAttribute('aria-sort', aSort[0].dir=="asc" ? "ascending" : "descending" );
6220					nextSort = asSorting[ aSort[0].index+1 ] || asSorting[0];
6221				}
6222				else {
6223					nextSort = asSorting[0];
6224				}
6225	
6226				label = sTitle + ( nextSort === "asc" ?
6227					oAria.sSortAscending :
6228					oAria.sSortDescending
6229				);
6230			}
6231			else {
6232				label = sTitle;
6233			}
6234	
6235			th.setAttribute('aria-label', label);
6236		}
6237	}
6238	
6239	
6240	/**
6241	 * Function to run on user sort request
6242	 *  @param {object} settings dataTables settings object
6243	 *  @param {node} attachTo node to attach the handler to
6244	 *  @param {int} colIdx column sorting index
6245	 *  @param {boolean} [append=false] Append the requested sort to the existing
6246	 *    sort if true (i.e. multi-column sort)
6247	 *  @param {function} [callback] callback function
6248	 *  @memberof DataTable#oApi
6249	 */
6250	function _fnSortListener ( settings, colIdx, append, callback )
6251	{
6252		var col = settings.aoColumns[ colIdx ];
6253		var sorting = settings.aaSorting;
6254		var asSorting = col.asSorting;
6255		var nextSortIdx;
6256		var next = function ( a, overflow ) {
6257			var idx = a._idx;
6258			if ( idx === undefined ) {
6259				idx = $.inArray( a[1], asSorting );
6260			}
6261	
6262			return idx+1 < asSorting.length ?
6263				idx+1 :
6264				overflow ?
6265					null :
6266					0;
6267		};
6268	
6269		// Convert to 2D array if needed
6270		if ( typeof sorting[0] === 'number' ) {
6271			sorting = settings.aaSorting = [ sorting ];
6272		}
6273	
6274		// If appending the sort then we are multi-column sorting
6275		if ( append && settings.oFeatures.bSortMulti ) {
6276			// Are we already doing some kind of sort on this column?
6277			var sortIdx = $.inArray( colIdx, _pluck(sorting, '0') );
6278	
6279			if ( sortIdx !== -1 ) {
6280				// Yes, modify the sort
6281				nextSortIdx = next( sorting[sortIdx], true );
6282	
6283				if ( nextSortIdx === null && sorting.length === 1 ) {
6284					nextSortIdx = 0; // can't remove sorting completely
6285				}
6286	
6287				if ( nextSortIdx === null ) {
6288					sorting.splice( sortIdx, 1 );
6289				}
6290				else {
6291					sorting[sortIdx][1] = asSorting[ nextSortIdx ];
6292					sorting[sortIdx]._idx = nextSortIdx;
6293				}
6294			}
6295			else {
6296				// No sort on this column yet
6297				sorting.push( [ colIdx, asSorting[0], 0 ] );
6298				sorting[sorting.length-1]._idx = 0;
6299			}
6300		}
6301		else if ( sorting.length && sorting[0][0] == colIdx ) {
6302			// Single column - already sorting on this column, modify the sort
6303			nextSortIdx = next( sorting[0] );
6304	
6305			sorting.length = 1;
6306			sorting[0][1] = asSorting[ nextSortIdx ];
6307			sorting[0]._idx = nextSortIdx;
6308		}
6309		else {
6310			// Single column - sort only on this column
6311			sorting.length = 0;
6312			sorting.push( [ colIdx, asSorting[0] ] );
6313			sorting[0]._idx = 0;
6314		}
6315	
6316		// Run the sort by calling a full redraw
6317		_fnReDraw( settings );
6318	
6319		// callback used for async user interaction
6320		if ( typeof callback == 'function' ) {
6321			callback( settings );
6322		}
6323	}
6324	
6325	
6326	/**
6327	 * Attach a sort handler (click) to a node
6328	 *  @param {object} settings dataTables settings object
6329	 *  @param {node} attachTo node to attach the handler to
6330	 *  @param {int} colIdx column sorting index
6331	 *  @param {function} [callback] callback function
6332	 *  @memberof DataTable#oApi
6333	 */
6334	function _fnSortAttachListener ( settings, attachTo, colIdx, callback )
6335	{
6336		var col = settings.aoColumns[ colIdx ];
6337	
6338		_fnBindAction( attachTo, {}, function (e) {
6339			/* If the column is not sortable - don't to anything */
6340			if ( col.bSortable === false ) {
6341				return;
6342			}
6343	
6344			// If processing is enabled use a timeout to allow the processing
6345			// display to be shown - otherwise to it synchronously
6346			if ( settings.oFeatures.bProcessing ) {
6347				_fnProcessingDisplay( settings, true );
6348	
6349				setTimeout( function() {
6350					_fnSortListener( settings, colIdx, e.shiftKey, callback );
6351	
6352					// In server-side processing, the draw callback will remove the
6353					// processing display
6354					if ( _fnDataSource( settings ) !== 'ssp' ) {
6355						_fnProcessingDisplay( settings, false );
6356					}
6357				}, 0 );
6358			}
6359			else {
6360				_fnSortListener( settings, colIdx, e.shiftKey, callback );
6361			}
6362		} );
6363	}
6364	
6365	
6366	/**
6367	 * Set the sorting classes on table's body, Note: it is safe to call this function
6368	 * when bSort and bSortClasses are false
6369	 *  @param {object} oSettings dataTables settings object
6370	 *  @memberof DataTable#oApi
6371	 */
6372	function _fnSortingClasses( settings )
6373	{
6374		var oldSort = settings.aLastSort;
6375		var sortClass = settings.oClasses.sSortColumn;
6376		var sort = _fnSortFlatten( settings );
6377		var features = settings.oFeatures;
6378		var i, ien, colIdx;
6379	
6380		if ( features.bSort && features.bSortClasses ) {
6381			// Remove old sorting classes
6382			for ( i=0, ien=oldSort.length ; i<ien ; i++ ) {
6383				colIdx = oldSort[i].src;
6384	
6385				// Remove column sorting
6386				$( _pluck( settings.aoData, 'anCells', colIdx ) )
6387					.removeClass( sortClass + (i<2 ? i+1 : 3) );
6388			}
6389	
6390			// Add new column sorting
6391			for ( i=0, ien=sort.length ; i<ien ; i++ ) {
6392				colIdx = sort[i].src;
6393	
6394				$( _pluck( settings.aoData, 'anCells', colIdx ) )
6395					.addClass( sortClass + (i<2 ? i+1 : 3) );
6396			}
6397		}
6398	
6399		settings.aLastSort = sort;
6400	}
6401	
6402	
6403	// Get the data to sort a column, be it from cache, fresh (populating the
6404	// cache), or from a sort formatter
6405	function _fnSortData( settings, idx )
6406	{
6407		// Custom sorting function - provided by the sort data type
6408		var column = settings.aoColumns[ idx ];
6409		var customSort = DataTable.ext.order[ column.sSortDataType ];
6410		var customData;
6411	
6412		if ( customSort ) {
6413			customData = customSort.call( settings.oInstance, settings, idx,
6414				_fnColumnIndexToVisible( settings, idx )
6415			);
6416		}
6417	
6418		// Use / populate cache
6419		var row, cellData;
6420		var formatter = DataTable.ext.type.order[ column.sType+"-pre" ];
6421	
6422		for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
6423			row = settings.aoData[i];
6424	
6425			if ( ! row._aSortData ) {
6426				row._aSortData = [];
6427			}
6428	
6429			if ( ! row._aSortData[idx] || customSort ) {
6430				cellData = customSort ?
6431					customData[i] : // If there was a custom sort function, use data from there
6432					_fnGetCellData( settings, i, idx, 'sort' );
6433	
6434				row._aSortData[ idx ] = formatter ?
6435					formatter( cellData ) :
6436					cellData;
6437			}
6438		}
6439	}
6440	
6441	
6442	
6443	/**
6444	 * Save the state of a table
6445	 *  @param {object} oSettings dataTables settings object
6446	 *  @memberof DataTable#oApi
6447	 */
6448	function _fnSaveState ( settings )
6449	{
6450		if (settings._bLoadingState) {
6451			return;
6452		}
6453	
6454		/* Store the interesting variables */
6455		var state = {
6456			time:    +new Date(),
6457			start:   settings._iDisplayStart,
6458			length:  settings._iDisplayLength,
6459			order:   $.extend( true, [], settings.aaSorting ),
6460			search:  _fnSearchToCamel( settings.oPreviousSearch ),
6461			columns: $.map( settings.aoColumns, function ( col, i ) {
6462				return {
6463					visible: col.bVisible,
6464					search: _fnSearchToCamel( settings.aoPreSearchCols[i] )
6465				};
6466			} )
6467		};
6468	
6469		settings.oSavedState = state;
6470		_fnCallbackFire( settings, "aoStateSaveParams", 'stateSaveParams', [settings, state] );
6471		
6472		if ( settings.oFeatures.bStateSave && !settings.bDestroying )
6473		{
6474			settings.fnStateSaveCallback.call( settings.oInstance, settings, state );
6475		}	
6476	}
6477	
6478	
6479	/**
6480	 * Attempt to load a saved table state
6481	 *  @param {object} oSettings dataTables settings object
6482	 *  @param {object} oInit DataTables init object so we can override settings
6483	 *  @param {function} callback Callback to execute when the state has been loaded
6484	 *  @memberof DataTable#oApi
6485	 */
6486	function _fnLoadState ( settings, oInit, callback )
6487	{
6488		if ( ! settings.oFeatures.bStateSave ) {
6489			callback();
6490			return;
6491		}
6492	
6493		var loaded = function(state) {
6494			_fnImplementState(settings, state, callback);
6495		}
6496	
6497		var state = settings.fnStateLoadCallback.call( settings.oInstance, settings, loaded );
6498	
6499		if ( state !== undefined ) {
6500			_fnImplementState( settings, state, callback );
6501		}
6502		// otherwise, wait for the loaded callback to be executed
6503	
6504		return true;
6505	}
6506	
6507	function _fnImplementState ( settings, s, callback) {
6508		var i, ien;
6509		var columns = settings.aoColumns;
6510		settings._bLoadingState = true;
6511	
6512		// When StateRestore was introduced the state could now be implemented at any time
6513		// Not just initialisation. To do this an api instance is required in some places
6514		var api = settings._bInitComplete ? new DataTable.Api(settings) : null;
6515	
6516		if ( ! s || ! s.time ) {
6517			settings._bLoadingState = false;
6518			callback();
6519			return;
6520		}
6521	
6522		// Allow custom and plug-in manipulation functions to alter the saved data set and
6523		// cancelling of loading by returning false
6524		var abStateLoad = _fnCallbackFire( settings, 'aoStateLoadParams', 'stateLoadParams', [settings, s] );
6525		if ( $.inArray( false, abStateLoad ) !== -1 ) {
6526			settings._bLoadingState = false;
6527			callback();
6528			return;
6529		}
6530	
6531		// Reject old data
6532		var duration = settings.iStateDuration;
6533		if ( duration > 0 && s.time < +new Date() - (duration*1000) ) {
6534			settings._bLoadingState = false;
6535			callback();
6536			return;
6537		}
6538	
6539		// Number of columns have changed - all bets are off, no restore of settings
6540		if ( s.columns && columns.length !== s.columns.length ) {
6541			settings._bLoadingState = false;
6542			callback();
6543			return;
6544		}
6545	
6546		// Store the saved state so it might be accessed at any time
6547		settings.oLoadedState = $.extend( true, {}, s );
6548	
6549		// Page Length
6550		if ( s.length !== undefined ) {
6551			// If already initialised just set the value directly so that the select element is also updated
6552			if (api) {
6553				api.page.len(s.length)
6554			}
6555			else {
6556				settings._iDisplayLength   = s.length;
6557			}
6558		}
6559	
6560		// Restore key features - todo - for 1.11 this needs to be done by
6561		// subscribed events
6562		if ( s.start !== undefined ) {
6563			if(api === null) {
6564				settings._iDisplayStart    = s.start;
6565				settings.iInitDisplayStart = s.start;
6566			}
6567			else {
6568				_fnPageChange(settings, s.start/settings._iDisplayLength);
6569			}
6570		}
6571	
6572		// Order
6573		if ( s.order !== undefined ) {
6574			settings.aaSorting = [];
6575			$.each( s.order, function ( i, col ) {
6576				settings.aaSorting.push( col[0] >= columns.length ?
6577					[ 0, col[1] ] :
6578					col
6579				);
6580			} );
6581		}
6582	
6583		// Search
6584		if ( s.search !== undefined ) {
6585			$.extend( settings.oPreviousSearch, _fnSearchToHung( s.search ) );
6586		}
6587	
6588		// Columns
6589		if ( s.columns ) {
6590			for ( i=0, ien=s.columns.length ; i<ien ; i++ ) {
6591				var col = s.columns[i];
6592	
6593				// Visibility
6594				if ( col.visible !== undefined ) {
6595					// If the api is defined, the table has been initialised so we need to use it rather than internal settings
6596					if (api) {
6597						// Don't redraw the columns on every iteration of this loop, we will do this at the end instead
6598						api.column(i).visible(col.visible, false);
6599					}
6600					else {
6601						columns[i].bVisible = col.visible;
6602					}
6603				}
6604	
6605				// Search
6606				if ( col.search !== undefined ) {
6607					$.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) );
6608				}
6609			}
6610			
6611			// If the api is defined then we need to adjust the columns once the visibility has been changed
6612			if (api) {
6613				api.columns.adjust();
6614			}
6615		}
6616	
6617		settings._bLoadingState = false;
6618		_fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, s] );
6619		callback();
6620	};
6621	
6622	
6623	/**
6624	 * Return the settings object for a particular table
6625	 *  @param {node} table table we are using as a dataTable
6626	 *  @returns {object} Settings object - or null if not found
6627	 *  @memberof DataTable#oApi
6628	 */
6629	function _fnSettingsFromNode ( table )
6630	{
6631		var settings = DataTable.settings;
6632		var idx = $.inArray( table, _pluck( settings, 'nTable' ) );
6633	
6634		return idx !== -1 ?
6635			settings[ idx ] :
6636			null;
6637	}
6638	
6639	
6640	/**
6641	 * Log an error message
6642	 *  @param {object} settings dataTables settings object
6643	 *  @param {int} level log error messages, or display them to the user
6644	 *  @param {string} msg error message
6645	 *  @param {int} tn Technical note id to get more information about the error.
6646	 *  @memberof DataTable#oApi
6647	 */
6648	function _fnLog( settings, level, msg, tn )
6649	{
6650		msg = 'DataTables warning: '+
6651			(settings ? 'table id='+settings.sTableId+' - ' : '')+msg;
6652	
6653		if ( tn ) {
6654			msg += '. For more information about this error, please see '+
6655			'http
6655s
vendor: 50,097 bytes, lines 6655-8586
6655://datatables.net/tn/'+tn;
6656		}
6657	
6658		if ( ! level  ) {
6659			// Backwards compatibility pre 1.10
6660			var ext = DataTable.ext;
6661			var type = ext.sErrMode || ext.errMode;
6662	
6663			if ( settings ) {
6664				_fnCallbackFire( settings, null, 'error', [ settings, tn, msg ] );
6665			}
6666	
6667			if ( type == 'alert' ) {
6668				alert( msg );
6669			}
6670			else if ( type == 'throw' ) {
6671				throw new Error(msg);
6672			}
6673			else if ( typeof type == 'function' ) {
6674				type( settings, tn, msg );
6675			}
6676		}
6677		else if ( window.console && console.log ) {
6678			console.log( msg );
6679		}
6680	}
6681	
6682	
6683	/**
6684	 * See if a property is defined on one object, if so assign it to the other object
6685	 *  @param {object} ret target object
6686	 *  @param {object} src source object
6687	 *  @param {string} name property
6688	 *  @param {string} [mappedName] name to map too - optional, name used if not given
6689	 *  @memberof DataTable#oApi
6690	 */
6691	function _fnMap( ret, src, name, mappedName )
6692	{
6693		if ( Array.isArray( name ) ) {
6694			$.each( name, function (i, val) {
6695				if ( Array.isArray( val ) ) {
6696					_fnMap( ret, src, val[0], val[1] );
6697				}
6698				else {
6699					_fnMap( ret, src, val );
6700				}
6701			} );
6702	
6703			return;
6704		}
6705	
6706		if ( mappedName === undefined ) {
6707			mappedName = name;
6708		}
6709	
6710		if ( src[name] !== undefined ) {
6711			ret[mappedName] = src[name];
6712		}
6713	}
6714	
6715	
6716	/**
6717	 * Extend objects - very similar to jQuery.extend, but deep copy objects, and
6718	 * shallow copy arrays. The reason we need to do this, is that we don't want to
6719	 * deep copy array init values (such as aaSorting) since the dev wouldn't be
6720	 * able to override them, but we do want to deep copy arrays.
6721	 *  @param {object} out Object to extend
6722	 *  @param {object} extender Object from which the properties will be applied to
6723	 *      out
6724	 *  @param {boolean} breakRefs If true, then arrays will be sliced to take an
6725	 *      independent copy with the exception of the `data` or `aaData` parameters
6726	 *      if they are present. This is so you can pass in a collection to
6727	 *      DataTables and have that used as your data source without breaking the
6728	 *      references
6729	 *  @returns {object} out Reference, just for convenience - out === the return.
6730	 *  @memberof DataTable#oApi
6731	 *  @todo This doesn't take account of arrays inside the deep copied objects.
6732	 */
6733	function _fnExtend( out, extender, breakRefs )
6734	{
6735		var val;
6736	
6737		for ( var prop in extender ) {
6738			if ( extender.hasOwnProperty(prop) ) {
6739				val = extender[prop];
6740	
6741				if ( $.isPlainObject( val ) ) {
6742					if ( ! $.isPlainObject( out[prop] ) ) {
6743						out[prop] = {};
6744					}
6745					$.extend( true, out[prop], val );
6746				}
6747				else if ( breakRefs && prop !== 'data' && prop !== 'aaData' && Array.isArray(val) ) {
6748					out[prop] = val.slice();
6749				}
6750				else {
6751					out[prop] = val;
6752				}
6753			}
6754		}
6755	
6756		return out;
6757	}
6758	
6759	
6760	/**
6761	 * Bind an event handers to allow a click or return key to activate the callback.
6762	 * This is good for accessibility since a return on the keyboard will have the
6763	 * same effect as a click, if the element has focus.
6764	 *  @param {element} n Element to bind the action to
6765	 *  @param {object} oData Data object to pass to the triggered function
6766	 *  @param {function} fn Callback function for when the event is triggered
6767	 *  @memberof DataTable#oApi
6768	 */
6769	function _fnBindAction( n, oData, fn )
6770	{
6771		$(n)
6772			.on( 'click.DT', oData, function (e) {
6773					$(n).trigger('blur'); // Remove focus outline for mouse users
6774					fn(e);
6775				} )
6776			.on( 'keypress.DT', oData, function (e){
6777					if ( e.which === 13 ) {
6778						e.preventDefault();
6779						fn(e);
6780					}
6781				} )
6782			.on( 'selectstart.DT', function () {
6783					/* Take the brutal approach to cancelling text selection */
6784					return false;
6785				} );
6786	}
6787	
6788	
6789	/**
6790	 * Register a callback function. Easily allows a callback function to be added to
6791	 * an array store of callback functions that can then all be called together.
6792	 *  @param {object} oSettings dataTables settings object
6793	 *  @param {string} sStore Name of the array storage for the callbacks in oSettings
6794	 *  @param {function} fn Function to be called back
6795	 *  @param {string} sName Identifying name for the callback (i.e. a label)
6796	 *  @memberof DataTable#oApi
6797	 */
6798	function _fnCallbackReg( oSettings, sStore, fn, sName )
6799	{
6800		if ( fn )
6801		{
6802			oSettings[sStore].push( {
6803				"fn": fn,
6804				"sName": sName
6805			} );
6806		}
6807	}
6808	
6809	
6810	/**
6811	 * Fire callback functions and trigger events. Note that the loop over the
6812	 * callback array store is done backwards! Further note that you do not want to
6813	 * fire off triggers in time sensitive applications (for example cell creation)
6814	 * as its slow.
6815	 *  @param {object} settings dataTables settings object
6816	 *  @param {string} callbackArr Name of the array storage for the callbacks in
6817	 *      oSettings
6818	 *  @param {string} eventName Name of the jQuery custom event to trigger. If
6819	 *      null no trigger is fired
6820	 *  @param {array} args Array of arguments to pass to the callback function /
6821	 *      trigger
6822	 *  @memberof DataTable#oApi
6823	 */
6824	function _fnCallbackFire( settings, callbackArr, eventName, args )
6825	{
6826		var ret = [];
6827	
6828		if ( callbackArr ) {
6829			ret = $.map( settings[callbackArr].slice().reverse(), function (val, i) {
6830				return val.fn.apply( settings.oInstance, args );
6831			} );
6832		}
6833	
6834		if ( eventName !== null ) {
6835			var e = $.Event( eventName+'.dt' );
6836			var table = $(settings.nTable);
6837	
6838			table.trigger( e, args );
6839	
6840			// If not yet attached to the document, trigger the event
6841			// on the body directly to sort of simulate the bubble
6842			if (table.parents('body').length === 0) {
6843				$('body').trigger( e, args );
6844			}
6845	
6846			ret.push( e.result );
6847		}
6848	
6849		return ret;
6850	}
6851	
6852	
6853	function _fnLengthOverflow ( settings )
6854	{
6855		var
6856			start = settings._iDisplayStart,
6857			end = settings.fnDisplayEnd(),
6858			len = settings._iDisplayLength;
6859	
6860		/* If we have space to show extra rows (backing up from the end point - then do so */
6861		if ( start >= end )
6862		{
6863			start = end - len;
6864		}
6865	
6866		// Keep the start record on the current page
6867		start -= (start % len);
6868	
6869		if ( len === -1 || start < 0 )
6870		{
6871			start = 0;
6872		}
6873	
6874		settings._iDisplayStart = start;
6875	}
6876	
6877	
6878	function _fnRenderer( settings, type )
6879	{
6880		var renderer = settings.renderer;
6881		var host = DataTable.ext.renderer[type];
6882	
6883		if ( $.isPlainObject( renderer ) && renderer[type] ) {
6884			// Specific renderer for this type. If available use it, otherwise use
6885			// the default.
6886			return host[renderer[type]] || host._;
6887		}
6888		else if ( typeof renderer === 'string' ) {
6889			// Common renderer - if there is one available for this type use it,
6890			// otherwise use the default
6891			return host[renderer] || host._;
6892		}
6893	
6894		// Use the default
6895		return host._;
6896	}
6897	
6898	
6899	/**
6900	 * Detect the data source being used for the table. Used to simplify the code
6901	 * a little (ajax) and to make it compress a little smaller.
6902	 *
6903	 *  @param {object} settings dataTables settings object
6904	 *  @returns {string} Data source
6905	 *  @memberof DataTable#oApi
6906	 */
6907	function _fnDataSource ( settings )
6908	{
6909		if ( settings.oFeatures.bServerSide ) {
6910			return 'ssp';
6911		}
6912		else if ( settings.ajax || settings.sAjaxSource ) {
6913			return 'ajax';
6914		}
6915		return 'dom';
6916	}
6917	
6918	
6919	
6920	
6921	/**
6922	 * Computed structure of the DataTables API, defined by the options passed to
6923	 * `DataTable.Api.register()` when building the API.
6924	 *
6925	 * The structure is built in order to speed creation and extension of the Api
6926	 * objects since the extensions are effectively pre-parsed.
6927	 *
6928	 * The array is an array of objects with the following structure, where this
6929	 * base array represents the Api prototype base:
6930	 *
6931	 *     [
6932	 *       {
6933	 *         name:      'data'                -- string   - Property name
6934	 *         val:       function () {},       -- function - Api method (or undefined if just an object
6935	 *         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
6936	 *         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
6937	 *       },
6938	 *       {
6939	 *         name:     'row'
6940	 *         val:       {},
6941	 *         methodExt: [ ... ],
6942	 *         propExt:   [
6943	 *           {
6944	 *             name:      'data'
6945	 *             val:       function () {},
6946	 *             methodExt: [ ... ],
6947	 *             propExt:   [ ... ]
6948	 *           },
6949	 *           ...
6950	 *         ]
6951	 *       }
6952	 *     ]
6953	 *
6954	 * @type {Array}
6955	 * @ignore
6956	 */
6957	var __apiStruct = [];
6958	
6959	
6960	/**
6961	 * `Array.prototype` reference.
6962	 *
6963	 * @type object
6964	 * @ignore
6965	 */
6966	var __arrayProto = Array.prototype;
6967	
6968	
6969	/**
6970	 * Abstraction for `context` parameter of the `Api` constructor to allow it to
6971	 * take several different forms for ease of use.
6972	 *
6973	 * Each of the input parameter types will be converted to a DataTables settings
6974	 * object where possible.
6975	 *
6976	 * @param  {string|node|jQuery|object} mixed DataTable identifier. Can be one
6977	 *   of:
6978	 *
6979	 *   * `string` - jQuery selector. Any DataTables' matching the given selector
6980	 *     with be found and used.
6981	 *   * `node` - `TABLE` node which has already been formed into a DataTable.
6982	 *   * `jQuery` - A jQuery object of `TABLE` nodes.
6983	 *   * `object` - DataTables settings object
6984	 *   * `DataTables.Api` - API instance
6985	 * @return {array|null} Matching DataTables settings objects. `null` or
6986	 *   `undefined` is returned if no matching DataTable is found.
6987	 * @ignore
6988	 */
6989	var _toSettings = function ( mixed )
6990	{
6991		var idx, jq;
6992		var settings = DataTable.settings;
6993		var tables = $.map( settings, function (el, i) {
6994			return el.nTable;
6995		} );
6996	
6997		if ( ! mixed ) {
6998			return [];
6999		}
7000		else if ( mixed.nTable && mixed.oApi ) {
7001			// DataTables settings object
7002			return [ mixed ];
7003		}
7004		else if ( mixed.nodeName && mixed.nodeName.toLowerCase() === 'table' ) {
7005			// Table node
7006			idx = $.inArray( mixed, tables );
7007			return idx !== -1 ? [ settings[idx] ] : null;
7008		}
7009		else if ( mixed && typeof mixed.settings === 'function' ) {
7010			return mixed.settings().toArray();
7011		}
7012		else if ( typeof mixed === 'string' ) {
7013			// jQuery selector
7014			jq = $(mixed);
7015		}
7016		else if ( mixed instanceof $ ) {
7017			// jQuery object (also DataTables instance)
7018			jq = mixed;
7019		}
7020	
7021		if ( jq ) {
7022			return jq.map( function(i) {
7023				idx = $.inArray( this, tables );
7024				return idx !== -1 ? settings[idx] : null;
7025			} ).toArray();
7026		}
7027	};
7028	
7029	
7030	/**
7031	 * DataTables API class - used to control and interface with  one or more
7032	 * DataTables enhanced tables.
7033	 *
7034	 * The API class is heavily based on jQuery, presenting a chainable interface
7035	 * that you can use to interact with tables. Each instance of the API class has
7036	 * a "context" - i.e. the tables that it will operate on. This could be a single
7037	 * table, all tables on a page or a sub-set thereof.
7038	 *
7039	 * Additionally the API is designed to allow you to easily work with the data in
7040	 * the tables, retrieving and manipulating it as required. This is done by
7041	 * presenting the API class as an array like interface. The contents of the
7042	 * array depend upon the actions requested by each method (for example
7043	 * `rows().nodes()` will return an array of nodes, while `rows().data()` will
7044	 * return an array of objects or arrays depending upon your table's
7045	 * configuration). The API object has a number of array like methods (`push`,
7046	 * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`,
7047	 * `unique` etc) to assist your working with the data held in a table.
7048	 *
7049	 * Most methods (those which return an Api instance) are chainable, which means
7050	 * the return from a method call also has all of the methods available that the
7051	 * top level object had. For example, these two calls are equivalent:
7052	 *
7053	 *     // Not chained
7054	 *     api.row.add( {...} );
7055	 *     api.draw();
7056	 *
7057	 *     // Chained
7058	 *     api.row.add( {...} ).draw();
7059	 *
7060	 * @class DataTable.Api
7061	 * @param {array|object|string|jQuery} context DataTable identifier. This is
7062	 *   used to define which DataTables enhanced tables this API will operate on.
7063	 *   Can be one of:
7064	 *
7065	 *   * `string` - jQuery selector. Any DataTables' matching the given selector
7066	 *     with be found and used.
7067	 *   * `node` - `TABLE` node which has already been formed into a DataTable.
7068	 *   * `jQuery` - A jQuery object of `TABLE` nodes.
7069	 *   * `object` - DataTables settings object
7070	 * @param {array} [data] Data to initialise the Api instance with.
7071	 *
7072	 * @example
7073	 *   // Direct initialisation during DataTables construction
7074	 *   var api = $('#example').DataTable();
7075	 *
7076	 * @example
7077	 *   // Initialisation using a DataTables jQuery object
7078	 *   var api = $('#example').dataTable().api();
7079	 *
7080	 * @example
7081	 *   // Initialisation as a constructor
7082	 *   var api = new $.fn.DataTable.Api( 'table.dataTable' );
7083	 */
7084	_Api = function ( context, data )
7085	{
7086		if ( ! (this instanceof _Api) ) {
7087			return new _Api( context, data );
7088		}
7089	
7090		var settings = [];
7091		var ctxSettings = function ( o ) {
7092			var a = _toSettings( o );
7093			if ( a ) {
7094				settings.push.apply( settings, a );
7095			}
7096		};
7097	
7098		if ( Array.isArray( context ) ) {
7099			for ( var i=0, ien=context.length ; i<ien ; i++ ) {
7100				ctxSettings( context[i] );
7101			}
7102		}
7103		else {
7104			ctxSettings( context );
7105		}
7106	
7107		// Remove duplicates
7108		this.context = _unique( settings );
7109	
7110		// Initial data
7111		if ( data ) {
7112			$.merge( this, data );
7113		}
7114	
7115		// selector
7116		this.selector = {
7117			rows: null,
7118			cols: null,
7119			opts: null
7120		};
7121	
7122		_Api.extend( this, this, __apiStruct );
7123	};
7124	
7125	DataTable.Api = _Api;
7126	
7127	// Don't destroy the existing prototype, just extend it. Required for jQuery 2's
7128	// isPlainObject.
7129	$.extend( _Api.prototype, {
7130		any: function ()
7131		{
7132			return this.count() !== 0;
7133		},
7134	
7135	
7136		concat:  __arrayProto.concat,
7137	
7138	
7139		context: [], // array of table settings objects
7140	
7141	
7142		count: function ()
7143		{
7144			return this.flatten().length;
7145		},
7146	
7147	
7148		each: function ( fn )
7149		{
7150			for ( var i=0, ien=this.length ; i<ien; i++ ) {
7151				fn.call( this, this[i], i, this );
7152			}
7153	
7154			return this;
7155		},
7156	
7157	
7158		eq: function ( idx )
7159		{
7160			var ctx = this.context;
7161	
7162			return ctx.length > idx ?
7163				new _Api( ctx[idx], this[idx] ) :
7164				null;
7165		},
7166	
7167	
7168		filter: function ( fn )
7169		{
7170			var a = [];
7171	
7172			if ( __arrayProto.filter ) {
7173				a = __arrayProto.filter.call( this, fn, this );
7174			}
7175			else {
7176				// Compatibility for browsers without EMCA-252-5 (JS 1.6)
7177				for ( var i=0, ien=this.length ; i<ien ; i++ ) {
7178					if ( fn.call( this, this[i], i, this ) ) {
7179						a.push( this[i] );
7180					}
7181				}
7182			}
7183	
7184			return new _Api( this.context, a );
7185		},
7186	
7187	
7188		flatten: function ()
7189		{
7190			var a = [];
7191			return new _Api( this.context, a.concat.apply( a, this.toArray() ) );
7192		},
7193	
7194	
7195		join:    __arrayProto.join,
7196	
7197	
7198		indexOf: __arrayProto.indexOf || function (obj, start)
7199		{
7200			for ( var i=(start || 0), ien=this.length ; i<ien ; i++ ) {
7201				if ( this[i] === obj ) {
7202					return i;
7203				}
7204			}
7205			return -1;
7206		},
7207	
7208		iterator: function ( flatten, type, fn, alwaysNew ) {
7209			var
7210				a = [], ret,
7211				i, ien, j, jen,
7212				context = this.context,
7213				rows, items, item,
7214				selector = this.selector;
7215	
7216			// Argument shifting
7217			if ( typeof flatten === 'string' ) {
7218				alwaysNew = fn;
7219				fn = type;
7220				type = flatten;
7221				flatten = false;
7222			}
7223	
7224			for ( i=0, ien=context.length ; i<ien ; i++ ) {
7225				var apiInst = new _Api( context[i] );
7226	
7227				if ( type === 'table' ) {
7228					ret = fn.call( apiInst, context[i], i );
7229	
7230					if ( ret !== undefined ) {
7231						a.push( ret );
7232					}
7233				}
7234				else if ( type === 'columns' || type === 'rows' ) {
7235					// this has same length as context - one entry for each table
7236					ret = fn.call( apiInst, context[i], this[i], i );
7237	
7238					if ( ret !== undefined ) {
7239						a.push( ret );
7240					}
7241				}
7242				else if ( type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell' ) {
7243					// columns and rows share the same structure.
7244					// 'this' is an array of column indexes for each context
7245					items = this[i];
7246	
7247					if ( type === 'column-rows' ) {
7248						rows = _selector_row_indexes( context[i], selector.opts );
7249					}
7250	
7251					for ( j=0, jen=items.length ; j<jen ; j++ ) {
7252						item = items[j];
7253	
7254						if ( type === 'cell' ) {
7255							ret = fn.call( apiInst, context[i], item.row, item.column, i, j );
7256						}
7257						else {
7258							ret = fn.call( apiInst, context[i], item, i, j, rows );
7259						}
7260	
7261						if ( ret !== undefined ) {
7262							a.push( ret );
7263						}
7264					}
7265				}
7266			}
7267	
7268			if ( a.length || alwaysNew ) {
7269				var api = new _Api( context, flatten ? a.concat.apply( [], a ) : a );
7270				var apiSelector = api.selector;
7271				apiSelector.rows = selector.rows;
7272				apiSelector.cols = selector.cols;
7273				apiSelector.opts = selector.opts;
7274				return api;
7275			}
7276			return this;
7277		},
7278	
7279	
7280		lastIndexOf: __arrayProto.lastIndexOf || function (obj, start)
7281		{
7282			// Bit cheeky...
7283			return this.indexOf.apply( this.toArray.reverse(), arguments );
7284		},
7285	
7286	
7287		length:  0,
7288	
7289	
7290		map: function ( fn )
7291		{
7292			var a = [];
7293	
7294			if ( __arrayProto.map ) {
7295				a = __arrayProto.map.call( this, fn, this );
7296			}
7297			else {
7298				// Compatibility for browsers without EMCA-252-5 (JS 1.6)
7299				for ( var i=0, ien=this.length ; i<ien ; i++ ) {
7300					a.push( fn.call( this, this[i], i ) );
7301				}
7302			}
7303	
7304			return new _Api( this.context, a );
7305		},
7306	
7307	
7308		pluck: function ( prop )
7309		{
7310			var fn = DataTable.util.get(prop);
7311	
7312			return this.map( function ( el ) {
7313				return fn(el);
7314			} );
7315		},
7316	
7317		pop:     __arrayProto.pop,
7318	
7319	
7320		push:    __arrayProto.push,
7321	
7322	
7323		// Does not return an API instance
7324		reduce: __arrayProto.reduce || function ( fn, init )
7325		{
7326			return _fnReduce( this, fn, init, 0, this.length, 1 );
7327		},
7328	
7329	
7330		reduceRight: __arrayProto.reduceRight || function ( fn, init )
7331		{
7332			return _fnReduce( this, fn, init, this.length-1, -1, -1 );
7333		},
7334	
7335	
7336		reverse: __arrayProto.reverse,
7337	
7338	
7339		// Object with rows, columns and opts
7340		selector: null,
7341	
7342	
7343		shift:   __arrayProto.shift,
7344	
7345	
7346		slice: function () {
7347			return new _Api( this.context, this );
7348		},
7349	
7350	
7351		sort:    __arrayProto.sort, // ? name - order?
7352	
7353	
7354		splice:  __arrayProto.splice,
7355	
7356	
7357		toArray: function ()
7358		{
7359			return __arrayProto.slice.call( this );
7360		},
7361	
7362	
7363		to$: function ()
7364		{
7365			return $( this );
7366		},
7367	
7368	
7369		toJQuery: function ()
7370		{
7371			return $( this );
7372		},
7373	
7374	
7375		unique: function ()
7376		{
7377			return new _Api( this.context, _unique(this) );
7378		},
7379	
7380	
7381		unshift: __arrayProto.unshift
7382	} );
7383	
7384	
7385	_Api.extend = function ( scope, obj, ext )
7386	{
7387		// Only extend API instances and static properties of the API
7388		if ( ! ext.length || ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) {
7389			return;
7390		}
7391	
7392		var
7393			i, ien,
7394			struct,
7395			methodScoping = function ( scope, fn, struc ) {
7396				return function () {
7397					var ret = fn.apply( scope, arguments );
7398	
7399					// Method extension
7400					_Api.extend( ret, ret, struc.methodExt );
7401					return ret;
7402				};
7403			};
7404	
7405		for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7406			struct = ext[i];
7407	
7408			// Value
7409			obj[ struct.name ] = struct.type === 'function' ?
7410				methodScoping( scope, struct.val, struct ) :
7411				struct.type === 'object' ?
7412					{} :
7413					struct.val;
7414	
7415			obj[ struct.name ].__dt_wrapper = true;
7416	
7417			// Property extension
7418			_Api.extend( scope, obj[ struct.name ], struct.propExt );
7419		}
7420	};
7421	
7422	
7423	// @todo - Is there need for an augment function?
7424	// _Api.augment = function ( inst, name )
7425	// {
7426	// 	// Find src object in the structure from the name
7427	// 	var parts = name.split('.');
7428	
7429	// 	_Api.extend( inst, obj );
7430	// };
7431	
7432	
7433	//     [
7434	//       {
7435	//         name:      'data'                -- string   - Property name
7436	//         val:       function () {},       -- function - Api method (or undefined if just an object
7437	//         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
7438	//         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
7439	//       },
7440	//       {
7441	//         name:     'row'
7442	//         val:       {},
7443	//         methodExt: [ ... ],
7444	//         propExt:   [
7445	//           {
7446	//             name:      'data'
7447	//             val:       function () {},
7448	//             methodExt: [ ... ],
7449	//             propExt:   [ ... ]
7450	//           },
7451	//           ...
7452	//         ]
7453	//       }
7454	//     ]
7455	
7456	_Api.register = _api_register = function ( name, val )
7457	{
7458		if ( Array.isArray( name ) ) {
7459			for ( var j=0, jen=name.length ; j<jen ; j++ ) {
7460				_Api.register( name[j], val );
7461			}
7462			return;
7463		}
7464	
7465		var
7466			i, ien,
7467			heir = name.split('.'),
7468			struct = __apiStruct,
7469			key, method;
7470	
7471		var find = function ( src, name ) {
7472			for ( var i=0, ien=src.length ; i<ien ; i++ ) {
7473				if ( src[i].name === name ) {
7474					return src[i];
7475				}
7476			}
7477			return null;
7478		};
7479	
7480		for ( i=0, ien=heir.length ; i<ien ; i++ ) {
7481			method = heir[i].indexOf('()') !== -1;
7482			key = method ?
7483				heir[i].replace('()', '') :
7484				heir[i];
7485	
7486			var src = find( struct, key );
7487			if ( ! src ) {
7488				src = {
7489					name:      key,
7490					val:       {},
7491					methodExt: [],
7492					propExt:   [],
7493					type:      'object'
7494				};
7495				struct.push( src );
7496			}
7497	
7498			if ( i === ien-1 ) {
7499				src.val = val;
7500				src.type = typeof val === 'function' ?
7501					'function' :
7502					$.isPlainObject( val ) ?
7503						'object' :
7504						'other';
7505			}
7506			else {
7507				struct = method ?
7508					src.methodExt :
7509					src.propExt;
7510			}
7511		}
7512	};
7513	
7514	_Api.registerPlural = _api_registerPlural = function ( pluralName, singularName, val ) {
7515		_Api.register( pluralName, val );
7516	
7517		_Api.register( singularName, function () {
7518			var ret = val.apply( this, arguments );
7519	
7520			if ( ret === this ) {
7521				// Returned item is the API instance that was passed in, return it
7522				return this;
7523			}
7524			else if ( ret instanceof _Api ) {
7525				// New API instance returned, want the value from the first item
7526				// in the returned array for the singular result.
7527				return ret.length ?
7528					Array.isArray( ret[0] ) ?
7529						new _Api( ret.context, ret[0] ) : // Array results are 'enhanced'
7530						ret[0] :
7531					undefined;
7532			}
7533	
7534			// Non-API return - just fire it back
7535			return ret;
7536		} );
7537	};
7538	
7539	
7540	/**
7541	 * Selector for HTML tables. Apply the given selector to the give array of
7542	 * DataTables settings objects.
7543	 *
7544	 * @param {string|integer} [selector] jQuery selector string or integer
7545	 * @param  {array} Array of DataTables settings objects to be filtered
7546	 * @return {array}
7547	 * @ignore
7548	 */
7549	var __table_selector = function ( selector, a )
7550	{
7551		if ( Array.isArray(selector) ) {
7552			return $.map( selector, function (item) {
7553				return __table_selector(item, a);
7554			} );
7555		}
7556	
7557		// Integer is used to pick out a table by index
7558		if ( typeof selector === 'number' ) {
7559			return [ a[ selector ] ];
7560		}
7561	
7562		// Perform a jQuery selector on the table nodes
7563		var nodes = $.map( a, function (el, i) {
7564			return el.nTable;
7565		} );
7566	
7567		return $(nodes)
7568			.filter( selector )
7569			.map( function (i) {
7570				// Need to translate back from the table node to the settings
7571				var idx = $.inArray( this, nodes );
7572				return a[ idx ];
7573			} )
7574			.toArray();
7575	};
7576	
7577	
7578	
7579	/**
7580	 * Context selector for the API's context (i.e. the tables the API instance
7581	 * refers to.
7582	 *
7583	 * @name    DataTable.Api#tables
7584	 * @param {string|integer} [selector] Selector to pick which tables the iterator
7585	 *   should operate on. If not given, all tables in the current context are
7586	 *   used. This can be given as a jQuery selector (for example `':gt(0)'`) to
7587	 *   select multiple tables or as an integer to select a single table.
7588	 * @returns {DataTable.Api} Returns a new API instance if a selector is given.
7589	 */
7590	_api_register( 'tables()', function ( selector ) {
7591		// A new instance is created if there was a selector specified
7592		return selector !== undefined && selector !== null ?
7593			new _Api( __table_selector( selector, this.context ) ) :
7594			this;
7595	} );
7596	
7597	
7598	_api_register( 'table()', function ( selector ) {
7599		var tables = this.tables( selector );
7600		var ctx = tables.context;
7601	
7602		// Truncate to the first matched table
7603		return ctx.length ?
7604			new _Api( ctx[0] ) :
7605			tables;
7606	} );
7607	
7608	
7609	_api_registerPlural( 'tables().nodes()', 'table().node()' , function () {
7610		return this.iterator( 'table', function ( ctx ) {
7611			return ctx.nTable;
7612		}, 1 );
7613	} );
7614	
7615	
7616	_api_registerPlural( 'tables().body()', 'table().body()' , function () {
7617		return this.iterator( 'table', function ( ctx ) {
7618			return ctx.nTBody;
7619		}, 1 );
7620	} );
7621	
7622	
7623	_api_registerPlural( 'tables().header()', 'table().header()' , function () {
7624		return this.iterator( 'table', function ( ctx ) {
7625			return ctx.nTHead;
7626		}, 1 );
7627	} );
7628	
7629	
7630	_api_registerPlural( 'tables().footer()', 'table().footer()' , function () {
7631		return this.iterator( 'table', function ( ctx ) {
7632			return ctx.nTFoot;
7633		}, 1 );
7634	} );
7635	
7636	
7637	_api_registerPlural( 'tables().containers()', 'table().container()' , function () {
7638		return this.iterator( 'table', function ( ctx ) {
7639			return ctx.nTableWrapper;
7640		}, 1 );
7641	} );
7642	
7643	
7644	
7645	/**
7646	 * Redraw the tables in the current context.
7647	 */
7648	_api_register( 'draw()', function ( paging ) {
7649		return this.iterator( 'table', function ( settings ) {
7650			if ( paging === 'page' ) {
7651				_fnDraw( settings );
7652			}
7653			else {
7654				if ( typeof paging === 'string' ) {
7655					paging = paging === 'full-hold' ?
7656						false :
7657						true;
7658				}
7659	
7660				_fnReDraw( settings, paging===false );
7661			}
7662		} );
7663	} );
7664	
7665	
7666	
7667	/**
7668	 * Get the current page index.
7669	 *
7670	 * @return {integer} Current page index (zero based)
7671	 *//**
7672	 * Set the current page.
7673	 *
7674	 * Note that if you attempt to show a page which does not exist, DataTables will
7675	 * not throw an error, but rather reset the paging.
7676	 *
7677	 * @param {integer|string} action The paging action to take. This can be one of:
7678	 *  * `integer` - The page index to jump to
7679	 *  * `string` - An action to take:
7680	 *    * `first` - Jump to first page.
7681	 *    * `next` - Jump to the next page
7682	 *    * `previous` - Jump to previous page
7683	 *    * `last` - Jump to the last page.
7684	 * @returns {DataTables.Api} this
7685	 */
7686	_api_register( 'page()', function ( action ) {
7687		if ( action === undefined ) {
7688			return this.page.info().page; // not an expensive call
7689		}
7690	
7691		// else, have an action to take on all tables
7692		return this.iterator( 'table', function ( settings ) {
7693			_fnPageChange( settings, action );
7694		} );
7695	} );
7696	
7697	
7698	/**
7699	 * Paging information for the first table in the current context.
7700	 *
7701	 * If you require paging information for another table, use the `table()` method
7702	 * with a suitable selector.
7703	 *
7704	 * @return {object} Object with the following properties set:
7705	 *  * `page` - Current page index (zero based - i.e. the first page is `0`)
7706	 *  * `pages` - Total number of pages
7707	 *  * `start` - Display index for the first record shown on the current page
7708	 *  * `end` - Display index for the last record shown on the current page
7709	 *  * `length` - Display length (number of records). Note that generally `start
7710	 *    + length = end`, but this is not always true, for example if there are
7711	 *    only 2 records to show on the final page, with a length of 10.
7712	 *  * `recordsTotal` - Full data set length
7713	 *  * `recordsDisplay` - Data set length once the current filtering criterion
7714	 *    are applied.
7715	 */
7716	_api_register( 'page.info()', function ( action ) {
7717		if ( this.context.length === 0 ) {
7718			return undefined;
7719		}
7720	
7721		var
7722			settings   = this.context[0],
7723			start      = settings._iDisplayStart,
7724			len        = settings.oFeatures.bPaginate ? settings._iDisplayLength : -1,
7725			visRecords = settings.fnRecordsDisplay(),
7726			all        = len === -1;
7727	
7728		return {
7729			"page":           all ? 0 : Math.floor( start / len ),
7730			"pages":          all ? 1 : Math.ceil( visRecords / len ),
7731			"start":          start,
7732			"end":            settings.fnDisplayEnd(),
7733			"length":         len,
7734			"recordsTotal":   settings.fnRecordsTotal(),
7735			"recordsDisplay": visRecords,
7736			"serverSide":     _fnDataSource( settings ) === 'ssp'
7737		};
7738	} );
7739	
7740	
7741	/**
7742	 * Get the current page length.
7743	 *
7744	 * @return {integer} Current page length. Note `-1` indicates that all records
7745	 *   are to be shown.
7746	 *//**
7747	 * Set the current page length.
7748	 *
7749	 * @param {integer} Page length to set. Use `-1` to show all records.
7750	 * @returns {DataTables.Api} this
7751	 */
7752	_api_register( 'page.len()', function ( len ) {
7753		// Note that we can't call this function 'length()' because `length`
7754		// is a Javascript property of functions which defines how many arguments
7755		// the function expects.
7756		if ( len === undefined ) {
7757			return this.context.length !== 0 ?
7758				this.context[0]._iDisplayLength :
7759				undefined;
7760		}
7761	
7762		// else, set the page length
7763		return this.iterator( 'table', function ( settings ) {
7764			_fnLengthChange( settings, len );
7765		} );
7766	} );
7767	
7768	
7769	
7770	var __reload = function ( settings, holdPosition, callback ) {
7771		// Use the draw event to trigger a callback
7772		if ( callback ) {
7773			var api = new _Api( settings );
7774	
7775			api.one( 'draw', function () {
7776				callback( api.ajax.json() );
7777			} );
7778		}
7779	
7780		if ( _fnDataSource( settings ) == 'ssp' ) {
7781			_fnReDraw( settings, holdPosition );
7782		}
7783		else {
7784			_fnProcessingDisplay( settings, true );
7785	
7786			// Cancel an existing request
7787			var xhr = settings.jqXHR;
7788			if ( xhr && xhr.readyState !== 4 ) {
7789				xhr.abort();
7790			}
7791	
7792			// Trigger xhr
7793			_fnBuildAjax( settings, [], function( json ) {
7794				_fnClearTable( settings );
7795	
7796				var data = _fnAjaxDataSrc( settings, json );
7797				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7798					_fnAddData( settings, data[i] );
7799				}
7800	
7801				_fnReDraw( settings, holdPosition );
7802				_fnProcessingDisplay( settings, false );
7803			} );
7804		}
7805	};
7806	
7807	
7808	/**
7809	 * Get the JSON response from the last Ajax request that DataTables made to the
7810	 * server. Note that this returns the JSON from the first table in the current
7811	 * context.
7812	 *
7813	 * @return {object} JSON received from the server.
7814	 */
7815	_api_register( 'ajax.json()', function () {
7816		var ctx = this.context;
7817	
7818		if ( ctx.length > 0 ) {
7819			return ctx[0].json;
7820		}
7821	
7822		// else return undefined;
7823	} );
7824	
7825	
7826	/**
7827	 * Get the data submitted in the last Ajax request
7828	 */
7829	_api_register( 'ajax.params()', function () {
7830		var ctx = this.context;
7831	
7832		if ( ctx.length > 0 ) {
7833			return ctx[0].oAjaxData;
7834		}
7835	
7836		// else return undefined;
7837	} );
7838	
7839	
7840	/**
7841	 * Reload tables from the Ajax data source. Note that this function will
7842	 * automatically re-draw the table when the remote data has been loaded.
7843	 *
7844	 * @param {boolean} [reset=true] Reset (default) or hold the current paging
7845	 *   position. A full re-sort and re-filter is performed when this method is
7846	 *   called, which is why the pagination reset is the default action.
7847	 * @returns {DataTables.Api} this
7848	 */
7849	_api_register( 'ajax.reload()', function ( callback, resetPaging ) {
7850		return this.iterator( 'table', function (settings) {
7851			__reload( settings, resetPaging===false, callback );
7852		} );
7853	} );
7854	
7855	
7856	/**
7857	 * Get the current Ajax URL. Note that this returns the URL from the first
7858	 * table in the current context.
7859	 *
7860	 * @return {string} Current Ajax source URL
7861	 *//**
7862	 * Set the Ajax URL. Note that this will set the URL for all tables in the
7863	 * current context.
7864	 *
7865	 * @param {string} url URL to set.
7866	 * @returns {DataTables.Api} this
7867	 */
7868	_api_register( 'ajax.url()', function ( url ) {
7869		var ctx = this.context;
7870	
7871		if ( url === undefined ) {
7872			// get
7873			if ( ctx.length === 0 ) {
7874				return undefined;
7875			}
7876			ctx = ctx[0];
7877	
7878			return ctx.ajax ?
7879				$.isPlainObject( ctx.ajax ) ?
7880					ctx.ajax.url :
7881					ctx.ajax :
7882				ctx.sAjaxSource;
7883		}
7884	
7885		// set
7886		return this.iterator( 'table', function ( settings ) {
7887			if ( $.isPlainObject( settings.ajax ) ) {
7888				settings.ajax.url = url;
7889			}
7890			else {
7891				settings.ajax = url;
7892			}
7893			// No need to consider sAjaxSource here since DataTables gives priority
7894			// to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any
7895			// value of `sAjaxSource` redundant.
7896		} );
7897	} );
7898	
7899	
7900	/**
7901	 * Load data from the newly set Ajax URL. Note that this method is only
7902	 * available when `ajax.url()` is used to set a URL. Additionally, this method
7903	 * has the same effect as calling `ajax.reload()` but is provided for
7904	 * convenience when setting a new URL. Like `ajax.reload()` it will
7905	 * automatically redraw the table once the remote data has been loaded.
7906	 *
7907	 * @returns {DataTables.Api} this
7908	 */
7909	_api_register( 'ajax.url().load()', function ( callback, resetPaging ) {
7910		// Same as a reload, but makes sense to present it for easy access after a
7911		// url change
7912		return this.iterator( 'table', function ( ctx ) {
7913			__reload( ctx, resetPaging===false, callback );
7914		} );
7915	} );
7916	
7917	
7918	
7919	
7920	var _selector_run = function ( type, selector, selectFn, settings, opts )
7921	{
7922		var
7923			out = [], res,
7924			a, i, ien, j, jen,
7925			selectorType = typeof selector;
7926	
7927		// Can't just check for isArray here, as an API or jQuery instance might be
7928		// given with their array like look
7929		if ( ! selector || selectorType === 'string' || selectorType === 'function' || selector.length === undefined ) {
7930			selector = [ selector ];
7931		}
7932	
7933		for ( i=0, ien=selector.length ; i<ien ; i++ ) {
7934			// Only split on simple strings - complex expressions will be jQuery selectors
7935			a = selector[i] && selector[i].split && ! selector[i].match(/[\[\(:]/) ?
7936				selector[i].split(',') :
7937				[ selector[i] ];
7938	
7939			for ( j=0, jen=a.length ; j<jen ; j++ ) {
7940				res = selectFn( typeof a[j] === 'string' ? (a[j]).trim() : a[j] );
7941	
7942				if ( res && res.length ) {
7943					out = out.concat( res );
7944				}
7945			}
7946		}
7947	
7948		// selector extensions
7949		var ext = _ext.selector[ type ];
7950		if ( ext.length ) {
7951			for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7952				out = ext[i]( settings, opts, out );
7953			}
7954		}
7955	
7956		return _unique( out );
7957	};
7958	
7959	
7960	var _selector_opts = function ( opts )
7961	{
7962		if ( ! opts ) {
7963			opts = {};
7964		}
7965	
7966		// Backwards compatibility for 1.9- which used the terminology filter rather
7967		// than search
7968		if ( opts.filter && opts.search === undefined ) {
7969			opts.search = opts.filter;
7970		}
7971	
7972		return $.extend( {
7973			search: 'none',
7974			order: 'current',
7975			page: 'all'
7976		}, opts );
7977	};
7978	
7979	
7980	var _selector_first = function ( inst )
7981	{
7982		// Reduce the API instance to the first item found
7983		for ( var i=0, ien=inst.length ; i<ien ; i++ ) {
7984			if ( inst[i].length > 0 ) {
7985				// Assign the first element to the first item in the instance
7986				// and truncate the instance and context
7987				inst[0] = inst[i];
7988				inst[0].length = 1;
7989				inst.length = 1;
7990				inst.context = [ inst.context[i] ];
7991	
7992				return inst;
7993			}
7994		}
7995	
7996		// Not found - return an empty instance
7997		inst.length = 0;
7998		return inst;
7999	};
8000	
8001	
8002	var _selector_row_indexes = function ( settings, opts )
8003	{
8004		var
8005			i, ien, tmp, a=[],
8006			displayFiltered = settings.aiDisplay,
8007			displayMaster = settings.aiDisplayMaster;
8008	
8009		var
8010			search = opts.search,  // none, applied, removed
8011			order  = opts.order,   // applied, current, index (original - compatibility with 1.9)
8012			page   = opts.page;    // all, current
8013	
8014		if ( _fnDataSource( settings ) == 'ssp' ) {
8015			// In server-side processing mode, most options are irrelevant since
8016			// rows not shown don't exist and the index order is the applied order
8017			// Removed is a special case - for consistency just return an empty
8018			// array
8019			return search === 'removed' ?
8020				[] :
8021				_range( 0, displayMaster.length );
8022		}
8023		else if ( page == 'current' ) {
8024			// Current page implies that order=current and filter=applied, since it is
8025			// fairly senseless otherwise, regardless of what order and search actually
8026			// are
8027			for ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i<ien ; i++ ) {
8028				a.push( displayFiltered[i] );
8029			}
8030		}
8031		else if ( order == 'current' || order == 'applied' ) {
8032			if ( search == 'none') {
8033				a = displayMaster.slice();
8034			}
8035			else if ( search == 'applied' ) {
8036				a = displayFiltered.slice();
8037			}
8038			else if ( search == 'removed' ) {
8039				// O(n+m) solution by creating a hash map
8040				var displayFilteredMap = {};
8041	
8042				for ( var i=0, ien=displayFiltered.length ; i<ien ; i++ ) {
8043					displayFilteredMap[displayFiltered[i]] = null;
8044				}
8045	
8046				a = $.map( displayMaster, function (el) {
8047					return ! displayFilteredMap.hasOwnProperty(el) ?
8048						el :
8049						null;
8050				} );
8051			}
8052		}
8053		else if ( order == 'index' || order == 'original' ) {
8054			for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
8055				if ( search == 'none' ) {
8056					a.push( i );
8057				}
8058				else { // applied | removed
8059					tmp = $.inArray( i, displayFiltered );
8060	
8061					if ((tmp === -1 && search == 'removed') ||
8062						(tmp >= 0   && search == 'applied') )
8063					{
8064						a.push( i );
8065					}
8066				}
8067			}
8068		}
8069	
8070		return a;
8071	};
8072	
8073	
8074	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
8075	 * Rows
8076	 *
8077	 * {}          - no selector - use all available rows
8078	 * {integer}   - row aoData index
8079	 * {node}      - TR node
8080	 * {string}    - jQuery selector to apply to the TR elements
8081	 * {array}     - jQuery array of nodes, or simply an array of TR nodes
8082	 *
8083	 */
8084	var __row_selector = function ( settings, selector, opts )
8085	{
8086		var rows;
8087		var run = function ( sel ) {
8088			var selInt = _intVal( sel );
8089			var i, ien;
8090			var aoData = settings.aoData;
8091	
8092			// Short cut - selector is a number and no options provided (default is
8093			// all records, so no need to check if the index is in there, since it
8094			// must be - dev error if the index doesn't exist).
8095			if ( selInt !== null && ! opts ) {
8096				return [ selInt ];
8097			}
8098	
8099			if ( ! rows ) {
8100				rows = _selector_row_indexes( settings, opts );
8101			}
8102	
8103			if ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) {
8104				// Selector - integer
8105				return [ selInt ];
8106			}
8107			else if ( sel === null || sel === undefined || sel === '' ) {
8108				// Selector - none
8109				return rows;
8110			}
8111	
8112			// Selector - function
8113			if ( typeof sel === 'function' ) {
8114				return $.map( rows, function (idx) {
8115					var row = aoData[ idx ];
8116					return sel( idx, row._aData, row.nTr ) ? idx : null;
8117				} );
8118			}
8119	
8120			// Selector - node
8121			if ( sel.nodeName ) {
8122				var rowIdx = sel._DT_RowIndex;  // Property added by DT for fast lookup
8123				var cellIdx = sel._DT_CellIndex;
8124	
8125				if ( rowIdx !== undefined ) {
8126					// Make sure that the row is actually still present in the table
8127					return aoData[ rowIdx ] && aoData[ rowIdx ].nTr === sel ?
8128						[ rowIdx ] :
8129						[];
8130				}
8131				else if ( cellIdx ) {
8132					return aoData[ cellIdx.row ] && aoData[ cellIdx.row ].nTr === sel.parentNode ?
8133						[ cellIdx.row ] :
8134						[];
8135				}
8136				else {
8137					var host = $(sel).closest('*[data-dt-row]');
8138					return host.length ?
8139						[ host.data('dt-row') ] :
8140						[];
8141				}
8142			}
8143	
8144			// ID selector. Want to always be able to select rows by id, regardless
8145			// of if the tr element has been created or not, so can't rely upon
8146			// jQuery here - hence a custom implementation. This does not match
8147			// Sizzle's fast selector or HTML4 - in HTML5 the ID can be anything,
8148			// but to select it using a CSS selector engine (like Sizzle or
8149			// querySelect) it would need to need to be escaped for some characters.
8150			// DataTables simplifies this for row selectors since you can select
8151			// only a row. A # indicates an id any anything that follows is the id -
8152			// unescaped.
8153			if ( typeof sel === 'string' && sel.charAt(0) === '#' ) {
8154				// get row index from id
8155				var rowObj = settings.aIds[ sel.replace( /^#/, '' ) ];
8156				if ( rowObj !== undefined ) {
8157					return [ rowObj.idx ];
8158				}
8159	
8160				// need to fall through to jQuery in case there is DOM id that
8161				// matches
8162			}
8163			
8164			// Get nodes in the order from the `rows` array with null values removed
8165			var nodes = _removeEmpty(
8166				_pluck_order( settings.aoData, rows, 'nTr' )
8167			);
8168	
8169			// Selector - jQuery selector string, array of nodes or jQuery object/
8170			// As jQuery's .filter() allows jQuery objects to be passed in filter,
8171			// it also allows arrays, so this will cope with all three options
8172			return $(nodes)
8173				.filter( sel )
8174				.map( function () {
8175					return this._DT_RowIndex;
8176				} )
8177				.toArray();
8178		};
8179	
8180		return _selector_run( 'row', selector, run, settings, opts );
8181	};
8182	
8183	
8184	_api_register( 'rows()', function ( selector, opts ) {
8185		// argument shifting
8186		if ( selector === undefined ) {
8187			selector = '';
8188		}
8189		else if ( $.isPlainObject( selector ) ) {
8190			opts = selector;
8191			selector = '';
8192		}
8193	
8194		opts = _selector_opts( opts );
8195	
8196		var inst = this.iterator( 'table', function ( settings ) {
8197			return __row_selector( settings, selector, opts );
8198		}, 1 );
8199	
8200		// Want argument shifting here and in __row_selector?
8201		inst.selector.rows = selector;
8202		inst.selector.opts = opts;
8203	
8204		return inst;
8205	} );
8206	
8207	_api_register( 'rows().nodes()', function () {
8208		return this.iterator( 'row', function ( settings, row ) {
8209			return settings.aoData[ row ].nTr || undefined;
8210		}, 1 );
8211	} );
8212	
8213	_api_register( 'rows().data()', function () {
8214		return this.iterator( true, 'rows', function ( settings, rows ) {
8215			return _pluck_order( settings.aoData, rows, '_aData' );
8216		}, 1 );
8217	} );
8218	
8219	_api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) {
8220		return this.iterator( 'row', function ( settings, row ) {
8221			var r = settings.aoData[ row ];
8222			return type === 'search' ? r._aFilterData : r._aSortData;
8223		}, 1 );
8224	} );
8225	
8226	_api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) {
8227		return this.iterator( 'row', function ( settings, row ) {
8228			_fnInvalidate( settings, row, src );
8229		} );
8230	} );
8231	
8232	_api_registerPlural( 'rows().indexes()', 'row().index()', function () {
8233		return this.iterator( 'row', function ( settings, row ) {
8234			return row;
8235		}, 1 );
8236	} );
8237	
8238	_api_registerPlural( 'rows().ids()', 'row().id()', function ( hash ) {
8239		var a = [];
8240		var context = this.context;
8241	
8242		// `iterator` will drop undefined values, but in this case we want them
8243		for ( var i=0, ien=context.length ; i<ien ; i++ ) {
8244			for ( var j=0, jen=this[i].length ; j<jen ; j++ ) {
8245				var id = context[i].rowIdFn( context[i].aoData[ this[i][j] ]._aData );
8246				a.push( (hash === true ? '#' : '' )+ id );
8247			}
8248		}
8249	
8250		return new _Api( context, a );
8251	} );
8252	
8253	_api_registerPlural( 'rows().remove()', 'row().remove()', function () {
8254		var that = this;
8255	
8256		this.iterator( 'row', function ( settings, row, thatIdx ) {
8257			var data = settings.aoData;
8258			var rowData = data[ row ];
8259			var i, ien, j, jen;
8260			var loopRow, loopCells;
8261	
8262			data.splice( row, 1 );
8263	
8264			// Update the cached indexes
8265			for ( i=0, ien=data.length ; i<ien ; i++ ) {
8266				loopRow = data[i];
8267				loopCells = loopRow.anCells;
8268	
8269				// Rows
8270				if ( loopRow.nTr !== null ) {
8271					loopRow.nTr._DT_RowIndex = i;
8272				}
8273	
8274				// Cells
8275				if ( loopCells !== null ) {
8276					for ( j=0, jen=loopCells.length ; j<jen ; j++ ) {
8277						loopCells[j]._DT_CellIndex.row = i;
8278					}
8279				}
8280			}
8281	
8282			// Delete from the display arrays
8283			_fnDeleteIndex( settings.aiDisplayMaster, row );
8284			_fnDeleteIndex( settings.aiDisplay, row );
8285			_fnDeleteIndex( that[ thatIdx ], row, false ); // maintain local indexes
8286	
8287			// For server-side processing tables - subtract the deleted row from the count
8288			if ( settings._iRecordsDisplay > 0 ) {
8289				settings._iRecordsDisplay--;
8290			}
8291	
8292			// Check for an 'overflow' they case for displaying the table
8293			_fnLengthOverflow( settings );
8294	
8295			// Remove the row's ID reference if there is one
8296			var id = settings.rowIdFn( rowData._aData );
8297			if ( id !== undefined ) {
8298				delete settings.aIds[ id ];
8299			}
8300		} );
8301	
8302		this.iterator( 'table', function ( settings ) {
8303			for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
8304				settings.aoData[i].idx = i;
8305			}
8306		} );
8307	
8308		return this;
8309	} );
8310	
8311	
8312	_api_register( 'rows.add()', function ( rows ) {
8313		var newRows = this.iterator( 'table', function ( settings ) {
8314				var row, i, ien;
8315				var out = [];
8316	
8317				for ( i=0, ien=rows.length ; i<ien ; i++ ) {
8318					row = rows[i];
8319	
8320					if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
8321						out.push( _fnAddTr( settings, row )[0] );
8322					}
8323					else {
8324						out.push( _fnAddData( settings, row ) );
8325					}
8326				}
8327	
8328				return out;
8329			}, 1 );
8330	
8331		// Return an Api.rows() extended instance, so rows().nodes() etc can be used
8332		var modRows = this.rows( -1 );
8333		modRows.pop();
8334		$.merge( modRows, newRows );
8335	
8336		return modRows;
8337	} );
8338	
8339	
8340	
8341	
8342	
8343	/**
8344	 *
8345	 */
8346	_api_register( 'row()', function ( selector, opts ) {
8347		return _selector_first( this.rows( selector, opts ) );
8348	} );
8349	
8350	
8351	_api_register( 'row().data()', function ( data ) {
8352		var ctx = this.context;
8353	
8354		if ( data === undefined ) {
8355			// Get
8356			return ctx.length && this.length ?
8357				ctx[0].aoData[ this[0] ]._aData :
8358				undefined;
8359		}
8360	
8361		// Set
8362		var row = ctx[0].aoData[ this[0] ];
8363		row._aData = data;
8364	
8365		// If the DOM has an id, and the data source is an array
8366		if ( Array.isArray( data ) && row.nTr && row.nTr.id ) {
8367			_fnSetObjectDataFn( ctx[0].rowId )( data, row.nTr.id );
8368		}
8369	
8370		// Automatically invalidate
8371		_fnInvalidate( ctx[0], this[0], 'data' );
8372	
8373		return this;
8374	} );
8375	
8376	
8377	_api_register( 'row().node()', function () {
8378		var ctx = this.context;
8379	
8380		return ctx.length && this.length ?
8381			ctx[0].aoData[ this[0] ].nTr || null :
8382			null;
8383	} );
8384	
8385	
8386	_api_register( 'row.add()', function ( row ) {
8387		// Allow a jQuery object to be passed in - only a single row is added from
8388		// it though - the first element in the set
8389		if ( row instanceof $ && row.length ) {
8390			row = row[0];
8391		}
8392	
8393		var rows = this.iterator( 'table', function ( settings ) {
8394			if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
8395				return _fnAddTr( settings, row )[0];
8396			}
8397			return _fnAddData( settings, row );
8398		} );
8399	
8400		// Return an Api.rows() extended instance, with the newly added row selected
8401		return this.row( rows[0] );
8402	} );
8403	
8404	
8405	$(document).on('plugin-init.dt', function (e, context) {
8406		var api = new _Api( context );
8407		var namespace = 'on-plugin-init';
8408		var stateSaveParamsEvent = 'stateSaveParams.' + namespace;
8409		var destroyEvent = 'destroy. ' + namespace;
8410	
8411		api.on( stateSaveParamsEvent, function ( e, settings, d ) {
8412			// This could be more compact with the API, but it is a lot faster as a simple
8413			// internal loop
8414			var idFn = settings.rowIdFn;
8415			var data = settings.aoData;
8416			var ids = [];
8417	
8418			for (var i=0 ; i<data.length ; i++) {
8419				if (data[i]._detailsShow) {
8420					ids.push( '#' + idFn(data[i]._aData) );
8421				}
8422			}
8423	
8424			d.childRows = ids;
8425		});
8426	
8427		api.on( destroyEvent, function () {
8428			api.off(stateSaveParamsEvent + ' ' + destroyEvent);
8429		});
8430	
8431		var loaded = api.state.loaded();
8432	
8433		if ( loaded && loaded.childRows ) {
8434			api
8435				.rows( $.map(loaded.childRows, function (id){
8436					return id.replace(/:/g, '\\:')
8437				}) )
8438				.every( function () {
8439					_fnCallbackFire( context, null, 'requestChild', [ this ] )
8440				});
8441		}
8442	});
8443	
8444	var __details_add = function ( ctx, row, data, klass )
8445	{
8446		// Convert to array of TR elements
8447		var rows = [];
8448		var addRow = function ( r, k ) {
8449			// Recursion to allow for arrays of jQuery objects
8450			if ( Array.isArray( r ) || r instanceof $ ) {
8451				for ( var i=0, ien=r.length ; i<ien ; i++ ) {
8452					addRow( r[i], k );
8453				}
8454				return;
8455			}
8456	
8457			// If we get a TR element, then just add it directly - up to the dev
8458			// to add the correct number of columns etc
8459			if ( r.nodeName && r.nodeName.toLowerCase() === 'tr' ) {
8460				rows.push( r );
8461			}
8462			else {
8463				// Otherwise create a row with a wrapper
8464				var created = $('<tr><td></td></tr>').addClass( k );
8465				$('td', created)
8466					.addClass( k )
8467					.html( r )
8468					[0].colSpan = _fnVisbleColumns( ctx );
8469	
8470				rows.push( created[0] );
8471			}
8472		};
8473	
8474		addRow( data, klass );
8475	
8476		if ( row._details ) {
8477			row._details.detach();
8478		}
8479	
8480		row._details = $(rows);
8481	
8482		// If the children were already shown, that state should be retained
8483		if ( row._detailsShow ) {
8484			row._details.insertAfter( row.nTr );
8485		}
8486	};
8487	
8488	
8489	// Make state saving of child row details async to allow them to be batch processed
8490	var __details_state = DataTable.util.throttle(
8491		function (ctx) {
8492			_fnSaveState( ctx[0] )
8493		},
8494		500
8495	);
8496	
8497	
8498	var __details_remove = function ( api, idx )
8499	{
8500		var ctx = api.context;
8501	
8502		if ( ctx.length ) {
8503			var row = ctx[0].aoData[ idx !== undefined ? idx : api[0] ];
8504	
8505			if ( row && row._details ) {
8506				row._details.remove();
8507	
8508				row._detailsShow = undefined;
8509				row._details = undefined;
8510				$( row.nTr ).removeClass( 'dt-hasChild' );
8511				__details_state( ctx );
8512			}
8513		}
8514	};
8515	
8516	
8517	var __details_display = function ( api, show ) {
8518		var ctx = api.context;
8519	
8520		if ( ctx.length && api.length ) {
8521			var row = ctx[0].aoData[ api[0] ];
8522	
8523			if ( row._details ) {
8524				row._detailsShow = show;
8525	
8526				if ( show ) {
8527					row._details.insertAfter( row.nTr );
8528					$( row.nTr ).addClass( 'dt-hasChild' );
8529				}
8530				else {
8531					row._details.detach();
8532					$( row.nTr ).removeClass( 'dt-hasChild' );
8533				}
8534	
8535				_fnCallbackFire( ctx[0], null, 'childRow', [ show, api.row( api[0] ) ] )
8536	
8537				__details_events( ctx[0] );
8538				__details_state( ctx );
8539			}
8540		}
8541	};
8542	
8543	
8544	var __details_events = function ( settings )
8545	{
8546		var api = new _Api( settings );
8547		var namespace = '.dt.DT_details';
8548		var drawEvent = 'draw'+namespace;
8549		var colvisEvent = 'column-sizing'+namespace;
8550		var destroyEvent = 'destroy'+namespace;
8551		var data = settings.aoData;
8552	
8553		api.off( drawEvent +' '+ colvisEvent +' '+ destroyEvent );
8554	
8555		if ( _pluck( data, '_details' ).length > 0 ) {
8556			// On each draw, insert the required elements into the document
8557			api.on( drawEvent, function ( e, ctx ) {
8558				if ( settings !== ctx ) {
8559					return;
8560				}
8561	
8562				api.rows( {page:'current'} ).eq(0).each( function (idx) {
8563					// Internal data grab
8564					var row = data[ idx ];
8565	
8566					if ( row._detailsShow ) {
8567						row._details.insertAfter( row.nTr );
8568					}
8569				} );
8570			} );
8571	
8572			// Column visibility change - update the colspan
8573			api.on( colvisEvent, function ( e, ctx, idx, vis ) {
8574				if ( settings !== ctx ) {
8575					return;
8576				}
8577	
8578				// Update the colspan for the details rows (note, only if it already has
8579				// a colspan)
8580				var row, visible = _fnVisbleColumns( ctx );
8581	
8582				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
8583					row = data[i];
8584	
8585					if ( row._details ) {
8586						row._details.
8586each(function () {
8587							var el = $(this).children('td');
8588	
8589							if (el.length == 1) {
8590								el.attr('colspan', visible);
8591							}
8592						}
vendor: 32,739 bytes, lines 8592-9799
8592);
8593					}
8594				}
8595			} );
8596	
8597			// Table destroyed - nuke any child rows
8598			api.on( destroyEvent, function ( e, ctx ) {
8599				if ( settings !== ctx ) {
8600					return;
8601				}
8602	
8603				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
8604					if ( data[i]._details ) {
8605						__details_remove( api, i );
8606					}
8607				}
8608			} );
8609		}
8610	};
8611	
8612	// Strings for the method names to help minification
8613	var _emp = '';
8614	var _child_obj = _emp+'row().child';
8615	var _child_mth = _child_obj+'()';
8616	
8617	// data can be:
8618	//  tr
8619	//  string
8620	//  jQuery or array of any of the above
8621	_api_register( _child_mth, function ( data, klass ) {
8622		var ctx = this.context;
8623	
8624		if ( data === undefined ) {
8625			// get
8626			return ctx.length && this.length ?
8627				ctx[0].aoData[ this[0] ]._details :
8628				undefined;
8629		}
8630		else if ( data === true ) {
8631			// show
8632			this.child.show();
8633		}
8634		else if ( data === false ) {
8635			// remove
8636			__details_remove( this );
8637		}
8638		else if ( ctx.length && this.length ) {
8639			// set
8640			__details_add( ctx[0], ctx[0].aoData[ this[0] ], data, klass );
8641		}
8642	
8643		return this;
8644	} );
8645	
8646	
8647	_api_register( [
8648		_child_obj+'.show()',
8649		_child_mth+'.show()' // only when `child()` was called with parameters (without
8650	], function ( show ) {   // it returns an object and this method is not executed)
8651		__details_display( this, true );
8652		return this;
8653	} );
8654	
8655	
8656	_api_register( [
8657		_child_obj+'.hide()',
8658		_child_mth+'.hide()' // only when `child()` was called with parameters (without
8659	], function () {         // it returns an object and this method is not executed)
8660		__details_display( this, false );
8661		return this;
8662	} );
8663	
8664	
8665	_api_register( [
8666		_child_obj+'.remove()',
8667		_child_mth+'.remove()' // only when `child()` was called with parameters (without
8668	], function () {           // it returns an object and this method is not executed)
8669		__details_remove( this );
8670		return this;
8671	} );
8672	
8673	
8674	_api_register( _child_obj+'.isShown()', function () {
8675		var ctx = this.context;
8676	
8677		if ( ctx.length && this.length ) {
8678			// _detailsShown as false or undefined will fall through to return false
8679			return ctx[0].aoData[ this[0] ]._detailsShow || false;
8680		}
8681		return false;
8682	} );
8683	
8684	
8685	
8686	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
8687	 * Columns
8688	 *
8689	 * {integer}           - column index (>=0 count from left, <0 count from right)
8690	 * "{integer}:visIdx"  - visible column index (i.e. translate to column index)  (>=0 count from left, <0 count from right)
8691	 * "{integer}:visible" - alias for {integer}:visIdx  (>=0 count from left, <0 count from right)
8692	 * "{string}:name"     - column name
8693	 * "{string}"          - jQuery selector on column header nodes
8694	 *
8695	 */
8696	
8697	// can be an array of these items, comma separated list, or an array of comma
8698	// separated lists
8699	
8700	var __re_column_selector = /^([^:]+):(name|visIdx|visible)$/;
8701	
8702	
8703	// r1 and r2 are redundant - but it means that the parameters match for the
8704	// iterator callback in columns().data()
8705	var __columnData = function ( settings, column, r1, r2, rows ) {
8706		var a = [];
8707		for ( var row=0, ien=rows.length ; row<ien ; row++ ) {
8708			a.push( _fnGetCellData( settings, rows[row], column ) );
8709		}
8710		return a;
8711	};
8712	
8713	
8714	var __column_selector = function ( settings, selector, opts )
8715	{
8716		var
8717			columns = settings.aoColumns,
8718			names = _pluck( columns, 'sName' ),
8719			nodes = _pluck( columns, 'nTh' );
8720	
8721		var run = function ( s ) {
8722			var selInt = _intVal( s );
8723	
8724			// Selector - all
8725			if ( s === '' ) {
8726				return _range( columns.length );
8727			}
8728	
8729			// Selector - index
8730			if ( selInt !== null ) {
8731				return [ selInt >= 0 ?
8732					selInt : // Count from left
8733					columns.length + selInt // Count from right (+ because its a negative value)
8734				];
8735			}
8736	
8737			// Selector = function
8738			if ( typeof s === 'function' ) {
8739				var rows = _selector_row_indexes( settings, opts );
8740	
8741				return $.map( columns, function (col, idx) {
8742					return s(
8743							idx,
8744							__columnData( settings, idx, 0, 0, rows ),
8745							nodes[ idx ]
8746						) ? idx : null;
8747				} );
8748			}
8749	
8750			// jQuery or string selector
8751			var match = typeof s === 'string' ?
8752				s.match( __re_column_selector ) :
8753				'';
8754	
8755			if ( match ) {
8756				switch( match[2] ) {
8757					case 'visIdx':
8758					case 'visible':
8759						var idx = parseInt( match[1], 10 );
8760						// Visible index given, convert to column index
8761						if ( idx < 0 ) {
8762							// Counting from the right
8763							var visColumns = $.map( columns, function (col,i) {
8764								return col.bVisible ? i : null;
8765							} );
8766							return [ visColumns[ visColumns.length + idx ] ];
8767						}
8768						// Counting from the left
8769						return [ _fnVisibleToColumnIndex( settings, idx ) ];
8770	
8771					case 'name':
8772						// match by name. `names` is column index complete and in order
8773						return $.map( names, function (name, i) {
8774							return name === match[1] ? i : null;
8775						} );
8776	
8777					default:
8778						return [];
8779				}
8780			}
8781	
8782			// Cell in the table body
8783			if ( s.nodeName && s._DT_CellIndex ) {
8784				return [ s._DT_CellIndex.column ];
8785			}
8786	
8787			// jQuery selector on the TH elements for the columns
8788			var jqResult = $( nodes )
8789				.filter( s )
8790				.map( function () {
8791					return $.inArray( this, nodes ); // `nodes` is column index complete and in order
8792				} )
8793				.toArray();
8794	
8795			if ( jqResult.length || ! s.nodeName ) {
8796				return jqResult;
8797			}
8798	
8799			// Otherwise a node which might have a `dt-column` data attribute, or be
8800			// a child or such an element
8801			var host = $(s).closest('*[data-dt-column]');
8802			return host.length ?
8803				[ host.data('dt-column') ] :
8804				[];
8805		};
8806	
8807		return _selector_run( 'column', selector, run, settings, opts );
8808	};
8809	
8810	
8811	var __setColumnVis = function ( settings, column, vis ) {
8812		var
8813			cols = settings.aoColumns,
8814			col  = cols[ column ],
8815			data = settings.aoData,
8816			row, cells, i, ien, tr;
8817	
8818		// Get
8819		if ( vis === undefined ) {
8820			return col.bVisible;
8821		}
8822	
8823		// Set
8824		// No change
8825		if ( col.bVisible === vis ) {
8826			return;
8827		}
8828	
8829		if ( vis ) {
8830			// Insert column
8831			// Need to decide if we should use appendChild or insertBefore
8832			var insertBefore = $.inArray( true, _pluck(cols, 'bVisible'), column+1 );
8833	
8834			for ( i=0, ien=data.length ; i<ien ; i++ ) {
8835				tr = data[i].nTr;
8836				cells = data[i].anCells;
8837	
8838				if ( tr ) {
8839					// insertBefore can act like appendChild if 2nd arg is null
8840					tr.insertBefore( cells[ column ], cells[ insertBefore ] || null );
8841				}
8842			}
8843		}
8844		else {
8845			// Remove column
8846			$( _pluck( settings.aoData, 'anCells', column ) ).detach();
8847		}
8848	
8849		// Common actions
8850		col.bVisible = vis;
8851	};
8852	
8853	
8854	_api_register( 'columns()', function ( selector, opts ) {
8855		// argument shifting
8856		if ( selector === undefined ) {
8857			selector = '';
8858		}
8859		else if ( $.isPlainObject( selector ) ) {
8860			opts = selector;
8861			selector = '';
8862		}
8863	
8864		opts = _selector_opts( opts );
8865	
8866		var inst = this.iterator( 'table', function ( settings ) {
8867			return __column_selector( settings, selector, opts );
8868		}, 1 );
8869	
8870		// Want argument shifting here and in _row_selector?
8871		inst.selector.cols = selector;
8872		inst.selector.opts = opts;
8873	
8874		return inst;
8875	} );
8876	
8877	_api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) {
8878		return this.iterator( 'column', function ( settings, column ) {
8879			return settings.aoColumns[column].nTh;
8880		}, 1 );
8881	} );
8882	
8883	_api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) {
8884		return this.iterator( 'column', function ( settings, column ) {
8885			return settings.aoColumns[column].nTf;
8886		}, 1 );
8887	} );
8888	
8889	_api_registerPlural( 'columns().data()', 'column().data()', function () {
8890		return this.iterator( 'column-rows', __columnData, 1 );
8891	} );
8892	
8893	_api_registerPlural( 'columns().dataSrc()', 'column().dataSrc()', function () {
8894		return this.iterator( 'column', function ( settings, column ) {
8895			return settings.aoColumns[column].mData;
8896		}, 1 );
8897	} );
8898	
8899	_api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) {
8900		return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8901			return _pluck_order( settings.aoData, rows,
8902				type === 'search' ? '_aFilterData' : '_aSortData', column
8903			);
8904		}, 1 );
8905	} );
8906	
8907	_api_registerPlural( 'columns().nodes()', 'column().nodes()', function () {
8908		return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8909			return _pluck_order( settings.aoData, rows, 'anCells', column ) ;
8910		}, 1 );
8911	} );
8912	
8913	_api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis, calc ) {
8914		var that = this;
8915		var ret = this.iterator( 'column', function ( settings, column ) {
8916			if ( vis === undefined ) {
8917				return settings.aoColumns[ column ].bVisible;
8918			} // else
8919			__setColumnVis( settings, column, vis );
8920		} );
8921	
8922		// Group the column visibility changes
8923		if ( vis !== undefined ) {
8924			this.iterator( 'table', function ( settings ) {
8925				// Redraw the header after changes
8926				_fnDrawHead( settings, settings.aoHeader );
8927				_fnDrawHead( settings, settings.aoFooter );
8928		
8929				// Update colspan for no records display. Child rows and extensions will use their own
8930				// listeners to do this - only need to update the empty table item here
8931				if ( ! settings.aiDisplay.length ) {
8932					$(settings.nTBody).find('td[colspan]').attr('colspan', _fnVisbleColumns(settings));
8933				}
8934		
8935				_fnSaveState( settings );
8936	
8937				// Second loop once the first is done for events
8938				that.iterator( 'column', function ( settings, column ) {
8939					_fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis, calc] );
8940				} );
8941	
8942				if ( calc === undefined || calc ) {
8943					that.columns.adjust();
8944				}
8945			});
8946		}
8947	
8948		return ret;
8949	} );
8950	
8951	_api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) {
8952		return this.iterator( 'column', function ( settings, column ) {
8953			return type === 'visible' ?
8954				_fnColumnIndexToVisible( settings, column ) :
8955				column;
8956		}, 1 );
8957	} );
8958	
8959	_api_register( 'columns.adjust()', function () {
8960		return this.iterator( 'table', function ( settings ) {
8961			_fnAdjustColumnSizing( settings );
8962		}, 1 );
8963	} );
8964	
8965	_api_register( 'column.index()', function ( type, idx ) {
8966		if ( this.context.length !== 0 ) {
8967			var ctx = this.context[0];
8968	
8969			if ( type === 'fromVisible' || type === 'toData' ) {
8970				return _fnVisibleToColumnIndex( ctx, idx );
8971			}
8972			else if ( type === 'fromData' || type === 'toVisible' ) {
8973				return _fnColumnIndexToVisible( ctx, idx );
8974			}
8975		}
8976	} );
8977	
8978	_api_register( 'column()', function ( selector, opts ) {
8979		return _selector_first( this.columns( selector, opts ) );
8980	} );
8981	
8982	var __cell_selector = function ( settings, selector, opts )
8983	{
8984		var data = settings.aoData;
8985		var rows = _selector_row_indexes( settings, opts );
8986		var cells = _removeEmpty( _pluck_order( data, rows, 'anCells' ) );
8987		var allCells = $(_flatten( [], cells ));
8988		var row;
8989		var columns = settings.aoColumns.length;
8990		var a, i, ien, j, o, host;
8991	
8992		var run = function ( s ) {
8993			var fnSelector = typeof s === 'function';
8994	
8995			if ( s === null || s === undefined || fnSelector ) {
8996				// All cells and function selectors
8997				a = [];
8998	
8999				for ( i=0, ien=rows.length ; i<ien ; i++ ) {
9000					row = rows[i];
9001	
9002					for ( j=0 ; j<columns ; j++ ) {
9003						o = {
9004							row: row,
9005							column: j
9006						};
9007	
9008						if ( fnSelector ) {
9009							// Selector - function
9010							host = data[ row ];
9011	
9012							if ( s( o, _fnGetCellData(settings, row, j), host.anCells ? host.anCells[j] : null ) ) {
9013								a.push( o );
9014							}
9015						}
9016						else {
9017							// Selector - all
9018							a.push( o );
9019						}
9020					}
9021				}
9022	
9023				return a;
9024			}
9025			
9026			// Selector - index
9027			if ( $.isPlainObject( s ) ) {
9028				// Valid cell index and its in the array of selectable rows
9029				return s.column !== undefined && s.row !== undefined && $.inArray( s.row, rows ) !== -1 ?
9030					[s] :
9031					[];
9032			}
9033	
9034			// Selector - jQuery filtered cells
9035			var jqResult = allCells
9036				.filter( s )
9037				.map( function (i, el) {
9038					return { // use a new object, in case someone changes the values
9039						row:    el._DT_CellIndex.row,
9040						column: el._DT_CellIndex.column
9041	 				};
9042				} )
9043				.toArray();
9044	
9045			if ( jqResult.length || ! s.nodeName ) {
9046				return jqResult;
9047			}
9048	
9049			// Otherwise the selector is a node, and there is one last option - the
9050			// element might be a child of an element which has dt-row and dt-column
9051			// data attributes
9052			host = $(s).closest('*[data-dt-row]');
9053			return host.length ?
9054				[ {
9055					row: host.data('dt-row'),
9056					column: host.data('dt-column')
9057				} ] :
9058				[];
9059		};
9060	
9061		return _selector_run( 'cell', selector, run, settings, opts );
9062	};
9063	
9064	
9065	
9066	
9067	_api_register( 'cells()', function ( rowSelector, columnSelector, opts ) {
9068		// Argument shifting
9069		if ( $.isPlainObject( rowSelector ) ) {
9070			// Indexes
9071			if ( rowSelector.row === undefined ) {
9072				// Selector options in first parameter
9073				opts = rowSelector;
9074				rowSelector = null;
9075			}
9076			else {
9077				// Cell index objects in first parameter
9078				opts = columnSelector;
9079				columnSelector = null;
9080			}
9081		}
9082		if ( $.isPlainObject( columnSelector ) ) {
9083			opts = columnSelector;
9084			columnSelector = null;
9085		}
9086	
9087		// Cell selector
9088		if ( columnSelector === null || columnSelector === undefined ) {
9089			return this.iterator( 'table', function ( settings ) {
9090				return __cell_selector( settings, rowSelector, _selector_opts( opts ) );
9091			} );
9092		}
9093	
9094		// The default built in options need to apply to row and columns
9095		var internalOpts = opts ? {
9096			page: opts.page,
9097			order: opts.order,
9098			search: opts.search
9099		} : {};
9100	
9101		// Row + column selector
9102		var columns = this.columns( columnSelector, internalOpts );
9103		var rows = this.rows( rowSelector, internalOpts );
9104		var i, ien, j, jen;
9105	
9106		var cellsNoOpts = this.iterator( 'table', function ( settings, idx ) {
9107			var a = [];
9108	
9109			for ( i=0, ien=rows[idx].length ; i<ien ; i++ ) {
9110				for ( j=0, jen=columns[idx].length ; j<jen ; j++ ) {
9111					a.push( {
9112						row:    rows[idx][i],
9113						column: columns[idx][j]
9114					} );
9115				}
9116			}
9117	
9118			return a;
9119		}, 1 );
9120	
9121		// There is currently only one extension which uses a cell selector extension
9122		// It is a _major_ performance drag to run this if it isn't needed, so this is
9123		// an extension specific check at the moment
9124		var cells = opts && opts.selected ?
9125			this.cells( cellsNoOpts, opts ) :
9126			cellsNoOpts;
9127	
9128		$.extend( cells.selector, {
9129			cols: columnSelector,
9130			rows: rowSelector,
9131			opts: opts
9132		} );
9133	
9134		return cells;
9135	} );
9136	
9137	
9138	_api_registerPlural( 'cells().nodes()', 'cell().node()', function () {
9139		return this.iterator( 'cell', function ( settings, row, column ) {
9140			var data = settings.aoData[ row ];
9141	
9142			return data && data.anCells ?
9143				data.anCells[ column ] :
9144				undefined;
9145		}, 1 );
9146	} );
9147	
9148	
9149	_api_register( 'cells().data()', function () {
9150		return this.iterator( 'cell', function ( settings, row, column ) {
9151			return _fnGetCellData( settings, row, column );
9152		}, 1 );
9153	} );
9154	
9155	
9156	_api_registerPlural( 'cells().cache()', 'cell().cache()', function ( type ) {
9157		type = type === 'search' ? '_aFilterData' : '_aSortData';
9158	
9159		return this.iterator( 'cell', function ( settings, row, column ) {
9160			return settings.aoData[ row ][ type ][ column ];
9161		}, 1 );
9162	} );
9163	
9164	
9165	_api_registerPlural( 'cells().render()', 'cell().render()', function ( type ) {
9166		return this.iterator( 'cell', function ( settings, row, column ) {
9167			return _fnGetCellData( settings, row, column, type );
9168		}, 1 );
9169	} );
9170	
9171	
9172	_api_registerPlural( 'cells().indexes()', 'cell().index()', function () {
9173		return this.iterator( 'cell', function ( settings, row, column ) {
9174			return {
9175				row: row,
9176				column: column,
9177				columnVisible: _fnColumnIndexToVisible( settings, column )
9178			};
9179		}, 1 );
9180	} );
9181	
9182	
9183	_api_registerPlural( 'cells().invalidate()', 'cell().invalidate()', function ( src ) {
9184		return this.iterator( 'cell', function ( settings, row, column ) {
9185			_fnInvalidate( settings, row, src, column );
9186		} );
9187	} );
9188	
9189	
9190	
9191	_api_register( 'cell()', function ( rowSelector, columnSelector, opts ) {
9192		return _selector_first( this.cells( rowSelector, columnSelector, opts ) );
9193	} );
9194	
9195	
9196	_api_register( 'cell().data()', function ( data ) {
9197		var ctx = this.context;
9198		var cell = this[0];
9199	
9200		if ( data === undefined ) {
9201			// Get
9202			return ctx.length && cell.length ?
9203				_fnGetCellData( ctx[0], cell[0].row, cell[0].column ) :
9204				undefined;
9205		}
9206	
9207		// Set
9208		_fnSetCellData( ctx[0], cell[0].row, cell[0].column, data );
9209		_fnInvalidate( ctx[0], cell[0].row, 'data', cell[0].column );
9210	
9211		return this;
9212	} );
9213	
9214	
9215	
9216	/**
9217	 * Get current ordering (sorting) that has been applied to the table.
9218	 *
9219	 * @returns {array} 2D array containing the sorting information for the first
9220	 *   table in the current context. Each element in the parent array represents
9221	 *   a column being sorted upon (i.e. multi-sorting with two columns would have
9222	 *   2 inner arrays). The inner arrays may have 2 or 3 elements. The first is
9223	 *   the column index that the sorting condition applies to, the second is the
9224	 *   direction of the sort (`desc` or `asc`) and, optionally, the third is the
9225	 *   index of the sorting order from the `column.sorting` initialisation array.
9226	 *//**
9227	 * Set the ordering for the table.
9228	 *
9229	 * @param {integer} order Column index to sort upon.
9230	 * @param {string} direction Direction of the sort to be applied (`asc` or `desc`)
9231	 * @returns {DataTables.Api} this
9232	 *//**
9233	 * Set the ordering for the table.
9234	 *
9235	 * @param {array} order 1D array of sorting information to be applied.
9236	 * @param {array} [...] Optional additional sorting conditions
9237	 * @returns {DataTables.Api} this
9238	 *//**
9239	 * Set the ordering for the table.
9240	 *
9241	 * @param {array} order 2D array of sorting information to be applied.
9242	 * @returns {DataTables.Api} this
9243	 */
9244	_api_register( 'order()', function ( order, dir ) {
9245		var ctx = this.context;
9246	
9247		if ( order === undefined ) {
9248			// get
9249			return ctx.length !== 0 ?
9250				ctx[0].aaSorting :
9251				undefined;
9252		}
9253	
9254		// set
9255		if ( typeof order === 'number' ) {
9256			// Simple column / direction passed in
9257			order = [ [ order, dir ] ];
9258		}
9259		else if ( order.length && ! Array.isArray( order[0] ) ) {
9260			// Arguments passed in (list of 1D arrays)
9261			order = Array.prototype.slice.call( arguments );
9262		}
9263		// otherwise a 2D array was passed in
9264	
9265		return this.iterator( 'table', function ( settings ) {
9266			settings.aaSorting = order.slice();
9267		} );
9268	} );
9269	
9270	
9271	/**
9272	 * Attach a sort listener to an element for a given column
9273	 *
9274	 * @param {node|jQuery|string} node Identifier for the element(s) to attach the
9275	 *   listener to. This can take the form of a single DOM node, a jQuery
9276	 *   collection of nodes or a jQuery selector which will identify the node(s).
9277	 * @param {integer} column the column that a click on this node will sort on
9278	 * @param {function} [callback] callback function when sort is run
9279	 * @returns {DataTables.Api} this
9280	 */
9281	_api_register( 'order.listener()', function ( node, column, callback ) {
9282		return this.iterator( 'table', function ( settings ) {
9283			_fnSortAttachListener( settings, node, column, callback );
9284		} );
9285	} );
9286	
9287	
9288	_api_register( 'order.fixed()', function ( set ) {
9289		if ( ! set ) {
9290			var ctx = this.context;
9291			var fixed = ctx.length ?
9292				ctx[0].aaSortingFixed :
9293				undefined;
9294	
9295			return Array.isArray( fixed ) ?
9296				{ pre: fixed } :
9297				fixed;
9298		}
9299	
9300		return this.iterator( 'table', function ( settings ) {
9301			settings.aaSortingFixed = $.extend( true, {}, set );
9302		} );
9303	} );
9304	
9305	
9306	// Order by the selected column(s)
9307	_api_register( [
9308		'columns().order()',
9309		'column().order()'
9310	], function ( dir ) {
9311		var that = this;
9312	
9313		return this.iterator( 'table', function ( settings, i ) {
9314			var sort = [];
9315	
9316			$.each( that[i], function (j, col) {
9317				sort.push( [ col, dir ] );
9318			} );
9319	
9320			settings.aaSorting = sort;
9321		} );
9322	} );
9323	
9324	
9325	
9326	_api_register( 'search()', function ( input, regex, smart, caseInsen ) {
9327		var ctx = this.context;
9328	
9329		if ( input === undefined ) {
9330			// get
9331			return ctx.length !== 0 ?
9332				ctx[0].oPreviousSearch.sSearch :
9333				undefined;
9334		}
9335	
9336		// set
9337		return this.iterator( 'table', function ( settings ) {
9338			if ( ! settings.oFeatures.bFilter ) {
9339				return;
9340			}
9341	
9342			_fnFilterComplete( settings, $.extend( {}, settings.oPreviousSearch, {
9343				"sSearch": input+"",
9344				"bRegex":  regex === null ? false : regex,
9345				"bSmart":  smart === null ? true  : smart,
9346				"bCaseInsensitive": caseInsen === null ? true : caseInsen
9347			} ), 1 );
9348		} );
9349	} );
9350	
9351	
9352	_api_registerPlural(
9353		'columns().search()',
9354		'column().search()',
9355		function ( input, regex, smart, caseInsen ) {
9356			return this.iterator( 'column', function ( settings, column ) {
9357				var preSearch = settings.aoPreSearchCols;
9358	
9359				if ( input === undefined ) {
9360					// get
9361					return preSearch[ column ].sSearch;
9362				}
9363	
9364				// set
9365				if ( ! settings.oFeatures.bFilter ) {
9366					return;
9367				}
9368	
9369				$.extend( preSearch[ column ], {
9370					"sSearch": input+"",
9371					"bRegex":  regex === null ? false : regex,
9372					"bSmart":  smart === null ? true  : smart,
9373					"bCaseInsensitive": caseInsen === null ? true : caseInsen
9374				} );
9375	
9376				_fnFilterComplete( settings, settings.oPreviousSearch, 1 );
9377			} );
9378		}
9379	);
9380	
9381	/*
9382	 * State API methods
9383	 */
9384	
9385	_api_register( 'state()', function () {
9386		return this.context.length ?
9387			this.context[0].oSavedState :
9388			null;
9389	} );
9390	
9391	
9392	_api_register( 'state.clear()', function () {
9393		return this.iterator( 'table', function ( settings ) {
9394			// Save an empty object
9395			settings.fnStateSaveCallback.call( settings.oInstance, settings, {} );
9396		} );
9397	} );
9398	
9399	
9400	_api_register( 'state.loaded()', function () {
9401		return this.context.length ?
9402			this.context[0].oLoadedState :
9403			null;
9404	} );
9405	
9406	
9407	_api_register( 'state.save()', function () {
9408		return this.iterator( 'table', function ( settings ) {
9409			_fnSaveState( settings );
9410		} );
9411	} );
9412	
9413	
9414	
9415	/**
9416	 * Set the jQuery or window object to be used by DataTables
9417	 *
9418	 * @param {*} module Library / container object
9419	 * @param {string} [type] Library or container type `lib`, `win` or `datetime`.
9420	 *   If not provided, automatic detection is attempted.
9421	 */
9422	DataTable.use = function (module, type) {
9423		if (type === 'lib' || module.fn) {
9424			$ = module;
9425		}
9426		else if (type == 'win' || module.document) {
9427			window = module;
9428			document = module.document;
9429		}
9430		else if (type === 'datetime' || module.type === 'DateTime') {
9431			DataTable.DateTime = module;
9432		}
9433	}
9434	
9435	/**
9436	 * CommonJS factory function pass through. This will check if the arguments
9437	 * given are a window object or a jQuery object. If so they are set
9438	 * accordingly.
9439	 * @param {*} root Window
9440	 * @param {*} jq jQUery
9441	 * @returns {boolean} Indicator
9442	 */
9443	DataTable.factory = function (root, jq) {
9444		var is = false;
9445	
9446		// Test if the first parameter is a window object
9447		if (root && root.document) {
9448			window = root;
9449			document = root.document;
9450		}
9451	
9452		// Test if the second parameter is a jQuery object
9453		if (jq && jq.fn && jq.fn.jquery) {
9454			$ = jq;
9455			is = true;
9456		}
9457	
9458		return is;
9459	}
9460	
9461	/**
9462	 * Provide a common method for plug-ins to check the version of DataTables being
9463	 * used, in order to ensure compatibility.
9464	 *
9465	 *  @param {string} version Version string to check for, in the format "X.Y.Z".
9466	 *    Note that the formats "X" and "X.Y" are also acceptable.
9467	 *  @returns {boolean} true if this version of DataTables is greater or equal to
9468	 *    the required version, or false if this version of DataTales is not
9469	 *    suitable
9470	 *  @static
9471	 *  @dtopt API-Static
9472	 *
9473	 *  @example
9474	 *    alert( $.fn.dataTable.versionCheck( '1.9.0' ) );
9475	 */
9476	DataTable.versionCheck = DataTable.fnVersionCheck = function( version )
9477	{
9478		var aThis = DataTable.version.split('.');
9479		var aThat = version.split('.');
9480		var iThis, iThat;
9481	
9482		for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) {
9483			iThis = parseInt( aThis[i], 10 ) || 0;
9484			iThat = parseInt( aThat[i], 10 ) || 0;
9485	
9486			// Parts are the same, keep comparing
9487			if (iThis === iThat) {
9488				continue;
9489			}
9490	
9491			// Parts are different, return immediately
9492			return iThis > iThat;
9493		}
9494	
9495		return true;
9496	};
9497	
9498	
9499	/**
9500	 * Check if a `<table>` node is a DataTable table already or not.
9501	 *
9502	 *  @param {node|jquery|string} table Table node, jQuery object or jQuery
9503	 *      selector for the table to test. Note that if more than more than one
9504	 *      table is passed on, only the first will be checked
9505	 *  @returns {boolean} true the table given is a DataTable, or false otherwise
9506	 *  @static
9507	 *  @dtopt API-Static
9508	 *
9509	 *  @example
9510	 *    if ( ! $.fn.DataTable.isDataTable( '#example' ) ) {
9511	 *      $('#example').dataTable();
9512	 *    }
9513	 */
9514	DataTable.isDataTable = DataTable.fnIsDataTable = function ( table )
9515	{
9516		var t = $(table).get(0);
9517		var is = false;
9518	
9519		if ( table instanceof DataTable.Api ) {
9520			return true;
9521		}
9522	
9523		$.each( DataTable.settings, function (i, o) {
9524			var head = o.nScrollHead ? $('table', o.nScrollHead)[0] : null;
9525			var foot = o.nScrollFoot ? $('table', o.nScrollFoot)[0] : null;
9526	
9527			if ( o.nTable === t || head === t || foot === t ) {
9528				is = true;
9529			}
9530		} );
9531	
9532		return is;
9533	};
9534	
9535	
9536	/**
9537	 * Get all DataTable tables that have been initialised - optionally you can
9538	 * select to get only currently visible tables.
9539	 *
9540	 *  @param {boolean} [visible=false] Flag to indicate if you want all (default)
9541	 *    or visible tables only.
9542	 *  @returns {array} Array of `table` nodes (not DataTable instances) which are
9543	 *    DataTables
9544	 *  @static
9545	 *  @dtopt API-Static
9546	 *
9547	 *  @example
9548	 *    $.each( $.fn.dataTable.tables(true), function () {
9549	 *      $(table).DataTable().columns.adjust();
9550	 *    } );
9551	 */
9552	DataTable.tables = DataTable.fnTables = function ( visible )
9553	{
9554		var api = false;
9555	
9556		if ( $.isPlainObject( visible ) ) {
9557			api = visible.api;
9558			visible = visible.visible;
9559		}
9560	
9561		var a = $.map( DataTable.settings, function (o) {
9562			if ( !visible || (visible && $(o.nTable).is(':visible')) ) {
9563				return o.nTable;
9564			}
9565		} );
9566	
9567		return api ?
9568			new _Api( a ) :
9569			a;
9570	};
9571	
9572	
9573	/**
9574	 * Convert from camel case parameters to Hungarian notation. This is made public
9575	 * for the extensions to provide the same ability as DataTables core to accept
9576	 * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase
9577	 * parameters.
9578	 *
9579	 *  @param {object} src The model object which holds all parameters that can be
9580	 *    mapped.
9581	 *  @param {object} user The object to convert from camel case to Hungarian.
9582	 *  @param {boolean} force When set to `true`, properties which already have a
9583	 *    Hungarian value in the `user` object will be overwritten. Otherwise they
9584	 *    won't be.
9585	 */
9586	DataTable.camelToHungarian = _fnCamelToHungarian;
9587	
9588	
9589	
9590	/**
9591	 *
9592	 */
9593	_api_register( '$()', function ( selector, opts ) {
9594		var
9595			rows   = this.rows( opts ).nodes(), // Get all rows
9596			jqRows = $(rows);
9597	
9598		return $( [].concat(
9599			jqRows.filter( selector ).toArray(),
9600			jqRows.find( selector ).toArray()
9601		) );
9602	} );
9603	
9604	
9605	// jQuery functions to operate on the tables
9606	$.each( [ 'on', 'one', 'off' ], function (i, key) {
9607		_api_register( key+'()', function ( /* event, handler */ ) {
9608			var args = Array.prototype.slice.call(arguments);
9609	
9610			// Add the `dt` namespace automatically if it isn't already present
9611			args[0] = $.map( args[0].split( /\s/ ), function ( e ) {
9612				return ! e.match(/\.dt\b/) ?
9613					e+'.dt' :
9614					e;
9615				} ).join( ' ' );
9616	
9617			var inst = $( this.tables().nodes() );
9618			inst[key].apply( inst, args );
9619			return this;
9620		} );
9621	} );
9622	
9623	
9624	_api_register( 'clear()', function () {
9625		return this.iterator( 'table', function ( settings ) {
9626			_fnClearTable( settings );
9627		} );
9628	} );
9629	
9630	
9631	_api_register( 'settings()', function () {
9632		return new _Api( this.context, this.context );
9633	} );
9634	
9635	
9636	_api_register( 'init()', function () {
9637		var ctx = this.context;
9638		return ctx.length ? ctx[0].oInit : null;
9639	} );
9640	
9641	
9642	_api_register( 'data()', function () {
9643		return this.iterator( 'table', function ( settings ) {
9644			return _pluck( settings.aoData, '_aData' );
9645		} ).flatten();
9646	} );
9647	
9648	
9649	_api_register( 'destroy()', function ( remove ) {
9650		remove = remove || false;
9651	
9652		return this.iterator( 'table', function ( settings ) {
9653			var classes   = settings.oClasses;
9654			var table     = settings.nTable;
9655			var tbody     = settings.nTBody;
9656			var thead     = settings.nTHead;
9657			var tfoot     = settings.nTFoot;
9658			var jqTable   = $(table);
9659			var jqTbody   = $(tbody);
9660			var jqWrapper = $(settings.nTableWrapper);
9661			var rows      = $.map( settings.aoData, function (r) { return r.nTr; } );
9662			var i, ien;
9663	
9664			// Flag to note that the table is currently being destroyed - no action
9665			// should be taken
9666			settings.bDestroying = true;
9667	
9668			// Fire off the destroy callbacks for plug-ins etc
9669			_fnCallbackFire( settings, "aoDestroyCallback", "destroy", [settings] );
9670	
9671			// If not being removed from the document, make all columns visible
9672			if ( ! remove ) {
9673				new _Api( settings ).columns().visible( true );
9674			}
9675	
9676			// Blitz all `DT` namespaced events (these are internal events, the
9677			// lowercase, `dt` events are user subscribed and they are responsible
9678			// for removing them
9679			jqWrapper.off('.DT').find(':not(tbody *)').off('.DT');
9680			$(window).off('.DT-'+settings.sInstance);
9681	
9682			// When scrolling we had to break the table up - restore it
9683			if ( table != thead.parentNode ) {
9684				jqTable.children('thead').detach();
9685				jqTable.append( thead );
9686			}
9687	
9688			if ( tfoot && table != tfoot.parentNode ) {
9689				jqTable.children('tfoot').detach();
9690				jqTable.append( tfoot );
9691			}
9692	
9693			settings.aaSorting = [];
9694			settings.aaSortingFixed = [];
9695			_fnSortingClasses( settings );
9696	
9697			$( rows ).removeClass( settings.asStripeClasses.join(' ') );
9698	
9699			$('th, td', thead).removeClass( classes.sSortable+' '+
9700				classes.sSortableAsc+' '+classes.sSortableDesc+' '+classes.sSortableNone
9701			);
9702	
9703			// Add the TR elements back into the table in their original order
9704			jqTbody.children().detach();
9705			jqTbody.append( rows );
9706	
9707			var orig = settings.nTableWrapper.parentNode;
9708	
9709			// Remove the DataTables generated nodes, events and classes
9710			var removedMethod = remove ? 'remove' : 'detach';
9711			jqTable[ removedMethod ]();
9712			jqWrapper[ removedMethod ]();
9713	
9714			// If we need to reattach the table to the document
9715			if ( ! remove && orig ) {
9716				// insertBefore acts like appendChild if !arg[1]
9717				orig.insertBefore( table, settings.nTableReinsertBefore );
9718	
9719				// Restore the width of the original table - was read from the style property,
9720				// so we can restore directly to that
9721				jqTable
9722					.css( 'width', settings.sDestroyWidth )
9723					.removeClass( classes.sTable );
9724	
9725				// If the were originally stripe classes - then we add them back here.
9726				// Note this is not fool proof (for example if not all rows had stripe
9727				// classes - but it's a good effort without getting carried away
9728				ien = settings.asDestroyStripes.length;
9729	
9730				if ( ien ) {
9731					jqTbody.children().each( function (i) {
9732						$(this).addClass( settings.asDestroyStripes[i % ien] );
9733					} );
9734				}
9735			}
9736	
9737			/* Remove the settings object from the settings array */
9738			var idx = $.inArray( settings, DataTable.settings );
9739			if ( idx !== -1 ) {
9740				DataTable.settings.splice( idx, 1 );
9741			}
9742		} );
9743	} );
9744	
9745	
9746	// Add the `every()` method for rows, columns and cells in a compact form
9747	$.each( [ 'column', 'row', 'cell' ], function ( i, type ) {
9748		_api_register( type+'s().every()', function ( fn ) {
9749			var opts = this.selector.opts;
9750			var api = this;
9751	
9752			return this.iterator( type, function ( settings, arg1, arg2, arg3, arg4 ) {
9753				// Rows and columns:
9754				//  arg1 - index
9755				//  arg2 - table counter
9756				//  arg3 - loop counter
9757				//  arg4 - undefined
9758				// Cells:
9759				//  arg1 - row index
9760				//  arg2 - column index
9761				//  arg3 - table counter
9762				//  arg4 - loop counter
9763				fn.call(
9764					api[ type ](
9765						arg1,
9766						type==='cell' ? arg2 : opts,
9767						type==='cell' ? opts : undefined
9768					),
9769					arg1, arg2, arg3, arg4
9770				);
9771			} );
9772		} );
9773	} );
9774	
9775	
9776	// i18n method for extensions to be able to use the language object from the
9777	// DataTable
9778	_api_register( 'i18n()', function ( token, def, plural ) {
9779		var ctx = this.context[0];
9780		var resolved = _fnGetObjectDataFn( token )( ctx.oLanguage );
9781	
9782		if ( resolved === undefined ) {
9783			resolved = def;
9784		}
9785	
9786		if ( plural !== undefined && $.isPlainObject( resolved ) ) {
9787			resolved = resolved[ plural ] !== undefined ?
9788				resolved[ plural ] :
9789				resolved._;
9790		}
9791	
9792		return typeof resolved === 'string'
9793			? resolved.replace( '%d', plural ) // nb: plural might be undefined,
9794			: resolved;
9795	} );	
9796	/**
9797	 * Version string for plug-ins to check compatibility. Allowed format is
9798	 * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used
9799	 * only for non-release builds. See http
9799s://semver.org/ for more information.
9800	 *  @member
9801	 *  @type string
9802	 *  @default Version number
9803	 */
9804	DataTable.version = "1.13.11
vendor: 17,667 bytes, lines 9804-10380
9804";
9805	
9806	/**
9807	 * Private data store, containing all of the settings objects that are
9808	 * created for the tables on a given page.
9809	 *
9810	 * Note that the `DataTable.settings` object is aliased to
9811	 * `jQuery.fn.dataTableExt` through which it may be accessed and
9812	 * manipulated, or `jQuery.fn.dataTable.settings`.
9813	 *  @member
9814	 *  @type array
9815	 *  @default []
9816	 *  @private
9817	 */
9818	DataTable.settings = [];
9819	
9820	/**
9821	 * Object models container, for the various models that DataTables has
9822	 * available to it. These models define the objects that are used to hold
9823	 * the active state and configuration of the table.
9824	 *  @namespace
9825	 */
9826	DataTable.models = {};
9827	
9828	
9829	
9830	/**
9831	 * Template object for the way in which DataTables holds information about
9832	 * search information for the global filter and individual column filters.
9833	 *  @namespace
9834	 */
9835	DataTable.models.oSearch = {
9836		/**
9837		 * Flag to indicate if the filtering should be case insensitive or not
9838		 *  @type boolean
9839		 *  @default true
9840		 */
9841		"bCaseInsensitive": true,
9842	
9843		/**
9844		 * Applied search term
9845		 *  @type string
9846		 *  @default <i>Empty string</i>
9847		 */
9848		"sSearch": "",
9849	
9850		/**
9851		 * Flag to indicate if the search term should be interpreted as a
9852		 * regular expression (true) or not (false) and therefore and special
9853		 * regex characters escaped.
9854		 *  @type boolean
9855		 *  @default false
9856		 */
9857		"bRegex": false,
9858	
9859		/**
9860		 * Flag to indicate if DataTables is to use its smart filtering or not.
9861		 *  @type boolean
9862		 *  @default true
9863		 */
9864		"bSmart": true,
9865	
9866		/**
9867		 * Flag to indicate if DataTables should only trigger a search when
9868		 * the return key is pressed.
9869		 *  @type boolean
9870		 *  @default false
9871		 */
9872		"return": false
9873	};
9874	
9875	
9876	
9877	
9878	/**
9879	 * Template object for the way in which DataTables holds information about
9880	 * each individual row. This is the object format used for the settings
9881	 * aoData array.
9882	 *  @namespace
9883	 */
9884	DataTable.models.oRow = {
9885		/**
9886		 * TR element for the row
9887		 *  @type node
9888		 *  @default null
9889		 */
9890		"nTr": null,
9891	
9892		/**
9893		 * Array of TD elements for each row. This is null until the row has been
9894		 * created.
9895		 *  @type array nodes
9896		 *  @default []
9897		 */
9898		"anCells": null,
9899	
9900		/**
9901		 * Data object from the original data source for the row. This is either
9902		 * an array if using the traditional form of DataTables, or an object if
9903		 * using mData options. The exact type will depend on the passed in
9904		 * data from the data source, or will be an array if using DOM a data
9905		 * source.
9906		 *  @type array|object
9907		 *  @default []
9908		 */
9909		"_aData": [],
9910	
9911		/**
9912		 * Sorting data cache - this array is ostensibly the same length as the
9913		 * number of columns (although each index is generated only as it is
9914		 * needed), and holds the data that is used for sorting each column in the
9915		 * row. We do this cache generation at the start of the sort in order that
9916		 * the formatting of the sort data need be done only once for each cell
9917		 * per sort. This array should not be read from or written to by anything
9918		 * other than the master sorting methods.
9919		 *  @type array
9920		 *  @default null
9921		 *  @private
9922		 */
9923		"_aSortData": null,
9924	
9925		/**
9926		 * Per cell filtering data cache. As per the sort data cache, used to
9927		 * increase the performance of the filtering in DataTables
9928		 *  @type array
9929		 *  @default null
9930		 *  @private
9931		 */
9932		"_aFilterData": null,
9933	
9934		/**
9935		 * Filtering data cache. This is the same as the cell filtering cache, but
9936		 * in this case a string rather than an array. This is easily computed with
9937		 * a join on `_aFilterData`, but is provided as a cache so the join isn't
9938		 * needed on every search (memory traded for performance)
9939		 *  @type array
9940		 *  @default null
9941		 *  @private
9942		 */
9943		"_sFilterRow": null,
9944	
9945		/**
9946		 * Cache of the class name that DataTables has applied to the row, so we
9947		 * can quickly look at this variable rather than needing to do a DOM check
9948		 * on className for the nTr property.
9949		 *  @type string
9950		 *  @default <i>Empty string</i>
9951		 *  @private
9952		 */
9953		"_sRowStripe": "",
9954	
9955		/**
9956		 * Denote if the original data source was from the DOM, or the data source
9957		 * object. This is used for invalidating data, so DataTables can
9958		 * automatically read data from the original source, unless uninstructed
9959		 * otherwise.
9960		 *  @type string
9961		 *  @default null
9962		 *  @private
9963		 */
9964		"src": null,
9965	
9966		/**
9967		 * Index in the aoData array. This saves an indexOf lookup when we have the
9968		 * object, but want to know the index
9969		 *  @type integer
9970		 *  @default -1
9971		 *  @private
9972		 */
9973		"idx": -1
9974	};
9975	
9976	
9977	/**
9978	 * Template object for the column information object in DataTables. This object
9979	 * is held in the settings aoColumns array and contains all the information that
9980	 * DataTables needs about each individual column.
9981	 *
9982	 * Note that this object is related to {@link DataTable.defaults.column}
9983	 * but this one is the internal data store for DataTables's cache of columns.
9984	 * It should NOT be manipulated outside of DataTables. Any configuration should
9985	 * be done through the initialisation options.
9986	 *  @namespace
9987	 */
9988	DataTable.models.oColumn = {
9989		/**
9990		 * Column index. This could be worked out on-the-fly with $.inArray, but it
9991		 * is faster to just hold it as a variable
9992		 *  @type integer
9993		 *  @default null
9994		 */
9995		"idx": null,
9996	
9997		/**
9998		 * A list of the columns that sorting should occur on when this column
9999		 * is sorted. That this property is an array allows multi-column sorting
10000		 * to be defined for a column (for example first name / last name columns
10001		 * would benefit from this). The values are integers pointing to the
10002		 * columns to be sorted on (typically it will be a single integer pointing
10003		 * at itself, but that doesn't need to be the case).
10004		 *  @type array
10005		 */
10006		"aDataSort": null,
10007	
10008		/**
10009		 * Define the sorting directions that are applied to the column, in sequence
10010		 * as the column is repeatedly sorted upon - i.e. the first value is used
10011		 * as the sorting direction when the column if first sorted (clicked on).
10012		 * Sort it again (click again) and it will move on to the next index.
10013		 * Repeat until loop.
10014		 *  @type array
10015		 */
10016		"asSorting": null,
10017	
10018		/**
10019		 * Flag to indicate if the column is searchable, and thus should be included
10020		 * in the filtering or not.
10021		 *  @type boolean
10022		 */
10023		"bSearchable": null,
10024	
10025		/**
10026		 * Flag to indicate if the column is sortable or not.
10027		 *  @type boolean
10028		 */
10029		"bSortable": null,
10030	
10031		/**
10032		 * Flag to indicate if the column is currently visible in the table or not
10033		 *  @type boolean
10034		 */
10035		"bVisible": null,
10036	
10037		/**
10038		 * Store for manual type assignment using the `column.type` option. This
10039		 * is held in store so we can manipulate the column's `sType` property.
10040		 *  @type string
10041		 *  @default null
10042		 *  @private
10043		 */
10044		"_sManualType": null,
10045	
10046		/**
10047		 * Flag to indicate if HTML5 data attributes should be used as the data
10048		 * source for filtering or sorting. True is either are.
10049		 *  @type boolean
10050		 *  @default false
10051		 *  @private
10052		 */
10053		"_bAttrSrc": false,
10054	
10055		/**
10056		 * Developer definable function that is called whenever a cell is created (Ajax source,
10057		 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
10058		 * allowing you to modify the DOM element (add background colour for example) when the
10059		 * element is available.
10060		 *  @type function
10061		 *  @param {element} nTd The TD node that has been created
10062		 *  @param {*} sData The Data for the cell
10063		 *  @param {array|object} oData The data for the whole row
10064		 *  @param {int} iRow The row index for the aoData data store
10065		 *  @default null
10066		 */
10067		"fnCreatedCell": null,
10068	
10069		/**
10070		 * Function to get data from a cell in a column. You should <b>never</b>
10071		 * access data directly through _aData internally in DataTables - always use
10072		 * the method attached to this property. It allows mData to function as
10073		 * required. This function is automatically assigned by the column
10074		 * initialisation method
10075		 *  @type function
10076		 *  @param {array|object} oData The data array/object for the array
10077		 *    (i.e. aoData[]._aData)
10078		 *  @param {string} sSpecific The specific data type you want to get -
10079		 *    'display', 'type' 'filter' 'sort'
10080		 *  @returns {*} The data for the cell from the given row's data
10081		 *  @default null
10082		 */
10083		"fnGetData": null,
10084	
10085		/**
10086		 * Function to set data for a cell in the column. You should <b>never</b>
10087		 * set the data directly to _aData internally in DataTables - always use
10088		 * this method. It allows mData to function as required. This function
10089		 * is automatically assigned by the column initialisation method
10090		 *  @type function
10091		 *  @param {array|object} oData The data array/object for the array
10092		 *    (i.e. aoData[]._aData)
10093		 *  @param {*} sValue Value to set
10094		 *  @default null
10095		 */
10096		"fnSetData": null,
10097	
10098		/**
10099		 * Property to read the value for the cells in the column from the data
10100		 * source array / object. If null, then the default content is used, if a
10101		 * function is given then the return from the function is used.
10102		 *  @type function|int|string|null
10103		 *  @default null
10104		 */
10105		"mData": null,
10106	
10107		/**
10108		 * Partner property to mData which is used (only when defined) to get
10109		 * the data - i.e. it is basically the same as mData, but without the
10110		 * 'set' option, and also the data fed to it is the result from mData.
10111		 * This is the rendering method to match the data method of mData.
10112		 *  @type function|int|string|null
10113		 *  @default null
10114		 */
10115		"mRender": null,
10116	
10117		/**
10118		 * Unique header TH/TD element for this column - this is what the sorting
10119		 * listener is attached to (if sorting is enabled.)
10120		 *  @type node
10121		 *  @default null
10122		 */
10123		"nTh": null,
10124	
10125		/**
10126		 * Unique footer TH/TD element for this column (if there is one). Not used
10127		 * in DataTables as such, but can be used for plug-ins to reference the
10128		 * footer for each column.
10129		 *  @type node
10130		 *  @default null
10131		 */
10132		"nTf": null,
10133	
10134		/**
10135		 * The class to apply to all TD elements in the table's TBODY for the column
10136		 *  @type string
10137		 *  @default null
10138		 */
10139		"sClass": null,
10140	
10141		/**
10142		 * When DataTables calculates the column widths to assign to each column,
10143		 * it finds the longest string in each column and then constructs a
10144		 * temporary table and reads the widths from that. The problem with this
10145		 * is that "mmm" is much wider then "iiii", but the latter is a longer
10146		 * string - thus the calculation can go wrong (doing it properly and putting
10147		 * it into an DOM object and measuring that is horribly(!) slow). Thus as
10148		 * a "work around" we provide this option. It will append its value to the
10149		 * text that is found to be the longest string for the column - i.e. padding.
10150		 *  @type string
10151		 */
10152		"sContentPadding": null,
10153	
10154		/**
10155		 * Allows a default value to be given for a column's data, and will be used
10156		 * whenever a null data source is encountered (this can be because mData
10157		 * is set to null, or because the data source itself is null).
10158		 *  @type string
10159		 *  @default null
10160		 */
10161		"sDefaultContent": null,
10162	
10163		/**
10164		 * Name for the column, allowing reference to the column by name as well as
10165		 * by index (needs a lookup to work by name).
10166		 *  @type string
10167		 */
10168		"sName": null,
10169	
10170		/**
10171		 * Custom sorting data type - defines which of the available plug-ins in
10172		 * afnSortData the custom sorting will use - if any is defined.
10173		 *  @type string
10174		 *  @default std
10175		 */
10176		"sSortDataType": 'std',
10177	
10178		/**
10179		 * Class to be applied to the header element when sorting on this column
10180		 *  @type string
10181		 *  @default null
10182		 */
10183		"sSortingClass": null,
10184	
10185		/**
10186		 * Class to be applied to the header element when sorting on this column -
10187		 * when jQuery UI theming is used.
10188		 *  @type string
10189		 *  @default null
10190		 */
10191		"sSortingClassJUI": null,
10192	
10193		/**
10194		 * Title of the column - what is seen in the TH element (nTh).
10195		 *  @type string
10196		 */
10197		"sTitle": null,
10198	
10199		/**
10200		 * Column sorting and filtering type
10201		 *  @type string
10202		 *  @default null
10203		 */
10204		"sType": null,
10205	
10206		/**
10207		 * Width of the column
10208		 *  @type string
10209		 *  @default null
10210		 */
10211		"sWidth": null,
10212	
10213		/**
10214		 * Width of the column when it was first "encountered"
10215		 *  @type string
10216		 *  @default null
10217		 */
10218		"sWidthOrig": null
10219	};
10220	
10221	
10222	/*
10223	 * Developer note: The properties of the object below are given in Hungarian
10224	 * notation, that was used as the interface for DataTables prior to v1.10, however
10225	 * from v1.10 onwards the primary interface is camel case. In order to avoid
10226	 * breaking backwards compatibility utterly with this change, the Hungarian
10227	 * version is still, internally the primary interface, but is is not documented
10228	 * - hence the @name tags in each doc comment. This allows a Javascript function
10229	 * to create a map from Hungarian notation to camel case (going the other direction
10230	 * would require each property to be listed, which would add around 3K to the size
10231	 * of DataTables, while this method is about a 0.5K hit).
10232	 *
10233	 * Ultimately this does pave the way for Hungarian notation to be dropped
10234	 * completely, but that is a massive amount of work and will break current
10235	 * installs (therefore is on-hold until v2).
10236	 */
10237	
10238	/**
10239	 * Initialisation options that can be given to DataTables at initialisation
10240	 * time.
10241	 *  @namespace
10242	 */
10243	DataTable.defaults = {
10244		/**
10245		 * An array of data to use for the table, passed in at initialisation which
10246		 * will be used in preference to any data which is already in the DOM. This is
10247		 * particularly useful for constructing tables purely in Javascript, for
10248		 * example with a custom Ajax call.
10249		 *  @type array
10250		 *  @default null
10251		 *
10252		 *  @dtopt Option
10253		 *  @name DataTable.defaults.data
10254		 *
10255		 *  @example
10256		 *    // Using a 2D array data source
10257		 *    $(document).ready( function () {
10258		 *      $('#example').dataTable( {
10259		 *        "data": [
10260		 *          ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
10261		 *          ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
10262		 *        ],
10263		 *        "columns": [
10264		 *          { "title": "Engine" },
10265		 *          { "title": "Browser" },
10266		 *          { "title": "Platform" },
10267		 *          { "title": "Version" },
10268		 *          { "title": "Grade" }
10269		 *        ]
10270		 *      } );
10271		 *    } );
10272		 *
10273		 *  @example
10274		 *    // Using an array of objects as a data source (`data`)
10275		 *    $(document).ready( function () {
10276		 *      $('#example').dataTable( {
10277		 *        "data": [
10278		 *          {
10279		 *            "engine":   "Trident",
10280		 *            "browser":  "Internet Explorer 4.0",
10281		 *            "platform": "Win 95+",
10282		 *            "version":  4,
10283		 *            "grade":    "X"
10284		 *          },
10285		 *          {
10286		 *            "engine":   "Trident",
10287		 *            "browser":  "Internet Explorer 5.0",
10288		 *            "platform": "Win 95+",
10289		 *            "version":  5,
10290		 *            "grade":    "C"
10291		 *          }
10292		 *        ],
10293		 *        "columns": [
10294		 *          { "title": "Engine",   "data": "engine" },
10295		 *          { "title": "Browser",  "data": "browser" },
10296		 *          { "title": "Platform", "data": "platform" },
10297		 *          { "title": "Version",  "data": "version" },
10298		 *          { "title": "Grade",    "data": "grade" }
10299		 *        ]
10300		 *      } );
10301		 *    } );
10302		 */
10303		"aaData": null,
10304	
10305	
10306		/**
10307		 * If ordering is enabled, then DataTables will perform a first pass sort on
10308		 * initialisation. You can define which column(s) the sort is performed
10309		 * upon, and the sorting direction, with this variable. The `sorting` array
10310		 * should contain an array for each column to be sorted initially containing
10311		 * the column's index and a direction string ('asc' or 'desc').
10312		 *  @type array
10313		 *  @default [[0,'asc']]
10314		 *
10315		 *  @dtopt Option
10316		 *  @name DataTable.defaults.order
10317		 *
10318		 *  @example
10319		 *    // Sort by 3rd column first, and then 4th column
10320		 *    $(document).ready( function() {
10321		 *      $('#example').dataTable( {
10322		 *        "order": [[2,'asc'], [3,'desc']]
10323		 *      } );
10324		 *    } );
10325		 *
10326		 *    // No initial sorting
10327		 *    $(document).ready( function() {
10328		 *      $('#example').dataTable( {
10329		 *        "order": []
10330		 *      } );
10331		 *    } );
10332		 */
10333		"aaSorting": [[0,'asc']],
10334	
10335	
10336		/**
10337		 * This parameter is basically identical to the `sorting` parameter, but
10338		 * cannot be overridden by user interaction with the table. What this means
10339		 * is that you could have a column (visible or hidden) which the sorting
10340		 * will always be forced on first - any sorting after that (from the user)
10341		 * will then be performed as required. This can be useful for grouping rows
10342		 * together.
10343		 *  @type array
10344		 *  @default null
10345		 *
10346		 *  @dtopt Option
10347		 *  @name DataTable.defaults.orderFixed
10348		 *
10349		 *  @example
10350		 *    $(document).ready( function() {
10351		 *      $('#example').dataTable( {
10352		 *        "orderFixed": [[0,'asc']]
10353		 *      } );
10354		 *    } )
10355		 */
10356		"aaSortingFixed": [],
10357	
10358	
10359		/**
10360		 * DataTables can be instructed to load data to display in the table from a
10361		 * Ajax source. This option defines how that Ajax call is made and where to.
10362		 *
10363		 * The `ajax` property has three different modes of operation, depending on
10364		 * how it is defined. These are:
10365		 *
10366		 * * `string` - Set the URL from where the data should be loaded from.
10367		 * * `object` - Define properties for `jQuery.ajax`.
10368		 * * `function` - Custom data get function
10369		 *
10370		 * `string`
10371		 * --------
10372		 *
10373		 * As a string, the `ajax` property simply defines the URL from which
10374		 * DataTables will load data.
10375		 *
10376		 * `object`
10377		 * --------
10378		 *
10379		 * As an object, the parameters in the object are passed to
10380		 * [jQuery.ajax](http
10380s
vendor: 54,865 bytes, lines 10380-12088
10380://api.jquery.com/jQuery.ajax/) allowing fine control
10381		 * of the Ajax request. DataTables has a number of default parameters which
10382		 * you can override using this option. Please refer to the jQuery
10383		 * documentation for a full description of the options available, although
10384		 * the following parameters provide additional options in DataTables or
10385		 * require special consideration:
10386		 *
10387		 * * `data` - As with jQuery, `data` can be provided as an object, but it
10388		 *   can also be used as a function to manipulate the data DataTables sends
10389		 *   to the server. The function takes a single parameter, an object of
10390		 *   parameters with the values that DataTables has readied for sending. An
10391		 *   object may be returned which will be merged into the DataTables
10392		 *   defaults, or you can add the items to the object that was passed in and
10393		 *   not return anything from the function. This supersedes `fnServerParams`
10394		 *   from DataTables 1.9-.
10395		 *
10396		 * * `dataSrc` - By default DataTables will look for the property `data` (or
10397		 *   `aaData` for compatibility with DataTables 1.9-) when obtaining data
10398		 *   from an Ajax source or for server-side processing - this parameter
10399		 *   allows that property to be changed. You can use Javascript dotted
10400		 *   object notation to get a data source for multiple levels of nesting, or
10401		 *   it my be used as a function. As a function it takes a single parameter,
10402		 *   the JSON returned from the server, which can be manipulated as
10403		 *   required, with the returned value being that used by DataTables as the
10404		 *   data source for the table. This supersedes `sAjaxDataProp` from
10405		 *   DataTables 1.9-.
10406		 *
10407		 * * `success` - Should not be overridden it is used internally in
10408		 *   DataTables. To manipulate / transform the data returned by the server
10409		 *   use `ajax.dataSrc`, or use `ajax` as a function (see below).
10410		 *
10411		 * `function`
10412		 * ----------
10413		 *
10414		 * As a function, making the Ajax call is left up to yourself allowing
10415		 * complete control of the Ajax request. Indeed, if desired, a method other
10416		 * than Ajax could be used to obtain the required data, such as Web storage
10417		 * or an AIR database.
10418		 *
10419		 * The function is given four parameters and no return is required. The
10420		 * parameters are:
10421		 *
10422		 * 1. _object_ - Data to send to the server
10423		 * 2. _function_ - Callback function that must be executed when the required
10424		 *    data has been obtained. That data should be passed into the callback
10425		 *    as the only parameter
10426		 * 3. _object_ - DataTables settings object for the table
10427		 *
10428		 * Note that this supersedes `fnServerData` from DataTables 1.9-.
10429		 *
10430		 *  @type string|object|function
10431		 *  @default null
10432		 *
10433		 *  @dtopt Option
10434		 *  @name DataTable.defaults.ajax
10435		 *  @since 1.10.0
10436		 *
10437		 * @example
10438		 *   // Get JSON data from a file via Ajax.
10439		 *   // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default).
10440		 *   $('#example').dataTable( {
10441		 *     "ajax": "data.json"
10442		 *   } );
10443		 *
10444		 * @example
10445		 *   // Get JSON data from a file via Ajax, using `dataSrc` to change
10446		 *   // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`)
10447		 *   $('#example').dataTable( {
10448		 *     "ajax": {
10449		 *       "url": "data.json",
10450		 *       "dataSrc": "tableData"
10451		 *     }
10452		 *   } );
10453		 *
10454		 * @example
10455		 *   // Get JSON data from a file via Ajax, using `dataSrc` to read data
10456		 *   // from a plain array rather than an array in an object
10457		 *   $('#example').dataTable( {
10458		 *     "ajax": {
10459		 *       "url": "data.json",
10460		 *       "dataSrc": ""
10461		 *     }
10462		 *   } );
10463		 *
10464		 * @example
10465		 *   // Manipulate the data returned from the server - add a link to data
10466		 *   // (note this can, should, be done using `render` for the column - this
10467		 *   // is just a simple example of how the data can be manipulated).
10468		 *   $('#example').dataTable( {
10469		 *     "ajax": {
10470		 *       "url": "data.json",
10471		 *       "dataSrc": function ( json ) {
10472		 *         for ( var i=0, ien=json.length ; i<ien ; i++ ) {
10473		 *           json[i][0] = '<a href="/message/'+json[i][0]+'>View message</a>';
10474		 *         }
10475		 *         return json;
10476		 *       }
10477		 *     }
10478		 *   } );
10479		 *
10480		 * @example
10481		 *   // Add data to the request
10482		 *   $('#example').dataTable( {
10483		 *     "ajax": {
10484		 *       "url": "data.json",
10485		 *       "data": function ( d ) {
10486		 *         return {
10487		 *           "extra_search": $('#extra').val()
10488		 *         };
10489		 *       }
10490		 *     }
10491		 *   } );
10492		 *
10493		 * @example
10494		 *   // Send request as POST
10495		 *   $('#example').dataTable( {
10496		 *     "ajax": {
10497		 *       "url": "data.json",
10498		 *       "type": "POST"
10499		 *     }
10500		 *   } );
10501		 *
10502		 * @example
10503		 *   // Get the data from localStorage (could interface with a form for
10504		 *   // adding, editing and removing rows).
10505		 *   $('#example').dataTable( {
10506		 *     "ajax": function (data, callback, settings) {
10507		 *       callback(
10508		 *         JSON.parse( localStorage.getItem('dataTablesData') )
10509		 *       );
10510		 *     }
10511		 *   } );
10512		 */
10513		"ajax": null,
10514	
10515	
10516		/**
10517		 * This parameter allows you to readily specify the entries in the length drop
10518		 * down menu that DataTables shows when pagination is enabled. It can be
10519		 * either a 1D array of options which will be used for both the displayed
10520		 * option and the value, or a 2D array which will use the array in the first
10521		 * position as the value, and the array in the second position as the
10522		 * displayed options (useful for language strings such as 'All').
10523		 *
10524		 * Note that the `pageLength` property will be automatically set to the
10525		 * first value given in this array, unless `pageLength` is also provided.
10526		 *  @type array
10527		 *  @default [ 10, 25, 50, 100 ]
10528		 *
10529		 *  @dtopt Option
10530		 *  @name DataTable.defaults.lengthMenu
10531		 *
10532		 *  @example
10533		 *    $(document).ready( function() {
10534		 *      $('#example').dataTable( {
10535		 *        "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
10536		 *      } );
10537		 *    } );
10538		 */
10539		"aLengthMenu": [ 10, 25, 50, 100 ],
10540	
10541	
10542		/**
10543		 * The `columns` option in the initialisation parameter allows you to define
10544		 * details about the way individual columns behave. For a full list of
10545		 * column options that can be set, please see
10546		 * {@link DataTable.defaults.column}. Note that if you use `columns` to
10547		 * define your columns, you must have an entry in the array for every single
10548		 * column that you have in your table (these can be null if you don't which
10549		 * to specify any options).
10550		 *  @member
10551		 *
10552		 *  @name DataTable.defaults.column
10553		 */
10554		"aoColumns": null,
10555	
10556		/**
10557		 * Very similar to `columns`, `columnDefs` allows you to target a specific
10558		 * column, multiple columns, or all columns, using the `targets` property of
10559		 * each object in the array. This allows great flexibility when creating
10560		 * tables, as the `columnDefs` arrays can be of any length, targeting the
10561		 * columns you specifically want. `columnDefs` may use any of the column
10562		 * options available: {@link DataTable.defaults.column}, but it _must_
10563		 * have `targets` defined in each object in the array. Values in the `targets`
10564		 * array may be:
10565		 *   <ul>
10566		 *     <li>a string - class name will be matched on the TH for the column</li>
10567		 *     <li>0 or a positive integer - column index counting from the left</li>
10568		 *     <li>a negative integer - column index counting from the right</li>
10569		 *     <li>the string "_all" - all columns (i.e. assign a default)</li>
10570		 *   </ul>
10571		 *  @member
10572		 *
10573		 *  @name DataTable.defaults.columnDefs
10574		 */
10575		"aoColumnDefs": null,
10576	
10577	
10578		/**
10579		 * Basically the same as `search`, this parameter defines the individual column
10580		 * filtering state at initialisation time. The array must be of the same size
10581		 * as the number of columns, and each element be an object with the parameters
10582		 * `search` and `escapeRegex` (the latter is optional). 'null' is also
10583		 * accepted and the default will be used.
10584		 *  @type array
10585		 *  @default []
10586		 *
10587		 *  @dtopt Option
10588		 *  @name DataTable.defaults.searchCols
10589		 *
10590		 *  @example
10591		 *    $(document).ready( function() {
10592		 *      $('#example').dataTable( {
10593		 *        "searchCols": [
10594		 *          null,
10595		 *          { "search": "My filter" },
10596		 *          null,
10597		 *          { "search": "^[0-9]", "escapeRegex": false }
10598		 *        ]
10599		 *      } );
10600		 *    } )
10601		 */
10602		"aoSearchCols": [],
10603	
10604	
10605		/**
10606		 * An array of CSS classes that should be applied to displayed rows. This
10607		 * array may be of any length, and DataTables will apply each class
10608		 * sequentially, looping when required.
10609		 *  @type array
10610		 *  @default null <i>Will take the values determined by the `oClasses.stripe*`
10611		 *    options</i>
10612		 *
10613		 *  @dtopt Option
10614		 *  @name DataTable.defaults.stripeClasses
10615		 *
10616		 *  @example
10617		 *    $(document).ready( function() {
10618		 *      $('#example').dataTable( {
10619		 *        "stripeClasses": [ 'strip1', 'strip2', 'strip3' ]
10620		 *      } );
10621		 *    } )
10622		 */
10623		"asStripeClasses": null,
10624	
10625	
10626		/**
10627		 * Enable or disable automatic column width calculation. This can be disabled
10628		 * as an optimisation (it takes some time to calculate the widths) if the
10629		 * tables widths are passed in using `columns`.
10630		 *  @type boolean
10631		 *  @default true
10632		 *
10633		 *  @dtopt Features
10634		 *  @name DataTable.defaults.autoWidth
10635		 *
10636		 *  @example
10637		 *    $(document).ready( function () {
10638		 *      $('#example').dataTable( {
10639		 *        "autoWidth": false
10640		 *      } );
10641		 *    } );
10642		 */
10643		"bAutoWidth": true,
10644	
10645	
10646		/**
10647		 * Deferred rendering can provide DataTables with a huge speed boost when you
10648		 * are using an Ajax or JS data source for the table. This option, when set to
10649		 * true, will cause DataTables to defer the creation of the table elements for
10650		 * each row until they are needed for a draw - saving a significant amount of
10651		 * time.
10652		 *  @type boolean
10653		 *  @default false
10654		 *
10655		 *  @dtopt Features
10656		 *  @name DataTable.defaults.deferRender
10657		 *
10658		 *  @example
10659		 *    $(document).ready( function() {
10660		 *      $('#example').dataTable( {
10661		 *        "ajax": "sources/arrays.txt",
10662		 *        "deferRender": true
10663		 *      } );
10664		 *    } );
10665		 */
10666		"bDeferRender": false,
10667	
10668	
10669		/**
10670		 * Replace a DataTable which matches the given selector and replace it with
10671		 * one which has the properties of the new initialisation object passed. If no
10672		 * table matches the selector, then the new DataTable will be constructed as
10673		 * per normal.
10674		 *  @type boolean
10675		 *  @default false
10676		 *
10677		 *  @dtopt Options
10678		 *  @name DataTable.defaults.destroy
10679		 *
10680		 *  @example
10681		 *    $(document).ready( function() {
10682		 *      $('#example').dataTable( {
10683		 *        "srollY": "200px",
10684		 *        "paginate": false
10685		 *      } );
10686		 *
10687		 *      // Some time later....
10688		 *      $('#example').dataTable( {
10689		 *        "filter": false,
10690		 *        "destroy": true
10691		 *      } );
10692		 *    } );
10693		 */
10694		"bDestroy": false,
10695	
10696	
10697		/**
10698		 * Enable or disable filtering of data. Filtering in DataTables is "smart" in
10699		 * that it allows the end user to input multiple words (space separated) and
10700		 * will match a row containing those words, even if not in the order that was
10701		 * specified (this allow matching across multiple columns). Note that if you
10702		 * wish to use filtering in DataTables this must remain 'true' - to remove the
10703		 * default filtering input box and retain filtering abilities, please use
10704		 * {@link DataTable.defaults.dom}.
10705		 *  @type boolean
10706		 *  @default true
10707		 *
10708		 *  @dtopt Features
10709		 *  @name DataTable.defaults.searching
10710		 *
10711		 *  @example
10712		 *    $(document).ready( function () {
10713		 *      $('#example').dataTable( {
10714		 *        "searching": false
10715		 *      } );
10716		 *    } );
10717		 */
10718		"bFilter": true,
10719	
10720	
10721		/**
10722		 * Enable or disable the table information display. This shows information
10723		 * about the data that is currently visible on the page, including information
10724		 * about filtered data if that action is being performed.
10725		 *  @type boolean
10726		 *  @default true
10727		 *
10728		 *  @dtopt Features
10729		 *  @name DataTable.defaults.info
10730		 *
10731		 *  @example
10732		 *    $(document).ready( function () {
10733		 *      $('#example').dataTable( {
10734		 *        "info": false
10735		 *      } );
10736		 *    } );
10737		 */
10738		"bInfo": true,
10739	
10740	
10741		/**
10742		 * Allows the end user to select the size of a formatted page from a select
10743		 * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`).
10744		 *  @type boolean
10745		 *  @default true
10746		 *
10747		 *  @dtopt Features
10748		 *  @name DataTable.defaults.lengthChange
10749		 *
10750		 *  @example
10751		 *    $(document).ready( function () {
10752		 *      $('#example').dataTable( {
10753		 *        "lengthChange": false
10754		 *      } );
10755		 *    } );
10756		 */
10757		"bLengthChange": true,
10758	
10759	
10760		/**
10761		 * Enable or disable pagination.
10762		 *  @type boolean
10763		 *  @default true
10764		 *
10765		 *  @dtopt Features
10766		 *  @name DataTable.defaults.paging
10767		 *
10768		 *  @example
10769		 *    $(document).ready( function () {
10770		 *      $('#example').dataTable( {
10771		 *        "paging": false
10772		 *      } );
10773		 *    } );
10774		 */
10775		"bPaginate": true,
10776	
10777	
10778		/**
10779		 * Enable or disable the display of a 'processing' indicator when the table is
10780		 * being processed (e.g. a sort). This is particularly useful for tables with
10781		 * large amounts of data where it can take a noticeable amount of time to sort
10782		 * the entries.
10783		 *  @type boolean
10784		 *  @default false
10785		 *
10786		 *  @dtopt Features
10787		 *  @name DataTable.defaults.processing
10788		 *
10789		 *  @example
10790		 *    $(document).ready( function () {
10791		 *      $('#example').dataTable( {
10792		 *        "processing": true
10793		 *      } );
10794		 *    } );
10795		 */
10796		"bProcessing": false,
10797	
10798	
10799		/**
10800		 * Retrieve the DataTables object for the given selector. Note that if the
10801		 * table has already been initialised, this parameter will cause DataTables
10802		 * to simply return the object that has already been set up - it will not take
10803		 * account of any changes you might have made to the initialisation object
10804		 * passed to DataTables (setting this parameter to true is an acknowledgement
10805		 * that you understand this). `destroy` can be used to reinitialise a table if
10806		 * you need.
10807		 *  @type boolean
10808		 *  @default false
10809		 *
10810		 *  @dtopt Options
10811		 *  @name DataTable.defaults.retrieve
10812		 *
10813		 *  @example
10814		 *    $(document).ready( function() {
10815		 *      initTable();
10816		 *      tableActions();
10817		 *    } );
10818		 *
10819		 *    function initTable ()
10820		 *    {
10821		 *      return $('#example').dataTable( {
10822		 *        "scrollY": "200px",
10823		 *        "paginate": false,
10824		 *        "retrieve": true
10825		 *      } );
10826		 *    }
10827		 *
10828		 *    function tableActions ()
10829		 *    {
10830		 *      var table = initTable();
10831		 *      // perform API operations with oTable
10832		 *    }
10833		 */
10834		"bRetrieve": false,
10835	
10836	
10837		/**
10838		 * When vertical (y) scrolling is enabled, DataTables will force the height of
10839		 * the table's viewport to the given height at all times (useful for layout).
10840		 * However, this can look odd when filtering data down to a small data set,
10841		 * and the footer is left "floating" further down. This parameter (when
10842		 * enabled) will cause DataTables to collapse the table's viewport down when
10843		 * the result set will fit within the given Y height.
10844		 *  @type boolean
10845		 *  @default false
10846		 *
10847		 *  @dtopt Options
10848		 *  @name DataTable.defaults.scrollCollapse
10849		 *
10850		 *  @example
10851		 *    $(document).ready( function() {
10852		 *      $('#example').dataTable( {
10853		 *        "scrollY": "200",
10854		 *        "scrollCollapse": true
10855		 *      } );
10856		 *    } );
10857		 */
10858		"bScrollCollapse": false,
10859	
10860	
10861		/**
10862		 * Configure DataTables to use server-side processing. Note that the
10863		 * `ajax` parameter must also be given in order to give DataTables a
10864		 * source to obtain the required data for each draw.
10865		 *  @type boolean
10866		 *  @default false
10867		 *
10868		 *  @dtopt Features
10869		 *  @dtopt Server-side
10870		 *  @name DataTable.defaults.serverSide
10871		 *
10872		 *  @example
10873		 *    $(document).ready( function () {
10874		 *      $('#example').dataTable( {
10875		 *        "serverSide": true,
10876		 *        "ajax": "xhr.php"
10877		 *      } );
10878		 *    } );
10879		 */
10880		"bServerSide": false,
10881	
10882	
10883		/**
10884		 * Enable or disable sorting of columns. Sorting of individual columns can be
10885		 * disabled by the `sortable` option for each column.
10886		 *  @type boolean
10887		 *  @default true
10888		 *
10889		 *  @dtopt Features
10890		 *  @name DataTable.defaults.ordering
10891		 *
10892		 *  @example
10893		 *    $(document).ready( function () {
10894		 *      $('#example').dataTable( {
10895		 *        "ordering": false
10896		 *      } );
10897		 *    } );
10898		 */
10899		"bSort": true,
10900	
10901	
10902		/**
10903		 * Enable or display DataTables' ability to sort multiple columns at the
10904		 * same time (activated by shift-click by the user).
10905		 *  @type boolean
10906		 *  @default true
10907		 *
10908		 *  @dtopt Options
10909		 *  @name DataTable.defaults.orderMulti
10910		 *
10911		 *  @example
10912		 *    // Disable multiple column sorting ability
10913		 *    $(document).ready( function () {
10914		 *      $('#example').dataTable( {
10915		 *        "orderMulti": false
10916		 *      } );
10917		 *    } );
10918		 */
10919		"bSortMulti": true,
10920	
10921	
10922		/**
10923		 * Allows control over whether DataTables should use the top (true) unique
10924		 * cell that is found for a single column, or the bottom (false - default).
10925		 * This is useful when using complex headers.
10926		 *  @type boolean
10927		 *  @default false
10928		 *
10929		 *  @dtopt Options
10930		 *  @name DataTable.defaults.orderCellsTop
10931		 *
10932		 *  @example
10933		 *    $(document).ready( function() {
10934		 *      $('#example').dataTable( {
10935		 *        "orderCellsTop": true
10936		 *      } );
10937		 *    } );
10938		 */
10939		"bSortCellsTop": false,
10940	
10941	
10942		/**
10943		 * Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and
10944		 * `sorting\_3` to the columns which are currently being sorted on. This is
10945		 * presented as a feature switch as it can increase processing time (while
10946		 * classes are removed and added) so for large data sets you might want to
10947		 * turn this off.
10948		 *  @type boolean
10949		 *  @default true
10950		 *
10951		 *  @dtopt Features
10952		 *  @name DataTable.defaults.orderClasses
10953		 *
10954		 *  @example
10955		 *    $(document).ready( function () {
10956		 *      $('#example').dataTable( {
10957		 *        "orderClasses": false
10958		 *      } );
10959		 *    } );
10960		 */
10961		"bSortClasses": true,
10962	
10963	
10964		/**
10965		 * Enable or disable state saving. When enabled HTML5 `localStorage` will be
10966		 * used to save table display information such as pagination information,
10967		 * display length, filtering and sorting. As such when the end user reloads
10968		 * the page the display display will match what thy had previously set up.
10969		 *
10970		 * Due to the use of `localStorage` the default state saving is not supported
10971		 * in IE6 or 7. If state saving is required in those browsers, use
10972		 * `stateSaveCallback` to provide a storage solution such as cookies.
10973		 *  @type boolean
10974		 *  @default false
10975		 *
10976		 *  @dtopt Features
10977		 *  @name DataTable.defaults.stateSave
10978		 *
10979		 *  @example
10980		 *    $(document).ready( function () {
10981		 *      $('#example').dataTable( {
10982		 *        "stateSave": true
10983		 *      } );
10984		 *    } );
10985		 */
10986		"bStateSave": false,
10987	
10988	
10989		/**
10990		 * This function is called when a TR element is created (and all TD child
10991		 * elements have been inserted), or registered if using a DOM source, allowing
10992		 * manipulation of the TR element (adding classes etc).
10993		 *  @type function
10994		 *  @param {node} row "TR" element for the current row
10995		 *  @param {array} data Raw data array for this row
10996		 *  @param {int} dataIndex The index of this row in the internal aoData array
10997		 *
10998		 *  @dtopt Callbacks
10999		 *  @name DataTable.defaults.createdRow
11000		 *
11001		 *  @example
11002		 *    $(document).ready( function() {
11003		 *      $('#example').dataTable( {
11004		 *        "createdRow": function( row, data, dataIndex ) {
11005		 *          // Bold the grade for all 'A' grade browsers
11006		 *          if ( data[4] == "A" )
11007		 *          {
11008		 *            $('td:eq(4)', row).html( '<b>A</b>' );
11009		 *          }
11010		 *        }
11011		 *      } );
11012		 *    } );
11013		 */
11014		"fnCreatedRow": null,
11015	
11016	
11017		/**
11018		 * This function is called on every 'draw' event, and allows you to
11019		 * dynamically modify any aspect you want about the created DOM.
11020		 *  @type function
11021		 *  @param {object} settings DataTables settings object
11022		 *
11023		 *  @dtopt Callbacks
11024		 *  @name DataTable.defaults.drawCallback
11025		 *
11026		 *  @example
11027		 *    $(document).ready( function() {
11028		 *      $('#example').dataTable( {
11029		 *        "drawCallback": function( settings ) {
11030		 *          alert( 'DataTables has redrawn the table' );
11031		 *        }
11032		 *      } );
11033		 *    } );
11034		 */
11035		"fnDrawCallback": null,
11036	
11037	
11038		/**
11039		 * Identical to fnHeaderCallback() but for the table footer this function
11040		 * allows you to modify the table footer on every 'draw' event.
11041		 *  @type function
11042		 *  @param {node} foot "TR" element for the footer
11043		 *  @param {array} data Full table data (as derived from the original HTML)
11044		 *  @param {int} start Index for the current display starting point in the
11045		 *    display array
11046		 *  @param {int} end Index for the current display ending point in the
11047		 *    display array
11048		 *  @param {array int} display Index array to translate the visual position
11049		 *    to the full data array
11050		 *
11051		 *  @dtopt Callbacks
11052		 *  @name DataTable.defaults.footerCallback
11053		 *
11054		 *  @example
11055		 *    $(document).ready( function() {
11056		 *      $('#example').dataTable( {
11057		 *        "footerCallback": function( tfoot, data, start, end, display ) {
11058		 *          tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start;
11059		 *        }
11060		 *      } );
11061		 *    } )
11062		 */
11063		"fnFooterCallback": null,
11064	
11065	
11066		/**
11067		 * When rendering large numbers in the information element for the table
11068		 * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
11069		 * to have a comma separator for the 'thousands' units (e.g. 1 million is
11070		 * rendered as "1,000,000") to help readability for the end user. This
11071		 * function will override the default method DataTables uses.
11072		 *  @type function
11073		 *  @member
11074		 *  @param {int} toFormat number to be formatted
11075		 *  @returns {string} formatted string for DataTables to show the number
11076		 *
11077		 *  @dtopt Callbacks
11078		 *  @name DataTable.defaults.formatNumber
11079		 *
11080		 *  @example
11081		 *    // Format a number using a single quote for the separator (note that
11082		 *    // this can also be done with the language.thousands option)
11083		 *    $(document).ready( function() {
11084		 *      $('#example').dataTable( {
11085		 *        "formatNumber": function ( toFormat ) {
11086		 *          return toFormat.toString().replace(
11087		 *            /\B(?=(\d{3})+(?!\d))/g, "'"
11088		 *          );
11089		 *        };
11090		 *      } );
11091		 *    } );
11092		 */
11093		"fnFormatNumber": function ( toFormat ) {
11094			return toFormat.toString().replace(
11095				/\B(?=(\d{3})+(?!\d))/g,
11096				this.oLanguage.sThousands
11097			);
11098		},
11099	
11100	
11101		/**
11102		 * This function is called on every 'draw' event, and allows you to
11103		 * dynamically modify the header row. This can be used to calculate and
11104		 * display useful information about the table.
11105		 *  @type function
11106		 *  @param {node} head "TR" element for the header
11107		 *  @param {array} data Full table data (as derived from the original HTML)
11108		 *  @param {int} start Index for the current display starting point in the
11109		 *    display array
11110		 *  @param {int} end Index for the current display ending point in the
11111		 *    display array
11112		 *  @param {array int} display Index array to translate the visual position
11113		 *    to the full data array
11114		 *
11115		 *  @dtopt Callbacks
11116		 *  @name DataTable.defaults.headerCallback
11117		 *
11118		 *  @example
11119		 *    $(document).ready( function() {
11120		 *      $('#example').dataTable( {
11121		 *        "fheaderCallback": function( head, data, start, end, display ) {
11122		 *          head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records";
11123		 *        }
11124		 *      } );
11125		 *    } )
11126		 */
11127		"fnHeaderCallback": null,
11128	
11129	
11130		/**
11131		 * The information element can be used to convey information about the current
11132		 * state of the table. Although the internationalisation options presented by
11133		 * DataTables are quite capable of dealing with most customisations, there may
11134		 * be times where you wish to customise the string further. This callback
11135		 * allows you to do exactly that.
11136		 *  @type function
11137		 *  @param {object} oSettings DataTables settings object
11138		 *  @param {int} start Starting position in data for the draw
11139		 *  @param {int} end End position in data for the draw
11140		 *  @param {int} max Total number of rows in the table (regardless of
11141		 *    filtering)
11142		 *  @param {int} total Total number of rows in the data set, after filtering
11143		 *  @param {string} pre The string that DataTables has formatted using it's
11144		 *    own rules
11145		 *  @returns {string} The string to be displayed in the information element.
11146		 *
11147		 *  @dtopt Callbacks
11148		 *  @name DataTable.defaults.infoCallback
11149		 *
11150		 *  @example
11151		 *    $('#example').dataTable( {
11152		 *      "infoCallback": function( settings, start, end, max, total, pre ) {
11153		 *        return start +" to "+ end;
11154		 *      }
11155		 *    } );
11156		 */
11157		"fnInfoCallback": null,
11158	
11159	
11160		/**
11161		 * Called when the table has been initialised. Normally DataTables will
11162		 * initialise sequentially and there will be no need for this function,
11163		 * however, this does not hold true when using external language information
11164		 * since that is obtained using an async XHR call.
11165		 *  @type function
11166		 *  @param {object} settings DataTables settings object
11167		 *  @param {object} json The JSON object request from the server - only
11168		 *    present if client-side Ajax sourced data is used
11169		 *
11170		 *  @dtopt Callbacks
11171		 *  @name DataTable.defaults.initComplete
11172		 *
11173		 *  @example
11174		 *    $(document).ready( function() {
11175		 *      $('#example').dataTable( {
11176		 *        "initComplete": function(settings, json) {
11177		 *          alert( 'DataTables has finished its initialisation.' );
11178		 *        }
11179		 *      } );
11180		 *    } )
11181		 */
11182		"fnInitComplete": null,
11183	
11184	
11185		/**
11186		 * Called at the very start of each table draw and can be used to cancel the
11187		 * draw by returning false, any other return (including undefined) results in
11188		 * the full draw occurring).
11189		 *  @type function
11190		 *  @param {object} settings DataTables settings object
11191		 *  @returns {boolean} False will cancel the draw, anything else (including no
11192		 *    return) will allow it to complete.
11193		 *
11194		 *  @dtopt Callbacks
11195		 *  @name DataTable.defaults.preDrawCallback
11196		 *
11197		 *  @example
11198		 *    $(document).ready( function() {
11199		 *      $('#example').dataTable( {
11200		 *        "preDrawCallback": function( settings ) {
11201		 *          if ( $('#test').val() == 1 ) {
11202		 *            return false;
11203		 *          }
11204		 *        }
11205		 *      } );
11206		 *    } );
11207		 */
11208		"fnPreDrawCallback": null,
11209	
11210	
11211		/**
11212		 * This function allows you to 'post process' each row after it have been
11213		 * generated for each table draw, but before it is rendered on screen. This
11214		 * function might be used for setting the row class name etc.
11215		 *  @type function
11216		 *  @param {node} row "TR" element for the current row
11217		 *  @param {array} data Raw data array for this row
11218		 *  @param {int} displayIndex The display index for the current table draw
11219		 *  @param {int} displayIndexFull The index of the data in the full list of
11220		 *    rows (after filtering)
11221		 *
11222		 *  @dtopt Callbacks
11223		 *  @name DataTable.defaults.rowCallback
11224		 *
11225		 *  @example
11226		 *    $(document).ready( function() {
11227		 *      $('#example').dataTable( {
11228		 *        "rowCallback": function( row, data, displayIndex, displayIndexFull ) {
11229		 *          // Bold the grade for all 'A' grade browsers
11230		 *          if ( data[4] == "A" ) {
11231		 *            $('td:eq(4)', row).html( '<b>A</b>' );
11232		 *          }
11233		 *        }
11234		 *      } );
11235		 *    } );
11236		 */
11237		"fnRowCallback": null,
11238	
11239	
11240		/**
11241		 * __Deprecated__ The functionality provided by this parameter has now been
11242		 * superseded by that provided through `ajax`, which should be used instead.
11243		 *
11244		 * This parameter allows you to override the default function which obtains
11245		 * the data from the server so something more suitable for your application.
11246		 * For example you could use POST data, or pull information from a Gears or
11247		 * AIR database.
11248		 *  @type function
11249		 *  @member
11250		 *  @param {string} source HTTP source to obtain the data from (`ajax`)
11251		 *  @param {array} data A key/value pair object containing the data to send
11252		 *    to the server
11253		 *  @param {function} callback to be called on completion of the data get
11254		 *    process that will draw the data on the page.
11255		 *  @param {object} settings DataTables settings object
11256		 *
11257		 *  @dtopt Callbacks
11258		 *  @dtopt Server-side
11259		 *  @name DataTable.defaults.serverData
11260		 *
11261		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11262		 */
11263		"fnServerData": null,
11264	
11265	
11266		/**
11267		 * __Deprecated__ The functionality provided by this parameter has now been
11268		 * superseded by that provided through `ajax`, which should be used instead.
11269		 *
11270		 *  It is often useful to send extra data to the server when making an Ajax
11271		 * request - for example custom filtering information, and this callback
11272		 * function makes it trivial to send extra information to the server. The
11273		 * passed in parameter is the data set that has been constructed by
11274		 * DataTables, and you can add to this or modify it as you require.
11275		 *  @type function
11276		 *  @param {array} data Data array (array of objects which are name/value
11277		 *    pairs) that has been constructed by DataTables and will be sent to the
11278		 *    server. In the case of Ajax sourced data with server-side processing
11279		 *    this will be an empty array, for server-side processing there will be a
11280		 *    significant number of parameters!
11281		 *  @returns {undefined} Ensure that you modify the data array passed in,
11282		 *    as this is passed by reference.
11283		 *
11284		 *  @dtopt Callbacks
11285		 *  @dtopt Server-side
11286		 *  @name DataTable.defaults.serverParams
11287		 *
11288		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11289		 */
11290		"fnServerParams": null,
11291	
11292	
11293		/**
11294		 * Load the table state. With this function you can define from where, and how, the
11295		 * state of a table is loaded. By default DataTables will load from `localStorage`
11296		 * but you might wish to use a server-side database or cookies.
11297		 *  @type function
11298		 *  @member
11299		 *  @param {object} settings DataTables settings object
11300		 *  @param {object} callback Callback that can be executed when done. It
11301		 *    should be passed the loaded state object.
11302		 *  @return {object} The DataTables state object to be loaded
11303		 *
11304		 *  @dtopt Callbacks
11305		 *  @name DataTable.defaults.stateLoadCallback
11306		 *
11307		 *  @example
11308		 *    $(document).ready( function() {
11309		 *      $('#example').dataTable( {
11310		 *        "stateSave": true,
11311		 *        "stateLoadCallback": function (settings, callback) {
11312		 *          $.ajax( {
11313		 *            "url": "/state_load",
11314		 *            "dataType": "json",
11315		 *            "success": function (json) {
11316		 *              callback( json );
11317		 *            }
11318		 *          } );
11319		 *        }
11320		 *      } );
11321		 *    } );
11322		 */
11323		"fnStateLoadCallback": function ( settings ) {
11324			try {
11325				return JSON.parse(
11326					(settings.iStateDuration === -1 ? sessionStorage : localStorage).getItem(
11327						'DataTables_'+settings.sInstance+'_'+location.pathname
11328					)
11329				);
11330			} catch (e) {
11331				return {};
11332			}
11333		},
11334	
11335	
11336		/**
11337		 * Callback which allows modification of the saved state prior to loading that state.
11338		 * This callback is called when the table is loading state from the stored data, but
11339		 * prior to the settings object being modified by the saved state. Note that for
11340		 * plug-in authors, you should use the `stateLoadParams` event to load parameters for
11341		 * a plug-in.
11342		 *  @type function
11343		 *  @param {object} settings DataTables settings object
11344		 *  @param {object} data The state object that is to be loaded
11345		 *
11346		 *  @dtopt Callbacks
11347		 *  @name DataTable.defaults.stateLoadParams
11348		 *
11349		 *  @example
11350		 *    // Remove a saved filter, so filtering is never loaded
11351		 *    $(document).ready( function() {
11352		 *      $('#example').dataTable( {
11353		 *        "stateSave": true,
11354		 *        "stateLoadParams": function (settings, data) {
11355		 *          data.oSearch.sSearch = "";
11356		 *        }
11357		 *      } );
11358		 *    } );
11359		 *
11360		 *  @example
11361		 *    // Disallow state loading by returning false
11362		 *    $(document).ready( function() {
11363		 *      $('#example').dataTable( {
11364		 *        "stateSave": true,
11365		 *        "stateLoadParams": function (settings, data) {
11366		 *          return false;
11367		 *        }
11368		 *      } );
11369		 *    } );
11370		 */
11371		"fnStateLoadParams": null,
11372	
11373	
11374		/**
11375		 * Callback that is called when the state has been loaded from the state saving method
11376		 * and the DataTables settings object has been modified as a result of the loaded state.
11377		 *  @type function
11378		 *  @param {object} settings DataTables settings object
11379		 *  @param {object} data The state object that was loaded
11380		 *
11381		 *  @dtopt Callbacks
11382		 *  @name DataTable.defaults.stateLoaded
11383		 *
11384		 *  @example
11385		 *    // Show an alert with the filtering value that was saved
11386		 *    $(document).ready( function() {
11387		 *      $('#example').dataTable( {
11388		 *        "stateSave": true,
11389		 *        "stateLoaded": function (settings, data) {
11390		 *          alert( 'Saved filter was: '+data.oSearch.sSearch );
11391		 *        }
11392		 *      } );
11393		 *    } );
11394		 */
11395		"fnStateLoaded": null,
11396	
11397	
11398		/**
11399		 * Save the table state. This function allows you to define where and how the state
11400		 * information for the table is stored By default DataTables will use `localStorage`
11401		 * but you might wish to use a server-side database or cookies.
11402		 *  @type function
11403		 *  @member
11404		 *  @param {object} settings DataTables settings object
11405		 *  @param {object} data The state object to be saved
11406		 *
11407		 *  @dtopt Callbacks
11408		 *  @name DataTable.defaults.stateSaveCallback
11409		 *
11410		 *  @example
11411		 *    $(document).ready( function() {
11412		 *      $('#example').dataTable( {
11413		 *        "stateSave": true,
11414		 *        "stateSaveCallback": function (settings, data) {
11415		 *          // Send an Ajax request to the server with the state object
11416		 *          $.ajax( {
11417		 *            "url": "/state_save",
11418		 *            "data": data,
11419		 *            "dataType": "json",
11420		 *            "method": "POST"
11421		 *            "success": function () {}
11422		 *          } );
11423		 *        }
11424		 *      } );
11425		 *    } );
11426		 */
11427		"fnStateSaveCallback": function ( settings, data ) {
11428			try {
11429				(settings.iStateDuration === -1 ? sessionStorage : localStorage).setItem(
11430					'DataTables_'+settings.sInstance+'_'+location.pathname,
11431					JSON.stringify( data )
11432				);
11433			} catch (e) {}
11434		},
11435	
11436	
11437		/**
11438		 * Callback which allows modification of the state to be saved. Called when the table
11439		 * has changed state a new state save is required. This method allows modification of
11440		 * the state saving object prior to actually doing the save, including addition or
11441		 * other state properties or modification. Note that for plug-in authors, you should
11442		 * use the `stateSaveParams` event to save parameters for a plug-in.
11443		 *  @type function
11444		 *  @param {object} settings DataTables settings object
11445		 *  @param {object} data The state object to be saved
11446		 *
11447		 *  @dtopt Callbacks
11448		 *  @name DataTable.defaults.stateSaveParams
11449		 *
11450		 *  @example
11451		 *    // Remove a saved filter, so filtering is never saved
11452		 *    $(document).ready( function() {
11453		 *      $('#example').dataTable( {
11454		 *        "stateSave": true,
11455		 *        "stateSaveParams": function (settings, data) {
11456		 *          data.oSearch.sSearch = "";
11457		 *        }
11458		 *      } );
11459		 *    } );
11460		 */
11461		"fnStateSaveParams": null,
11462	
11463	
11464		/**
11465		 * Duration for which the saved state information is considered valid. After this period
11466		 * has elapsed the state will be returned to the default.
11467		 * Value is given in seconds.
11468		 *  @type int
11469		 *  @default 7200 <i>(2 hours)</i>
11470		 *
11471		 *  @dtopt Options
11472		 *  @name DataTable.defaults.stateDuration
11473		 *
11474		 *  @example
11475		 *    $(document).ready( function() {
11476		 *      $('#example').dataTable( {
11477		 *        "stateDuration": 60*60*24; // 1 day
11478		 *      } );
11479		 *    } )
11480		 */
11481		"iStateDuration": 7200,
11482	
11483	
11484		/**
11485		 * When enabled DataTables will not make a request to the server for the first
11486		 * page draw - rather it will use the data already on the page (no sorting etc
11487		 * will be applied to it), thus saving on an XHR at load time. `deferLoading`
11488		 * is used to indicate that deferred loading is required, but it is also used
11489		 * to tell DataTables how many records there are in the full table (allowing
11490		 * the information element and pagination to be displayed correctly). In the case
11491		 * where a filtering is applied to the table on initial load, this can be
11492		 * indicated by giving the parameter as an array, where the first element is
11493		 * the number of records available after filtering and the second element is the
11494		 * number of records without filtering (allowing the table information element
11495		 * to be shown correctly).
11496		 *  @type int | array
11497		 *  @default null
11498		 *
11499		 *  @dtopt Options
11500		 *  @name DataTable.defaults.deferLoading
11501		 *
11502		 *  @example
11503		 *    // 57 records available in the table, no filtering applied
11504		 *    $(document).ready( function() {
11505		 *      $('#example').dataTable( {
11506		 *        "serverSide": true,
11507		 *        "ajax": "scripts/server_processing.php",
11508		 *        "deferLoading": 57
11509		 *      } );
11510		 *    } );
11511		 *
11512		 *  @example
11513		 *    // 57 records after filtering, 100 without filtering (an initial filter applied)
11514		 *    $(document).ready( function() {
11515		 *      $('#example').dataTable( {
11516		 *        "serverSide": true,
11517		 *        "ajax": "scripts/server_processing.php",
11518		 *        "deferLoading": [ 57, 100 ],
11519		 *        "search": {
11520		 *          "search": "my_filter"
11521		 *        }
11522		 *      } );
11523		 *    } );
11524		 */
11525		"iDeferLoading": null,
11526	
11527	
11528		/**
11529		 * Number of rows to display on a single page when using pagination. If
11530		 * feature enabled (`lengthChange`) then the end user will be able to override
11531		 * this to a custom setting using a pop-up menu.
11532		 *  @type int
11533		 *  @default 10
11534		 *
11535		 *  @dtopt Options
11536		 *  @name DataTable.defaults.pageLength
11537		 *
11538		 *  @example
11539		 *    $(document).ready( function() {
11540		 *      $('#example').dataTable( {
11541		 *        "pageLength": 50
11542		 *      } );
11543		 *    } )
11544		 */
11545		"iDisplayLength": 10,
11546	
11547	
11548		/**
11549		 * Define the starting point for data display when using DataTables with
11550		 * pagination. Note that this parameter is the number of records, rather than
11551		 * the page number, so if you have 10 records per page and want to start on
11552		 * the third page, it should be "20".
11553		 *  @type int
11554		 *  @default 0
11555		 *
11556		 *  @dtopt Options
11557		 *  @name DataTable.defaults.displayStart
11558		 *
11559		 *  @example
11560		 *    $(document).ready( function() {
11561		 *      $('#example').dataTable( {
11562		 *        "displayStart": 20
11563		 *      } );
11564		 *    } )
11565		 */
11566		"iDisplayStart": 0,
11567	
11568	
11569		/**
11570		 * By default DataTables allows keyboard navigation of the table (sorting, paging,
11571		 * and filtering) by adding a `tabindex` attribute to the required elements. This
11572		 * allows you to tab through the controls and press the enter key to activate them.
11573		 * The tabindex is default 0, meaning that the tab follows the flow of the document.
11574		 * You can overrule this using this parameter if you wish. Use a value of -1 to
11575		 * disable built-in keyboard navigation.
11576		 *  @type int
11577		 *  @default 0
11578		 *
11579		 *  @dtopt Options
11580		 *  @name DataTable.defaults.tabIndex
11581		 *
11582		 *  @example
11583		 *    $(document).ready( function() {
11584		 *      $('#example').dataTable( {
11585		 *        "tabIndex": 1
11586		 *      } );
11587		 *    } );
11588		 */
11589		"iTabIndex": 0,
11590	
11591	
11592		/**
11593		 * Classes that DataTables assigns to the various components and features
11594		 * that it adds to the HTML table. This allows classes to be configured
11595		 * during initialisation in addition to through the static
11596		 * {@link DataTable.ext.oStdClasses} object).
11597		 *  @namespace
11598		 *  @name DataTable.defaults.classes
11599		 */
11600		"oClasses": {},
11601	
11602	
11603		/**
11604		 * All strings that DataTables uses in the user interface that it creates
11605		 * are defined in this object, allowing you to modified them individually or
11606		 * completely replace them all as required.
11607		 *  @namespace
11608		 *  @name DataTable.defaults.language
11609		 */
11610		"oLanguage": {
11611			/**
11612			 * Strings that are used for WAI-ARIA labels and controls only (these are not
11613			 * actually visible on the page, but will be read by screenreaders, and thus
11614			 * must be internationalised as well).
11615			 *  @namespace
11616			 *  @name DataTable.defaults.language.aria
11617			 */
11618			"oAria": {
11619				/**
11620				 * ARIA label that is added to the table headers when the column may be
11621				 * sorted ascending by activing the column (click or return when focused).
11622				 * Note that the column header is prefixed to this string.
11623				 *  @type string
11624				 *  @default : activate to sort column ascending
11625				 *
11626				 *  @dtopt Language
11627				 *  @name DataTable.defaults.language.aria.sortAscending
11628				 *
11629				 *  @example
11630				 *    $(document).ready( function() {
11631				 *      $('#example').dataTable( {
11632				 *        "language": {
11633				 *          "aria": {
11634				 *            "sortAscending": " - click/return to sort ascending"
11635				 *          }
11636				 *        }
11637				 *      } );
11638				 *    } );
11639				 */
11640				"sSortAscending": ": activate to sort column ascending",
11641	
11642				/**
11643				 * ARIA label that is added to the table headers when the column may be
11644				 * sorted descending by activing the column (click or return when focused).
11645				 * Note that the column header is prefixed to this string.
11646				 *  @type string
11647				 *  @default : activate to sort column ascending
11648				 *
11649				 *  @dtopt Language
11650				 *  @name DataTable.defaults.language.aria.sortDescending
11651				 *
11652				 *  @example
11653				 *    $(document).ready( function() {
11654				 *      $('#example').dataTable( {
11655				 *        "language": {
11656				 *          "aria": {
11657				 *            "sortDescending": " - click/return to sort descending"
11658				 *          }
11659				 *        }
11660				 *      } );
11661				 *    } );
11662				 */
11663				"sSortDescending": ": activate to sort column descending"
11664			},
11665	
11666			/**
11667			 * Pagination string used by DataTables for the built-in pagination
11668			 * control types.
11669			 *  @namespace
11670			 *  @name DataTable.defaults.language.paginate
11671			 */
11672			"oPaginate": {
11673				/**
11674				 * Text to use when using the 'full_numbers' type of pagination for the
11675				 * button to take the user to the first page.
11676				 *  @type string
11677				 *  @default First
11678				 *
11679				 *  @dtopt Language
11680				 *  @name DataTable.defaults.language.paginate.first
11681				 *
11682				 *  @example
11683				 *    $(document).ready( function() {
11684				 *      $('#example').dataTable( {
11685				 *        "language": {
11686				 *          "paginate": {
11687				 *            "first": "First page"
11688				 *          }
11689				 *        }
11690				 *      } );
11691				 *    } );
11692				 */
11693				"sFirst": "First",
11694	
11695	
11696				/**
11697				 * Text to use when using the 'full_numbers' type of pagination for the
11698				 * button to take the user to the last page.
11699				 *  @type string
11700				 *  @default Last
11701				 *
11702				 *  @dtopt Language
11703				 *  @name DataTable.defaults.language.paginate.last
11704				 *
11705				 *  @example
11706				 *    $(document).ready( function() {
11707				 *      $('#example').dataTable( {
11708				 *        "language": {
11709				 *          "paginate": {
11710				 *            "last": "Last page"
11711				 *          }
11712				 *        }
11713				 *      } );
11714				 *    } );
11715				 */
11716				"sLast": "Last",
11717	
11718	
11719				/**
11720				 * Text to use for the 'next' pagination button (to take the user to the
11721				 * next page).
11722				 *  @type string
11723				 *  @default Next
11724				 *
11725				 *  @dtopt Language
11726				 *  @name DataTable.defaults.language.paginate.next
11727				 *
11728				 *  @example
11729				 *    $(document).ready( function() {
11730				 *      $('#example').dataTable( {
11731				 *        "language": {
11732				 *          "paginate": {
11733				 *            "next": "Next page"
11734				 *          }
11735				 *        }
11736				 *      } );
11737				 *    } );
11738				 */
11739				"sNext": "Next",
11740	
11741	
11742				/**
11743				 * Text to use for the 'previous' pagination button (to take the user to
11744				 * the previous page).
11745				 *  @type string
11746				 *  @default Previous
11747				 *
11748				 *  @dtopt Language
11749				 *  @name DataTable.defaults.language.paginate.previous
11750				 *
11751				 *  @example
11752				 *    $(document).ready( function() {
11753				 *      $('#example').dataTable( {
11754				 *        "language": {
11755				 *          "paginate": {
11756				 *            "previous": "Previous page"
11757				 *          }
11758				 *        }
11759				 *      } );
11760				 *    } );
11761				 */
11762				"sPrevious": "Previous"
11763			},
11764	
11765			/**
11766			 * This string is shown in preference to `zeroRecords` when the table is
11767			 * empty of data (regardless of filtering). Note that this is an optional
11768			 * parameter - if it is not given, the value of `zeroRecords` will be used
11769			 * instead (either the default or given value).
11770			 *  @type string
11771			 *  @default No data available in table
11772			 *
11773			 *  @dtopt Language
11774			 *  @name DataTable.defaults.language.emptyTable
11775			 *
11776			 *  @example
11777			 *    $(document).ready( function() {
11778			 *      $('#example').dataTable( {
11779			 *        "language": {
11780			 *          "emptyTable": "No data available in table"
11781			 *        }
11782			 *      } );
11783			 *    } );
11784			 */
11785			"sEmptyTable": "No data available in table",
11786	
11787	
11788			/**
11789			 * This string gives information to the end user about the information
11790			 * that is current on display on the page. The following tokens can be
11791			 * used in the string and will be dynamically replaced as the table
11792			 * display updates. This tokens can be placed anywhere in the string, or
11793			 * removed as needed by the language requires:
11794			 *
11795			 * * `\_START\_` - Display index of the first record on the current page
11796			 * * `\_END\_` - Display index of the last record on the current page
11797			 * * `\_TOTAL\_` - Number of records in the table after filtering
11798			 * * `\_MAX\_` - Number of records in the table without filtering
11799			 * * `\_PAGE\_` - Current page number
11800			 * * `\_PAGES\_` - Total number of pages of data in the table
11801			 *
11802			 *  @type string
11803			 *  @default Showing _START_ to _END_ of _TOTAL_ entries
11804			 *
11805			 *  @dtopt Language
11806			 *  @name DataTable.defaults.language.info
11807			 *
11808			 *  @example
11809			 *    $(document).ready( function() {
11810			 *      $('#example').dataTable( {
11811			 *        "language": {
11812			 *          "info": "Showing page _PAGE_ of _PAGES_"
11813			 *        }
11814			 *      } );
11815			 *    } );
11816			 */
11817			"sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
11818	
11819	
11820			/**
11821			 * Display information string for when the table is empty. Typically the
11822			 * format of this string should match `info`.
11823			 *  @type string
11824			 *  @default Showing 0 to 0 of 0 entries
11825			 *
11826			 *  @dtopt Language
11827			 *  @name DataTable.defaults.language.infoEmpty
11828			 *
11829			 *  @example
11830			 *    $(document).ready( function() {
11831			 *      $('#example').dataTable( {
11832			 *        "language": {
11833			 *          "infoEmpty": "No entries to show"
11834			 *        }
11835			 *      } );
11836			 *    } );
11837			 */
11838			"sInfoEmpty": "Showing 0 to 0 of 0 entries",
11839	
11840	
11841			/**
11842			 * When a user filters the information in a table, this string is appended
11843			 * to the information (`info`) to give an idea of how strong the filtering
11844			 * is. The variable _MAX_ is dynamically updated.
11845			 *  @type string
11846			 *  @default (filtered from _MAX_ total entries)
11847			 *
11848			 *  @dtopt Language
11849			 *  @name DataTable.defaults.language.infoFiltered
11850			 *
11851			 *  @example
11852			 *    $(document).ready( function() {
11853			 *      $('#example').dataTable( {
11854			 *        "language": {
11855			 *          "infoFiltered": " - filtering from _MAX_ records"
11856			 *        }
11857			 *      } );
11858			 *    } );
11859			 */
11860			"sInfoFiltered": "(filtered from _MAX_ total entries)",
11861	
11862	
11863			/**
11864			 * If can be useful to append extra information to the info string at times,
11865			 * and this variable does exactly that. This information will be appended to
11866			 * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are
11867			 * being used) at all times.
11868			 *  @type string
11869			 *  @default <i>Empty string</i>
11870			 *
11871			 *  @dtopt Language
11872			 *  @name DataTable.defaults.language.infoPostFix
11873			 *
11874			 *  @example
11875			 *    $(document).ready( function() {
11876			 *      $('#example').dataTable( {
11877			 *        "language": {
11878			 *          "infoPostFix": "All records shown are derived from real information."
11879			 *        }
11880			 *      } );
11881			 *    } );
11882			 */
11883			"sInfoPostFix": "",
11884	
11885	
11886			/**
11887			 * This decimal place operator is a little different from the other
11888			 * language options since DataTables doesn't output floating point
11889			 * numbers, so it won't ever use this for display of a number. Rather,
11890			 * what this parameter does is modify the sort methods of the table so
11891			 * that numbers which are in a format which has a character other than
11892			 * a period (`.`) as a decimal place will be sorted numerically.
11893			 *
11894			 * Note that numbers with different decimal places cannot be shown in
11895			 * the same table and still be sortable, the table must be consistent.
11896			 * However, multiple different tables on the page can use different
11897			 * decimal place characters.
11898			 *  @type string
11899			 *  @default 
11900			 *
11901			 *  @dtopt Language
11902			 *  @name DataTable.defaults.language.decimal
11903			 *
11904			 *  @example
11905			 *    $(document).ready( function() {
11906			 *      $('#example').dataTable( {
11907			 *        "language": {
11908			 *          "decimal": ","
11909			 *          "thousands": "."
11910			 *        }
11911			 *      } );
11912			 *    } );
11913			 */
11914			"sDecimal": "",
11915	
11916	
11917			/**
11918			 * DataTables has a build in number formatter (`formatNumber`) which is
11919			 * used to format large numbers that are used in the table information.
11920			 * By default a comma is used, but this can be trivially changed to any
11921			 * character you wish with this parameter.
11922			 *  @type string
11923			 *  @default ,
11924			 *
11925			 *  @dtopt Language
11926			 *  @name DataTable.defaults.language.thousands
11927			 *
11928			 *  @example
11929			 *    $(document).ready( function() {
11930			 *      $('#example').dataTable( {
11931			 *        "language": {
11932			 *          "thousands": "'"
11933			 *        }
11934			 *      } );
11935			 *    } );
11936			 */
11937			"sThousands": ",",
11938	
11939	
11940			/**
11941			 * Detail the action that will be taken when the drop down menu for the
11942			 * pagination length option is changed. The '_MENU_' variable is replaced
11943			 * with a default select list of 10, 25, 50 and 100, and can be replaced
11944			 * with a custom select box if required.
11945			 *  @type string
11946			 *  @default Show _MENU_ entries
11947			 *
11948			 *  @dtopt Language
11949			 *  @name DataTable.defaults.language.lengthMenu
11950			 *
11951			 *  @example
11952			 *    // Language change only
11953			 *    $(document).ready( function() {
11954			 *      $('#example').dataTable( {
11955			 *        "language": {
11956			 *          "lengthMenu": "Display _MENU_ records"
11957			 *        }
11958			 *      } );
11959			 *    } );
11960			 *
11961			 *  @example
11962			 *    // Language and options change
11963			 *    $(document).ready( function() {
11964			 *      $('#example').dataTable( {
11965			 *        "language": {
11966			 *          "lengthMenu": 'Display <select>'+
11967			 *            '<option value="10">10</option>'+
11968			 *            '<option value="20">20</option>'+
11969			 *            '<option value="30">30</option>'+
11970			 *            '<option value="40">40</option>'+
11971			 *            '<option value="50">50</option>'+
11972			 *            '<option value="-1">All</option>'+
11973			 *            '</select> records'
11974			 *        }
11975			 *      } );
11976			 *    } );
11977			 */
11978			"sLengthMenu": "Show _MENU_ entries",
11979	
11980	
11981			/**
11982			 * When using Ajax sourced data and during the first draw when DataTables is
11983			 * gathering the data, this message is shown in an empty row in the table to
11984			 * indicate to the end user the the data is being loaded. Note that this
11985			 * parameter is not used when loading data by server-side processing, just
11986			 * Ajax sourced data with client-side processing.
11987			 *  @type string
11988			 *  @default Loading...
11989			 *
11990			 *  @dtopt Language
11991			 *  @name DataTable.defaults.language.loadingRecords
11992			 *
11993			 *  @example
11994			 *    $(document).ready( function() {
11995			 *      $('#example').dataTable( {
11996			 *        "language": {
11997			 *          "loadingRecords": "Please wait - loading..."
11998			 *        }
11999			 *      } );
12000			 *    } );
12001			 */
12002			"sLoadingRecords": "Loading...",
12003	
12004	
12005			/**
12006			 * Text which is displayed when the table is processing a user action
12007			 * (usually a sort command or similar).
12008			 *  @type string
12009			 *
12010			 *  @dtopt Language
12011			 *  @name DataTable.defaults.language.processing
12012			 *
12013			 *  @example
12014			 *    $(document).ready( function() {
12015			 *      $('#example').dataTable( {
12016			 *        "language": {
12017			 *          "processing": "DataTables is currently busy"
12018			 *        }
12019			 *      } );
12020			 *    } );
12021			 */
12022			"sProcessing": "",
12023	
12024	
12025			/**
12026			 * Details the actions that will be taken when the user types into the
12027			 * filtering input text box. The variable "_INPUT_", if used in the string,
12028			 * is replaced with the HTML text box for the filtering input allowing
12029			 * control over where it appears in the string. If "_INPUT_" is not given
12030			 * then the input box is appended to the string automatically.
12031			 *  @type string
12032			 *  @default Search:
12033			 *
12034			 *  @dtopt Language
12035			 *  @name DataTable.defaults.language.search
12036			 *
12037			 *  @example
12038			 *    // Input text box will be appended at the end automatically
12039			 *    $(document).ready( function() {
12040			 *      $('#example').dataTable( {
12041			 *        "language": {
12042			 *          "search": "Filter records:"
12043			 *        }
12044			 *      } );
12045			 *    } );
12046			 *
12047			 *  @example
12048			 *    // Specify where the filter should appear
12049			 *    $(document).ready( function() {
12050			 *      $('#example').dataTable( {
12051			 *        "language": {
12052			 *          "search": "Apply filter _INPUT_ to table"
12053			 *        }
12054			 *      } );
12055			 *    } );
12056			 */
12057			"sSearch": "Search:",
12058	
12059	
12060			/**
12061			 * Assign a `placeholder` attribute to the search `input` element
12062			 *  @type string
12063			 *  @default 
12064			 *
12065			 *  @dtopt Language
12066			 *  @name DataTable.defaults.language.searchPlaceholder
12067			 */
12068			"sSearchPlaceholder": "",
12069	
12070	
12071			/**
12072			 * All of the language information can be stored in a file on the
12073			 * server-side, which DataTables will look up if this parameter is passed.
12074			 * It must store the URL of the language file, which is in a JSON format,
12075			 * and the object has the same properties as the oLanguage object in the
12076			 * initialiser object (i.e. the above parameters). Please refer to one of
12077			 * the example language files to see how this works in action.
12078			 *  @type string
12079			 *  @default <i>Empty string - i.e. disabled</i>
12080			 *
12081			 *  @dtopt Language
12082			 *  @name DataTable.defaults.language.url
12083			 *
12084			 *  @example
12085			 *    $(document).ready( function() {
12086			 *      $('#example').dataTable( {
12087			 *        "language": {
12088			 *          "url": "http
12088s
vendor: 83,377 bytes, lines 12088-14869
12088://www.sprymedia.co.uk/dataTables/lang.txt"
12089			 *        }
12090			 *      } );
12091			 *    } );
12092			 */
12093			"sUrl": "",
12094	
12095	
12096			/**
12097			 * Text shown inside the table records when the is no information to be
12098			 * displayed after filtering. `emptyTable` is shown when there is simply no
12099			 * information in the table at all (regardless of filtering).
12100			 *  @type string
12101			 *  @default No matching records found
12102			 *
12103			 *  @dtopt Language
12104			 *  @name DataTable.defaults.language.zeroRecords
12105			 *
12106			 *  @example
12107			 *    $(document).ready( function() {
12108			 *      $('#example').dataTable( {
12109			 *        "language": {
12110			 *          "zeroRecords": "No records to display"
12111			 *        }
12112			 *      } );
12113			 *    } );
12114			 */
12115			"sZeroRecords": "No matching records found"
12116		},
12117	
12118	
12119		/**
12120		 * This parameter allows you to have define the global filtering state at
12121		 * initialisation time. As an object the `search` parameter must be
12122		 * defined, but all other parameters are optional. When `regex` is true,
12123		 * the search string will be treated as a regular expression, when false
12124		 * (default) it will be treated as a straight string. When `smart`
12125		 * DataTables will use it's smart filtering methods (to word match at
12126		 * any point in the data), when false this will not be done.
12127		 *  @namespace
12128		 *  @extends DataTable.models.oSearch
12129		 *
12130		 *  @dtopt Options
12131		 *  @name DataTable.defaults.search
12132		 *
12133		 *  @example
12134		 *    $(document).ready( function() {
12135		 *      $('#example').dataTable( {
12136		 *        "search": {"search": "Initial search"}
12137		 *      } );
12138		 *    } )
12139		 */
12140		"oSearch": $.extend( {}, DataTable.models.oSearch ),
12141	
12142	
12143		/**
12144		 * __Deprecated__ The functionality provided by this parameter has now been
12145		 * superseded by that provided through `ajax`, which should be used instead.
12146		 *
12147		 * By default DataTables will look for the property `data` (or `aaData` for
12148		 * compatibility with DataTables 1.9-) when obtaining data from an Ajax
12149		 * source or for server-side processing - this parameter allows that
12150		 * property to be changed. You can use Javascript dotted object notation to
12151		 * get a data source for multiple levels of nesting.
12152		 *  @type string
12153		 *  @default data
12154		 *
12155		 *  @dtopt Options
12156		 *  @dtopt Server-side
12157		 *  @name DataTable.defaults.ajaxDataProp
12158		 *
12159		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
12160		 */
12161		"sAjaxDataProp": "data",
12162	
12163	
12164		/**
12165		 * __Deprecated__ The functionality provided by this parameter has now been
12166		 * superseded by that provided through `ajax`, which should be used instead.
12167		 *
12168		 * You can instruct DataTables to load data from an external
12169		 * source using this parameter (use aData if you want to pass data in you
12170		 * already have). Simply provide a url a JSON object can be obtained from.
12171		 *  @type string
12172		 *  @default null
12173		 *
12174		 *  @dtopt Options
12175		 *  @dtopt Server-side
12176		 *  @name DataTable.defaults.ajaxSource
12177		 *
12178		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
12179		 */
12180		"sAjaxSource": null,
12181	
12182	
12183		/**
12184		 * This initialisation variable allows you to specify exactly where in the
12185		 * DOM you want DataTables to inject the various controls it adds to the page
12186		 * (for example you might want the pagination controls at the top of the
12187		 * table). DIV elements (with or without a custom class) can also be added to
12188		 * aid styling. The follow syntax is used:
12189		 *   <ul>
12190		 *     <li>The following options are allowed:
12191		 *       <ul>
12192		 *         <li>'l' - Length changing</li>
12193		 *         <li>'f' - Filtering input</li>
12194		 *         <li>'t' - The table!</li>
12195		 *         <li>'i' - Information</li>
12196		 *         <li>'p' - Pagination</li>
12197		 *         <li>'r' - pRocessing</li>
12198		 *       </ul>
12199		 *     </li>
12200		 *     <li>The following constants are allowed:
12201		 *       <ul>
12202		 *         <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>
12203		 *         <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>
12204		 *       </ul>
12205		 *     </li>
12206		 *     <li>The following syntax is expected:
12207		 *       <ul>
12208		 *         <li>'&lt;' and '&gt;' - div elements</li>
12209		 *         <li>'&lt;"class" and '&gt;' - div with a class</li>
12210		 *         <li>'&lt;"#id" and '&gt;' - div with an ID</li>
12211		 *       </ul>
12212		 *     </li>
12213		 *     <li>Examples:
12214		 *       <ul>
12215		 *         <li>'&lt;"wrapper"flipt&gt;'</li>
12216		 *         <li>'&lt;lf&lt;t&gt;ip&gt;'</li>
12217		 *       </ul>
12218		 *     </li>
12219		 *   </ul>
12220		 *  @type string
12221		 *  @default lfrtip <i>(when `jQueryUI` is false)</i> <b>or</b>
12222		 *    <"H"lfr>t<"F"ip> <i>(when `jQueryUI` is true)</i>
12223		 *
12224		 *  @dtopt Options
12225		 *  @name DataTable.defaults.dom
12226		 *
12227		 *  @example
12228		 *    $(document).ready( function() {
12229		 *      $('#example').dataTable( {
12230		 *        "dom": '&lt;"top"i&gt;rt&lt;"bottom"flp&gt;&lt;"clear"&gt;'
12231		 *      } );
12232		 *    } );
12233		 */
12234		"sDom": "lfrtip",
12235	
12236	
12237		/**
12238		 * Search delay option. This will throttle full table searches that use the
12239		 * DataTables provided search input element (it does not effect calls to
12240		 * `dt-api search()`, providing a delay before the search is made.
12241		 *  @type integer
12242		 *  @default 0
12243		 *
12244		 *  @dtopt Options
12245		 *  @name DataTable.defaults.searchDelay
12246		 *
12247		 *  @example
12248		 *    $(document).ready( function() {
12249		 *      $('#example').dataTable( {
12250		 *        "searchDelay": 200
12251		 *      } );
12252		 *    } )
12253		 */
12254		"searchDelay": null,
12255	
12256	
12257		/**
12258		 * DataTables features six different built-in options for the buttons to
12259		 * display for pagination control:
12260		 *
12261		 * * `numbers` - Page number buttons only
12262		 * * `simple` - 'Previous' and 'Next' buttons only
12263		 * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers
12264		 * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons
12265		 * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus page numbers
12266		 * * `first_last_numbers` - 'First' and 'Last' buttons, plus page numbers
12267		 *  
12268		 * Further methods can be added using {@link DataTable.ext.oPagination}.
12269		 *  @type string
12270		 *  @default simple_numbers
12271		 *
12272		 *  @dtopt Options
12273		 *  @name DataTable.defaults.pagingType
12274		 *
12275		 *  @example
12276		 *    $(document).ready( function() {
12277		 *      $('#example').dataTable( {
12278		 *        "pagingType": "full_numbers"
12279		 *      } );
12280		 *    } )
12281		 */
12282		"sPaginationType": "simple_numbers",
12283	
12284	
12285		/**
12286		 * Enable horizontal scrolling. When a table is too wide to fit into a
12287		 * certain layout, or you have a large number of columns in the table, you
12288		 * can enable x-scrolling to show the table in a viewport, which can be
12289		 * scrolled. This property can be `true` which will allow the table to
12290		 * scroll horizontally when needed, or any CSS unit, or a number (in which
12291		 * case it will be treated as a pixel measurement). Setting as simply `true`
12292		 * is recommended.
12293		 *  @type boolean|string
12294		 *  @default <i>blank string - i.e. disabled</i>
12295		 *
12296		 *  @dtopt Features
12297		 *  @name DataTable.defaults.scrollX
12298		 *
12299		 *  @example
12300		 *    $(document).ready( function() {
12301		 *      $('#example').dataTable( {
12302		 *        "scrollX": true,
12303		 *        "scrollCollapse": true
12304		 *      } );
12305		 *    } );
12306		 */
12307		"sScrollX": "",
12308	
12309	
12310		/**
12311		 * This property can be used to force a DataTable to use more width than it
12312		 * might otherwise do when x-scrolling is enabled. For example if you have a
12313		 * table which requires to be well spaced, this parameter is useful for
12314		 * "over-sizing" the table, and thus forcing scrolling. This property can by
12315		 * any CSS unit, or a number (in which case it will be treated as a pixel
12316		 * measurement).
12317		 *  @type string
12318		 *  @default <i>blank string - i.e. disabled</i>
12319		 *
12320		 *  @dtopt Options
12321		 *  @name DataTable.defaults.scrollXInner
12322		 *
12323		 *  @example
12324		 *    $(document).ready( function() {
12325		 *      $('#example').dataTable( {
12326		 *        "scrollX": "100%",
12327		 *        "scrollXInner": "110%"
12328		 *      } );
12329		 *    } );
12330		 */
12331		"sScrollXInner": "",
12332	
12333	
12334		/**
12335		 * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
12336		 * to the given height, and enable scrolling for any data which overflows the
12337		 * current viewport. This can be used as an alternative to paging to display
12338		 * a lot of data in a small area (although paging and scrolling can both be
12339		 * enabled at the same time). This property can be any CSS unit, or a number
12340		 * (in which case it will be treated as a pixel measurement).
12341		 *  @type string
12342		 *  @default <i>blank string - i.e. disabled</i>
12343		 *
12344		 *  @dtopt Features
12345		 *  @name DataTable.defaults.scrollY
12346		 *
12347		 *  @example
12348		 *    $(document).ready( function() {
12349		 *      $('#example').dataTable( {
12350		 *        "scrollY": "200px",
12351		 *        "paginate": false
12352		 *      } );
12353		 *    } );
12354		 */
12355		"sScrollY": "",
12356	
12357	
12358		/**
12359		 * __Deprecated__ The functionality provided by this parameter has now been
12360		 * superseded by that provided through `ajax`, which should be used instead.
12361		 *
12362		 * Set the HTTP method that is used to make the Ajax call for server-side
12363		 * processing or Ajax sourced data.
12364		 *  @type string
12365		 *  @default GET
12366		 *
12367		 *  @dtopt Options
12368		 *  @dtopt Server-side
12369		 *  @name DataTable.defaults.serverMethod
12370		 *
12371		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
12372		 */
12373		"sServerMethod": "GET",
12374	
12375	
12376		/**
12377		 * DataTables makes use of renderers when displaying HTML elements for
12378		 * a table. These renderers can be added or modified by plug-ins to
12379		 * generate suitable mark-up for a site. For example the Bootstrap
12380		 * integration plug-in for DataTables uses a paging button renderer to
12381		 * display pagination buttons in the mark-up required by Bootstrap.
12382		 *
12383		 * For further information about the renderers available see
12384		 * DataTable.ext.renderer
12385		 *  @type string|object
12386		 *  @default null
12387		 *
12388		 *  @name DataTable.defaults.renderer
12389		 *
12390		 */
12391		"renderer": null,
12392	
12393	
12394		/**
12395		 * Set the data property name that DataTables should use to get a row's id
12396		 * to set as the `id` property in the node.
12397		 *  @type string
12398		 *  @default DT_RowId
12399		 *
12400		 *  @name DataTable.defaults.rowId
12401		 */
12402		"rowId": "DT_RowId"
12403	};
12404	
12405	_fnHungarianMap( DataTable.defaults );
12406	
12407	
12408	
12409	/*
12410	 * Developer note - See note in model.defaults.js about the use of Hungarian
12411	 * notation and camel case.
12412	 */
12413	
12414	/**
12415	 * Column options that can be given to DataTables at initialisation time.
12416	 *  @namespace
12417	 */
12418	DataTable.defaults.column = {
12419		/**
12420		 * Define which column(s) an order will occur on for this column. This
12421		 * allows a column's ordering to take multiple columns into account when
12422		 * doing a sort or use the data from a different column. For example first
12423		 * name / last name columns make sense to do a multi-column sort over the
12424		 * two columns.
12425		 *  @type array|int
12426		 *  @default null <i>Takes the value of the column index automatically</i>
12427		 *
12428		 *  @name DataTable.defaults.column.orderData
12429		 *  @dtopt Columns
12430		 *
12431		 *  @example
12432		 *    // Using `columnDefs`
12433		 *    $(document).ready( function() {
12434		 *      $('#example').dataTable( {
12435		 *        "columnDefs": [
12436		 *          { "orderData": [ 0, 1 ], "targets": [ 0 ] },
12437		 *          { "orderData": [ 1, 0 ], "targets": [ 1 ] },
12438		 *          { "orderData": 2, "targets": [ 2 ] }
12439		 *        ]
12440		 *      } );
12441		 *    } );
12442		 *
12443		 *  @example
12444		 *    // Using `columns`
12445		 *    $(document).ready( function() {
12446		 *      $('#example').dataTable( {
12447		 *        "columns": [
12448		 *          { "orderData": [ 0, 1 ] },
12449		 *          { "orderData": [ 1, 0 ] },
12450		 *          { "orderData": 2 },
12451		 *          null,
12452		 *          null
12453		 *        ]
12454		 *      } );
12455		 *    } );
12456		 */
12457		"aDataSort": null,
12458		"iDataSort": -1,
12459	
12460	
12461		/**
12462		 * You can control the default ordering direction, and even alter the
12463		 * behaviour of the sort handler (i.e. only allow ascending ordering etc)
12464		 * using this parameter.
12465		 *  @type array
12466		 *  @default [ 'asc', 'desc' ]
12467		 *
12468		 *  @name DataTable.defaults.column.orderSequence
12469		 *  @dtopt Columns
12470		 *
12471		 *  @example
12472		 *    // Using `columnDefs`
12473		 *    $(document).ready( function() {
12474		 *      $('#example').dataTable( {
12475		 *        "columnDefs": [
12476		 *          { "orderSequence": [ "asc" ], "targets": [ 1 ] },
12477		 *          { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] },
12478		 *          { "orderSequence": [ "desc" ], "targets": [ 3 ] }
12479		 *        ]
12480		 *      } );
12481		 *    } );
12482		 *
12483		 *  @example
12484		 *    // Using `columns`
12485		 *    $(document).ready( function() {
12486		 *      $('#example').dataTable( {
12487		 *        "columns": [
12488		 *          null,
12489		 *          { "orderSequence": [ "asc" ] },
12490		 *          { "orderSequence": [ "desc", "asc", "asc" ] },
12491		 *          { "orderSequence": [ "desc" ] },
12492		 *          null
12493		 *        ]
12494		 *      } );
12495		 *    } );
12496		 */
12497		"asSorting": [ 'asc', 'desc' ],
12498	
12499	
12500		/**
12501		 * Enable or disable filtering on the data in this column.
12502		 *  @type boolean
12503		 *  @default true
12504		 *
12505		 *  @name DataTable.defaults.column.searchable
12506		 *  @dtopt Columns
12507		 *
12508		 *  @example
12509		 *    // Using `columnDefs`
12510		 *    $(document).ready( function() {
12511		 *      $('#example').dataTable( {
12512		 *        "columnDefs": [
12513		 *          { "searchable": false, "targets": [ 0 ] }
12514		 *        ] } );
12515		 *    } );
12516		 *
12517		 *  @example
12518		 *    // Using `columns`
12519		 *    $(document).ready( function() {
12520		 *      $('#example').dataTable( {
12521		 *        "columns": [
12522		 *          { "searchable": false },
12523		 *          null,
12524		 *          null,
12525		 *          null,
12526		 *          null
12527		 *        ] } );
12528		 *    } );
12529		 */
12530		"bSearchable": true,
12531	
12532	
12533		/**
12534		 * Enable or disable ordering on this column.
12535		 *  @type boolean
12536		 *  @default true
12537		 *
12538		 *  @name DataTable.defaults.column.orderable
12539		 *  @dtopt Columns
12540		 *
12541		 *  @example
12542		 *    // Using `columnDefs`
12543		 *    $(document).ready( function() {
12544		 *      $('#example').dataTable( {
12545		 *        "columnDefs": [
12546		 *          { "orderable": false, "targets": [ 0 ] }
12547		 *        ] } );
12548		 *    } );
12549		 *
12550		 *  @example
12551		 *    // Using `columns`
12552		 *    $(document).ready( function() {
12553		 *      $('#example').dataTable( {
12554		 *        "columns": [
12555		 *          { "orderable": false },
12556		 *          null,
12557		 *          null,
12558		 *          null,
12559		 *          null
12560		 *        ] } );
12561		 *    } );
12562		 */
12563		"bSortable": true,
12564	
12565	
12566		/**
12567		 * Enable or disable the display of this column.
12568		 *  @type boolean
12569		 *  @default true
12570		 *
12571		 *  @name DataTable.defaults.column.visible
12572		 *  @dtopt Columns
12573		 *
12574		 *  @example
12575		 *    // Using `columnDefs`
12576		 *    $(document).ready( function() {
12577		 *      $('#example').dataTable( {
12578		 *        "columnDefs": [
12579		 *          { "visible": false, "targets": [ 0 ] }
12580		 *        ] } );
12581		 *    } );
12582		 *
12583		 *  @example
12584		 *    // Using `columns`
12585		 *    $(document).ready( function() {
12586		 *      $('#example').dataTable( {
12587		 *        "columns": [
12588		 *          { "visible": false },
12589		 *          null,
12590		 *          null,
12591		 *          null,
12592		 *          null
12593		 *        ] } );
12594		 *    } );
12595		 */
12596		"bVisible": true,
12597	
12598	
12599		/**
12600		 * Developer definable function that is called whenever a cell is created (Ajax source,
12601		 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
12602		 * allowing you to modify the DOM element (add background colour for example) when the
12603		 * element is available.
12604		 *  @type function
12605		 *  @param {element} td The TD node that has been created
12606		 *  @param {*} cellData The Data for the cell
12607		 *  @param {array|object} rowData The data for the whole row
12608		 *  @param {int} row The row index for the aoData data store
12609		 *  @param {int} col The column index for aoColumns
12610		 *
12611		 *  @name DataTable.defaults.column.createdCell
12612		 *  @dtopt Columns
12613		 *
12614		 *  @example
12615		 *    $(document).ready( function() {
12616		 *      $('#example').dataTable( {
12617		 *        "columnDefs": [ {
12618		 *          "targets": [3],
12619		 *          "createdCell": function (td, cellData, rowData, row, col) {
12620		 *            if ( cellData == "1.7" ) {
12621		 *              $(td).css('color', 'blue')
12622		 *            }
12623		 *          }
12624		 *        } ]
12625		 *      });
12626		 *    } );
12627		 */
12628		"fnCreatedCell": null,
12629	
12630	
12631		/**
12632		 * This parameter has been replaced by `data` in DataTables to ensure naming
12633		 * consistency. `dataProp` can still be used, as there is backwards
12634		 * compatibility in DataTables for this option, but it is strongly
12635		 * recommended that you use `data` in preference to `dataProp`.
12636		 *  @name DataTable.defaults.column.dataProp
12637		 */
12638	
12639	
12640		/**
12641		 * This property can be used to read data from any data source property,
12642		 * including deeply nested objects / properties. `data` can be given in a
12643		 * number of different ways which effect its behaviour:
12644		 *
12645		 * * `integer` - treated as an array index for the data source. This is the
12646		 *   default that DataTables uses (incrementally increased for each column).
12647		 * * `string` - read an object property from the data source. There are
12648		 *   three 'special' options that can be used in the string to alter how
12649		 *   DataTables reads the data from the source object:
12650		 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
12651		 *      Javascript to read from nested objects, so to can the options
12652		 *      specified in `data`. For example: `browser.version` or
12653		 *      `browser.name`. If your object parameter name contains a period, use
12654		 *      `\\` to escape it - i.e. `first\\.name`.
12655		 *    * `[]` - Array notation. DataTables can automatically combine data
12656		 *      from and array source, joining the data with the characters provided
12657		 *      between the two brackets. For example: `name[, ]` would provide a
12658		 *      comma-space separated list from the source array. If no characters
12659		 *      are provided between the brackets, the original array source is
12660		 *      returned.
12661		 *    * `()` - Function notation. Adding `()` to the end of a parameter will
12662		 *      execute a function of the name given. For example: `browser()` for a
12663		 *      simple function on the data source, `browser.version()` for a
12664		 *      function in a nested property or even `browser().version` to get an
12665		 *      object property if the function called returns an object. Note that
12666		 *      function notation is recommended for use in `render` rather than
12667		 *      `data` as it is much simpler to use as a renderer.
12668		 * * `null` - use the original data source for the row rather than plucking
12669		 *   data directly from it. This action has effects on two other
12670		 *   initialisation options:
12671		 *    * `defaultContent` - When null is given as the `data` option and
12672		 *      `defaultContent` is specified for the column, the value defined by
12673		 *      `defaultContent` will be used for the cell.
12674		 *    * `render` - When null is used for the `data` option and the `render`
12675		 *      option is specified for the column, the whole data source for the
12676		 *      row is used for the renderer.
12677		 * * `function` - the function given will be executed whenever DataTables
12678		 *   needs to set or get the data for a cell in the column. The function
12679		 *   takes three parameters:
12680		 *    * Parameters:
12681		 *      * `{array|object}` The data source for the row
12682		 *      * `{string}` The type call data requested - this will be 'set' when
12683		 *        setting data or 'filter', 'display', 'type', 'sort' or undefined
12684		 *        when gathering data. Note that when `undefined` is given for the
12685		 *        type DataTables expects to get the raw data for the object back<
12686		 *      * `{*}` Data to set when the second parameter is 'set'.
12687		 *    * Return:
12688		 *      * The return value from the function is not required when 'set' is
12689		 *        the type of call, but otherwise the return is what will be used
12690		 *        for the data requested.
12691		 *
12692		 * Note that `data` is a getter and setter option. If you just require
12693		 * formatting of data for output, you will likely want to use `render` which
12694		 * is simply a getter and thus simpler to use.
12695		 *
12696		 * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The
12697		 * name change reflects the flexibility of this property and is consistent
12698		 * with the naming of mRender. If 'mDataProp' is given, then it will still
12699		 * be used by DataTables, as it automatically maps the old name to the new
12700		 * if required.
12701		 *
12702		 *  @type string|int|function|null
12703		 *  @default null <i>Use automatically calculated column index</i>
12704		 *
12705		 *  @name DataTable.defaults.column.data
12706		 *  @dtopt Columns
12707		 *
12708		 *  @example
12709		 *    // Read table data from objects
12710		 *    // JSON structure for each row:
12711		 *    //   {
12712		 *    //      "engine": {value},
12713		 *    //      "browser": {value},
12714		 *    //      "platform": {value},
12715		 *    //      "version": {value},
12716		 *    //      "grade": {value}
12717		 *    //   }
12718		 *    $(document).ready( function() {
12719		 *      $('#example').dataTable( {
12720		 *        "ajaxSource": "sources/objects.txt",
12721		 *        "columns": [
12722		 *          { "data": "engine" },
12723		 *          { "data": "browser" },
12724		 *          { "data": "platform" },
12725		 *          { "data": "version" },
12726		 *          { "data": "grade" }
12727		 *        ]
12728		 *      } );
12729		 *    } );
12730		 *
12731		 *  @example
12732		 *    // Read information from deeply nested objects
12733		 *    // JSON structure for each row:
12734		 *    //   {
12735		 *    //      "engine": {value},
12736		 *    //      "browser": {value},
12737		 *    //      "platform": {
12738		 *    //         "inner": {value}
12739		 *    //      },
12740		 *    //      "details": [
12741		 *    //         {value}, {value}
12742		 *    //      ]
12743		 *    //   }
12744		 *    $(document).ready( function() {
12745		 *      $('#example').dataTable( {
12746		 *        "ajaxSource": "sources/deep.txt",
12747		 *        "columns": [
12748		 *          { "data": "engine" },
12749		 *          { "data": "browser" },
12750		 *          { "data": "platform.inner" },
12751		 *          { "data": "details.0" },
12752		 *          { "data": "details.1" }
12753		 *        ]
12754		 *      } );
12755		 *    } );
12756		 *
12757		 *  @example
12758		 *    // Using `data` as a function to provide different information for
12759		 *    // sorting, filtering and display. In this case, currency (price)
12760		 *    $(document).ready( function() {
12761		 *      $('#example').dataTable( {
12762		 *        "columnDefs": [ {
12763		 *          "targets": [ 0 ],
12764		 *          "data": function ( source, type, val ) {
12765		 *            if (type === 'set') {
12766		 *              source.price = val;
12767		 *              // Store the computed display and filter values for efficiency
12768		 *              source.price_display = val=="" ? "" : "$"+numberFormat(val);
12769		 *              source.price_filter  = val=="" ? "" : "$"+numberFormat(val)+" "+val;
12770		 *              return;
12771		 *            }
12772		 *            else if (type === 'display') {
12773		 *              return source.price_display;
12774		 *            }
12775		 *            else if (type === 'filter') {
12776		 *              return source.price_filter;
12777		 *            }
12778		 *            // 'sort', 'type' and undefined all just use the integer
12779		 *            return source.price;
12780		 *          }
12781		 *        } ]
12782		 *      } );
12783		 *    } );
12784		 *
12785		 *  @example
12786		 *    // Using default content
12787		 *    $(document).ready( function() {
12788		 *      $('#example').dataTable( {
12789		 *        "columnDefs": [ {
12790		 *          "targets": [ 0 ],
12791		 *          "data": null,
12792		 *          "defaultContent": "Click to edit"
12793		 *        } ]
12794		 *      } );
12795		 *    } );
12796		 *
12797		 *  @example
12798		 *    // Using array notation - outputting a list from an array
12799		 *    $(document).ready( function() {
12800		 *      $('#example').dataTable( {
12801		 *        "columnDefs": [ {
12802		 *          "targets": [ 0 ],
12803		 *          "data": "name[, ]"
12804		 *        } ]
12805		 *      } );
12806		 *    } );
12807		 *
12808		 */
12809		"mData": null,
12810	
12811	
12812		/**
12813		 * This property is the rendering partner to `data` and it is suggested that
12814		 * when you want to manipulate data for display (including filtering,
12815		 * sorting etc) without altering the underlying data for the table, use this
12816		 * property. `render` can be considered to be the the read only companion to
12817		 * `data` which is read / write (then as such more complex). Like `data`
12818		 * this option can be given in a number of different ways to effect its
12819		 * behaviour:
12820		 *
12821		 * * `integer` - treated as an array index for the data source. This is the
12822		 *   default that DataTables uses (incrementally increased for each column).
12823		 * * `string` - read an object property from the data source. There are
12824		 *   three 'special' options that can be used in the string to alter how
12825		 *   DataTables reads the data from the source object:
12826		 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
12827		 *      Javascript to read from nested objects, so to can the options
12828		 *      specified in `data`. For example: `browser.version` or
12829		 *      `browser.name`. If your object parameter name contains a period, use
12830		 *      `\\` to escape it - i.e. `first\\.name`.
12831		 *    * `[]` - Array notation. DataTables can automatically combine data
12832		 *      from and array source, joining the data with the characters provided
12833		 *      between the two brackets. For example: `name[, ]` would provide a
12834		 *      comma-space separated list from the source array. If no characters
12835		 *      are provided between the brackets, the original array source is
12836		 *      returned.
12837		 *    * `()` - Function notation. Adding `()` to the end of a parameter will
12838		 *      execute a function of the name given. For example: `browser()` for a
12839		 *      simple function on the data source, `browser.version()` for a
12840		 *      function in a nested property or even `browser().version` to get an
12841		 *      object property if the function called returns an object.
12842		 * * `object` - use different data for the different data types requested by
12843		 *   DataTables ('filter', 'display', 'type' or 'sort'). The property names
12844		 *   of the object is the data type the property refers to and the value can
12845		 *   defined using an integer, string or function using the same rules as
12846		 *   `render` normally does. Note that an `_` option _must_ be specified.
12847		 *   This is the default value to use if you haven't specified a value for
12848		 *   the data type requested by DataTables.
12849		 * * `function` - the function given will be executed whenever DataTables
12850		 *   needs to set or get the data for a cell in the column. The function
12851		 *   takes three parameters:
12852		 *    * Parameters:
12853		 *      * {array|object} The data source for the row (based on `data`)
12854		 *      * {string} The type call data requested - this will be 'filter',
12855		 *        'display', 'type' or 'sort'.
12856		 *      * {array|object} The full data source for the row (not based on
12857		 *        `data`)
12858		 *    * Return:
12859		 *      * The return value from the function is what will be used for the
12860		 *        data requested.
12861		 *
12862		 *  @type string|int|function|object|null
12863		 *  @default null Use the data source value.
12864		 *
12865		 *  @name DataTable.defaults.column.render
12866		 *  @dtopt Columns
12867		 *
12868		 *  @example
12869		 *    // Create a comma separated list from an array of objects
12870		 *    $(document).ready( function() {
12871		 *      $('#example').dataTable( {
12872		 *        "ajaxSource": "sources/deep.txt",
12873		 *        "columns": [
12874		 *          { "data": "engine" },
12875		 *          { "data": "browser" },
12876		 *          {
12877		 *            "data": "platform",
12878		 *            "render": "[, ].name"
12879		 *          }
12880		 *        ]
12881		 *      } );
12882		 *    } );
12883		 *
12884		 *  @example
12885		 *    // Execute a function to obtain data
12886		 *    $(document).ready( function() {
12887		 *      $('#example').dataTable( {
12888		 *        "columnDefs": [ {
12889		 *          "targets": [ 0 ],
12890		 *          "data": null, // Use the full data source object for the renderer's source
12891		 *          "render": "browserName()"
12892		 *        } ]
12893		 *      } );
12894		 *    } );
12895		 *
12896		 *  @example
12897		 *    // As an object, extracting different data for the different types
12898		 *    // This would be used with a data source such as:
12899		 *    //   { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" }
12900		 *    // Here the `phone` integer is used for sorting and type detection, while `phone_filter`
12901		 *    // (which has both forms) is used for filtering for if a user inputs either format, while
12902		 *    // the formatted phone number is the one that is shown in the table.
12903		 *    $(document).ready( function() {
12904		 *      $('#example').dataTable( {
12905		 *        "columnDefs": [ {
12906		 *          "targets": [ 0 ],
12907		 *          "data": null, // Use the full data source object for the renderer's source
12908		 *          "render": {
12909		 *            "_": "phone",
12910		 *            "filter": "phone_filter",
12911		 *            "display": "phone_display"
12912		 *          }
12913		 *        } ]
12914		 *      } );
12915		 *    } );
12916		 *
12917		 *  @example
12918		 *    // Use as a function to create a link from the data source
12919		 *    $(document).ready( function() {
12920		 *      $('#example').dataTable( {
12921		 *        "columnDefs": [ {
12922		 *          "targets": [ 0 ],
12923		 *          "data": "download_link",
12924		 *          "render": function ( data, type, full ) {
12925		 *            return '<a href="'+data+'">Download</a>';
12926		 *          }
12927		 *        } ]
12928		 *      } );
12929		 *    } );
12930		 */
12931		"mRender": null,
12932	
12933	
12934		/**
12935		 * Change the cell type created for the column - either TD cells or TH cells. This
12936		 * can be useful as TH cells have semantic meaning in the table body, allowing them
12937		 * to act as a header for a row (you may wish to add scope='row' to the TH elements).
12938		 *  @type string
12939		 *  @default td
12940		 *
12941		 *  @name DataTable.defaults.column.cellType
12942		 *  @dtopt Columns
12943		 *
12944		 *  @example
12945		 *    // Make the first column use TH cells
12946		 *    $(document).ready( function() {
12947		 *      $('#example').dataTable( {
12948		 *        "columnDefs": [ {
12949		 *          "targets": [ 0 ],
12950		 *          "cellType": "th"
12951		 *        } ]
12952		 *      } );
12953		 *    } );
12954		 */
12955		"sCellType": "td",
12956	
12957	
12958		/**
12959		 * Class to give to each cell in this column.
12960		 *  @type string
12961		 *  @default <i>Empty string</i>
12962		 *
12963		 *  @name DataTable.defaults.column.class
12964		 *  @dtopt Columns
12965		 *
12966		 *  @example
12967		 *    // Using `columnDefs`
12968		 *    $(document).ready( function() {
12969		 *      $('#example').dataTable( {
12970		 *        "columnDefs": [
12971		 *          { "class": "my_class", "targets": [ 0 ] }
12972		 *        ]
12973		 *      } );
12974		 *    } );
12975		 *
12976		 *  @example
12977		 *    // Using `columns`
12978		 *    $(document).ready( function() {
12979		 *      $('#example').dataTable( {
12980		 *        "columns": [
12981		 *          { "class": "my_class" },
12982		 *          null,
12983		 *          null,
12984		 *          null,
12985		 *          null
12986		 *        ]
12987		 *      } );
12988		 *    } );
12989		 */
12990		"sClass": "",
12991	
12992		/**
12993		 * When DataTables calculates the column widths to assign to each column,
12994		 * it finds the longest string in each column and then constructs a
12995		 * temporary table and reads the widths from that. The problem with this
12996		 * is that "mmm" is much wider then "iiii", but the latter is a longer
12997		 * string - thus the calculation can go wrong (doing it properly and putting
12998		 * it into an DOM object and measuring that is horribly(!) slow). Thus as
12999		 * a "work around" we provide this option. It will append its value to the
13000		 * text that is found to be the longest string for the column - i.e. padding.
13001		 * Generally you shouldn't need this!
13002		 *  @type string
13003		 *  @default <i>Empty string<i>
13004		 *
13005		 *  @name DataTable.defaults.column.contentPadding
13006		 *  @dtopt Columns
13007		 *
13008		 *  @example
13009		 *    // Using `columns`
13010		 *    $(document).ready( function() {
13011		 *      $('#example').dataTable( {
13012		 *        "columns": [
13013		 *          null,
13014		 *          null,
13015		 *          null,
13016		 *          {
13017		 *            "contentPadding": "mmm"
13018		 *          }
13019		 *        ]
13020		 *      } );
13021		 *    } );
13022		 */
13023		"sContentPadding": "",
13024	
13025	
13026		/**
13027		 * Allows a default value to be given for a column's data, and will be used
13028		 * whenever a null data source is encountered (this can be because `data`
13029		 * is set to null, or because the data source itself is null).
13030		 *  @type string
13031		 *  @default null
13032		 *
13033		 *  @name DataTable.defaults.column.defaultContent
13034		 *  @dtopt Columns
13035		 *
13036		 *  @example
13037		 *    // Using `columnDefs`
13038		 *    $(document).ready( function() {
13039		 *      $('#example').dataTable( {
13040		 *        "columnDefs": [
13041		 *          {
13042		 *            "data": null,
13043		 *            "defaultContent": "Edit",
13044		 *            "targets": [ -1 ]
13045		 *          }
13046		 *        ]
13047		 *      } );
13048		 *    } );
13049		 *
13050		 *  @example
13051		 *    // Using `columns`
13052		 *    $(document).ready( function() {
13053		 *      $('#example').dataTable( {
13054		 *        "columns": [
13055		 *          null,
13056		 *          null,
13057		 *          null,
13058		 *          {
13059		 *            "data": null,
13060		 *            "defaultContent": "Edit"
13061		 *          }
13062		 *        ]
13063		 *      } );
13064		 *    } );
13065		 */
13066		"sDefaultContent": null,
13067	
13068	
13069		/**
13070		 * This parameter is only used in DataTables' server-side processing. It can
13071		 * be exceptionally useful to know what columns are being displayed on the
13072		 * client side, and to map these to database fields. When defined, the names
13073		 * also allow DataTables to reorder information from the server if it comes
13074		 * back in an unexpected order (i.e. if you switch your columns around on the
13075		 * client-side, your server-side code does not also need updating).
13076		 *  @type string
13077		 *  @default <i>Empty string</i>
13078		 *
13079		 *  @name DataTable.defaults.column.name
13080		 *  @dtopt Columns
13081		 *
13082		 *  @example
13083		 *    // Using `columnDefs`
13084		 *    $(document).ready( function() {
13085		 *      $('#example').dataTable( {
13086		 *        "columnDefs": [
13087		 *          { "name": "engine", "targets": [ 0 ] },
13088		 *          { "name": "browser", "targets": [ 1 ] },
13089		 *          { "name": "platform", "targets": [ 2 ] },
13090		 *          { "name": "version", "targets": [ 3 ] },
13091		 *          { "name": "grade", "targets": [ 4 ] }
13092		 *        ]
13093		 *      } );
13094		 *    } );
13095		 *
13096		 *  @example
13097		 *    // Using `columns`
13098		 *    $(document).ready( function() {
13099		 *      $('#example').dataTable( {
13100		 *        "columns": [
13101		 *          { "name": "engine" },
13102		 *          { "name": "browser" },
13103		 *          { "name": "platform" },
13104		 *          { "name": "version" },
13105		 *          { "name": "grade" }
13106		 *        ]
13107		 *      } );
13108		 *    } );
13109		 */
13110		"sName": "",
13111	
13112	
13113		/**
13114		 * Defines a data source type for the ordering which can be used to read
13115		 * real-time information from the table (updating the internally cached
13116		 * version) prior to ordering. This allows ordering to occur on user
13117		 * editable elements such as form inputs.
13118		 *  @type string
13119		 *  @default std
13120		 *
13121		 *  @name DataTable.defaults.column.orderDataType
13122		 *  @dtopt Columns
13123		 *
13124		 *  @example
13125		 *    // Using `columnDefs`
13126		 *    $(document).ready( function() {
13127		 *      $('#example').dataTable( {
13128		 *        "columnDefs": [
13129		 *          { "orderDataType": "dom-text", "targets": [ 2, 3 ] },
13130		 *          { "type": "numeric", "targets": [ 3 ] },
13131		 *          { "orderDataType": "dom-select", "targets": [ 4 ] },
13132		 *          { "orderDataType": "dom-checkbox", "targets": [ 5 ] }
13133		 *        ]
13134		 *      } );
13135		 *    } );
13136		 *
13137		 *  @example
13138		 *    // Using `columns`
13139		 *    $(document).ready( function() {
13140		 *      $('#example').dataTable( {
13141		 *        "columns": [
13142		 *          null,
13143		 *          null,
13144		 *          { "orderDataType": "dom-text" },
13145		 *          { "orderDataType": "dom-text", "type": "numeric" },
13146		 *          { "orderDataType": "dom-select" },
13147		 *          { "orderDataType": "dom-checkbox" }
13148		 *        ]
13149		 *      } );
13150		 *    } );
13151		 */
13152		"sSortDataType": "std",
13153	
13154	
13155		/**
13156		 * The title of this column.
13157		 *  @type string
13158		 *  @default null <i>Derived from the 'TH' value for this column in the
13159		 *    original HTML table.</i>
13160		 *
13161		 *  @name DataTable.defaults.column.title
13162		 *  @dtopt Columns
13163		 *
13164		 *  @example
13165		 *    // Using `columnDefs`
13166		 *    $(document).ready( function() {
13167		 *      $('#example').dataTable( {
13168		 *        "columnDefs": [
13169		 *          { "title": "My column title", "targets": [ 0 ] }
13170		 *        ]
13171		 *      } );
13172		 *    } );
13173		 *
13174		 *  @example
13175		 *    // Using `columns`
13176		 *    $(document).ready( function() {
13177		 *      $('#example').dataTable( {
13178		 *        "columns": [
13179		 *          { "title": "My column title" },
13180		 *          null,
13181		 *          null,
13182		 *          null,
13183		 *          null
13184		 *        ]
13185		 *      } );
13186		 *    } );
13187		 */
13188		"sTitle": null,
13189	
13190	
13191		/**
13192		 * The type allows you to specify how the data for this column will be
13193		 * ordered. Four types (string, numeric, date and html (which will strip
13194		 * HTML tags before ordering)) are currently available. Note that only date
13195		 * formats understood by Javascript's Date() object will be accepted as type
13196		 * date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string',
13197		 * 'numeric', 'date' or 'html' (by default). Further types can be adding
13198		 * through plug-ins.
13199		 *  @type string
13200		 *  @default null <i>Auto-detected from raw data</i>
13201		 *
13202		 *  @name DataTable.defaults.column.type
13203		 *  @dtopt Columns
13204		 *
13205		 *  @example
13206		 *    // Using `columnDefs`
13207		 *    $(document).ready( function() {
13208		 *      $('#example').dataTable( {
13209		 *        "columnDefs": [
13210		 *          { "type": "html", "targets": [ 0 ] }
13211		 *        ]
13212		 *      } );
13213		 *    } );
13214		 *
13215		 *  @example
13216		 *    // Using `columns`
13217		 *    $(document).ready( function() {
13218		 *      $('#example').dataTable( {
13219		 *        "columns": [
13220		 *          { "type": "html" },
13221		 *          null,
13222		 *          null,
13223		 *          null,
13224		 *          null
13225		 *        ]
13226		 *      } );
13227		 *    } );
13228		 */
13229		"sType": null,
13230	
13231	
13232		/**
13233		 * Defining the width of the column, this parameter may take any CSS value
13234		 * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not
13235		 * been given a specific width through this interface ensuring that the table
13236		 * remains readable.
13237		 *  @type string
13238		 *  @default null <i>Automatic</i>
13239		 *
13240		 *  @name DataTable.defaults.column.width
13241		 *  @dtopt Columns
13242		 *
13243		 *  @example
13244		 *    // Using `columnDefs`
13245		 *    $(document).ready( function() {
13246		 *      $('#example').dataTable( {
13247		 *        "columnDefs": [
13248		 *          { "width": "20%", "targets": [ 0 ] }
13249		 *        ]
13250		 *      } );
13251		 *    } );
13252		 *
13253		 *  @example
13254		 *    // Using `columns`
13255		 *    $(document).ready( function() {
13256		 *      $('#example').dataTable( {
13257		 *        "columns": [
13258		 *          { "width": "20%" },
13259		 *          null,
13260		 *          null,
13261		 *          null,
13262		 *          null
13263		 *        ]
13264		 *      } );
13265		 *    } );
13266		 */
13267		"sWidth": null
13268	};
13269	
13270	_fnHungarianMap( DataTable.defaults.column );
13271	
13272	
13273	
13274	/**
13275	 * DataTables settings object - this holds all the information needed for a
13276	 * given table, including configuration, data and current application of the
13277	 * table options. DataTables does not have a single instance for each DataTable
13278	 * with the settings attached to that instance, but rather instances of the
13279	 * DataTable "class" are created on-the-fly as needed (typically by a
13280	 * $().dataTable() call) and the settings object is then applied to that
13281	 * instance.
13282	 *
13283	 * Note that this object is related to {@link DataTable.defaults} but this
13284	 * one is the internal data store for DataTables's cache of columns. It should
13285	 * NOT be manipulated outside of DataTables. Any configuration should be done
13286	 * through the initialisation options.
13287	 *  @namespace
13288	 *  @todo Really should attach the settings object to individual instances so we
13289	 *    don't need to create new instances on each $().dataTable() call (if the
13290	 *    table already exists). It would also save passing oSettings around and
13291	 *    into every single function. However, this is a very significant
13292	 *    architecture change for DataTables and will almost certainly break
13293	 *    backwards compatibility with older installations. This is something that
13294	 *    will be done in 2.0.
13295	 */
13296	DataTable.models.oSettings = {
13297		/**
13298		 * Primary features of DataTables and their enablement state.
13299		 *  @namespace
13300		 */
13301		"oFeatures": {
13302	
13303			/**
13304			 * Flag to say if DataTables should automatically try to calculate the
13305			 * optimum table and columns widths (true) or not (false).
13306			 * Note that this parameter will be set by the initialisation routine. To
13307			 * set a default use {@link DataTable.defaults}.
13308			 *  @type boolean
13309			 */
13310			"bAutoWidth": null,
13311	
13312			/**
13313			 * Delay the creation of TR and TD elements until they are actually
13314			 * needed by a driven page draw. This can give a significant speed
13315			 * increase for Ajax source and Javascript source data, but makes no
13316			 * difference at all for DOM and server-side processing tables.
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			"bDeferRender": null,
13322	
13323			/**
13324			 * Enable filtering on the table or not. Note that if this is disabled
13325			 * then there is no filtering at all on the table, including fnFilter.
13326			 * To just remove the filtering input use sDom and remove the 'f' option.
13327			 * Note that this parameter will be set by the initialisation routine. To
13328			 * set a default use {@link DataTable.defaults}.
13329			 *  @type boolean
13330			 */
13331			"bFilter": null,
13332	
13333			/**
13334			 * Table information element (the 'Showing x of y records' div) enable
13335			 * flag.
13336			 * Note that this parameter will be set by the initialisation routine. To
13337			 * set a default use {@link DataTable.defaults}.
13338			 *  @type boolean
13339			 */
13340			"bInfo": null,
13341	
13342			/**
13343			 * Present a user control allowing the end user to change the page size
13344			 * when pagination is enabled.
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			"bLengthChange": null,
13350	
13351			/**
13352			 * Pagination enabled or not. Note that if this is disabled then length
13353			 * changing must also be disabled.
13354			 * Note that this parameter will be set by the initialisation routine. To
13355			 * set a default use {@link DataTable.defaults}.
13356			 *  @type boolean
13357			 */
13358			"bPaginate": null,
13359	
13360			/**
13361			 * Processing indicator enable flag whenever DataTables is enacting a
13362			 * user request - typically an Ajax request for server-side processing.
13363			 * Note that this parameter will be set by the initialisation routine. To
13364			 * set a default use {@link DataTable.defaults}.
13365			 *  @type boolean
13366			 */
13367			"bProcessing": null,
13368	
13369			/**
13370			 * Server-side processing enabled flag - when enabled DataTables will
13371			 * get all data from the server for every draw - there is no filtering,
13372			 * sorting or paging done on the client-side.
13373			 * Note that this parameter will be set by the initialisation routine. To
13374			 * set a default use {@link DataTable.defaults}.
13375			 *  @type boolean
13376			 */
13377			"bServerSide": null,
13378	
13379			/**
13380			 * Sorting enablement flag.
13381			 * Note that this parameter will be set by the initialisation routine. To
13382			 * set a default use {@link DataTable.defaults}.
13383			 *  @type boolean
13384			 */
13385			"bSort": null,
13386	
13387			/**
13388			 * Multi-column sorting
13389			 * Note that this parameter will be set by the initialisation routine. To
13390			 * set a default use {@link DataTable.defaults}.
13391			 *  @type boolean
13392			 */
13393			"bSortMulti": null,
13394	
13395			/**
13396			 * Apply a class to the columns which are being sorted to provide a
13397			 * visual highlight or not. This can slow things down when enabled since
13398			 * there is a lot of DOM interaction.
13399			 * Note that this parameter will be set by the initialisation routine. To
13400			 * set a default use {@link DataTable.defaults}.
13401			 *  @type boolean
13402			 */
13403			"bSortClasses": null,
13404	
13405			/**
13406			 * State saving enablement flag.
13407			 * Note that this parameter will be set by the initialisation routine. To
13408			 * set a default use {@link DataTable.defaults}.
13409			 *  @type boolean
13410			 */
13411			"bStateSave": null
13412		},
13413	
13414	
13415		/**
13416		 * Scrolling settings for a table.
13417		 *  @namespace
13418		 */
13419		"oScroll": {
13420			/**
13421			 * When the table is shorter in height than sScrollY, collapse the
13422			 * table container down to the height of the table (when true).
13423			 * Note that this parameter will be set by the initialisation routine. To
13424			 * set a default use {@link DataTable.defaults}.
13425			 *  @type boolean
13426			 */
13427			"bCollapse": null,
13428	
13429			/**
13430			 * Width of the scrollbar for the web-browser's platform. Calculated
13431			 * during table initialisation.
13432			 *  @type int
13433			 *  @default 0
13434			 */
13435			"iBarWidth": 0,
13436	
13437			/**
13438			 * Viewport width for horizontal scrolling. Horizontal scrolling is
13439			 * disabled if an empty string.
13440			 * Note that this parameter will be set by the initialisation routine. To
13441			 * set a default use {@link DataTable.defaults}.
13442			 *  @type string
13443			 */
13444			"sX": null,
13445	
13446			/**
13447			 * Width to expand the table to when using x-scrolling. Typically you
13448			 * should not need to use this.
13449			 * Note that this parameter will be set by the initialisation routine. To
13450			 * set a default use {@link DataTable.defaults}.
13451			 *  @type string
13452			 *  @deprecated
13453			 */
13454			"sXInner": null,
13455	
13456			/**
13457			 * Viewport height for vertical scrolling. Vertical scrolling is disabled
13458			 * if an empty string.
13459			 * Note that this parameter will be set by the initialisation routine. To
13460			 * set a default use {@link DataTable.defaults}.
13461			 *  @type string
13462			 */
13463			"sY": null
13464		},
13465	
13466		/**
13467		 * Language information for the table.
13468		 *  @namespace
13469		 *  @extends DataTable.defaults.oLanguage
13470		 */
13471		"oLanguage": {
13472			/**
13473			 * Information callback function. See
13474			 * {@link DataTable.defaults.fnInfoCallback}
13475			 *  @type function
13476			 *  @default null
13477			 */
13478			"fnInfoCallback": null
13479		},
13480	
13481		/**
13482		 * Browser support parameters
13483		 *  @namespace
13484		 */
13485		"oBrowser": {
13486			/**
13487			 * Indicate if the browser incorrectly calculates width:100% inside a
13488			 * scrolling element (IE6/7)
13489			 *  @type boolean
13490			 *  @default false
13491			 */
13492			"bScrollOversize": false,
13493	
13494			/**
13495			 * Determine if the vertical scrollbar is on the right or left of the
13496			 * scrolling container - needed for rtl language layout, although not
13497			 * all browsers move the scrollbar (Safari).
13498			 *  @type boolean
13499			 *  @default false
13500			 */
13501			"bScrollbarLeft": false,
13502	
13503			/**
13504			 * Flag for if `getBoundingClientRect` is fully supported or not
13505			 *  @type boolean
13506			 *  @default false
13507			 */
13508			"bBounding": false,
13509	
13510			/**
13511			 * Browser scrollbar width
13512			 *  @type integer
13513			 *  @default 0
13514			 */
13515			"barWidth": 0
13516		},
13517	
13518	
13519		"ajax": null,
13520	
13521	
13522		/**
13523		 * Array referencing the nodes which are used for the features. The
13524		 * parameters of this object match what is allowed by sDom - i.e.
13525		 *   <ul>
13526		 *     <li>'l' - Length changing</li>
13527		 *     <li>'f' - Filtering input</li>
13528		 *     <li>'t' - The table!</li>
13529		 *     <li>'i' - Information</li>
13530		 *     <li>'p' - Pagination</li>
13531		 *     <li>'r' - pRocessing</li>
13532		 *   </ul>
13533		 *  @type array
13534		 *  @default []
13535		 */
13536		"aanFeatures": [],
13537	
13538		/**
13539		 * Store data information - see {@link DataTable.models.oRow} for detailed
13540		 * information.
13541		 *  @type array
13542		 *  @default []
13543		 */
13544		"aoData": [],
13545	
13546		/**
13547		 * Array of indexes which are in the current display (after filtering etc)
13548		 *  @type array
13549		 *  @default []
13550		 */
13551		"aiDisplay": [],
13552	
13553		/**
13554		 * Array of indexes for display - no filtering
13555		 *  @type array
13556		 *  @default []
13557		 */
13558		"aiDisplayMaster": [],
13559	
13560		/**
13561		 * Map of row ids to data indexes
13562		 *  @type object
13563		 *  @default {}
13564		 */
13565		"aIds": {},
13566	
13567		/**
13568		 * Store information about each column that is in use
13569		 *  @type array
13570		 *  @default []
13571		 */
13572		"aoColumns": [],
13573	
13574		/**
13575		 * Store information about the table's header
13576		 *  @type array
13577		 *  @default []
13578		 */
13579		"aoHeader": [],
13580	
13581		/**
13582		 * Store information about the table's footer
13583		 *  @type array
13584		 *  @default []
13585		 */
13586		"aoFooter": [],
13587	
13588		/**
13589		 * Store the applied global search information in case we want to force a
13590		 * research or compare the old search to a new one.
13591		 * Note that this parameter will be set by the initialisation routine. To
13592		 * set a default use {@link DataTable.defaults}.
13593		 *  @namespace
13594		 *  @extends DataTable.models.oSearch
13595		 */
13596		"oPreviousSearch": {},
13597	
13598		/**
13599		 * Store the applied search for each column - see
13600		 * {@link DataTable.models.oSearch} for the format that is used for the
13601		 * filtering information for each column.
13602		 *  @type array
13603		 *  @default []
13604		 */
13605		"aoPreSearchCols": [],
13606	
13607		/**
13608		 * Sorting that is applied to the table. Note that the inner arrays are
13609		 * used in the following manner:
13610		 * <ul>
13611		 *   <li>Index 0 - column number</li>
13612		 *   <li>Index 1 - current sorting direction</li>
13613		 * </ul>
13614		 * Note that this parameter will be set by the initialisation routine. To
13615		 * set a default use {@link DataTable.defaults}.
13616		 *  @type array
13617		 *  @todo These inner arrays should really be objects
13618		 */
13619		"aaSorting": null,
13620	
13621		/**
13622		 * Sorting that is always applied to the table (i.e. prefixed in front of
13623		 * aaSorting).
13624		 * Note that this parameter will be set by the initialisation routine. To
13625		 * set a default use {@link DataTable.defaults}.
13626		 *  @type array
13627		 *  @default []
13628		 */
13629		"aaSortingFixed": [],
13630	
13631		/**
13632		 * Classes to use for the striping of a table.
13633		 * Note that this parameter will be set by the initialisation routine. To
13634		 * set a default use {@link DataTable.defaults}.
13635		 *  @type array
13636		 *  @default []
13637		 */
13638		"asStripeClasses": null,
13639	
13640		/**
13641		 * If restoring a table - we should restore its striping classes as well
13642		 *  @type array
13643		 *  @default []
13644		 */
13645		"asDestroyStripes": [],
13646	
13647		/**
13648		 * If restoring a table - we should restore its width
13649		 *  @type int
13650		 *  @default 0
13651		 */
13652		"sDestroyWidth": 0,
13653	
13654		/**
13655		 * Callback functions array for every time a row is inserted (i.e. on a draw).
13656		 *  @type array
13657		 *  @default []
13658		 */
13659		"aoRowCallback": [],
13660	
13661		/**
13662		 * Callback functions for the header on each draw.
13663		 *  @type array
13664		 *  @default []
13665		 */
13666		"aoHeaderCallback": [],
13667	
13668		/**
13669		 * Callback function for the footer on each draw.
13670		 *  @type array
13671		 *  @default []
13672		 */
13673		"aoFooterCallback": [],
13674	
13675		/**
13676		 * Array of callback functions for draw callback functions
13677		 *  @type array
13678		 *  @default []
13679		 */
13680		"aoDrawCallback": [],
13681	
13682		/**
13683		 * Array of callback functions for row created function
13684		 *  @type array
13685		 *  @default []
13686		 */
13687		"aoRowCreatedCallback": [],
13688	
13689		/**
13690		 * Callback functions for just before the table is redrawn. A return of
13691		 * false will be used to cancel the draw.
13692		 *  @type array
13693		 *  @default []
13694		 */
13695		"aoPreDrawCallback": [],
13696	
13697		/**
13698		 * Callback functions for when the table has been initialised.
13699		 *  @type array
13700		 *  @default []
13701		 */
13702		"aoInitComplete": [],
13703	
13704	
13705		/**
13706		 * Callbacks for modifying the settings to be stored for state saving, prior to
13707		 * saving state.
13708		 *  @type array
13709		 *  @default []
13710		 */
13711		"aoStateSaveParams": [],
13712	
13713		/**
13714		 * Callbacks for modifying the settings that have been stored for state saving
13715		 * prior to using the stored values to restore the state.
13716		 *  @type array
13717		 *  @default []
13718		 */
13719		"aoStateLoadParams": [],
13720	
13721		/**
13722		 * Callbacks for operating on the settings object once the saved state has been
13723		 * loaded
13724		 *  @type array
13725		 *  @default []
13726		 */
13727		"aoStateLoaded": [],
13728	
13729		/**
13730		 * Cache the table ID for quick access
13731		 *  @type string
13732		 *  @default <i>Empty string</i>
13733		 */
13734		"sTableId": "",
13735	
13736		/**
13737		 * The TABLE node for the main table
13738		 *  @type node
13739		 *  @default null
13740		 */
13741		"nTable": null,
13742	
13743		/**
13744		 * Permanent ref to the thead element
13745		 *  @type node
13746		 *  @default null
13747		 */
13748		"nTHead": null,
13749	
13750		/**
13751		 * Permanent ref to the tfoot element - if it exists
13752		 *  @type node
13753		 *  @default null
13754		 */
13755		"nTFoot": null,
13756	
13757		/**
13758		 * Permanent ref to the tbody element
13759		 *  @type node
13760		 *  @default null
13761		 */
13762		"nTBody": null,
13763	
13764		/**
13765		 * Cache the wrapper node (contains all DataTables controlled elements)
13766		 *  @type node
13767		 *  @default null
13768		 */
13769		"nTableWrapper": null,
13770	
13771		/**
13772		 * Indicate if when using server-side processing the loading of data
13773		 * should be deferred until the second draw.
13774		 * Note that this parameter will be set by the initialisation routine. To
13775		 * set a default use {@link DataTable.defaults}.
13776		 *  @type boolean
13777		 *  @default false
13778		 */
13779		"bDeferLoading": false,
13780	
13781		/**
13782		 * Indicate if all required information has been read in
13783		 *  @type boolean
13784		 *  @default false
13785		 */
13786		"bInitialised": false,
13787	
13788		/**
13789		 * Information about open rows. Each object in the array has the parameters
13790		 * 'nTr' and 'nParent'
13791		 *  @type array
13792		 *  @default []
13793		 */
13794		"aoOpenRows": [],
13795	
13796		/**
13797		 * Dictate the positioning of DataTables' control elements - see
13798		 * {@link DataTable.model.oInit.sDom}.
13799		 * Note that this parameter will be set by the initialisation routine. To
13800		 * set a default use {@link DataTable.defaults}.
13801		 *  @type string
13802		 *  @default null
13803		 */
13804		"sDom": null,
13805	
13806		/**
13807		 * Search delay (in mS)
13808		 *  @type integer
13809		 *  @default null
13810		 */
13811		"searchDelay": null,
13812	
13813		/**
13814		 * Which type of pagination should be used.
13815		 * Note that this parameter will be set by the initialisation routine. To
13816		 * set a default use {@link DataTable.defaults}.
13817		 *  @type string
13818		 *  @default two_button
13819		 */
13820		"sPaginationType": "two_button",
13821	
13822		/**
13823		 * The state duration (for `stateSave`) in seconds.
13824		 * Note that this parameter will be set by the initialisation routine. To
13825		 * set a default use {@link DataTable.defaults}.
13826		 *  @type int
13827		 *  @default 0
13828		 */
13829		"iStateDuration": 0,
13830	
13831		/**
13832		 * Array of callback functions for state saving. Each array element is an
13833		 * object with the following parameters:
13834		 *   <ul>
13835		 *     <li>function:fn - function to call. Takes two parameters, oSettings
13836		 *       and the JSON string to save that has been thus far created. Returns
13837		 *       a JSON string to be inserted into a json object
13838		 *       (i.e. '"param": [ 0, 1, 2]')</li>
13839		 *     <li>string:sName - name of callback</li>
13840		 *   </ul>
13841		 *  @type array
13842		 *  @default []
13843		 */
13844		"aoStateSave": [],
13845	
13846		/**
13847		 * Array of callback functions for state loading. Each array element is an
13848		 * object with the following parameters:
13849		 *   <ul>
13850		 *     <li>function:fn - function to call. Takes two parameters, oSettings
13851		 *       and the object stored. May return false to cancel state loading</li>
13852		 *     <li>string:sName - name of callback</li>
13853		 *   </ul>
13854		 *  @type array
13855		 *  @default []
13856		 */
13857		"aoStateLoad": [],
13858	
13859		/**
13860		 * State that was saved. Useful for back reference
13861		 *  @type object
13862		 *  @default null
13863		 */
13864		"oSavedState": null,
13865	
13866		/**
13867		 * State that was loaded. Useful for back reference
13868		 *  @type object
13869		 *  @default null
13870		 */
13871		"oLoadedState": null,
13872	
13873		/**
13874		 * Source url for AJAX data for the table.
13875		 * Note that this parameter will be set by the initialisation routine. To
13876		 * set a default use {@link DataTable.defaults}.
13877		 *  @type string
13878		 *  @default null
13879		 */
13880		"sAjaxSource": null,
13881	
13882		/**
13883		 * Property from a given object from which to read the table data from. This
13884		 * can be an empty string (when not server-side processing), in which case
13885		 * it is  assumed an an array is given directly.
13886		 * Note that this parameter will be set by the initialisation routine. To
13887		 * set a default use {@link DataTable.defaults}.
13888		 *  @type string
13889		 */
13890		"sAjaxDataProp": null,
13891	
13892		/**
13893		 * The last jQuery XHR object that was used for server-side data gathering.
13894		 * This can be used for working with the XHR information in one of the
13895		 * callbacks
13896		 *  @type object
13897		 *  @default null
13898		 */
13899		"jqXHR": null,
13900	
13901		/**
13902		 * JSON returned from the server in the last Ajax request
13903		 *  @type object
13904		 *  @default undefined
13905		 */
13906		"json": undefined,
13907	
13908		/**
13909		 * Data submitted as part of the last Ajax request
13910		 *  @type object
13911		 *  @default undefined
13912		 */
13913		"oAjaxData": undefined,
13914	
13915		/**
13916		 * Function to get the server-side data.
13917		 * Note that this parameter will be set by the initialisation routine. To
13918		 * set a default use {@link DataTable.defaults}.
13919		 *  @type function
13920		 */
13921		"fnServerData": null,
13922	
13923		/**
13924		 * Functions which are called prior to sending an Ajax request so extra
13925		 * parameters can easily be sent to the server
13926		 *  @type array
13927		 *  @default []
13928		 */
13929		"aoServerParams": [],
13930	
13931		/**
13932		 * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
13933		 * required).
13934		 * Note that this parameter will be set by the initialisation routine. To
13935		 * set a default use {@link DataTable.defaults}.
13936		 *  @type string
13937		 */
13938		"sServerMethod": null,
13939	
13940		/**
13941		 * Format numbers for display.
13942		 * Note that this parameter will be set by the initialisation routine. To
13943		 * set a default use {@link DataTable.defaults}.
13944		 *  @type function
13945		 */
13946		"fnFormatNumber": null,
13947	
13948		/**
13949		 * List of options that can be used for the user selectable length menu.
13950		 * Note that this parameter will be set by the initialisation routine. To
13951		 * set a default use {@link DataTable.defaults}.
13952		 *  @type array
13953		 *  @default []
13954		 */
13955		"aLengthMenu": null,
13956	
13957		/**
13958		 * Counter for the draws that the table does. Also used as a tracker for
13959		 * server-side processing
13960		 *  @type int
13961		 *  @default 0
13962		 */
13963		"iDraw": 0,
13964	
13965		/**
13966		 * Indicate if a redraw is being done - useful for Ajax
13967		 *  @type boolean
13968		 *  @default false
13969		 */
13970		"bDrawing": false,
13971	
13972		/**
13973		 * Draw index (iDraw) of the last error when parsing the returned data
13974		 *  @type int
13975		 *  @default -1
13976		 */
13977		"iDrawError": -1,
13978	
13979		/**
13980		 * Paging display length
13981		 *  @type int
13982		 *  @default 10
13983		 */
13984		"_iDisplayLength": 10,
13985	
13986		/**
13987		 * Paging start point - aiDisplay index
13988		 *  @type int
13989		 *  @default 0
13990		 */
13991		"_iDisplayStart": 0,
13992	
13993		/**
13994		 * Server-side processing - number of records in the result set
13995		 * (i.e. before filtering), Use fnRecordsTotal rather than
13996		 * this property to get the value of the number of records, regardless of
13997		 * the server-side processing setting.
13998		 *  @type int
13999		 *  @default 0
14000		 *  @private
14001		 */
14002		"_iRecordsTotal": 0,
14003	
14004		/**
14005		 * Server-side processing - number of records in the current display set
14006		 * (i.e. after filtering). Use fnRecordsDisplay rather than
14007		 * this property to get the value of the number of records, regardless of
14008		 * the server-side processing setting.
14009		 *  @type boolean
14010		 *  @default 0
14011		 *  @private
14012		 */
14013		"_iRecordsDisplay": 0,
14014	
14015		/**
14016		 * The classes to use for the table
14017		 *  @type object
14018		 *  @default {}
14019		 */
14020		"oClasses": {},
14021	
14022		/**
14023		 * Flag attached to the settings object so you can check in the draw
14024		 * callback if filtering has been done in the draw. Deprecated in favour of
14025		 * events.
14026		 *  @type boolean
14027		 *  @default false
14028		 *  @deprecated
14029		 */
14030		"bFiltered": false,
14031	
14032		/**
14033		 * Flag attached to the settings object so you can check in the draw
14034		 * callback if sorting has been done in the draw. Deprecated in favour of
14035		 * events.
14036		 *  @type boolean
14037		 *  @default false
14038		 *  @deprecated
14039		 */
14040		"bSorted": false,
14041	
14042		/**
14043		 * Indicate that if multiple rows are in the header and there is more than
14044		 * one unique cell per column, if the top one (true) or bottom one (false)
14045		 * should be used for sorting / title by DataTables.
14046		 * Note that this parameter will be set by the initialisation routine. To
14047		 * set a default use {@link DataTable.defaults}.
14048		 *  @type boolean
14049		 */
14050		"bSortCellsTop": null,
14051	
14052		/**
14053		 * Initialisation object that is used for the table
14054		 *  @type object
14055		 *  @default null
14056		 */
14057		"oInit": null,
14058	
14059		/**
14060		 * Destroy callback functions - for plug-ins to attach themselves to the
14061		 * destroy so they can clean up markup and events.
14062		 *  @type array
14063		 *  @default []
14064		 */
14065		"aoDestroyCallback": [],
14066	
14067	
14068		/**
14069		 * Get the number of records in the current record set, before filtering
14070		 *  @type function
14071		 */
14072		"fnRecordsTotal": function ()
14073		{
14074			return _fnDataSource( this ) == 'ssp' ?
14075				this._iRecordsTotal * 1 :
14076				this.aiDisplayMaster.length;
14077		},
14078	
14079		/**
14080		 * Get the number of records in the current record set, after filtering
14081		 *  @type function
14082		 */
14083		"fnRecordsDisplay": function ()
14084		{
14085			return _fnDataSource( this ) == 'ssp' ?
14086				this._iRecordsDisplay * 1 :
14087				this.aiDisplay.length;
14088		},
14089	
14090		/**
14091		 * Get the display end point - aiDisplay index
14092		 *  @type function
14093		 */
14094		"fnDisplayEnd": function ()
14095		{
14096			var
14097				len      = this._iDisplayLength,
14098				start    = this._iDisplayStart,
14099				calc     = start + len,
14100				records  = this.aiDisplay.length,
14101				features = this.oFeatures,
14102				paginate = features.bPaginate;
14103	
14104			if ( features.bServerSide ) {
14105				return paginate === false || len === -1 ?
14106					start + records :
14107					Math.min( start+len, this._iRecordsDisplay );
14108			}
14109			else {
14110				return ! paginate || calc>records || len===-1 ?
14111					records :
14112					calc;
14113			}
14114		},
14115	
14116		/**
14117		 * The DataTables object for this table
14118		 *  @type object
14119		 *  @default null
14120		 */
14121		"oInstance": null,
14122	
14123		/**
14124		 * Unique identifier for each instance of the DataTables object. If there
14125		 * is an ID on the table node, then it takes that value, otherwise an
14126		 * incrementing internal counter is used.
14127		 *  @type string
14128		 *  @default null
14129		 */
14130		"sInstance": null,
14131	
14132		/**
14133		 * tabindex attribute value that is added to DataTables control elements, allowing
14134		 * keyboard navigation of the table and its controls.
14135		 */
14136		"iTabIndex": 0,
14137	
14138		/**
14139		 * DIV container for the footer scrolling table if scrolling
14140		 */
14141		"nScrollHead": null,
14142	
14143		/**
14144		 * DIV container for the footer scrolling table if scrolling
14145		 */
14146		"nScrollFoot": null,
14147	
14148		/**
14149		 * Last applied sort
14150		 *  @type array
14151		 *  @default []
14152		 */
14153		"aLastSort": [],
14154	
14155		/**
14156		 * Stored plug-in instances
14157		 *  @type object
14158		 *  @default {}
14159		 */
14160		"oPlugins": {},
14161	
14162		/**
14163		 * Function used to get a row's id from the row's data
14164		 *  @type function
14165		 *  @default null
14166		 */
14167		"rowIdFn": null,
14168	
14169		/**
14170		 * Data location where to store a row's id
14171		 *  @type string
14172		 *  @default null
14173		 */
14174		"rowId": null
14175	};
14176	
14177	/**
14178	 * Extension object for DataTables that is used to provide all extension
14179	 * options.
14180	 *
14181	 * Note that the `DataTable.ext` object is available through
14182	 * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is
14183	 * also aliased to `jQuery.fn.dataTableExt` for historic reasons.
14184	 *  @namespace
14185	 *  @extends DataTable.models.ext
14186	 */
14187	
14188	
14189	/**
14190	 * DataTables extensions
14191	 * 
14192	 * This namespace acts as a collection area for plug-ins that can be used to
14193	 * extend DataTables capabilities. Indeed many of the build in methods
14194	 * use this method to provide their own capabilities (sorting methods for
14195	 * example).
14196	 *
14197	 * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy
14198	 * reasons
14199	 *
14200	 *  @namespace
14201	 */
14202	DataTable.ext = _ext = {
14203		/**
14204		 * Buttons. For use with the Buttons extension for DataTables. This is
14205		 * defined here so other extensions can define buttons regardless of load
14206		 * order. It is _not_ used by DataTables core.
14207		 *
14208		 *  @type object
14209		 *  @default {}
14210		 */
14211		buttons: {},
14212	
14213	
14214		/**
14215		 * Element class names
14216		 *
14217		 *  @type object
14218		 *  @default {}
14219		 */
14220		classes: {},
14221	
14222	
14223		/**
14224		 * DataTables build type (expanded by the download builder)
14225		 *
14226		 *  @type string
14227		 */
14228		builder: "-source-",
14229	
14230	
14231		/**
14232		 * Error reporting.
14233		 * 
14234		 * How should DataTables report an error. Can take the value 'alert',
14235		 * 'throw', 'none' or a function.
14236		 *
14237		 *  @type string|function
14238		 *  @default alert
14239		 */
14240		errMode: "alert",
14241	
14242	
14243		/**
14244		 * Feature plug-ins.
14245		 * 
14246		 * This is an array of objects which describe the feature plug-ins that are
14247		 * available to DataTables. These feature plug-ins are then available for
14248		 * use through the `dom` initialisation option.
14249		 * 
14250		 * Each feature plug-in is described by an object which must have the
14251		 * following properties:
14252		 * 
14253		 * * `fnInit` - function that is used to initialise the plug-in,
14254		 * * `cFeature` - a character so the feature can be enabled by the `dom`
14255		 *   instillation option. This is case sensitive.
14256		 *
14257		 * The `fnInit` function has the following input parameters:
14258		 *
14259		 * 1. `{object}` DataTables settings object: see
14260		 *    {@link DataTable.models.oSettings}
14261		 *
14262		 * And the following return is expected:
14263		 * 
14264		 * * {node|null} The element which contains your feature. Note that the
14265		 *   return may also be void if your plug-in does not require to inject any
14266		 *   DOM elements into DataTables control (`dom`) - for example this might
14267		 *   be useful when developing a plug-in which allows table control via
14268		 *   keyboard entry
14269		 *
14270		 *  @type array
14271		 *
14272		 *  @example
14273		 *    $.fn.dataTable.ext.features.push( {
14274		 *      "fnInit": function( oSettings ) {
14275		 *        return new TableTools( { "oDTSettings": oSettings } );
14276		 *      },
14277		 *      "cFeature": "T"
14278		 *    } );
14279		 */
14280		feature: [],
14281	
14282	
14283		/**
14284		 * Row searching.
14285		 * 
14286		 * This method of searching is complimentary to the default type based
14287		 * searching, and a lot more comprehensive as it allows you complete control
14288		 * over the searching logic. Each element in this array is a function
14289		 * (parameters described below) that is called for every row in the table,
14290		 * and your logic decides if it should be included in the searching data set
14291		 * or not.
14292		 *
14293		 * Searching functions have the following input parameters:
14294		 *
14295		 * 1. `{object}` DataTables settings object: see
14296		 *    {@link DataTable.models.oSettings}
14297		 * 2. `{array|object}` Data for the row to be processed (same as the
14298		 *    original format that was passed in as the data source, or an array
14299		 *    from a DOM data source
14300		 * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which
14301		 *    can be useful to retrieve the `TR` element if you need DOM interaction.
14302		 *
14303		 * And the following return is expected:
14304		 *
14305		 * * {boolean} Include the row in the searched result set (true) or not
14306		 *   (false)
14307		 *
14308		 * Note that as with the main search ability in DataTables, technically this
14309		 * is "filtering", since it is subtractive. However, for consistency in
14310		 * naming we call it searching here.
14311		 *
14312		 *  @type array
14313		 *  @default []
14314		 *
14315		 *  @example
14316		 *    // The following example shows custom search being applied to the
14317		 *    // fourth column (i.e. the data[3] index) based on two input values
14318		 *    // from the end-user, matching the data in a certain range.
14319		 *    $.fn.dataTable.ext.search.push(
14320		 *      function( settings, data, dataIndex ) {
14321		 *        var min = document.getElementById('min').value * 1;
14322		 *        var max = document.getElementById('max').value * 1;
14323		 *        var version = data[3] == "-" ? 0 : data[3]*1;
14324		 *
14325		 *        if ( min == "" && max == "" ) {
14326		 *          return true;
14327		 *        }
14328		 *        else if ( min == "" && version < max ) {
14329		 *          return true;
14330		 *        }
14331		 *        else if ( min < version && "" == max ) {
14332		 *          return true;
14333		 *        }
14334		 *        else if ( min < version && version < max ) {
14335		 *          return true;
14336		 *        }
14337		 *        return false;
14338		 *      }
14339		 *    );
14340		 */
14341		search: [],
14342	
14343	
14344		/**
14345		 * Selector extensions
14346		 *
14347		 * The `selector` option can be used to extend the options available for the
14348		 * selector modifier options (`selector-modifier` object data type) that
14349		 * each of the three built in selector types offer (row, column and cell +
14350		 * their plural counterparts). For example the Select extension uses this
14351		 * mechanism to provide an option to select only rows, columns and cells
14352		 * that have been marked as selected by the end user (`{selected: true}`),
14353		 * which can be used in conjunction with the existing built in selector
14354		 * options.
14355		 *
14356		 * Each property is an array to which functions can be pushed. The functions
14357		 * take three attributes:
14358		 *
14359		 * * Settings object for the host table
14360		 * * Options object (`selector-modifier` object type)
14361		 * * Array of selected item indexes
14362		 *
14363		 * The return is an array of the resulting item indexes after the custom
14364		 * selector has been applied.
14365		 *
14366		 *  @type object
14367		 */
14368		selector: {
14369			cell: [],
14370			column: [],
14371			row: []
14372		},
14373	
14374	
14375		/**
14376		 * Internal functions, exposed for used in plug-ins.
14377		 * 
14378		 * Please note that you should not need to use the internal methods for
14379		 * anything other than a plug-in (and even then, try to avoid if possible).
14380		 * The internal function may change between releases.
14381		 *
14382		 *  @type object
14383		 *  @default {}
14384		 */
14385		internal: {},
14386	
14387	
14388		/**
14389		 * Legacy configuration options. Enable and disable legacy options that
14390		 * are available in DataTables.
14391		 *
14392		 *  @type object
14393		 */
14394		legacy: {
14395			/**
14396			 * Enable / disable DataTables 1.9 compatible server-side processing
14397			 * requests
14398			 *
14399			 *  @type boolean
14400			 *  @default null
14401			 */
14402			ajax: null
14403		},
14404	
14405	
14406		/**
14407		 * Pagination plug-in methods.
14408		 * 
14409		 * Each entry in this object is a function and defines which buttons should
14410		 * be shown by the pagination rendering method that is used for the table:
14411		 * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the
14412		 * buttons are displayed in the document, while the functions here tell it
14413		 * what buttons to display. This is done by returning an array of button
14414		 * descriptions (what each button will do).
14415		 *
14416		 * Pagination types (the four built in options and any additional plug-in
14417		 * options defined here) can be used through the `paginationType`
14418		 * initialisation parameter.
14419		 *
14420		 * The functions defined take two parameters:
14421		 *
14422		 * 1. `{int} page` The current page index
14423		 * 2. `{int} pages` The number of pages in the table
14424		 *
14425		 * Each function is expected to return an array where each element of the
14426		 * array can be one of:
14427		 *
14428		 * * `first` - Jump to first page when activated
14429		 * * `last` - Jump to last page when activated
14430		 * * `previous` - Show previous page when activated
14431		 * * `next` - Show next page when activated
14432		 * * `{int}` - Show page of the index given
14433		 * * `{array}` - A nested array containing the above elements to add a
14434		 *   containing 'DIV' element (might be useful for styling).
14435		 *
14436		 * Note that DataTables v1.9- used this object slightly differently whereby
14437		 * an object with two functions would be defined for each plug-in. That
14438		 * ability is still supported by DataTables 1.10+ to provide backwards
14439		 * compatibility, but this option of use is now decremented and no longer
14440		 * documented in DataTables 1.10+.
14441		 *
14442		 *  @type object
14443		 *  @default {}
14444		 *
14445		 *  @example
14446		 *    // Show previous, next and current page buttons only
14447		 *    $.fn.dataTableExt.oPagination.current = function ( page, pages ) {
14448		 *      return [ 'previous', page, 'next' ];
14449		 *    };
14450		 */
14451		pager: {},
14452	
14453	
14454		renderer: {
14455			pageButton: {},
14456			header: {}
14457		},
14458	
14459	
14460		/**
14461		 * Ordering plug-ins - custom data source
14462		 * 
14463		 * The extension options for ordering of data available here is complimentary
14464		 * to the default type based ordering that DataTables typically uses. It
14465		 * allows much greater control over the the data that is being used to
14466		 * order a column, but is necessarily therefore more complex.
14467		 * 
14468		 * This type of ordering is useful if you want to do ordering based on data
14469		 * live from the DOM (for example the contents of an 'input' element) rather
14470		 * than just the static string that DataTables knows of.
14471		 * 
14472		 * The way these plug-ins work is that you create an array of the values you
14473		 * wish to be ordering for the column in question and then return that
14474		 * array. The data in the array much be in the index order of the rows in
14475		 * the table (not the currently ordering order!). Which order data gathering
14476		 * function is run here depends on the `dt-init columns.orderDataType`
14477		 * parameter that is used for the column (if any).
14478		 *
14479		 * The functions defined take two parameters:
14480		 *
14481		 * 1. `{object}` DataTables settings object: see
14482		 *    {@link DataTable.models.oSettings}
14483		 * 2. `{int}` Target column index
14484		 *
14485		 * Each function is expected to return an array:
14486		 *
14487		 * * `{array}` Data for the column to be ordering upon
14488		 *
14489		 *  @type array
14490		 *
14491		 *  @example
14492		 *    // Ordering using `input` node values
14493		 *    $.fn.dataTable.ext.order['dom-text'] = function  ( settings, col )
14494		 *    {
14495		 *      return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
14496		 *        return $('input', td).val();
14497		 *      } );
14498		 *    }
14499		 */
14500		order: {},
14501	
14502	
14503		/**
14504		 * Type based plug-ins.
14505		 *
14506		 * Each column in DataTables has a type assigned to it, either by automatic
14507		 * detection or by direct assignment using the `type` option for the column.
14508		 * The type of a column will effect how it is ordering and search (plug-ins
14509		 * can also make use of the column type if required).
14510		 *
14511		 * @namespace
14512		 */
14513		type: {
14514			/**
14515			 * Type detection functions.
14516			 *
14517			 * The functions defined in this object are used to automatically detect
14518			 * a column's type, making initialisation of DataTables super easy, even
14519			 * when complex data is in the table.
14520			 *
14521			 * The functions defined take two parameters:
14522			 *
14523		     *  1. `{*}` Data from the column cell to be analysed
14524		     *  2. `{settings}` DataTables settings object. This can be used to
14525		     *     perform context specific type detection - for example detection
14526		     *     based on language settings such as using a comma for a decimal
14527		     *     place. Generally speaking the options from the settings will not
14528		     *     be required
14529			 *
14530			 * Each function is expected to return:
14531			 *
14532			 * * `{string|null}` Data type detected, or null if unknown (and thus
14533			 *   pass it on to the other type detection functions.
14534			 *
14535			 *  @type array
14536			 *
14537			 *  @example
14538			 *    // Currency type detection plug-in:
14539			 *    $.fn.dataTable.ext.type.detect.push(
14540			 *      function ( data, settings ) {
14541			 *        // Check the numeric part
14542			 *        if ( ! data.substring(1).match(/[0-9]/) ) {
14543			 *          return null;
14544			 *        }
14545			 *
14546			 *        // Check prefixed by currency
14547			 *        if ( data.charAt(0) == '$' || data.charAt(0) == '&pound;' ) {
14548			 *          return 'currency';
14549			 *        }
14550			 *        return null;
14551			 *      }
14552			 *    );
14553			 */
14554			detect: [],
14555	
14556	
14557			/**
14558			 * Type based search formatting.
14559			 *
14560			 * The type based searching functions can be used to pre-format the
14561			 * data to be search on. For example, it can be used to strip HTML
14562			 * tags or to de-format telephone numbers for numeric only searching.
14563			 *
14564			 * Note that is a search is not defined for a column of a given type,
14565			 * no search formatting will be performed.
14566			 * 
14567			 * Pre-processing of searching data plug-ins - When you assign the sType
14568			 * for a column (or have it automatically detected for you by DataTables
14569			 * or a type detection plug-in), you will typically be using this for
14570			 * custom sorting, but it can also be used to provide custom searching
14571			 * by allowing you to pre-processing the data and returning the data in
14572			 * the format that should be searched upon. This is done by adding
14573			 * functions this object with a parameter name which matches the sType
14574			 * for that target column. This is the corollary of <i>afnSortData</i>
14575			 * for searching data.
14576			 *
14577			 * The functions defined take a single parameter:
14578			 *
14579		     *  1. `{*}` Data from the column cell to be prepared for searching
14580			 *
14581			 * Each function is expected to return:
14582			 *
14583			 * * `{string|null}` Formatted string that will be used for the searching.
14584			 *
14585			 *  @type object
14586			 *  @default {}
14587			 *
14588			 *  @example
14589			 *    $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) {
14590			 *      return d.replace(/\n/g," ").replace( /<.*?>/g, "" );
14591			 *    }
14592			 */
14593			search: {},
14594	
14595	
14596			/**
14597			 * Type based ordering.
14598			 *
14599			 * The column type tells DataTables what ordering to apply to the table
14600			 * when a column is sorted upon. The order for each type that is defined,
14601			 * is defined by the functions available in this object.
14602			 *
14603			 * Each ordering option can be described by three properties added to
14604			 * this object:
14605			 *
14606			 * * `{type}-pre` - Pre-formatting function
14607			 * * `{type}-asc` - Ascending order function
14608			 * * `{type}-desc` - Descending order function
14609			 *
14610			 * All three can be used together, only `{type}-pre` or only
14611			 * `{type}-asc` and `{type}-desc` together. It is generally recommended
14612			 * that only `{type}-pre` is used, as this provides the optimal
14613			 * implementation in terms of speed, although the others are provided
14614			 * for compatibility with existing Javascript sort functions.
14615			 *
14616			 * `{type}-pre`: Functions defined take a single parameter:
14617			 *
14618		     *  1. `{*}` Data from the column cell to be prepared for ordering
14619			 *
14620			 * And return:
14621			 *
14622			 * * `{*}` Data to be sorted upon
14623			 *
14624			 * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort
14625			 * functions, taking two parameters:
14626			 *
14627		     *  1. `{*}` Data to compare to the second parameter
14628		     *  2. `{*}` Data to compare to the first parameter
14629			 *
14630			 * And returning:
14631			 *
14632			 * * `{*}` Ordering match: <0 if first parameter should be sorted lower
14633			 *   than the second parameter, ===0 if the two parameters are equal and
14634			 *   >0 if the first parameter should be sorted height than the second
14635			 *   parameter.
14636			 * 
14637			 *  @type object
14638			 *  @default {}
14639			 *
14640			 *  @example
14641			 *    // Numeric ordering of formatted numbers with a pre-formatter
14642			 *    $.extend( $.fn.dataTable.ext.type.order, {
14643			 *      "string-pre": function(x) {
14644			 *        a = (a === "-" || a === "") ? 0 : a.replace( /[^\d\-\.]/g, "" );
14645			 *        return parseFloat( a );
14646			 *      }
14647			 *    } );
14648			 *
14649			 *  @example
14650			 *    // Case-sensitive string ordering, with no pre-formatting method
14651			 *    $.extend( $.fn.dataTable.ext.order, {
14652			 *      "string-case-asc": function(x,y) {
14653			 *        return ((x < y) ? -1 : ((x > y) ? 1 : 0));
14654			 *      },
14655			 *      "string-case-desc": function(x,y) {
14656			 *        return ((x < y) ? 1 : ((x > y) ? -1 : 0));
14657			 *      }
14658			 *    } );
14659			 */
14660			order: {}
14661		},
14662	
14663		/**
14664		 * Unique DataTables instance counter
14665		 *
14666		 * @type int
14667		 * @private
14668		 */
14669		_unique: 0,
14670	
14671	
14672		//
14673		// Depreciated
14674		// The following properties are retained for backwards compatibility only.
14675		// The should not be used in new projects and will be removed in a future
14676		// version
14677		//
14678	
14679		/**
14680		 * Version check function.
14681		 *  @type function
14682		 *  @depreciated Since 1.10
14683		 */
14684		fnVersionCheck: DataTable.fnVersionCheck,
14685	
14686	
14687		/**
14688		 * Index for what 'this' index API functions should use
14689		 *  @type int
14690		 *  @deprecated Since v1.10
14691		 */
14692		iApiIndex: 0,
14693	
14694	
14695		/**
14696		 * jQuery UI class container
14697		 *  @type object
14698		 *  @deprecated Since v1.10
14699		 */
14700		oJUIClasses: {},
14701	
14702	
14703		/**
14704		 * Software version
14705		 *  @type string
14706		 *  @deprecated Since v1.10
14707		 */
14708		sVersion: DataTable.version
14709	};
14710	
14711	
14712	//
14713	// Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts
14714	//
14715	$.extend( _ext, {
14716		afnFiltering: _ext.search,
14717		aTypes:       _ext.type.detect,
14718		ofnSearch:    _ext.type.search,
14719		oSort:        _ext.type.order,
14720		afnSortData:  _ext.order,
14721		aoFeatures:   _ext.feature,
14722		oApi:         _ext.internal,
14723		oStdClasses:  _ext.classes,
14724		oPagination:  _ext.pager
14725	} );
14726	
14727	
14728	$.extend( DataTable.ext.classes, {
14729		"sTable": "dataTable",
14730		"sNoFooter": "no-footer",
14731	
14732		/* Paging buttons */
14733		"sPageButton": "paginate_button",
14734		"sPageButtonActive": "current",
14735		"sPageButtonDisabled": "disabled",
14736	
14737		/* Striping classes */
14738		"sStripeOdd": "odd",
14739		"sStripeEven": "even",
14740	
14741		/* Empty row */
14742		"sRowEmpty": "dataTables_empty",
14743	
14744		/* Features */
14745		"sWrapper": "dataTables_wrapper",
14746		"sFilter": "dataTables_filter",
14747		"sInfo": "dataTables_info",
14748		"sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
14749		"sLength": "dataTables_length",
14750		"sProcessing": "dataTables_processing",
14751	
14752		/* Sorting */
14753		"sSortAsc": "sorting_asc",
14754		"sSortDesc": "sorting_desc",
14755		"sSortable": "sorting", /* Sortable in both directions */
14756		"sSortableAsc": "sorting_desc_disabled",
14757		"sSortableDesc": "sorting_asc_disabled",
14758		"sSortableNone": "sorting_disabled",
14759		"sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
14760	
14761		/* Filtering */
14762		"sFilterInput": "",
14763	
14764		/* Page length */
14765		"sLengthSelect": "",
14766	
14767		/* Scrolling */
14768		"sScrollWrapper": "dataTables_scroll",
14769		"sScrollHead": "dataTables_scrollHead",
14770		"sScrollHeadInner": "dataTables_scrollHeadInner",
14771		"sScrollBody": "dataTables_scrollBody",
14772		"sScrollFoot": "dataTables_scrollFoot",
14773		"sScrollFootInner": "dataTables_scrollFootInner",
14774	
14775		/* Misc */
14776		"sHeaderTH": "",
14777		"sFooterTH": "",
14778	
14779		// Deprecated
14780		"sSortJUIAsc": "",
14781		"sSortJUIDesc": "",
14782		"sSortJUI": "",
14783		"sSortJUIAscAllowed": "",
14784		"sSortJUIDescAllowed": "",
14785		"sSortJUIWrapper": "",
14786		"sSortIcon": "",
14787		"sJUIHeader": "",
14788		"sJUIFooter": ""
14789	} );
14790	
14791	
14792	var extPagination = DataTable.ext.pager;
14793	
14794	function _numbers ( page, pages ) {
14795		var
14796			numbers = [],
14797			buttons = extPagination.numbers_length,
14798			half = Math.floor( buttons / 2 ),
14799			i = 1;
14800	
14801		if ( pages <= buttons ) {
14802			numbers = _range( 0, pages );
14803		}
14804		else if ( page <= half ) {
14805			numbers = _range( 0, buttons-2 );
14806			numbers.push( 'ellipsis' );
14807			numbers.push( pages-1 );
14808		}
14809		else if ( page >= pages - 1 - half ) {
14810			numbers = _range( pages-(buttons-2), pages );
14811			numbers.splice( 0, 0, 'ellipsis' ); // no unshift in ie6
14812			numbers.splice( 0, 0, 0 );
14813		}
14814		else {
14815			numbers = _range( page-half+2, page+half-1 );
14816			numbers.push( 'ellipsis' );
14817			numbers.push( pages-1 );
14818			numbers.splice( 0, 0, 'ellipsis' );
14819			numbers.splice( 0, 0, 0 );
14820		}
14821	
14822		numbers.DT_el = 'span';
14823		return numbers;
14824	}
14825	
14826	
14827	$.extend( extPagination, {
14828		simple: function ( page, pages ) {
14829			return [ 'previous', 'next' ];
14830		},
14831	
14832		full: function ( page, pages ) {
14833			return [  'first', 'previous', 'next', 'last' ];
14834		},
14835	
14836		numbers: function ( page, pages ) {
14837			return [ _numbers(page, pages) ];
14838		},
14839	
14840		simple_numbers: function ( page, pages ) {
14841			return [ 'previous', _numbers(page, pages), 'next' ];
14842		},
14843	
14844		full_numbers: function ( page, pages ) {
14845			return [ 'first', 'previous', _numbers(page, pages), 'next', 'last' ];
14846		},
14847		
14848		first_last_numbers: function (page, pages) {
14849	 		return ['first', _numbers(page, pages), 'last'];
14850	 	},
14851	
14852		// For testing and plug-ins to use
14853		_numbers: _numbers,
14854	
14855		// Number of number buttons (including ellipsis) to show. _Must be odd!_
14856		numbers_length: 7
14857	} );
14858	
14859	
14860	$.extend( true, DataTable.ext.renderer, {
14861		pageButton: {
14862			_: function ( settings, host, idx, buttons, page, pages ) {
14863				var classes = settings.oClasses;
14864				var lang = settings.oLanguage.oPaginate;
14865				var aria = settings.oLanguage.oAria.paginate || {};
14866				var btnDisplay, btnClass;
14867	
14868				var attach = function( container, buttons ) {
14869					var i, ien, node, button
vendor: 7,650 bytes, lines 14869-15165
14869;
14870					var disabledClass = classes.sPageButtonDisabled;
14871					var clickHandler = function ( e ) {
14872						_fnPageChange( settings, e.data.action, true );
14873					};
14874	
14875					for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
14876						button = buttons[i];
14877	
14878						if ( Array.isArray( button ) ) {
14879							var inner = $( '<'+(button.DT_el || 'div')+'/>' )
14880								.appendTo( container );
14881							attach( inner, button );
14882						}
14883						else {
14884							var disabled = false;
14885	
14886							btnDisplay = null;
14887							btnClass = button;
14888	
14889							switch ( button ) {
14890								case 'ellipsis':
14891									container.append('<span class="ellipsis">&#x2026;</span>');
14892									break;
14893	
14894								case 'first':
14895									btnDisplay = lang.sFirst;
14896	
14897									if ( page === 0 ) {
14898										disabled = true;
14899									}
14900									break;
14901	
14902								case 'previous':
14903									btnDisplay = lang.sPrevious;
14904	
14905									if ( page === 0 ) {
14906										disabled = true;
14907									}
14908									break;
14909	
14910								case 'next':
14911									btnDisplay = lang.sNext;
14912	
14913									if ( pages === 0 || page === pages-1 ) {
14914										disabled = true;
14915									}
14916									break;
14917	
14918								case 'last':
14919									btnDisplay = lang.sLast;
14920	
14921									if ( pages === 0 || page === pages-1 ) {
14922										disabled = true;
14923									}
14924									break;
14925	
14926								default:
14927									btnDisplay = settings.fnFormatNumber( button + 1 );
14928									btnClass = page === button ?
14929										classes.sPageButtonActive : '';
14930									break;
14931							}
14932	
14933							if ( btnDisplay !== null ) {
14934								var tag = settings.oInit.pagingTag || 'a';
14935	
14936								if (disabled) {
14937									btnClass += ' ' + disabledClass;
14938								}
14939	
14940								node = $('<'+tag+'>', {
14941										'class': classes.sPageButton+' '+btnClass,
14942										'aria-controls': settings.sTableId,
14943										'aria-disabled': disabled ? 'true' : null,
14944										'aria-label': aria[ button ],
14945										'role': 'link',
14946										'aria-current': btnClass === classes.sPageButtonActive ? 'page' : null,
14947										'data-dt-idx': button,
14948										'tabindex': disabled ? -1 : settings.iTabIndex,
14949										'id': idx === 0 && typeof button === 'string' ?
14950											settings.sTableId +'_'+ button :
14951											null
14952									} )
14953									.html( btnDisplay )
14954									.appendTo( container );
14955	
14956								_fnBindAction(
14957									node, {action: button}, clickHandler
14958								);
14959							}
14960						}
14961					}
14962				};
14963	
14964				// IE9 throws an 'unknown error' if document.activeElement is used
14965				// inside an iframe or frame. Try / catch the error. Not good for
14966				// accessibility, but neither are frames.
14967				var activeEl;
14968	
14969				try {
14970					// Because this approach is destroying and recreating the paging
14971					// elements, focus is lost on the select button which is bad for
14972					// accessibility. So we want to restore focus once the draw has
14973					// completed
14974					activeEl = $(host).find(document.activeElement).data('dt-idx');
14975				}
14976				catch (e) {}
14977	
14978				attach( $(host).empty(), buttons );
14979	
14980				if ( activeEl !== undefined ) {
14981					$(host).find( '[data-dt-idx='+activeEl+']' ).trigger('focus');
14982				}
14983			}
14984		}
14985	} );
14986	
14987	
14988	
14989	// Built in type detection. See model.ext.aTypes for information about
14990	// what is required from this methods.
14991	$.extend( DataTable.ext.type.detect, [
14992		// Plain numbers - first since V8 detects some plain numbers as dates
14993		// e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...).
14994		function ( d, settings )
14995		{
14996			var decimal = settings.oLanguage.sDecimal;
14997			return _isNumber( d, decimal ) ? 'num'+decimal : null;
14998		},
14999	
15000		// Dates (only those recognised by the browser's Date.parse)
15001		function ( d, settings )
15002		{
15003			// V8 tries _very_ hard to make a string passed into `Date.parse()`
15004			// valid, so we need to use a regex to restrict date formats. Use a
15005			// plug-in for anything other than ISO8601 style strings
15006			if ( d && !(d instanceof Date) && ! _re_date.test(d) ) {
15007				return null;
15008			}
15009			var parsed = Date.parse(d);
15010			return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null;
15011		},
15012	
15013		// Formatted numbers
15014		function ( d, settings )
15015		{
15016			var decimal = settings.oLanguage.sDecimal;
15017			return _isNumber( d, decimal, true ) ? 'num-fmt'+decimal : null;
15018		},
15019	
15020		// HTML numeric
15021		function ( d, settings )
15022		{
15023			var decimal = settings.oLanguage.sDecimal;
15024			return _htmlNumeric( d, decimal ) ? 'html-num'+decimal : null;
15025		},
15026	
15027		// HTML numeric, formatted
15028		function ( d, settings )
15029		{
15030			var decimal = settings.oLanguage.sDecimal;
15031			return _htmlNumeric( d, decimal, true ) ? 'html-num-fmt'+decimal : null;
15032		},
15033	
15034		// HTML (this is strict checking - there must be html)
15035		function ( d, settings )
15036		{
15037			return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ?
15038				'html' : null;
15039		}
15040	] );
15041	
15042	
15043	
15044	// Filter formatting functions. See model.ext.ofnSearch for information about
15045	// what is required from these methods.
15046	// 
15047	// Note that additional search methods are added for the html numbers and
15048	// html formatted numbers by `_addNumericSort()` when we know what the decimal
15049	// place is
15050	
15051	
15052	$.extend( DataTable.ext.type.search, {
15053		html: function ( data ) {
15054			return _empty(data) ?
15055				data :
15056				typeof data === 'string' ?
15057					data
15058						.replace( _re_new_lines, " " )
15059						.replace( _re_html, "" ) :
15060					'';
15061		},
15062	
15063		string: function ( data ) {
15064			return _empty(data) ?
15065				data :
15066				typeof data === 'string' ?
15067					data.replace( _re_new_lines, " " ) :
15068					data;
15069		}
15070	} );
15071	
15072	
15073	
15074	var __numericReplace = function ( d, decimalPlace, re1, re2 ) {
15075		if ( d !== 0 && (!d || d === '-') ) {
15076			return -Infinity;
15077		}
15078		
15079		var type = typeof d;
15080	
15081		if (type === 'number' || type === 'bigint') {
15082			return d;
15083		}
15084	
15085		// If a decimal place other than `.` is used, it needs to be given to the
15086		// function so we can detect it and replace with a `.` which is the only
15087		// decimal place Javascript recognises - it is not locale aware.
15088		if ( decimalPlace ) {
15089			d = _numToDecimal( d, decimalPlace );
15090		}
15091	
15092		if ( d.replace ) {
15093			if ( re1 ) {
15094				d = d.replace( re1, '' );
15095			}
15096	
15097			if ( re2 ) {
15098				d = d.replace( re2, '' );
15099			}
15100		}
15101	
15102		return d * 1;
15103	};
15104	
15105	
15106	// Add the numeric 'deformatting' functions for sorting and search. This is done
15107	// in a function to provide an easy ability for the language options to add
15108	// additional methods if a non-period decimal place is used.
15109	function _addNumericSort ( decimalPlace ) {
15110		$.each(
15111			{
15112				// Plain numbers
15113				"num": function ( d ) {
15114					return __numericReplace( d, decimalPlace );
15115				},
15116	
15117				// Formatted numbers
15118				"num-fmt": function ( d ) {
15119					return __numericReplace( d, decimalPlace, _re_formatted_numeric );
15120				},
15121	
15122				// HTML numeric
15123				"html-num": function ( d ) {
15124					return __numericReplace( d, decimalPlace, _re_html );
15125				},
15126	
15127				// HTML numeric, formatted
15128				"html-num-fmt": function ( d ) {
15129					return __numericReplace( d, decimalPlace, _re_html, _re_formatted_numeric );
15130				}
15131			},
15132			function ( key, fn ) {
15133				// Add the ordering method
15134				_ext.type.order[ key+decimalPlace+'-pre' ] = fn;
15135	
15136				// For HTML types add a search formatter that will strip the HTML
15137				if ( key.match(/^html\-/) ) {
15138					_ext.type.search[ key+decimalPlace ] = _ext.type.search.html;
15139				}
15140			}
15141		);
15142	}
15143	
15144	
15145	// Default sort methods
15146	$.extend( _ext.type.order, {
15147		// Dates
15148		"date-pre": function ( d ) {
15149			var ts = Date.parse( d );
15150			return isNaN(ts) ? -Infinity : ts;
15151		},
15152	
15153		// html
15154		"html-pre": function ( a ) {
15155			return _empty(a) ?
15156				'' :
15157				a.replace ?
15158					a.replace( /<.*?>/g, "" ).toLowerCase() :
15159					a+'';
15160		},
15161	
15162		// string
15163		"string-pre": function ( a ) {
15164			// This is a little complex, but faster than always calling toString,
15165			// https
vendor: 15,860 bytes, lines 15165-15733
15165://jsperf.com/tostring-v-check
15166			return _empty(a) ?
15167				'' :
15168				typeof a === 'string' ?
15169					a.toLowerCase() :
15170					! a.toString ?
15171						'' :
15172						a.toString();
15173		},
15174	
15175		// string-asc and -desc are retained only for compatibility with the old
15176		// sort methods
15177		"string-asc": function ( x, y ) {
15178			return ((x < y) ? -1 : ((x > y) ? 1 : 0));
15179		},
15180	
15181		"string-desc": function ( x, y ) {
15182			return ((x < y) ? 1 : ((x > y) ? -1 : 0));
15183		}
15184	} );
15185	
15186	
15187	// Numeric sorting types - order doesn't matter here
15188	_addNumericSort( '' );
15189	
15190	
15191	$.extend( true, DataTable.ext.renderer, {
15192		header: {
15193			_: function ( settings, cell, column, classes ) {
15194				// No additional mark-up required
15195				// Attach a sort listener to update on sort - note that using the
15196				// `DT` namespace will allow the event to be removed automatically
15197				// on destroy, while the `dt` namespaced event is the one we are
15198				// listening for
15199				$(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
15200					if ( settings !== ctx ) { // need to check this this is the host
15201						return;               // table, not a nested one
15202					}
15203	
15204					var colIdx = column.idx;
15205	
15206					cell
15207						.removeClass(
15208							classes.sSortAsc +' '+
15209							classes.sSortDesc
15210						)
15211						.addClass( columns[ colIdx ] == 'asc' ?
15212							classes.sSortAsc : columns[ colIdx ] == 'desc' ?
15213								classes.sSortDesc :
15214								column.sSortingClass
15215						);
15216				} );
15217			},
15218	
15219			jqueryui: function ( settings, cell, column, classes ) {
15220				$('<div/>')
15221					.addClass( classes.sSortJUIWrapper )
15222					.append( cell.contents() )
15223					.append( $('<span/>')
15224						.addClass( classes.sSortIcon+' '+column.sSortingClassJUI )
15225					)
15226					.appendTo( cell );
15227	
15228				// Attach a sort listener to update on sort
15229				$(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
15230					if ( settings !== ctx ) {
15231						return;
15232					}
15233	
15234					var colIdx = column.idx;
15235	
15236					cell
15237						.removeClass( classes.sSortAsc +" "+classes.sSortDesc )
15238						.addClass( columns[ colIdx ] == 'asc' ?
15239							classes.sSortAsc : columns[ colIdx ] == 'desc' ?
15240								classes.sSortDesc :
15241								column.sSortingClass
15242						);
15243	
15244					cell
15245						.find( 'span.'+classes.sSortIcon )
15246						.removeClass(
15247							classes.sSortJUIAsc +" "+
15248							classes.sSortJUIDesc +" "+
15249							classes.sSortJUI +" "+
15250							classes.sSortJUIAscAllowed +" "+
15251							classes.sSortJUIDescAllowed
15252						)
15253						.addClass( columns[ colIdx ] == 'asc' ?
15254							classes.sSortJUIAsc : columns[ colIdx ] == 'desc' ?
15255								classes.sSortJUIDesc :
15256								column.sSortingClassJUI
15257						);
15258				} );
15259			}
15260		}
15261	} );
15262	
15263	/*
15264	 * Public helper functions. These aren't used internally by DataTables, or
15265	 * called by any of the options passed into DataTables, but they can be used
15266	 * externally by developers working with DataTables. They are helper functions
15267	 * to make working with DataTables a little bit easier.
15268	 */
15269	
15270	var __htmlEscapeEntities = function ( d ) {
15271		if (Array.isArray(d)) {
15272			d = d.join(',');
15273		}
15274	
15275		return typeof d === 'string' ?
15276			d
15277				.replace(/&/g, '&amp;')
15278				.replace(/</g, '&lt;')
15279				.replace(/>/g, '&gt;')
15280				.replace(/"/g, '&quot;') :
15281			d;
15282	};
15283	
15284	// Common logic for moment, luxon or a date action
15285	function __mld( dt, momentFn, luxonFn, dateFn, arg1 ) {
15286		if (window.moment) {
15287			return dt[momentFn]( arg1 );
15288		}
15289		else if (window.luxon) {
15290			return dt[luxonFn]( arg1 );
15291		}
15292		
15293		return dateFn ? dt[dateFn]( arg1 ) : dt;
15294	}
15295	
15296	
15297	var __mlWarning = false;
15298	function __mldObj (d, format, locale) {
15299		var dt;
15300	
15301		if (window.moment) {
15302			dt = window.moment.utc( d, format, locale, true );
15303	
15304			if (! dt.isValid()) {
15305				return null;
15306			}
15307		}
15308		else if (window.luxon) {
15309			dt = format && typeof d === 'string'
15310				? window.luxon.DateTime.fromFormat( d, format )
15311				: window.luxon.DateTime.fromISO( d );
15312	
15313			if (! dt.isValid) {
15314				return null;
15315			}
15316	
15317			dt.setLocale(locale);
15318		}
15319		else if (! format) {
15320			// No format given, must be ISO
15321			dt = new Date(d);
15322		}
15323		else {
15324			if (! __mlWarning) {
15325				alert('DataTables warning: Formatted date without Moment.js or Luxon - https://datatables.net/tn/17');
15326			}
15327	
15328			__mlWarning = true;
15329		}
15330	
15331		return dt;
15332	}
15333	
15334	// Wrapper for date, datetime and time which all operate the same way with the exception of
15335	// the output string for auto locale support
15336	function __mlHelper (localeString) {
15337		return function ( from, to, locale, def ) {
15338			// Luxon and Moment support
15339			// Argument shifting
15340			if ( arguments.length === 0 ) {
15341				locale = 'en';
15342				to = null; // means toLocaleString
15343				from = null; // means iso8601
15344			}
15345			else if ( arguments.length === 1 ) {
15346				locale = 'en';
15347				to = from;
15348				from = null;
15349			}
15350			else if ( arguments.length === 2 ) {
15351				locale = to;
15352				to = from;
15353				from = null;
15354			}
15355	
15356			var typeName = 'datetime-' + to;
15357	
15358			// Add type detection and sorting specific to this date format - we need to be able to identify
15359			// date type columns as such, rather than as numbers in extensions. Hence the need for this.
15360			if (! DataTable.ext.type.order[typeName]) {
15361				// The renderer will give the value to type detect as the type!
15362				DataTable.ext.type.detect.unshift(function (d) {
15363					return d === typeName ? typeName : false;
15364				});
15365	
15366				// The renderer gives us Moment, Luxon or Date obects for the sorting, all of which have a
15367				// `valueOf` which gives milliseconds epoch
15368				DataTable.ext.type.order[typeName + '-asc'] = function (a, b) {
15369					var x = a.valueOf();
15370					var y = b.valueOf();
15371	
15372					return x === y
15373						? 0
15374						: x < y
15375							? -1
15376							: 1;
15377				}
15378	
15379				DataTable.ext.type.order[typeName + '-desc'] = function (a, b) {
15380					var x = a.valueOf();
15381					var y = b.valueOf();
15382	
15383					return x === y
15384						? 0
15385						: x > y
15386							? -1
15387							: 1;
15388				}
15389			}
15390		
15391			return function ( d, type ) {
15392				// Allow for a default value
15393				if (d === null || d === undefined) {
15394					if (def === '--now') {
15395						// We treat everything as UTC further down, so no changes are
15396						// made, as such need to get the local date / time as if it were
15397						// UTC
15398						var local = new Date();
15399						d = new Date( Date.UTC(
15400							local.getFullYear(), local.getMonth(), local.getDate(),
15401							local.getHours(), local.getMinutes(), local.getSeconds()
15402						) );
15403					}
15404					else {
15405						d = '';
15406					}
15407				}
15408	
15409				if (type === 'type') {
15410					// Typing uses the type name for fast matching
15411					return typeName;
15412				}
15413	
15414				if (d === '') {
15415					return type !== 'sort'
15416						? ''
15417						: __mldObj('0000-01-01 00:00:00', null, locale);
15418				}
15419	
15420				// Shortcut. If `from` and `to` are the same, we are using the renderer to
15421				// format for ordering, not display - its already in the display format.
15422				if ( to !== null && from === to && type !== 'sort' && type !== 'type' && ! (d instanceof Date) ) {
15423					return d;
15424				}
15425	
15426				var dt = __mldObj(d, from, locale);
15427	
15428				if (dt === null) {
15429					return d;
15430				}
15431	
15432				if (type === 'sort') {
15433					return dt;
15434				}
15435				
15436				var formatted = to === null
15437					? __mld(dt, 'toDate', 'toJSDate', '')[localeString]()
15438					: __mld(dt, 'format', 'toFormat', 'toISOString', to);
15439	
15440				// XSS protection
15441				return type === 'display' ?
15442					__htmlEscapeEntities( formatted ) :
15443					formatted;
15444			};
15445		}
15446	}
15447	
15448	// Based on locale, determine standard number formatting
15449	// Fallback for legacy browsers is US English
15450	var __thousands = ',';
15451	var __decimal = '.';
15452	
15453	if (window.Intl !== undefined) {
15454		try {
15455			var num = new Intl.NumberFormat().formatToParts(100000.1);
15456		
15457			for (var i=0 ; i<num.length ; i++) {
15458				if (num[i].type === 'group') {
15459					__thousands = num[i].value;
15460				}
15461				else if (num[i].type === 'decimal') {
15462					__decimal = num[i].value;
15463				}
15464			}
15465		}
15466		catch (e) {
15467			// noop
15468		}
15469	}
15470	
15471	// Formatted date time detection - use by declaring the formats you are going to use
15472	DataTable.datetime = function ( format, locale ) {
15473		var typeName = 'datetime-detect-' + format;
15474	
15475		if (! locale) {
15476			locale = 'en';
15477		}
15478	
15479		if (! DataTable.ext.type.order[typeName]) {
15480			DataTable.ext.type.detect.unshift(function (d) {
15481				var dt = __mldObj(d, format, locale);
15482				return d === '' || dt ? typeName : false;
15483			});
15484	
15485			DataTable.ext.type.order[typeName + '-pre'] = function (d) {
15486				return __mldObj(d, format, locale) || 0;
15487			}
15488		}
15489	}
15490	
15491	/**
15492	 * Helpers for `columns.render`.
15493	 *
15494	 * The options defined here can be used with the `columns.render` initialisation
15495	 * option to provide a display renderer. The following functions are defined:
15496	 *
15497	 * * `number` - Will format numeric data (defined by `columns.data`) for
15498	 *   display, retaining the original unformatted data for sorting and filtering.
15499	 *   It takes 5 parameters:
15500	 *   * `string` - Thousands grouping separator
15501	 *   * `string` - Decimal point indicator
15502	 *   * `integer` - Number of decimal points to show
15503	 *   * `string` (optional) - Prefix.
15504	 *   * `string` (optional) - Postfix (/suffix).
15505	 * * `text` - Escape HTML to help prevent XSS attacks. It has no optional
15506	 *   parameters.
15507	 *
15508	 * @example
15509	 *   // Column definition using the number renderer
15510	 *   {
15511	 *     data: "salary",
15512	 *     render: $.fn.dataTable.render.number( '\'', '.', 0, '$' )
15513	 *   }
15514	 *
15515	 * @namespace
15516	 */
15517	DataTable.render = {
15518		date: __mlHelper('toLocaleDateString'),
15519		datetime: __mlHelper('toLocaleString'),
15520		time: __mlHelper('toLocaleTimeString'),
15521		number: function ( thousands, decimal, precision, prefix, postfix ) {
15522			// Auto locale detection
15523			if (thousands === null || thousands === undefined) {
15524				thousands = __thousands;
15525			}
15526	
15527			if (decimal === null || decimal === undefined) {
15528				decimal = __decimal;
15529			}
15530	
15531			return {
15532				display: function ( d ) {
15533					if ( typeof d !== 'number' && typeof d !== 'string' ) {
15534						return d;
15535					}
15536	
15537					if (d === '' || d === null) {
15538						return d;
15539					}
15540	
15541					var negative = d < 0 ? '-' : '';
15542					var flo = parseFloat( d );
15543	
15544					// If NaN then there isn't much formatting that we can do - just
15545					// return immediately, escaping any HTML (this was supposed to
15546					// be a number after all)
15547					if ( isNaN( flo ) ) {
15548						return __htmlEscapeEntities( d );
15549					}
15550	
15551					flo = flo.toFixed( precision );
15552					d = Math.abs( flo );
15553	
15554					var intPart = parseInt( d, 10 );
15555					var floatPart = precision ?
15556						decimal+(d - intPart).toFixed( precision ).substring( 2 ):
15557						'';
15558	
15559					// If zero, then can't have a negative prefix
15560					if (intPart === 0 && parseFloat(floatPart) === 0) {
15561						negative = '';
15562					}
15563	
15564					return negative + (prefix||'') +
15565						intPart.toString().replace(
15566							/\B(?=(\d{3})+(?!\d))/g, thousands
15567						) +
15568						floatPart +
15569						(postfix||'');
15570				}
15571			};
15572		},
15573	
15574		text: function () {
15575			return {
15576				display: __htmlEscapeEntities,
15577				filter: __htmlEscapeEntities
15578			};
15579		}
15580	};
15581	
15582	
15583	/*
15584	 * This is really a good bit rubbish this method of exposing the internal methods
15585	 * publicly... - To be fixed in 2.0 using methods on the prototype
15586	 */
15587	
15588	
15589	/**
15590	 * Create a wrapper function for exporting an internal functions to an external API.
15591	 *  @param {string} fn API function name
15592	 *  @returns {function} wrapped function
15593	 *  @memberof DataTable#internal
15594	 */
15595	function _fnExternApiFunc (fn)
15596	{
15597		return function() {
15598			var args = [_fnSettingsFromNode( this[DataTable.ext.iApiIndex] )].concat(
15599				Array.prototype.slice.call(arguments)
15600			);
15601			return DataTable.ext.internal[fn].apply( this, args );
15602		};
15603	}
15604	
15605	
15606	/**
15607	 * Reference to internal functions for use by plug-in developers. Note that
15608	 * these methods are references to internal functions and are considered to be
15609	 * private. If you use these methods, be aware that they are liable to change
15610	 * between versions.
15611	 *  @namespace
15612	 */
15613	$.extend( DataTable.ext.internal, {
15614		_fnExternApiFunc: _fnExternApiFunc,
15615		_fnBuildAjax: _fnBuildAjax,
15616		_fnAjaxUpdate: _fnAjaxUpdate,
15617		_fnAjaxParameters: _fnAjaxParameters,
15618		_fnAjaxUpdateDraw: _fnAjaxUpdateDraw,
15619		_fnAjaxDataSrc: _fnAjaxDataSrc,
15620		_fnAddColumn: _fnAddColumn,
15621		_fnColumnOptions: _fnColumnOptions,
15622		_fnAdjustColumnSizing: _fnAdjustColumnSizing,
15623		_fnVisibleToColumnIndex: _fnVisibleToColumnIndex,
15624		_fnColumnIndexToVisible: _fnColumnIndexToVisible,
15625		_fnVisbleColumns: _fnVisbleColumns,
15626		_fnGetColumns: _fnGetColumns,
15627		_fnColumnTypes: _fnColumnTypes,
15628		_fnApplyColumnDefs: _fnApplyColumnDefs,
15629		_fnHungarianMap: _fnHungarianMap,
15630		_fnCamelToHungarian: _fnCamelToHungarian,
15631		_fnLanguageCompat: _fnLanguageCompat,
15632		_fnBrowserDetect: _fnBrowserDetect,
15633		_fnAddData: _fnAddData,
15634		_fnAddTr: _fnAddTr,
15635		_fnNodeToDataIndex: _fnNodeToDataIndex,
15636		_fnNodeToColumnIndex: _fnNodeToColumnIndex,
15637		_fnGetCellData: _fnGetCellData,
15638		_fnSetCellData: _fnSetCellData,
15639		_fnSplitObjNotation: _fnSplitObjNotation,
15640		_fnGetObjectDataFn: _fnGetObjectDataFn,
15641		_fnSetObjectDataFn: _fnSetObjectDataFn,
15642		_fnGetDataMaster: _fnGetDataMaster,
15643		_fnClearTable: _fnClearTable,
15644		_fnDeleteIndex: _fnDeleteIndex,
15645		_fnInvalidate: _fnInvalidate,
15646		_fnGetRowElements: _fnGetRowElements,
15647		_fnCreateTr: _fnCreateTr,
15648		_fnBuildHead: _fnBuildHead,
15649		_fnDrawHead: _fnDrawHead,
15650		_fnDraw: _fnDraw,
15651		_fnReDraw: _fnReDraw,
15652		_fnAddOptionsHtml: _fnAddOptionsHtml,
15653		_fnDetectHeader: _fnDetectHeader,
15654		_fnGetUniqueThs: _fnGetUniqueThs,
15655		_fnFeatureHtmlFilter: _fnFeatureHtmlFilter,
15656		_fnFilterComplete: _fnFilterComplete,
15657		_fnFilterCustom: _fnFilterCustom,
15658		_fnFilterColumn: _fnFilterColumn,
15659		_fnFilter: _fnFilter,
15660		_fnFilterCreateSearch: _fnFilterCreateSearch,
15661		_fnEscapeRegex: _fnEscapeRegex,
15662		_fnFilterData: _fnFilterData,
15663		_fnFeatureHtmlInfo: _fnFeatureHtmlInfo,
15664		_fnUpdateInfo: _fnUpdateInfo,
15665		_fnInfoMacros: _fnInfoMacros,
15666		_fnInitialise: _fnInitialise,
15667		_fnInitComplete: _fnInitComplete,
15668		_fnLengthChange: _fnLengthChange,
15669		_fnFeatureHtmlLength: _fnFeatureHtmlLength,
15670		_fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate,
15671		_fnPageChange: _fnPageChange,
15672		_fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing,
15673		_fnProcessingDisplay: _fnProcessingDisplay,
15674		_fnFeatureHtmlTable: _fnFeatureHtmlTable,
15675		_fnScrollDraw: _fnScrollDraw,
15676		_fnApplyToChildren: _fnApplyToChildren,
15677		_fnCalculateColumnWidths: _fnCalculateColumnWidths,
15678		_fnThrottle: _fnThrottle,
15679		_fnConvertToWidth: _fnConvertToWidth,
15680		_fnGetWidestNode: _fnGetWidestNode,
15681		_fnGetMaxLenString: _fnGetMaxLenString,
15682		_fnStringToCss: _fnStringToCss,
15683		_fnSortFlatten: _fnSortFlatten,
15684		_fnSort: _fnSort,
15685		_fnSortAria: _fnSortAria,
15686		_fnSortListener: _fnSortListener,
15687		_fnSortAttachListener: _fnSortAttachListener,
15688		_fnSortingClasses: _fnSortingClasses,
15689		_fnSortData: _fnSortData,
15690		_fnSaveState: _fnSaveState,
15691		_fnLoadState: _fnLoadState,
15692		_fnImplementState: _fnImplementState,
15693		_fnSettingsFromNode: _fnSettingsFromNode,
15694		_fnLog: _fnLog,
15695		_fnMap: _fnMap,
15696		_fnBindAction: _fnBindAction,
15697		_fnCallbackReg: _fnCallbackReg,
15698		_fnCallbackFire: _fnCallbackFire,
15699		_fnLengthOverflow: _fnLengthOverflow,
15700		_fnRenderer: _fnRenderer,
15701		_fnDataSource: _fnDataSource,
15702		_fnRowAttributes: _fnRowAttributes,
15703		_fnExtend: _fnExtend,
15704		_fnCalculateEnd: function () {} // Used by a lot of plug-ins, but redundant
15705		                                // in 1.10, so this dead-end function is
15706		                                // added to prevent errors
15707	} );
15708	
15709	
15710	// jQuery access
15711	$.fn.dataTable = DataTable;
15712	
15713	// Provide access to the host jQuery object (circular reference)
15714	DataTable.$ = $;
15715	
15716	// Legacy aliases
15717	$.fn.dataTableSettings = DataTable.settings;
15718	$.fn.dataTableExt = DataTable.ext;
15719	
15720	// With a capital `D` we return a DataTables API instance rather than a
15721	// jQuery object
15722	$.fn.DataTable = function ( opts ) {
15723		return $(this).dataTable( opts ).api();
15724	};
15725	
15726	// All properties that are available to $.fn.dataTable should also be
15727	// available on $.fn.DataTable
15728	$.each( DataTable, function ( prop, val ) {
15729		$.fn.DataTable[ prop ] = val;
15730	} );
15731
15732	return DataTable;
15733}));

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