PageSourceSearch

https://pia.gov.ng/wp-content/plugins/wp-google-maps/js/jquery.dataTables.js?ver=6.0.16

js pia.gov.ng collected 2026-10-05 08:50:45 UTC 469,231 bytes, 15,580 lines download raw bytes

vendor: 5,670 bytes, lines 1-116
1/*! DataTables 1.12.1
2 * ©2008-2022 SpryMedia Ltd - datatables.net/license
3 */
4
5/**
6 * @summary     DataTables
7 * @description Paginate, search and order HTML tables
8 * @version     1.12.1
9 * @author      SpryMedia Ltd
10 * @contact     www.datatables.net
11 * @copyright   SpryMedia Ltd.
12 *
13 * This source file is free software, available under the following license:
14 *   MIT license - http://datatables.net/license
15 *
16 * This source file is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
19 *
20 * For details please refer to: http://www.datatables.net
21 */
22
23/*jslint evil: true, undef: true, browser: true */
24/*globals $,require,jQuery,define,_selector_run,_selector_opts,_selector_first,_selector_row_indexes,_ext,_Api,_api_register,_api_registerPlural,_re_new_lines,_re_html,_re_formatted_numeric,_re_escape_regex,_empty,_intVal,_numToDecimal,_isNumber,_isHtml,_htmlNumeric,_pluck,_pluck_order,_range,_stripHtml,_unique,_fnBuildAjax,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnAjaxDataSrc,_fnAddColumn,_fnColumnOptions,_fnAdjustColumnSizing,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnVisbleColumns,_fnGetColumns,_fnColumnTypes,_fnApplyColumnDefs,_fnHungarianMap,_fnCamelToHungarian,_fnLanguageCompat,_fnBrowserDetect,_fnAddData,_fnAddTr,_fnNodeToDataIndex,_fnNodeToColumnIndex,_fnGetCellData,_fnSetCellData,_fnSplitObjNotation,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnGetDataMaster,_fnClearTable,_fnDeleteIndex,_fnInvalidate,_fnGetRowElements,_fnCreateTr,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAddOptionsHtml,_fnDetectHeader,_fnGetUniqueThs,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnFilterCreateSearch,_fnEscapeRegex,_fnFilterData,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnInfoMacros,_fnInitialise,_fnInitComplete,_fnLengthChange,_fnFeatureHtmlLength,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnFeatureHtmlTable,_fnScrollDraw,_fnApplyToChildren,_fnCalculateColumnWidths,_fnThrottle,_fnConvertToWidth,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnSortFlatten,_fnSort,_fnSortAria,_fnSortListener,_fnSortAttachListener,_fnSortingClasses,_fnSortData,_fnSaveState,_fnLoadState,_fnSettingsFromNode,_fnLog,_fnMap,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnLengthOverflow,_fnRenderer,_fnDataSource,_fnRowAttributes*/
25
26(function( factory ) {
27	"use strict";
28
29	if ( typeof define === 'function' && define.amd ) {
30		// AMD
31		define( ['jquery'], function ( $ ) {
32			return factory( $, window, document );
33		} );
34	}
35	else if ( typeof exports === 'object' ) {
36		// CommonJS
37		module.exports = function (root, $) {
38			if ( ! root ) {
39				// CommonJS environments without a window global must pass a
40				// root. This will give an error otherwise
41				root = window;
42			}
43
44			if ( ! $ ) {
45				$ = typeof window !== 'undefined' ? // jQuery's factory checks for a global window
46					require('jquery') :
47					require('jquery')( root );
48			}
49
50			return factory( $, root, root.document );
51		};
52	}
53	else {
54		// Browser
55		window.DataTable = factory( jQuery, window, document );
56	}
57}
58(function( $, window, document, undefined ) {
59	"use strict";
60
61	
62	var DataTable = function ( selector, options )
63	{
64		// When creating with `new`, create a new DataTable, returning the API instance
65		if (this instanceof DataTable) {
66			return $(selector).DataTable(options);
67		}
68		else {
69			// Argument switching
70			options = selector;
71		}
72	
73		/**
74		 * Perform a jQuery selector action on the table's TR elements (from the tbody) and
75		 * return the resulting jQuery object.
76		 *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
77		 *  @param {object} [oOpts] Optional parameters for modifying the rows to be included
78		 *  @param {string} [oOpts.filter=none] Select TR elements that meet the current filter
79		 *    criterion ("applied") or all TR elements (i.e. no filter).
80		 *  @param {string} [oOpts.order=current] Order of the TR elements in the processed array.
81		 *    Can be either 'current', whereby the current sorting of the table is used, or
82		 *    'original' whereby the original order the data was read into the table is used.
83		 *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
84		 *    ("current") or not ("all"). If 'current' is given, then order is assumed to be
85		 *    'current' and filter is 'applied', regardless of what they might be given as.
86		 *  @returns {object} jQuery object, filtered by the given selector.
87		 *  @dtopt API
88		 *  @deprecated Since v1.10
89		 *
90		 *  @example
91		 *    $(document).ready(function() {
92		 *      var oTable = $('#example').dataTable();
93		 *
94		 *      // Highlight every second row
95		 *      oTable.$('tr:odd').css('backgroundColor', 'blue');
96		 *    } );
97		 *
98		 *  @example
99		 *    $(document).ready(function() {
100		 *      var oTable = $('#example').dataTable();
101		 *
102		 *      // Filter to rows with 'Webkit' in them, add a background colour and then
103		 *      // remove the filter, thus highlighting the 'Webkit' rows only.
104		 *      oTable.fnFilter('Webkit');
105		 *      oTable.$('tr', {"search": "applied"}).css('backgroundColor', 'blue');
106		 *      oTable.fnFilter('');
107		 *    } );
108		 */
109		this.$ = function ( sSelector, oOpts )
110		{
111			return this.api(true).$( sSelector, oOpts );
112		};
113		
114		
115		/**
116		 * Almost identical to $ in operation, but in this case returns the data for the matched
117		 * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes
118		 * rather than any descendants, so the data can be obtained for the row/cell. If matching
119		 * rows are found, the data returned is the original data array/object that was used to
120		 * create the row (or a generated array if from a DOM source).
121		 *
122		 * This method is often useful in-combination with $ where both functions are given the
123		 * same parameters and the array indexes will match identically.
124		 *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
125		 *  @param {object} [oOpts] Optional parameters for modifying the rows to be included
126		 *  @param {string} [oOpts.filter=none] Select elements that meet the current filter
127		 *    criterion ("applied") or all elements (i.e. no filter).
128		 *  @param {string} [oOpts.order=current] Order of the data in the processed array.
129		 *    Can be either 'current', whereby the current sorting of the table is used, or
130		 *    'original' whereby the original order the data was read into the table is used.
131		 *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
132		 *    ("current") or not ("all"). If 'current' is given, then order is assumed to be
133		 *    'current' and filter is 'applied', regardless of what they might be given as.
134		 *  @returns {array} Data for the matched elements. If any elements, as a result of the
135		 *    selector, were not TR, TD or TH elements in the DataTable, they will have a null
136		 *    entry in the array.
137		 *  @dtopt API
138		 *  @deprecated Since v1.10
139		 *
140		 *  @example
141		 *    $(document).ready(function() {
142		 *      var oTable = $('#example').dataTable();
143		 *
144		 *      // Get the data from the first row in the table
145		 *      var data = oTable._('tr:first');
146		 *
147		 *      // Do something useful with the data
148		 *      alert( "First cell is: "+data[0] );
149		 *    } );
150		 *
151		 *  @example
152		 *    $(document).ready(function() {
153		 *      var oTable = $('#example').dataTable();
154		 *
155		 *      // Filter to 'Webkit' and get all data for
156		 *      oTable.fnFilter('Webkit');
157		 *      var data = oTable._('tr', {"search": "applied"});
158		 *
159		 *      // Do something with the data
160		 *      alert( data.length+" rows matched the search" );
161		 *    } );
162		 */
163		this._ = function ( sSelector, oOpts )
164		{
165			return this.api(true).rows( sSelector, oOpts ).data();
166		};
167		
168		
169		/**
170		 * Create a DataTables Api instance, with the currently selected tables for
171		 * the Api's context.
172		 * @param {boolean} [traditional=false] Set the API instance's context to be
173		 *   only the table referred to by the `DataTable.ext.iApiIndex` option, as was
174		 *   used in the API presented by DataTables 1.9- (i.e. the traditional mode),
175		 *   or if all tables captured in the jQuery object should be used.
176		 * @return {DataTables.Api}
177		 */
178		this.api = function ( traditional )
179		{
180			return traditional ?
181				new _Api(
182					_fnSettingsFromNode( this[ _ext.iApiIndex ] )
183				) :
184				new _Api( this );
185		};
186		
187		
188		/**
189		 * Add a single new row or multiple rows of data to the table. Please note
190		 * that this is suitable for client-side processing only - if you are using
191		 * server-side processing (i.e. "bServerSide": true), then to add data, you
192		 * must add it to the data source, i.e. the server-side, through an Ajax call.
193		 *  @param {array|object} data The data to be added to the table. This can be:
194		 *    <ul>
195		 *      <li>1D array of data - add a single row with the data provided</li>
196		 *      <li>2D array of arrays - add multiple rows in a single call</li>
197		 *      <li>object - data object when using <i>mData</i></li>
198		 *      <li>array of objects - multiple data objects when using <i>mData</i></li>
199		 *    </ul>
200		 *  @param {bool} [redraw=true] redraw the table or not
201		 *  @returns {array} An array of integers, representing the list of indexes in
202		 *    <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to
203		 *    the table.
204		 *  @dtopt API
205		 *  @deprecated Since v1.10
206		 *
207		 *  @example
208		 *    // Global var for counter
209		 *    var giCount = 2;
210		 *
211		 *    $(document).ready(function() {
212		 *      $('#example').dataTable();
213		 *    } );
214		 *
215		 *    function fnClickAddRow() {
216		 *      $('#example').dataTable().fnAddData( [
217		 *        giCount+".1",
218		 *        giCount+".2",
219		 *        giCount+".3",
220		 *        giCount+".4" ]
221		 *      );
222		 *
223		 *      giCount++;
224		 *    }
225		 */
226		this.fnAddData = function( data, redraw )
227		{
228			var api = this.api( true );
229		
230			/* Check if we want to add multiple rows or not */
231			var rows = Array.isArray(data) && ( Array.isArray(data[0]) || $.isPlainObject(data[0]) ) ?
232				api.rows.add( data ) :
233				api.row.add( data );
234		
235			if ( redraw === undefined || redraw ) {
236				api.draw();
237			}
238		
239			return rows.flatten().toArray();
240		};
241		
242		
243		/**
244		 * This function will make DataTables recalculate the column sizes, based on the data
245		 * contained in the table and the sizes applied to the columns (in the DOM, CSS or
246		 * through the sWidth parameter). This can be useful when the width of the table's
vendor: 200,033 bytes, lines 247-6961
247		 * parent element changes (for example a window resize).
248		 *  @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to
249		 *  @dtopt API
250		 *  @deprecated Since v1.10
251		 *
252		 *  @example
253		 *    $(document).ready(function() {
254		 *      var oTable = $('#example').dataTable( {
255		 *        "sScrollY": "200px",
256		 *        "bPaginate": false
257		 *      } );
258		 *
259		 *      $(window).on('resize', function () {
260		 *        oTable.fnAdjustColumnSizing();
261		 *      } );
262		 *    } );
263		 */
264		this.fnAdjustColumnSizing = function ( bRedraw )
265		{
266			var api = this.api( true ).columns.adjust();
267			var settings = api.settings()[0];
268			var scroll = settings.oScroll;
269		
270			if ( bRedraw === undefined || bRedraw ) {
271				api.draw( false );
272			}
273			else if ( scroll.sX !== "" || scroll.sY !== "" ) {
274				/* If not redrawing, but scrolling, we want to apply the new column sizes anyway */
275				_fnScrollDraw( settings );
276			}
277		};
278		
279		
280		/**
281		 * Quickly and simply clear a table
282		 *  @param {bool} [bRedraw=true] redraw the table or not
283		 *  @dtopt API
284		 *  @deprecated Since v1.10
285		 *
286		 *  @example
287		 *    $(document).ready(function() {
288		 *      var oTable = $('#example').dataTable();
289		 *
290		 *      // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...)
291		 *      oTable.fnClearTable();
292		 *    } );
293		 */
294		this.fnClearTable = function( bRedraw )
295		{
296			var api = this.api( true ).clear();
297		
298			if ( bRedraw === undefined || bRedraw ) {
299				api.draw();
300			}
301		};
302		
303		
304		/**
305		 * The exact opposite of 'opening' a row, this function will close any rows which
306		 * are currently 'open'.
307		 *  @param {node} nTr the table row to 'close'
308		 *  @returns {int} 0 on success, or 1 if failed (can't find the row)
309		 *  @dtopt API
310		 *  @deprecated Since v1.10
311		 *
312		 *  @example
313		 *    $(document).ready(function() {
314		 *      var oTable;
315		 *
316		 *      // 'open' an information row when a row is clicked on
317		 *      $('#example tbody tr').click( function () {
318		 *        if ( oTable.fnIsOpen(this) ) {
319		 *          oTable.fnClose( this );
320		 *        } else {
321		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
322		 *        }
323		 *      } );
324		 *
325		 *      oTable = $('#example').dataTable();
326		 *    } );
327		 */
328		this.fnClose = function( nTr )
329		{
330			this.api( true ).row( nTr ).child.hide();
331		};
332		
333		
334		/**
335		 * Remove a row for the table
336		 *  @param {mixed} target The index of the row from aoData to be deleted, or
337		 *    the TR element you want to delete
338		 *  @param {function|null} [callBack] Callback function
339		 *  @param {bool} [redraw=true] Redraw the table or not
340		 *  @returns {array} The row that was deleted
341		 *  @dtopt API
342		 *  @deprecated Since v1.10
343		 *
344		 *  @example
345		 *    $(document).ready(function() {
346		 *      var oTable = $('#example').dataTable();
347		 *
348		 *      // Immediately remove the first row
349		 *      oTable.fnDeleteRow( 0 );
350		 *    } );
351		 */
352		this.fnDeleteRow = function( target, callback, redraw )
353		{
354			var api = this.api( true );
355			var rows = api.rows( target );
356			var settings = rows.settings()[0];
357			var data = settings.aoData[ rows[0][0] ];
358		
359			rows.remove();
360		
361			if ( callback ) {
362				callback.call( this, settings, data );
363			}
364		
365			if ( redraw === undefined || redraw ) {
366				api.draw();
367			}
368		
369			return data;
370		};
371		
372		
373		/**
374		 * Restore the table to it's original state in the DOM by removing all of DataTables
375		 * enhancements, alterations to the DOM structure of the table and event listeners.
376		 *  @param {boolean} [remove=false] Completely remove the table from the DOM
377		 *  @dtopt API
378		 *  @deprecated Since v1.10
379		 *
380		 *  @example
381		 *    $(document).ready(function() {
382		 *      // This example is fairly pointless in reality, but shows how fnDestroy can be used
383		 *      var oTable = $('#example').dataTable();
384		 *      oTable.fnDestroy();
385		 *    } );
386		 */
387		this.fnDestroy = function ( remove )
388		{
389			this.api( true ).destroy( remove );
390		};
391		
392		
393		/**
394		 * Redraw the table
395		 *  @param {bool} [complete=true] Re-filter and resort (if enabled) the table before the draw.
396		 *  @dtopt API
397		 *  @deprecated Since v1.10
398		 *
399		 *  @example
400		 *    $(document).ready(function() {
401		 *      var oTable = $('#example').dataTable();
402		 *
403		 *      // Re-draw the table - you wouldn't want to do it here, but it's an example :-)
404		 *      oTable.fnDraw();
405		 *    } );
406		 */
407		this.fnDraw = function( complete )
408		{
409			// Note that this isn't an exact match to the old call to _fnDraw - it takes
410			// into account the new data, but can hold position.
411			this.api( true ).draw( complete );
412		};
413		
414		
415		/**
416		 * Filter the input based on data
417		 *  @param {string} sInput String to filter the table on
418		 *  @param {int|null} [iColumn] Column to limit filtering to
419		 *  @param {bool} [bRegex=false] Treat as regular expression or not
420		 *  @param {bool} [bSmart=true] Perform smart filtering or not
421		 *  @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es)
422		 *  @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false)
423		 *  @dtopt API
424		 *  @deprecated Since v1.10
425		 *
426		 *  @example
427		 *    $(document).ready(function() {
428		 *      var oTable = $('#example').dataTable();
429		 *
430		 *      // Sometime later - filter...
431		 *      oTable.fnFilter( 'test string' );
432		 *    } );
433		 */
434		this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive )
435		{
436			var api = this.api( true );
437		
438			if ( iColumn === null || iColumn === undefined ) {
439				api.search( sInput, bRegex, bSmart, bCaseInsensitive );
440			}
441			else {
442				api.column( iColumn ).search( sInput, bRegex, bSmart, bCaseInsensitive );
443			}
444		
445			api.draw();
446		};
447		
448		
449		/**
450		 * Get the data for the whole table, an individual row or an individual cell based on the
451		 * provided parameters.
452		 *  @param {int|node} [src] A TR row node, TD/TH cell node or an integer. If given as
453		 *    a TR node then the data source for the whole row will be returned. If given as a
454		 *    TD/TH cell node then iCol will be automatically calculated and the data for the
455		 *    cell returned. If given as an integer, then this is treated as the aoData internal
456		 *    data index for the row (see fnGetPosition) and the data for that row used.
457		 *  @param {int} [col] Optional column index that you want the data of.
458		 *  @returns {array|object|string} If mRow is undefined, then the data for all rows is
459		 *    returned. If mRow is defined, just data for that row, and is iCol is
460		 *    defined, only data for the designated cell is returned.
461		 *  @dtopt API
462		 *  @deprecated Since v1.10
463		 *
464		 *  @example
465		 *    // Row data
466		 *    $(document).ready(function() {
467		 *      oTable = $('#example').dataTable();
468		 *
469		 *      oTable.$('tr').click( function () {
470		 *        var data = oTable.fnGetData( this );
471		 *        // ... do something with the array / object of data for the row
472		 *      } );
473		 *    } );
474		 *
475		 *  @example
476		 *    // Individual cell data
477		 *    $(document).ready(function() {
478		 *      oTable = $('#example').dataTable();
479		 *
480		 *      oTable.$('td').click( function () {
481		 *        var sData = oTable.fnGetData( this );
482		 *        alert( 'The cell clicked on had the value of '+sData );
483		 *      } );
484		 *    } );
485		 */
486		this.fnGetData = function( src, col )
487		{
488			var api = this.api( true );
489		
490			if ( src !== undefined ) {
491				var type = src.nodeName ? src.nodeName.toLowerCase() : '';
492		
493				return col !== undefined || type == 'td' || type == 'th' ?
494					api.cell( src, col ).data() :
495					api.row( src ).data() || null;
496			}
497		
498			return api.data().toArray();
499		};
500		
501		
502		/**
503		 * Get an array of the TR nodes that are used in the table's body. Note that you will
504		 * typically want to use the '$' API method in preference to this as it is more
505		 * flexible.
506		 *  @param {int} [iRow] Optional row index for the TR element you want
507		 *  @returns {array|node} If iRow is undefined, returns an array of all TR elements
508		 *    in the table's body, or iRow is defined, just the TR element requested.
509		 *  @dtopt API
510		 *  @deprecated Since v1.10
511		 *
512		 *  @example
513		 *    $(document).ready(function() {
514		 *      var oTable = $('#example').dataTable();
515		 *
516		 *      // Get the nodes from the table
517		 *      var nNodes = oTable.fnGetNodes( );
518		 *    } );
519		 */
520		this.fnGetNodes = function( iRow )
521		{
522			var api = this.api( true );
523		
524			return iRow !== undefined ?
525				api.row( iRow ).node() :
526				api.rows().nodes().flatten().toArray();
527		};
528		
529		
530		/**
531		 * Get the array indexes of a particular cell from it's DOM element
532		 * and column index including hidden columns
533		 *  @param {node} node this can either be a TR, TD or TH in the table's body
534		 *  @returns {int} If nNode is given as a TR, then a single index is returned, or
535		 *    if given as a cell, an array of [row index, column index (visible),
536		 *    column index (all)] is given.
537		 *  @dtopt API
538		 *  @deprecated Since v1.10
539		 *
540		 *  @example
541		 *    $(document).ready(function() {
542		 *      $('#example tbody td').click( function () {
543		 *        // Get the position of the current data from the node
544		 *        var aPos = oTable.fnGetPosition( this );
545		 *
546		 *        // Get the data array for this row
547		 *        var aData = oTable.fnGetData( aPos[0] );
548		 *
549		 *        // Update the data array and return the value
550		 *        aData[ aPos[1] ] = 'clicked';
551		 *        this.innerHTML = 'clicked';
552		 *      } );
553		 *
554		 *      // Init DataTables
555		 *      oTable = $('#example').dataTable();
556		 *    } );
557		 */
558		this.fnGetPosition = function( node )
559		{
560			var api = this.api( true );
561			var nodeName = node.nodeName.toUpperCase();
562		
563			if ( nodeName == 'TR' ) {
564				return api.row( node ).index();
565			}
566			else if ( nodeName == 'TD' || nodeName == 'TH' ) {
567				var cell = api.cell( node ).index();
568		
569				return [
570					cell.row,
571					cell.columnVisible,
572					cell.column
573				];
574			}
575			return null;
576		};
577		
578		
579		/**
580		 * Check to see if a row is 'open' or not.
581		 *  @param {node} nTr the table row to check
582		 *  @returns {boolean} true if the row is currently open, false otherwise
583		 *  @dtopt API
584		 *  @deprecated Since v1.10
585		 *
586		 *  @example
587		 *    $(document).ready(function() {
588		 *      var oTable;
589		 *
590		 *      // 'open' an information row when a row is clicked on
591		 *      $('#example tbody tr').click( function () {
592		 *        if ( oTable.fnIsOpen(this) ) {
593		 *          oTable.fnClose( this );
594		 *        } else {
595		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
596		 *        }
597		 *      } );
598		 *
599		 *      oTable = $('#example').dataTable();
600		 *    } );
601		 */
602		this.fnIsOpen = function( nTr )
603		{
604			return this.api( true ).row( nTr ).child.isShown();
605		};
606		
607		
608		/**
609		 * This function will place a new row directly after a row which is currently
610		 * on display on the page, with the HTML contents that is passed into the
611		 * function. This can be used, for example, to ask for confirmation that a
612		 * particular record should be deleted.
613		 *  @param {node} nTr The table row to 'open'
614		 *  @param {string|node|jQuery} mHtml The HTML to put into the row
615		 *  @param {string} sClass Class to give the new TD cell
616		 *  @returns {node} The row opened. Note that if the table row passed in as the
617		 *    first parameter, is not found in the table, this method will silently
618		 *    return.
619		 *  @dtopt API
620		 *  @deprecated Since v1.10
621		 *
622		 *  @example
623		 *    $(document).ready(function() {
624		 *      var oTable;
625		 *
626		 *      // 'open' an information row when a row is clicked on
627		 *      $('#example tbody tr').click( function () {
628		 *        if ( oTable.fnIsOpen(this) ) {
629		 *          oTable.fnClose( this );
630		 *        } else {
631		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
632		 *        }
633		 *      } );
634		 *
635		 *      oTable = $('#example').dataTable();
636		 *    } );
637		 */
638		this.fnOpen = function( nTr, mHtml, sClass )
639		{
640			return this.api( true )
641				.row( nTr )
642				.child( mHtml, sClass )
643				.show()
644				.child()[0];
645		};
646		
647		
648		/**
649		 * Change the pagination - provides the internal logic for pagination in a simple API
650		 * function. With this function you can have a DataTables table go to the next,
651		 * previous, first or last pages.
652		 *  @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
653		 *    or page number to jump to (integer), note that page 0 is the first page.
654		 *  @param {bool} [bRedraw=true] Redraw the table or not
655		 *  @dtopt API
656		 *  @deprecated Since v1.10
657		 *
658		 *  @example
659		 *    $(document).ready(function() {
660		 *      var oTable = $('#example').dataTable();
661		 *      oTable.fnPageChange( 'next' );
662		 *    } );
663		 */
664		this.fnPageChange = function ( mAction, bRedraw )
665		{
666			var api = this.api( true ).page( mAction );
667		
668			if ( bRedraw === undefined || bRedraw ) {
669				api.draw(false);
670			}
671		};
672		
673		
674		/**
675		 * Show a particular column
676		 *  @param {int} iCol The column whose display should be changed
677		 *  @param {bool} bShow Show (true) or hide (false) the column
678		 *  @param {bool} [bRedraw=true] Redraw the table or not
679		 *  @dtopt API
680		 *  @deprecated Since v1.10
681		 *
682		 *  @example
683		 *    $(document).ready(function() {
684		 *      var oTable = $('#example').dataTable();
685		 *
686		 *      // Hide the second column after initialisation
687		 *      oTable.fnSetColumnVis( 1, false );
688		 *    } );
689		 */
690		this.fnSetColumnVis = function ( iCol, bShow, bRedraw )
691		{
692			var api = this.api( true ).column( iCol ).visible( bShow );
693		
694			if ( bRedraw === undefined || bRedraw ) {
695				api.columns.adjust().draw();
696			}
697		};
698		
699		
700		/**
701		 * Get the settings for a particular table for external manipulation
702		 *  @returns {object} DataTables settings object. See
703		 *    {@link DataTable.models.oSettings}
704		 *  @dtopt API
705		 *  @deprecated Since v1.10
706		 *
707		 *  @example
708		 *    $(document).ready(function() {
709		 *      var oTable = $('#example').dataTable();
710		 *      var oSettings = oTable.fnSettings();
711		 *
712		 *      // Show an example parameter from the settings
713		 *      alert( oSettings._iDisplayStart );
714		 *    } );
715		 */
716		this.fnSettings = function()
717		{
718			return _fnSettingsFromNode( this[_ext.iApiIndex] );
719		};
720		
721		
722		/**
723		 * Sort the table by a particular column
724		 *  @param {int} iCol the data index to sort on. Note that this will not match the
725		 *    'display index' if you have hidden data entries
726		 *  @dtopt API
727		 *  @deprecated Since v1.10
728		 *
729		 *  @example
730		 *    $(document).ready(function() {
731		 *      var oTable = $('#example').dataTable();
732		 *
733		 *      // Sort immediately with columns 0 and 1
734		 *      oTable.fnSort( [ [0,'asc'], [1,'asc'] ] );
735		 *    } );
736		 */
737		this.fnSort = function( aaSort )
738		{
739			this.api( true ).order( aaSort ).draw();
740		};
741		
742		
743		/**
744		 * Attach a sort listener to an element for a given column
745		 *  @param {node} nNode the element to attach the sort listener to
746		 *  @param {int} iColumn the column that a click on this node will sort on
747		 *  @param {function} [fnCallback] callback function when sort is run
748		 *  @dtopt API
749		 *  @deprecated Since v1.10
750		 *
751		 *  @example
752		 *    $(document).ready(function() {
753		 *      var oTable = $('#example').dataTable();
754		 *
755		 *      // Sort on column 1, when 'sorter' is clicked on
756		 *      oTable.fnSortListener( document.getElementById('sorter'), 1 );
757		 *    } );
758		 */
759		this.fnSortListener = function( nNode, iColumn, fnCallback )
760		{
761			this.api( true ).order.listener( nNode, iColumn, fnCallback );
762		};
763		
764		
765		/**
766		 * Update a table cell or row - this method will accept either a single value to
767		 * update the cell with, an array of values with one element for each column or
768		 * an object in the same format as the original data source. The function is
769		 * self-referencing in order to make the multi column updates easier.
770		 *  @param {object|array|string} mData Data to update the cell/row with
771		 *  @param {node|int} mRow TR element you want to update or the aoData index
772		 *  @param {int} [iColumn] The column to update, give as null or undefined to
773		 *    update a whole row.
774		 *  @param {bool} [bRedraw=true] Redraw the table or not
775		 *  @param {bool} [bAction=true] Perform pre-draw actions or not
776		 *  @returns {int} 0 on success, 1 on error
777		 *  @dtopt API
778		 *  @deprecated Since v1.10
779		 *
780		 *  @example
781		 *    $(document).ready(function() {
782		 *      var oTable = $('#example').dataTable();
783		 *      oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell
784		 *      oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], $('tbody tr')[0] ); // Row
785		 *    } );
786		 */
787		this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction )
788		{
789			var api = this.api( true );
790		
791			if ( iColumn === undefined || iColumn === null ) {
792				api.row( mRow ).data( mData );
793			}
794			else {
795				api.cell( mRow, iColumn ).data( mData );
796			}
797		
798			if ( bAction === undefined || bAction ) {
799				api.columns.adjust();
800			}
801		
802			if ( bRedraw === undefined || bRedraw ) {
803				api.draw();
804			}
805			return 0;
806		};
807		
808		
809		/**
810		 * Provide a common method for plug-ins to check the version of DataTables being used, in order
811		 * to ensure compatibility.
812		 *  @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the
813		 *    formats "X" and "X.Y" are also acceptable.
814		 *  @returns {boolean} true if this version of DataTables is greater or equal to the required
815		 *    version, or false if this version of DataTales is not suitable
816		 *  @method
817		 *  @dtopt API
818		 *  @deprecated Since v1.10
819		 *
820		 *  @example
821		 *    $(document).ready(function() {
822		 *      var oTable = $('#example').dataTable();
823		 *      alert( oTable.fnVersionCheck( '1.9.0' ) );
824		 *    } );
825		 */
826		this.fnVersionCheck = _ext.fnVersionCheck;
827		
828	
829		var _that = this;
830		var emptyInit = options === undefined;
831		var len = this.length;
832	
833		if ( emptyInit ) {
834			options = {};
835		}
836	
837		this.oApi = this.internal = _ext.internal;
838	
839		// Extend with old style plug-in API methods
840		for ( var fn in DataTable.ext.internal ) {
841			if ( fn ) {
842				this[fn] = _fnExternApiFunc(fn);
843			}
844		}
845	
846		this.each(function() {
847			// For each initialisation we want to give it a clean initialisation
848			// object that can be bashed around
849			var o = {};
850			var oInit = len > 1 ? // optimisation for single table case
851				_fnExtend( o, options, true ) :
852				options;
853	
854			/*global oInit,_that,emptyInit*/
855			var i=0, iLen, j, jLen, k, kLen;
856			var sId = this.getAttribute( 'id' );
857			var bInitHandedOff = false;
858			var defaults = DataTable.defaults;
859			var $this = $(this);
860			
861			
862			/* Sanity check */
863			if ( this.nodeName.toLowerCase() != 'table' )
864			{
865				_fnLog( null, 0, 'Non-table node initialisation ('+this.nodeName+')', 2 );
866				return;
867			}
868			
869			/* Backwards compatibility for the defaults */
870			_fnCompatOpts( defaults );
871			_fnCompatCols( defaults.column );
872			
873			/* Convert the camel-case defaults to Hungarian */
874			_fnCamelToHungarian( defaults, defaults, true );
875			_fnCamelToHungarian( defaults.column, defaults.column, true );
876			
877			/* Setting up the initialisation object */
878			_fnCamelToHungarian( defaults, $.extend( oInit, $this.data() ), true );
879			
880			
881			
882			/* Check to see if we are re-initialising a table */
883			var allSettings = DataTable.settings;
884			for ( i=0, iLen=allSettings.length ; i<iLen ; i++ )
885			{
886				var s = allSettings[i];
887			
888				/* Base check on table node */
889				if (
890					s.nTable == this ||
891					(s.nTHead && s.nTHead.parentNode == this) ||
892					(s.nTFoot && s.nTFoot.parentNode == this)
893				) {
894					var bRetrieve = oInit.bRetrieve !== undefined ? oInit.bRetrieve : defaults.bRetrieve;
895					var bDestroy = oInit.bDestroy !== undefined ? oInit.bDestroy : defaults.bDestroy;
896			
897					if ( emptyInit || bRetrieve )
898					{
899						return s.oInstance;
900					}
901					else if ( bDestroy )
902					{
903						s.oInstance.fnDestroy();
904						break;
905					}
906					else
907					{
908						_fnLog( s, 0, 'Cannot reinitialise DataTable', 3 );
909						return;
910					}
911				}
912			
913				/* If the element we are initialising has the same ID as a table which was previously
914				 * initialised, but the table nodes don't match (from before) then we destroy the old
915				 * instance by simply deleting it. This is under the assumption that the table has been
916				 * destroyed by other methods. Anyone using non-id selectors will need to do this manually
917				 */
918				if ( s.sTableId == this.id )
919				{
920					allSettings.splice( i, 1 );
921					break;
922				}
923			}
924			
925			/* Ensure the table has an ID - required for accessibility */
926			if ( sId === null || sId === "" )
927			{
928				sId = "DataTables_Table_"+(DataTable.ext._unique++);
929				this.id = sId;
930			}
931			
932			/* Create the settings object for this table and set some of the default parameters */
933			var oSettings = $.extend( true, {}, DataTable.models.oSettings, {
934				"sDestroyWidth": $this[0].style.width,
935				"sInstance":     sId,
936				"sTableId":      sId
937			} );
938			oSettings.nTable = this;
939			oSettings.oApi   = _that.internal;
940			oSettings.oInit  = oInit;
941			
942			allSettings.push( oSettings );
943			
944			// Need to add the instance after the instance after the settings object has been added
945			// to the settings array, so we can self reference the table instance if more than one
946			oSettings.oInstance = (_that.length===1) ? _that : $this.dataTable();
947			
948			// Backwards compatibility, before we apply all the defaults
949			_fnCompatOpts( oInit );
950			_fnLanguageCompat( oInit.oLanguage );
951			
952			// If the length menu is given, but the init display length is not, use the length menu
953			if ( oInit.aLengthMenu && ! oInit.iDisplayLength )
954			{
955				oInit.iDisplayLength = Array.isArray( oInit.aLengthMenu[0] ) ?
956					oInit.aLengthMenu[0][0] : oInit.aLengthMenu[0];
957			}
958			
959			// Apply the defaults and init options to make a single init object will all
960			// options defined from defaults and instance options.
961			oInit = _fnExtend( $.extend( true, {}, defaults ), oInit );
962			
963			
964			// Map the initialisation options onto the settings object
965			_fnMap( oSettings.oFeatures, oInit, [
966				"bPaginate",
967				"bLengthChange",
968				"bFilter",
969				"bSort",
970				"bSortMulti",
971				"bInfo",
972				"bProcessing",
973				"bAutoWidth",
974				"bSortClasses",
975				"bServerSide",
976				"bDeferRender"
977			] );
978			_fnMap( oSettings, oInit, [
979				"asStripeClasses",
980				"ajax",
981				"fnServerData",
982				"fnFormatNumber",
983				"sServerMethod",
984				"aaSorting",
985				"aaSortingFixed",
986				"aLengthMenu",
987				"sPaginationType",
988				"sAjaxSource",
989				"sAjaxDataProp",
990				"iStateDuration",
991				"sDom",
992				"bSortCellsTop",
993				"iTabIndex",
994				"fnStateLoadCallback",
995				"fnStateSaveCallback",
996				"renderer",
997				"searchDelay",
998				"rowId",
999				[ "iCookieDuration", "iStateDuration" ], // backwards compat
1000				[ "oSearch", "oPreviousSearch" ],
1001				[ "aoSearchCols", "aoPreSearchCols" ],
1002				[ "iDisplayLength", "_iDisplayLength" ]
1003			] );
1004			_fnMap( oSettings.oScroll, oInit, [
1005				[ "sScrollX", "sX" ],
1006				[ "sScrollXInner", "sXInner" ],
1007				[ "sScrollY", "sY" ],
1008				[ "bScrollCollapse", "bCollapse" ]
1009			] );
1010			_fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" );
1011			
1012			/* Callback functions which are array driven */
1013			_fnCallbackReg( oSettings, 'aoDrawCallback',       oInit.fnDrawCallback,      'user' );
1014			_fnCallbackReg( oSettings, 'aoServerParams',       oInit.fnServerParams,      'user' );
1015			_fnCallbackReg( oSettings, 'aoStateSaveParams',    oInit.fnStateSaveParams,   'user' );
1016			_fnCallbackReg( oSettings, 'aoStateLoadParams',    oInit.fnStateLoadParams,   'user' );
1017			_fnCallbackReg( oSettings, 'aoStateLoaded',        oInit.fnStateLoaded,       'user' );
1018			_fnCallbackReg( oSettings, 'aoRowCallback',        oInit.fnRowCallback,       'user' );
1019			_fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow,        'user' );
1020			_fnCallbackReg( oSettings, 'aoHeaderCallback',     oInit.fnHeaderCallback,    'user' );
1021			_fnCallbackReg( oSettings, 'aoFooterCallback',     oInit.fnFooterCallback,    'user' );
1022			_fnCallbackReg( oSettings, 'aoInitComplete',       oInit.fnInitComplete,      'user' );
1023			_fnCallbackReg( oSettings, 'aoPreDrawCallback',    oInit.fnPreDrawCallback,   'user' );
1024			
1025			oSettings.rowIdFn = _fnGetObjectDataFn( oInit.rowId );
1026			
1027			/* Browser support detection */
1028			_fnBrowserDetect( oSettings );
1029			
1030			var oClasses = oSettings.oClasses;
1031			
1032			$.extend( oClasses, DataTable.ext.classes, oInit.oClasses );
1033			$this.addClass( oClasses.sTable );
1034			
1035			
1036			if ( oSettings.iInitDisplayStart === undefined )
1037			{
1038				/* Display start point, taking into account the save saving */
1039				oSettings.iInitDisplayStart = oInit.iDisplayStart;
1040				oSettings._iDisplayStart = oInit.iDisplayStart;
1041			}
1042			
1043			if ( oInit.iDeferLoading !== null )
1044			{
1045				oSettings.bDeferLoading = true;
1046				var tmp = Array.isArray( oInit.iDeferLoading );
1047				oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading;
1048				oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading;
1049			}
1050			
1051			/* Language definitions */
1052			var oLanguage = oSettings.oLanguage;
1053			$.extend( true, oLanguage, oInit.oLanguage );
1054			
1055			if ( oLanguage.sUrl )
1056			{
1057				/* Get the language definitions from a file - because this Ajax call makes the language
1058				 * get async to the remainder of this function we use bInitHandedOff to indicate that
1059				 * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor
1060				 */
1061				$.ajax( {
1062					dataType: 'json',
1063					url: oLanguage.sUrl,
1064					success: function ( json ) {
1065						_fnCamelToHungarian( defaults.oLanguage, json );
1066						_fnLanguageCompat( json );
1067						$.extend( true, oLanguage, json, oSettings.oInit.oLanguage );
1068			
1069						_fnCallbackFire( oSettings, null, 'i18n', [oSettings]);
1070						_fnInitialise( oSettings );
1071					},
1072					error: function () {
1073						// Error occurred loading language file, continue on as best we can
1074						_fnInitialise( oSettings );
1075					}
1076				} );
1077				bInitHandedOff = true;
1078			}
1079			else {
1080				_fnCallbackFire( oSettings, null, 'i18n', [oSettings]);
1081			}
1082			
1083			/*
1084			 * Stripes
1085			 */
1086			if ( oInit.asStripeClasses === null )
1087			{
1088				oSettings.asStripeClasses =[
1089					oClasses.sStripeOdd,
1090					oClasses.sStripeEven
1091				];
1092			}
1093			
1094			/* Remove row stripe classes if they are already on the table row */
1095			var stripeClasses = oSettings.asStripeClasses;
1096			var rowOne = $this.children('tbody').find('tr').eq(0);
1097			if ( $.inArray( true, $.map( stripeClasses, function(el, i) {
1098				return rowOne.hasClass(el);
1099			} ) ) !== -1 ) {
1100				$('tbody tr', this).removeClass( stripeClasses.join(' ') );
1101				oSettings.asDestroyStripes = stripeClasses.slice();
1102			}
1103			
1104			/*
1105			 * Columns
1106			 * See if we should load columns automatically or use defined ones
1107			 */
1108			var anThs = [];
1109			var aoColumnsInit;
1110			var nThead = this.getElementsByTagName('thead');
1111			if ( nThead.length !== 0 )
1112			{
1113				_fnDetectHeader( oSettings.aoHeader, nThead[0] );
1114				anThs = _fnGetUniqueThs( oSettings );
1115			}
1116			
1117			/* If not given a column array, generate one with nulls */
1118			if ( oInit.aoColumns === null )
1119			{
1120				aoColumnsInit = [];
1121				for ( i=0, iLen=anThs.length ; i<iLen ; i++ )
1122				{
1123					aoColumnsInit.push( null );
1124				}
1125			}
1126			else
1127			{
1128				aoColumnsInit = oInit.aoColumns;
1129			}
1130			
1131			/* Add the columns */
1132			for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ )
1133			{
1134				_fnAddColumn( oSettings, anThs ? anThs[i] : null );
1135			}
1136			
1137			/* Apply the column definitions */
1138			_fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) {
1139				_fnColumnOptions( oSettings, iCol, oDef );
1140			} );
1141			
1142			/* HTML5 attribute detection - build an mData object automatically if the
1143			 * attributes are found
1144			 */
1145			if ( rowOne.length ) {
1146				var a = function ( cell, name ) {
1147					return cell.getAttribute( 'data-'+name ) !== null ? name : null;
1148				};
1149			
1150				$( rowOne[0] ).children('th, td').each( function (i, cell) {
1151					var col = oSettings.aoColumns[i];
1152			
1153					if ( col.mData === i ) {
1154						var sort = a( cell, 'sort' ) || a( cell, 'order' );
1155						var filter = a( cell, 'filter' ) || a( cell, 'search' );
1156			
1157						if ( sort !== null || filter !== null ) {
1158							col.mData = {
1159								_:      i+'.display',
1160								sort:   sort !== null   ? i+'.@data-'+sort   : undefined,
1161								type:   sort !== null   ? i+'.@data-'+sort   : undefined,
1162								filter: filter !== null ? i+'.@data-'+filter : undefined
1163							};
1164			
1165							_fnColumnOptions( oSettings, i );
1166						}
1167					}
1168				} );
1169			}
1170			
1171			var features = oSettings.oFeatures;
1172			var loadedInit = function () {
1173				/*
1174				 * Sorting
1175				 * @todo For modularisation (1.11) this needs to do into a sort start up handler
1176				 */
1177			
1178				// If aaSorting is not defined, then we use the first indicator in asSorting
1179				// in case that has been altered, so the default sort reflects that option
1180				if ( oInit.aaSorting === undefined ) {
1181					var sorting = oSettings.aaSorting;
1182					for ( i=0, iLen=sorting.length ; i<iLen ; i++ ) {
1183						sorting[i][1] = oSettings.aoColumns[ i ].asSorting[0];
1184					}
1185				}
1186			
1187				/* Do a first pass on the sorting classes (allows any size changes to be taken into
1188				 * account, and also will apply sorting disabled classes if disabled
1189				 */
1190				_fnSortingClasses( oSettings );
1191			
1192				if ( features.bSort ) {
1193					_fnCallbackReg( oSettings, 'aoDrawCallback', function () {
1194						if ( oSettings.bSorted ) {
1195							var aSort = _fnSortFlatten( oSettings );
1196							var sortedColumns = {};
1197			
1198							$.each( aSort, function (i, val) {
1199								sortedColumns[ val.src ] = val.dir;
1200							} );
1201			
1202							_fnCallbackFire( oSettings, null, 'order', [oSettings, aSort, sortedColumns] );
1203							_fnSortAria( oSettings );
1204						}
1205					} );
1206				}
1207			
1208				_fnCallbackReg( oSettings, 'aoDrawCallback', function () {
1209					if ( oSettings.bSorted || _fnDataSource( oSettings ) === 'ssp' || features.bDeferRender ) {
1210						_fnSortingClasses( oSettings );
1211					}
1212				}, 'sc' );
1213			
1214			
1215				/*
1216				 * Final init
1217				 * Cache the header, body and footer as required, creating them if needed
1218				 */
1219			
1220				// Work around for Webkit bug 83867 - store the caption-side before removing from doc
1221				var captions = $this.children('caption').each( function () {
1222					this._captionSide = $(this).css('caption-side');
1223				} );
1224			
1225				var thead = $this.children('thead');
1226				if ( thead.length === 0 ) {
1227					thead = $('<thead/>').appendTo($this);
1228				}
1229				oSettings.nTHead = thead[0];
1230			
1231				var tbody = $this.children('tbody');
1232				if ( tbody.length === 0 ) {
1233					tbody = $('<tbody/>').insertAfter(thead);
1234				}
1235				oSettings.nTBody = tbody[0];
1236			
1237				var tfoot = $this.children('tfoot');
1238				if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") ) {
1239					// If we are a scrolling table, and no footer has been given, then we need to create
1240					// a tfoot element for the caption element to be appended to
1241					tfoot = $('<tfoot/>').appendTo($this);
1242				}
1243			
1244				if ( tfoot.length === 0 || tfoot.children().length === 0 ) {
1245					$this.addClass( oClasses.sNoFooter );
1246				}
1247				else if ( tfoot.length > 0 ) {
1248					oSettings.nTFoot = tfoot[0];
1249					_fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );
1250				}
1251			
1252				/* Check if there is data passing into the constructor */
1253				if ( oInit.aaData ) {
1254					for ( i=0 ; i<oInit.aaData.length ; i++ ) {
1255						_fnAddData( oSettings, oInit.aaData[ i ] );
1256					}
1257				}
1258				else if ( oSettings.bDeferLoading || _fnDataSource( oSettings ) == 'dom' ) {
1259					/* Grab the data from the page - only do this when deferred loading or no Ajax
1260					 * source since there is no point in reading the DOM data if we are then going
1261					 * to replace it with Ajax data
1262					 */
1263					_fnAddTr( oSettings, $(oSettings.nTBody).children('tr') );
1264				}
1265			
1266				/* Copy the data index array */
1267				oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
1268			
1269				/* Initialisation complete - table can be drawn */
1270				oSettings.bInitialised = true;
1271			
1272				/* Check if we need to initialise the table (it might not have been handed off to the
1273				 * language processor)
1274				 */
1275				if ( bInitHandedOff === false ) {
1276					_fnInitialise( oSettings );
1277				}
1278			};
1279			
1280			/* Must be done after everything which can be overridden by the state saving! */
1281			_fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' );
1282			
1283			if ( oInit.bStateSave )
1284			{
1285				features.bStateSave = true;
1286				_fnLoadState( oSettings, oInit, loadedInit );
1287			}
1288			else {
1289				loadedInit();
1290			}
1291			
1292		} );
1293		_that = null;
1294		return this;
1295	};
1296	
1297	
1298	/*
1299	 * It is useful to have variables which are scoped locally so only the
1300	 * DataTables functions can access them and they don't leak into global space.
1301	 * At the same time these functions are often useful over multiple files in the
1302	 * core and API, so we list, or at least document, all variables which are used
1303	 * by DataTables as private variables here. This also ensures that there is no
1304	 * clashing of variable names and that they can easily referenced for reuse.
1305	 */
1306	
1307	
1308	// Defined else where
1309	//  _selector_run
1310	//  _selector_opts
1311	//  _selector_first
1312	//  _selector_row_indexes
1313	
1314	var _ext; // DataTable.ext
1315	var _Api; // DataTable.Api
1316	var _api_register; // DataTable.Api.register
1317	var _api_registerPlural; // DataTable.Api.registerPlural
1318	
1319	var _re_dic = {};
1320	var _re_new_lines = /[\r\n\u2028]/g;
1321	var _re_html = /<.*?>/g;
1322	
1323	// This is not strict ISO8601 - Date.parse() is quite lax, although
1324	// implementations differ between browsers.
1325	var _re_date = /^\d{2,4}[\.\/\-]\d{1,2}[\.\/\-]\d{1,2}([T ]{1}\d{1,2}[:\.]\d{2}([\.:]\d{2})?)?$/;
1326	
1327	// Escape regular expression special characters
1328	var _re_escape_regex = new RegExp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' );
1329	
1330	// http://en.wikipedia.org/wiki/Foreign_exchange_market
1331	// - \u20BD - Russian ruble.
1332	// - \u20a9 - South Korean Won
1333	// - \u20BA - Turkish Lira
1334	// - \u20B9 - Indian Rupee
1335	// - R - Brazil (R$) and South Africa
1336	// - fr - Swiss Franc
1337	// - kr - Swedish krona, Norwegian krone and Danish krone
1338	// - \u2009 is thin space and \u202F is narrow no-break space, both used in many
1339	// - Ƀ - Bitcoin
1340	// - Ξ - Ethereum
1341	//   standards as thousands separators.
1342	var _re_formatted_numeric = /['\u00A0,$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfkɃΞ]/gi;
1343	
1344	
1345	var _empty = function ( d ) {
1346		return !d || d === true || d === '-' ? true : false;
1347	};
1348	
1349	
1350	var _intVal = function ( s ) {
1351		var integer = parseInt( s, 10 );
1352		return !isNaN(integer) && isFinite(s) ? integer : null;
1353	};
1354	
1355	// Convert from a formatted number with characters other than `.` as the
1356	// decimal place, to a Javascript number
1357	var _numToDecimal = function ( num, decimalPoint ) {
1358		// Cache created regular expressions for speed as this function is called often
1359		if ( ! _re_dic[ decimalPoint ] ) {
1360			_re_dic[ decimalPoint ] = new RegExp( _fnEscapeRegex( decimalPoint ), 'g' );
1361		}
1362		return typeof num === 'string' && decimalPoint !== '.' ?
1363			num.replace( /\./g, '' ).replace( _re_dic[ decimalPoint ], '.' ) :
1364			num;
1365	};
1366	
1367	
1368	var _isNumber = function ( d, decimalPoint, formatted ) {
1369		var strType = typeof d === 'string';
1370	
1371		// If empty return immediately so there must be a number if it is a
1372		// formatted string (this stops the string "k", or "kr", etc being detected
1373		// as a formatted number for currency
1374		if ( _empty( d ) ) {
1375			return true;
1376		}
1377	
1378		if ( decimalPoint && strType ) {
1379			d = _numToDecimal( d, decimalPoint );
1380		}
1381	
1382		if ( formatted && strType ) {
1383			d = d.replace( _re_formatted_numeric, '' );
1384		}
1385	
1386		return !isNaN( parseFloat(d) ) && isFinite( d );
1387	};
1388	
1389	
1390	// A string without HTML in it can be considered to be HTML still
1391	var _isHtml = function ( d ) {
1392		return _empty( d ) || typeof d === 'string';
1393	};
1394	
1395	
1396	var _htmlNumeric = function ( d, decimalPoint, formatted ) {
1397		if ( _empty( d ) ) {
1398			return true;
1399		}
1400	
1401		var html = _isHtml( d );
1402		return ! html ?
1403			null :
1404			_isNumber( _stripHtml( d ), decimalPoint, formatted ) ?
1405				true :
1406				null;
1407	};
1408	
1409	
1410	var _pluck = function ( a, prop, prop2 ) {
1411		var out = [];
1412		var i=0, ien=a.length;
1413	
1414		// Could have the test in the loop for slightly smaller code, but speed
1415		// is essential here
1416		if ( prop2 !== undefined ) {
1417			for ( ; i<ien ; i++ ) {
1418				if ( a[i] && a[i][ prop ] ) {
1419					out.push( a[i][ prop ][ prop2 ] );
1420				}
1421			}
1422		}
1423		else {
1424			for ( ; i<ien ; i++ ) {
1425				if ( a[i] ) {
1426					out.push( a[i][ prop ] );
1427				}
1428			}
1429		}
1430	
1431		return out;
1432	};
1433	
1434	
1435	// Basically the same as _pluck, but rather than looping over `a` we use `order`
1436	// as the indexes to pick from `a`
1437	var _pluck_order = function ( a, order, prop, prop2 )
1438	{
1439		var out = [];
1440		var i=0, ien=order.length;
1441	
1442		// Could have the test in the loop for slightly smaller code, but speed
1443		// is essential here
1444		if ( prop2 !== undefined ) {
1445			for ( ; i<ien ; i++ ) {
1446				if ( a[ order[i] ][ prop ] ) {
1447					out.push( a[ order[i] ][ prop ][ prop2 ] );
1448				}
1449			}
1450		}
1451		else {
1452			for ( ; i<ien ; i++ ) {
1453				out.push( a[ order[i] ][ prop ] );
1454			}
1455		}
1456	
1457		return out;
1458	};
1459	
1460	
1461	var _range = function ( len, start )
1462	{
1463		var out = [];
1464		var end;
1465	
1466		if ( start === undefined ) {
1467			start = 0;
1468			end = len;
1469		}
1470		else {
1471			end = start;
1472			start = len;
1473		}
1474	
1475		for ( var i=start ; i<end ; i++ ) {
1476			out.push( i );
1477		}
1478	
1479		return out;
1480	};
1481	
1482	
1483	var _removeEmpty = function ( a )
1484	{
1485		var out = [];
1486	
1487		for ( var i=0, ien=a.length ; i<ien ; i++ ) {
1488			if ( a[i] ) { // careful - will remove all falsy values!
1489				out.push( a[i] );
1490			}
1491		}
1492	
1493		return out;
1494	};
1495	
1496	
1497	var _stripHtml = function ( d ) {
1498		return d.replace( _re_html, '' );
1499	};
1500	
1501	
1502	/**
1503	 * Determine if all values in the array are unique. This means we can short
1504	 * cut the _unique method at the cost of a single loop. A sorted array is used
1505	 * to easily check the values.
1506	 *
1507	 * @param  {array} src Source array
1508	 * @return {boolean} true if all unique, false otherwise
1509	 * @ignore
1510	 */
1511	var _areAllUnique = function ( src ) {
1512		if ( src.length < 2 ) {
1513			return true;
1514		}
1515	
1516		var sorted = src.slice().sort();
1517		var last = sorted[0];
1518	
1519		for ( var i=1, ien=sorted.length ; i<ien ; i++ ) {
1520			if ( sorted[i] === last ) {
1521				return false;
1522			}
1523	
1524			last = sorted[i];
1525		}
1526	
1527		return true;
1528	};
1529	
1530	
1531	/**
1532	 * Find the unique elements in a source array.
1533	 *
1534	 * @param  {array} src Source array
1535	 * @return {array} Array of unique items
1536	 * @ignore
1537	 */
1538	var _unique = function ( src )
1539	{
1540		if ( _areAllUnique( src ) ) {
1541			return src.slice();
1542		}
1543	
1544		// A faster unique method is to use object keys to identify used values,
1545		// but this doesn't work with arrays or objects, which we must also
1546		// consider. See jsperf.com/compare-array-unique-versions/4 for more
1547		// information.
1548		var
1549			out = [],
1550			val,
1551			i, ien=src.length,
1552			j, k=0;
1553	
1554		again: for ( i=0 ; i<ien ; i++ ) {
1555			val = src[i];
1556	
1557			for ( j=0 ; j<k ; j++ ) {
1558				if ( out[j] === val ) {
1559					continue again;
1560				}
1561			}
1562	
1563			out.push( val );
1564			k++;
1565		}
1566	
1567		return out;
1568	};
1569	
1570	// Surprisingly this is faster than [].concat.apply
1571	// https://jsperf.com/flatten-an-array-loop-vs-reduce/2
1572	var _flatten = function (out, val) {
1573		if (Array.isArray(val)) {
1574			for (var i=0 ; i<val.length ; i++) {
1575				_flatten(out, val[i]);
1576			}
1577		}
1578		else {
1579			out.push(val);
1580		}
1581	  
1582		return out;
1583	}
1584	
1585	var _includes = function (search, start) {
1586		if (start === undefined) {
1587			start = 0;
1588		}
1589	
1590		return this.indexOf(search, start) !== -1;	
1591	};
1592	
1593	// Array.isArray polyfill.
1594	// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
1595	if (! Array.isArray) {
1596	    Array.isArray = function(arg) {
1597	        return Object.prototype.toString.call(arg) === '[object Array]';
1598	    };
1599	}
1600	
1601	if (! Array.prototype.includes) {
1602		Array.prototype.includes = _includes;
1603	}
1604	
1605	// .trim() polyfill
1606	// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trim
1607	if (!String.prototype.trim) {
1608	  String.prototype.trim = function () {
1609	    return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
1610	  };
1611	}
1612	
1613	if (! String.prototype.includes) {
1614		String.prototype.includes = _includes;
1615	}
1616	
1617	/**
1618	 * DataTables utility methods
1619	 * 
1620	 * This namespace provides helper methods that DataTables uses internally to
1621	 * create a DataTable, but which are not exclusively used only for DataTables.
1622	 * These methods can be used by extension authors to save the duplication of
1623	 * code.
1624	 *
1625	 *  @namespace
1626	 */
1627	DataTable.util = {
1628		/**
1629		 * Throttle the calls to a function. Arguments and context are maintained
1630		 * for the throttled function.
1631		 *
1632		 * @param {function} fn Function to be called
1633		 * @param {integer} freq Call frequency in mS
1634		 * @return {function} Wrapped function
1635		 */
1636		throttle: function ( fn, freq ) {
1637			var
1638				frequency = freq !== undefined ? freq : 200,
1639				last,
1640				timer;
1641	
1642			return function () {
1643				var
1644					that = this,
1645					now  = +new Date(),
1646					args = arguments;
1647	
1648				if ( last && now < last + frequency ) {
1649					clearTimeout( timer );
1650	
1651					timer = setTimeout( function () {
1652						last = undefined;
1653						fn.apply( that, args );
1654					}, frequency );
1655				}
1656				else {
1657					last = now;
1658					fn.apply( that, args );
1659				}
1660			};
1661		},
1662	
1663	
1664		/**
1665		 * Escape a string such that it can be used in a regular expression
1666		 *
1667		 *  @param {string} val string to escape
1668		 *  @returns {string} escaped string
1669		 */
1670		escapeRegex: function ( val ) {
1671			return val.replace( _re_escape_regex, '\\$1' );
1672		},
1673	
1674		/**
1675		 * Create a function that will write to a nested object or array
1676		 * @param {*} source JSON notation string
1677		 * @returns Write function
1678		 */
1679		set: function ( source ) {
1680			if ( $.isPlainObject( source ) ) {
1681				/* Unlike get, only the underscore (global) option is used for for
1682				 * setting data since we don't know the type here. This is why an object
1683				 * option is not documented for `mData` (which is read/write), but it is
1684				 * for `mRender` which is read only.
1685				 */
1686				return DataTable.util.set( source._ );
1687			}
1688			else if ( source === null ) {
1689				// Nothing to do when the data source is null
1690				return function () {};
1691			}
1692			else if ( typeof source === 'function' ) {
1693				return function (data, val, meta) {
1694					source( data, 'set', val, meta );
1695				};
1696			}
1697			else if ( typeof source === 'string' && (source.indexOf('.') !== -1 ||
1698					  source.indexOf('[') !== -1 || source.indexOf('(') !== -1) )
1699			{
1700				// Like the get, we need to get data from a nested object
1701				var setData = function (data, val, src) {
1702					var a = _fnSplitObjNotation( src ), b;
1703					var aLast = a[a.length-1];
1704					var arrayNotation, funcNotation, o, innerSrc;
1705		
1706					for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ ) {
1707						// Protect against prototype pollution
1708						if (a[i] === '__proto__' || a[i] === 'constructor') {
1709							throw new Error('Cannot set prototype values');
1710						}
1711		
1712						// Check if we are dealing with an array notation request
1713						arrayNotation = a[i].match(__reArray);
1714						funcNotation = a[i].match(__reFn);
1715		
1716						if ( arrayNotation ) {
1717							a[i] = a[i].replace(__reArray, '');
1718							data[ a[i] ] = [];
1719		
1720							// Get the remainder of the nested object to set so we can recurse
1721							b = a.slice();
1722							b.splice( 0, i+1 );
1723							innerSrc = b.join('.');
1724		
1725							// Traverse each entry in the array setting the properties requested
1726							if ( Array.isArray( val ) ) {
1727								for ( var j=0, jLen=val.length ; j<jLen ; j++ ) {
1728									o = {};
1729									setData( o, val[j], innerSrc );
1730									data[ a[i] ].push( o );
1731								}
1732							}
1733							else {
1734								// We've been asked to save data to an array, but it
1735								// isn't array data to be saved. Best that can be done
1736								// is to just save the value.
1737								data[ a[i] ] = val;
1738							}
1739		
1740							// The inner call to setData has already traversed through the remainder
1741							// of the source and has set the data, thus we can exit here
1742							return;
1743						}
1744						else if ( funcNotation ) {
1745							// Function call
1746							a[i] = a[i].replace(__reFn, '');
1747							data = data[ a[i] ]( val );
1748						}
1749		
1750						// If the nested object doesn't currently exist - since we are
1751						// trying to set the value - create it
1752						if ( data[ a[i] ] === null || data[ a[i] ] === undefined ) {
1753							data[ a[i] ] = {};
1754						}
1755						data = data[ a[i] ];
1756					}
1757		
1758					// Last item in the input - i.e, the actual set
1759					if ( aLast.match(__reFn ) ) {
1760						// Function call
1761						data = data[ aLast.replace(__reFn, '') ]( val );
1762					}
1763					else {
1764						// If array notation is used, we just want to strip it and use the property name
1765						// and assign the value. If it isn't used, then we get the result we want anyway
1766						data[ aLast.replace(__reArray, '') ] = val;
1767					}
1768				};
1769		
1770				return function (data, val) { // meta is also passed in, but not used
1771					return setData( data, val, source );
1772				};
1773			}
1774			else {
1775				// Array or flat object mapping
1776				return function (data, val) { // meta is also passed in, but not used
1777					data[source] = val;
1778				};
1779			}
1780		},
1781	
1782		/**
1783		 * Create a function that will read nested objects from arrays, based on JSON notation
1784		 * @param {*} source JSON notation string
1785		 * @returns Value read
1786		 */
1787		get: function ( source ) {
1788			if ( $.isPlainObject( source ) ) {
1789				// Build an object of get functions, and wrap them in a single call
1790				var o = {};
1791				$.each( source, function (key, val) {
1792					if ( val ) {
1793						o[key] = DataTable.util.get( val );
1794					}
1795				} );
1796		
1797				return function (data, type, row, meta) {
1798					var t = o[type] || o._;
1799					return t !== undefined ?
1800						t(data, type, row, meta) :
1801						data;
1802				};
1803			}
1804			else if ( source === null ) {
1805				// Give an empty string for rendering / sorting etc
1806				return function (data) { // type, row and meta also passed, but not used
1807					return data;
1808				};
1809			}
1810			else if ( typeof source === 'function' ) {
1811				return function (data, type, row, meta) {
1812					return source( data, type, row, meta );
1813				};
1814			}
1815			else if ( typeof source === 'string' && (source.indexOf('.') !== -1 ||
1816					  source.indexOf('[') !== -1 || source.indexOf('(') !== -1) )
1817			{
1818				/* If there is a . in the source string then the data source is in a
1819				 * nested object so we loop over the data for each level to get the next
1820				 * level down. On each loop we test for undefined, and if found immediately
1821				 * return. This allows entire objects to be missing and sDefaultContent to
1822				 * be used if defined, rather than throwing an error
1823				 */
1824				var fetchData = function (data, type, src) {
1825					var arrayNotation, funcNotation, out, innerSrc;
1826		
1827					if ( src !== "" ) {
1828						var a = _fnSplitObjNotation( src );
1829		
1830						for ( var i=0, iLen=a.length ; i<iLen ; i++ ) {
1831							// Check if we are dealing with special notation
1832							arrayNotation = a[i].match(__reArray);
1833							funcNotation = a[i].match(__reFn);
1834		
1835							if ( arrayNotation ) {
1836								// Array notation
1837								a[i] = a[i].replace(__reArray, '');
1838		
1839								// Condition allows simply [] to be passed in
1840								if ( a[i] !== "" ) {
1841									data = data[ a[i] ];
1842								}
1843								out = [];
1844		
1845								// Get the remainder of the nested object to get
1846								a.splice( 0, i+1 );
1847								innerSrc = a.join('.');
1848		
1849								// Traverse each entry in the array getting the properties requested
1850								if ( Array.isArray( data ) ) {
1851									for ( var j=0, jLen=data.length ; j<jLen ; j++ ) {
1852										out.push( fetchData( data[j], type, innerSrc ) );
1853									}
1854								}
1855		
1856								// If a string is given in between the array notation indicators, that
1857								// is used to join the strings together, otherwise an array is returned
1858								var join = arrayNotation[0].substring(1, arrayNotation[0].length-1);
1859								data = (join==="") ? out : out.join(join);
1860		
1861								// The inner call to fetchData has already traversed through the remainder
1862								// of the source requested, so we exit from the loop
1863								break;
1864							}
1865							else if ( funcNotation ) {
1866								// Function call
1867								a[i] = a[i].replace(__reFn, '');
1868								data = data[ a[i] ]();
1869								continue;
1870							}
1871		
1872							if ( data === null || data[ a[i] ] === undefined ) {
1873								return undefined;
1874							}
1875	
1876							data = data[ a[i] ];
1877						}
1878					}
1879		
1880					return data;
1881				};
1882		
1883				return function (data, type) { // row and meta also passed, but not used
1884					return fetchData( data, type, source );
1885				};
1886			}
1887			else {
1888				// Array or flat object mapping
1889				return function (data, type) { // row and meta also passed, but not used
1890					return data[source];
1891				};
1892			}
1893		}
1894	};
1895	
1896	
1897	
1898	/**
1899	 * Create a mapping object that allows camel case parameters to be looked up
1900	 * for their Hungarian counterparts. The mapping is stored in a private
1901	 * parameter called `_hungarianMap` which can be accessed on the source object.
1902	 *  @param {object} o
1903	 *  @memberof DataTable#oApi
1904	 */
1905	function _fnHungarianMap ( o )
1906	{
1907		var
1908			hungarian = 'a aa ai ao as b fn i m o s ',
1909			match,
1910			newKey,
1911			map = {};
1912	
1913		$.each( o, function (key, val) {
1914			match = key.match(/^([^A-Z]+?)([A-Z])/);
1915	
1916			if ( match && hungarian.indexOf(match[1]+' ') !== -1 )
1917			{
1918				newKey = key.replace( match[0], match[2].toLowerCase() );
1919				map[ newKey ] = key;
1920	
1921				if ( match[1] === 'o' )
1922				{
1923					_fnHungarianMap( o[key] );
1924				}
1925			}
1926		} );
1927	
1928		o._hungarianMap = map;
1929	}
1930	
1931	
1932	/**
1933	 * Convert from camel case parameters to Hungarian, based on a Hungarian map
1934	 * created by _fnHungarianMap.
1935	 *  @param {object} src The model object which holds all parameters that can be
1936	 *    mapped.
1937	 *  @param {object} user The object to convert from camel case to Hungarian.
1938	 *  @param {boolean} force When set to `true`, properties which already have a
1939	 *    Hungarian value in the `user` object will be overwritten. Otherwise they
1940	 *    won't be.
1941	 *  @memberof DataTable#oApi
1942	 */
1943	function _fnCamelToHungarian ( src, user, force )
1944	{
1945		if ( ! src._hungarianMap ) {
1946			_fnHungarianMap( src );
1947		}
1948	
1949		var hungarianKey;
1950	
1951		$.each( user, function (key, val) {
1952			hungarianKey = src._hungarianMap[ key ];
1953	
1954			if ( hungarianKey !== undefined && (force || user[hungarianKey] === undefined) )
1955			{
1956				// For objects, we need to buzz down into the object to copy parameters
1957				if ( hungarianKey.charAt(0) === 'o' )
1958				{
1959					// Copy the camelCase options over to the hungarian
1960					if ( ! user[ hungarianKey ] ) {
1961						user[ hungarianKey ] = {};
1962					}
1963					$.extend( true, user[hungarianKey], user[key] );
1964	
1965					_fnCamelToHungarian( src[hungarianKey], user[hungarianKey], force );
1966				}
1967				else {
1968					user[hungarianKey] = user[ key ];
1969				}
1970			}
1971		} );
1972	}
1973	
1974	
1975	/**
1976	 * Language compatibility - when certain options are given, and others aren't, we
1977	 * need to duplicate the values over, in order to provide backwards compatibility
1978	 * with older language files.
1979	 *  @param {object} oSettings dataTables settings object
1980	 *  @memberof DataTable#oApi
1981	 */
1982	function _fnLanguageCompat( lang )
1983	{
1984		// Note the use of the Hungarian notation for the parameters in this method as
1985		// this is called after the mapping of camelCase to Hungarian
1986		var defaults = DataTable.defaults.oLanguage;
1987	
1988		// Default mapping
1989		var defaultDecimal = defaults.sDecimal;
1990		if ( defaultDecimal ) {
1991			_addNumericSort( defaultDecimal );
1992		}
1993	
1994		if ( lang ) {
1995			var zeroRecords = lang.sZeroRecords;
1996	
1997			// Backwards compatibility - if there is no sEmptyTable given, then use the same as
1998			// sZeroRecords - assuming that is given.
1999			if ( ! lang.sEmptyTable && zeroRecords &&
2000				defaults.sEmptyTable === "No data available in table" )
2001			{
2002				_fnMap( lang, lang, 'sZeroRecords', 'sEmptyTable' );
2003			}
2004	
2005			// Likewise with loading records
2006			if ( ! lang.sLoadingRecords && zeroRecords &&
2007				defaults.sLoadingRecords === "Loading..." )
2008			{
2009				_fnMap( lang, lang, 'sZeroRecords', 'sLoadingRecords' );
2010			}
2011	
2012			// Old parameter name of the thousands separator mapped onto the new
2013			if ( lang.sInfoThousands ) {
2014				lang.sThousands = lang.sInfoThousands;
2015			}
2016	
2017			var decimal = lang.sDecimal;
2018			if ( decimal && defaultDecimal !== decimal ) {
2019				_addNumericSort( decimal );
2020			}
2021		}
2022	}
2023	
2024	
2025	/**
2026	 * Map one parameter onto another
2027	 *  @param {object} o Object to map
2028	 *  @param {*} knew The new parameter name
2029	 *  @param {*} old The old parameter name
2030	 */
2031	var _fnCompatMap = function ( o, knew, old ) {
2032		if ( o[ knew ] !== undefined ) {
2033			o[ old ] = o[ knew ];
2034		}
2035	};
2036	
2037	
2038	/**
2039	 * Provide backwards compatibility for the main DT options. Note that the new
2040	 * options are mapped onto the old parameters, so this is an external interface
2041	 * change only.
2042	 *  @param {object} init Object to map
2043	 */
2044	function _fnCompatOpts ( init )
2045	{
2046		_fnCompatMap( init, 'ordering',      'bSort' );
2047		_fnCompatMap( init, 'orderMulti',    'bSortMulti' );
2048		_fnCompatMap( init, 'orderClasses',  'bSortClasses' );
2049		_fnCompatMap( init, 'orderCellsTop', 'bSortCellsTop' );
2050		_fnCompatMap( init, 'order',         'aaSorting' );
2051		_fnCompatMap( init, 'orderFixed',    'aaSortingFixed' );
2052		_fnCompatMap( init, 'paging',        'bPaginate' );
2053		_fnCompatMap( init, 'pagingType',    'sPaginationType' );
2054		_fnCompatMap( init, 'pageLength',    'iDisplayLength' );
2055		_fnCompatMap( init, 'searching',     'bFilter' );
2056	
2057		// Boolean initialisation of x-scrolling
2058		if ( typeof init.sScrollX === 'boolean' ) {
2059			init.sScrollX = init.sScrollX ? '100%' : '';
2060		}
2061		if ( typeof init.scrollX === 'boolean' ) {
2062			init.scrollX = init.scrollX ? '100%' : '';
2063		}
2064	
2065		// Column search objects are in an array, so it needs to be converted
2066		// element by element
2067		var searchCols = init.aoSearchCols;
2068	
2069		if ( searchCols ) {
2070			for ( var i=0, ien=searchCols.length ; i<ien ; i++ ) {
2071				if ( searchCols[i] ) {
2072					_fnCamelToHungarian( DataTable.models.oSearch, searchCols[i] );
2073				}
2074			}
2075		}
2076	}
2077	
2078	
2079	/**
2080	 * Provide backwards compatibility for column options. Note that the new options
2081	 * are mapped onto the old parameters, so this is an external interface change
2082	 * only.
2083	 *  @param {object} init Object to map
2084	 */
2085	function _fnCompatCols ( init )
2086	{
2087		_fnCompatMap( init, 'orderable',     'bSortable' );
2088		_fnCompatMap( init, 'orderData',     'aDataSort' );
2089		_fnCompatMap( init, 'orderSequence', 'asSorting' );
2090		_fnCompatMap( init, 'orderDataType', 'sortDataType' );
2091	
2092		// orderData can be given as an integer
2093		var dataSort = init.aDataSort;
2094		if ( typeof dataSort === 'number' && ! Array.isArray( dataSort ) ) {
2095			init.aDataSort = [ dataSort ];
2096		}
2097	}
2098	
2099	
2100	/**
2101	 * Browser feature detection for capabilities, quirks
2102	 *  @param {object} settings dataTables settings object
2103	 *  @memberof DataTable#oApi
2104	 */
2105	function _fnBrowserDetect( settings )
2106	{
2107		// We don't need to do this every time DataTables is constructed, the values
2108		// calculated are specific to the browser and OS configuration which we
2109		// don't expect to change between initialisations
2110		if ( ! DataTable.__browser ) {
2111			var browser = {};
2112			DataTable.__browser = browser;
2113	
2114			// Scrolling feature / quirks detection
2115			var n = $('<div/>')
2116				.css( {
2117					position: 'fixed',
2118					top: 0,
2119					left: $(window).scrollLeft()*-1, // allow for scrolling
2120					height: 1,
2121					width: 1,
2122					overflow: 'hidden'
2123				} )
2124				.append(
2125					$('<div/>')
2126						.css( {
2127							position: 'absolute',
2128							top: 1,
2129							left: 1,
2130							width: 100,
2131							overflow: 'scroll'
2132						} )
2133						.append(
2134							$('<div/>')
2135								.css( {
2136									width: '100%',
2137									height: 10
2138								} )
2139						)
2140				)
2141				.appendTo( 'body' );
2142	
2143			var outer = n.children();
2144			var inner = outer.children();
2145	
2146			// Numbers below, in order, are:
2147			// inner.offsetWidth, inner.clientWidth, outer.offsetWidth, outer.clientWidth
2148			//
2149			// IE6 XP:                           100 100 100  83
2150			// IE7 Vista:                        100 100 100  83
2151			// IE 8+ Windows:                     83  83 100  83
2152			// Evergreen Windows:                 83  83 100  83
2153			// Evergreen Mac with scrollbars:     85  85 100  85
2154			// Evergreen Mac without scrollbars: 100 100 100 100
2155	
2156			// Get scrollbar width
2157			browser.barWidth = outer[0].offsetWidth - outer[0].clientWidth;
2158	
2159			// IE6/7 will oversize a width 100% element inside a scrolling element, to
2160			// include the width of the scrollbar, while other browsers ensure the inner
2161			// element is contained without forcing scrolling
2162			browser.bScrollOversize = inner[0].offsetWidth === 100 && outer[0].clientWidth !== 100;
2163	
2164			// In rtl text layout, some browsers (most, but not all) will place the
2165			// scrollbar on the left, rather than the right.
2166			browser.bScrollbarLeft = Math.round( inner.offset().left ) !== 1;
2167	
2168			// IE8- don't provide height and width for getBoundingClientRect
2169			browser.bBounding = n[0].getBoundingClientRect().width ? true : false;
2170	
2171			n.remove();
2172		}
2173	
2174		$.extend( settings.oBrowser, DataTable.__browser );
2175		settings.oScroll.iBarWidth = DataTable.__browser.barWidth;
2176	}
2177	
2178	
2179	/**
2180	 * Array.prototype reduce[Right] method, used for browsers which don't support
2181	 * JS 1.6. Done this way to reduce code size, since we iterate either way
2182	 *  @param {object} settings dataTables settings object
2183	 *  @memberof DataTable#oApi
2184	 */
2185	function _fnReduce ( that, fn, init, start, end, inc )
2186	{
2187		var
2188			i = start,
2189			value,
2190			isSet = false;
2191	
2192		if ( init !== undefined ) {
2193			value = init;
2194			isSet = true;
2195		}
2196	
2197		while ( i !== end ) {
2198			if ( ! that.hasOwnProperty(i) ) {
2199				continue;
2200			}
2201	
2202			value = isSet ?
2203				fn( value, that[i], i, that ) :
2204				that[i];
2205	
2206			isSet = true;
2207			i += inc;
2208		}
2209	
2210		return value;
2211	}
2212	
2213	/**
2214	 * Add a column to the list used for the table with default values
2215	 *  @param {object} oSettings dataTables settings object
2216	 *  @param {node} nTh The th element for this column
2217	 *  @memberof DataTable#oApi
2218	 */
2219	function _fnAddColumn( oSettings, nTh )
2220	{
2221		// Add column to aoColumns array
2222		var oDefaults = DataTable.defaults.column;
2223		var iCol = oSettings.aoColumns.length;
2224		var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {
2225			"nTh": nTh ? nTh : document.createElement('th'),
2226			"sTitle":    oDefaults.sTitle    ? oDefaults.sTitle    : nTh ? nTh.innerHTML : '',
2227			"aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],
2228			"mData": oDefaults.mData ? oDefaults.mData : iCol,
2229			idx: iCol
2230		} );
2231		oSettings.aoColumns.push( oCol );
2232	
2233		// Add search object for column specific search. Note that the `searchCols[ iCol ]`
2234		// passed into extend can be undefined. This allows the user to give a default
2235		// with only some of the parameters defined, and also not give a default
2236		var searchCols = oSettings.aoPreSearchCols;
2237		searchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] );
2238	
2239		// Use the default column options function to initialise classes etc
2240		_fnColumnOptions( oSettings, iCol, $(nTh).data() );
2241	}
2242	
2243	
2244	/**
2245	 * Apply options for a column
2246	 *  @param {object} oSettings dataTables settings object
2247	 *  @param {int} iCol column index to consider
2248	 *  @param {object} oOptions object with sType, bVisible and bSearchable etc
2249	 *  @memberof DataTable#oApi
2250	 */
2251	function _fnColumnOptions( oSettings, iCol, oOptions )
2252	{
2253		var oCol = oSettings.aoColumns[ iCol ];
2254		var oClasses = oSettings.oClasses;
2255		var th = $(oCol.nTh);
2256	
2257		// Try to get width information from the DOM. We can't get it from CSS
2258		// as we'd need to parse the CSS stylesheet. `width` option can override
2259		if ( ! oCol.sWidthOrig ) {
2260			// Width attribute
2261			oCol.sWidthOrig = th.attr('width') || null;
2262	
2263			// Style attribute
2264			var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/);
2265			if ( t ) {
2266				oCol.sWidthOrig = t[1];
2267			}
2268		}
2269	
2270		/* User specified column options */
2271		if ( oOptions !== undefined && oOptions !== null )
2272		{
2273			// Backwards compatibility
2274			_fnCompatCols( oOptions );
2275	
2276			// Map camel case parameters to their Hungarian counterparts
2277			_fnCamelToHungarian( DataTable.defaults.column, oOptions, true );
2278	
2279			/* Backwards compatibility for mDataProp */
2280			if ( oOptions.mDataProp !== undefined && !oOptions.mData )
2281			{
2282				oOptions.mData = oOptions.mDataProp;
2283			}
2284	
2285			if ( oOptions.sType )
2286			{
2287				oCol._sManualType = oOptions.sType;
2288			}
2289	
2290			// `class` is a reserved word in Javascript, so we need to provide
2291			// the ability to use a valid name for the camel case input
2292			if ( oOptions.className && ! oOptions.sClass )
2293			{
2294				oOptions.sClass = oOptions.className;
2295			}
2296			if ( oOptions.sClass ) {
2297				th.addClass( oOptions.sClass );
2298			}
2299	
2300			var origClass = oCol.sClass;
2301	
2302			$.extend( oCol, oOptions );
2303			_fnMap( oCol, oOptions, "sWidth", "sWidthOrig" );
2304	
2305			// Merge class from previously defined classes with this one, rather than just
2306			// overwriting it in the extend above
2307			if (origClass !== oCol.sClass) {
2308				oCol.sClass = origClass + ' ' + oCol.sClass;
2309			}
2310	
2311			/* iDataSort to be applied (backwards compatibility), but aDataSort will take
2312			 * priority if defined
2313			 */
2314			if ( oOptions.iDataSort !== undefined )
2315			{
2316				oCol.aDataSort = [ oOptions.iDataSort ];
2317			}
2318			_fnMap( oCol, oOptions, "aDataSort" );
2319		}
2320	
2321		/* Cache the data get and set functions for speed */
2322		var mDataSrc = oCol.mData;
2323		var mData = _fnGetObjectDataFn( mDataSrc );
2324		var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null;
2325	
2326		var attrTest = function( src ) {
2327			return typeof src === 'string' && src.indexOf('@') !== -1;
2328		};
2329		oCol._bAttrSrc = $.isPlainObject( mDataSrc ) && (
2330			attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter)
2331		);
2332		oCol._setter = null;
2333	
2334		oCol.fnGetData = function (rowData, type, meta) {
2335			var innerData = mData( rowData, type, undefined, meta );
2336	
2337			return mRender && type ?
2338				mRender( innerData, type, rowData, meta ) :
2339				innerData;
2340		};
2341		oCol.fnSetData = function ( rowData, val, meta ) {
2342			return _fnSetObjectDataFn( mDataSrc )( rowData, val, meta );
2343		};
2344	
2345		// Indicate if DataTables should read DOM data as an object or array
2346		// Used in _fnGetRowElements
2347		if ( typeof mDataSrc !== 'number' ) {
2348			oSettings._rowReadObject = true;
2349		}
2350	
2351		/* Feature sorting overrides column specific when off */
2352		if ( !oSettings.oFeatures.bSort )
2353		{
2354			oCol.bSortable = false;
2355			th.addClass( oClasses.sSortableNone ); // Have to add class here as order event isn't called
2356		}
2357	
2358		/* Check that the class assignment is correct for sorting */
2359		var bAsc = $.inArray('asc', oCol.asSorting) !== -1;
2360		var bDesc = $.inArray('desc', oCol.asSorting) !== -1;
2361		if ( !oCol.bSortable || (!bAsc && !bDesc) )
2362		{
2363			oCol.sSortingClass = oClasses.sSortableNone;
2364			oCol.sSortingClassJUI = "";
2365		}
2366		else if ( bAsc && !bDesc )
2367		{
2368			oCol.sSortingClass = oClasses.sSortableAsc;
2369			oCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed;
2370		}
2371		else if ( !bAsc && bDesc )
2372		{
2373			oCol.sSortingClass = oClasses.sSortableDesc;
2374			oCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed;
2375		}
2376		else
2377		{
2378			oCol.sSortingClass = oClasses.sSortable;
2379			oCol.sSortingClassJUI = oClasses.sSortJUI;
2380		}
2381	}
2382	
2383	
2384	/**
2385	 * Adjust the table column widths for new data. Note: you would probably want to
2386	 * do a redraw after calling this function!
2387	 *  @param {object} settings dataTables settings object
2388	 *  @memberof DataTable#oApi
2389	 */
2390	function _fnAdjustColumnSizing ( settings )
2391	{
2392		/* Not interested in doing column width calculation if auto-width is disabled */
2393		if ( settings.oFeatures.bAutoWidth !== false )
2394		{
2395			var columns = settings.aoColumns;
2396	
2397			_fnCalculateColumnWidths( settings );
2398			for ( var i=0 , iLen=columns.length ; i<iLen ; i++ )
2399			{
2400				columns[i].nTh.style.width = columns[i].sWidth;
2401			}
2402		}
2403	
2404		var scroll = settings.oScroll;
2405		if ( scroll.sY !== '' || scroll.sX !== '')
2406		{
2407			_fnScrollDraw( settings );
2408		}
2409	
2410		_fnCallbackFire( settings, null, 'column-sizing', [settings] );
2411	}
2412	
2413	
2414	/**
2415	 * Convert the index of a visible column to the index in the data array (take account
2416	 * of hidden columns)
2417	 *  @param {object} oSettings dataTables settings object
2418	 *  @param {int} iMatch Visible column index to lookup
2419	 *  @returns {int} i the data index
2420	 *  @memberof DataTable#oApi
2421	 */
2422	function _fnVisibleToColumnIndex( oSettings, iMatch )
2423	{
2424		var aiVis = _fnGetColumns( oSettings, 'bVisible' );
2425	
2426		return typeof aiVis[iMatch] === 'number' ?
2427			aiVis[iMatch] :
2428			null;
2429	}
2430	
2431	
2432	/**
2433	 * Convert the index of an index in the data array and convert it to the visible
2434	 *   column index (take account of hidden columns)
2435	 *  @param {int} iMatch Column index to lookup
2436	 *  @param {object} oSettings dataTables settings object
2437	 *  @returns {int} i the data index
2438	 *  @memberof DataTable#oApi
2439	 */
2440	function _fnColumnIndexToVisible( oSettings, iMatch )
2441	{
2442		var aiVis = _fnGetColumns( oSettings, 'bVisible' );
2443		var iPos = $.inArray( iMatch, aiVis );
2444	
2445		return iPos !== -1 ? iPos : null;
2446	}
2447	
2448	
2449	/**
2450	 * Get the number of visible columns
2451	 *  @param {object} oSettings dataTables settings object
2452	 *  @returns {int} i the number of visible columns
2453	 *  @memberof DataTable#oApi
2454	 */
2455	function _fnVisbleColumns( oSettings )
2456	{
2457		var vis = 0;
2458	
2459		// No reduce in IE8, use a loop for now
2460		$.each( oSettings.aoColumns, function ( i, col ) {
2461			if ( col.bVisible && $(col.nTh).css('display') !== 'none' ) {
2462				vis++;
2463			}
2464		} );
2465	
2466		return vis;
2467	}
2468	
2469	
2470	/**
2471	 * Get an array of column indexes that match a given property
2472	 *  @param {object} oSettings dataTables settings object
2473	 *  @param {string} sParam Parameter in aoColumns to look for - typically
2474	 *    bVisible or bSearchable
2475	 *  @returns {array} Array of indexes with matched properties
2476	 *  @memberof DataTable#oApi
2477	 */
2478	function _fnGetColumns( oSettings, sParam )
2479	{
2480		var a = [];
2481	
2482		$.map( oSettings.aoColumns, function(val, i) {
2483			if ( val[sParam] ) {
2484				a.push( i );
2485			}
2486		} );
2487	
2488		return a;
2489	}
2490	
2491	
2492	/**
2493	 * Calculate the 'type' of a column
2494	 *  @param {object} settings dataTables settings object
2495	 *  @memberof DataTable#oApi
2496	 */
2497	function _fnColumnTypes ( settings )
2498	{
2499		var columns = settings.aoColumns;
2500		var data = settings.aoData;
2501		var types = DataTable.ext.type.detect;
2502		var i, ien, j, jen, k, ken;
2503		var col, cell, detectedType, cache;
2504	
2505		// For each column, spin over the 
2506		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
2507			col = columns[i];
2508			cache = [];
2509	
2510			if ( ! col.sType && col._sManualType ) {
2511				col.sType = col._sManualType;
2512			}
2513			else if ( ! col.sType ) {
2514				for ( j=0, jen=types.length ; j<jen ; j++ ) {
2515					for ( k=0, ken=data.length ; k<ken ; k++ ) {
2516						// Use a cache array so we only need to get the type data
2517						// from the formatter once (when using multiple detectors)
2518						if ( cache[k] === undefined ) {
2519							cache[k] = _fnGetCellData( settings, k, i, 'type' );
2520						}
2521	
2522						detectedType = types[j]( cache[k], settings );
2523	
2524						// If null, then this type can't apply to this column, so
2525						// rather than testing all cells, break out. There is an
2526						// exception for the last type which is `html`. We need to
2527						// scan all rows since it is possible to mix string and HTML
2528						// types
2529						if ( ! detectedType && j !== types.length-1 ) {
2530							break;
2531						}
2532	
2533						// Only a single match is needed for html type since it is
2534						// bottom of the pile and very similar to string - but it
2535						// must not be empty
2536						if ( detectedType === 'html' && ! _empty(cache[k]) ) {
2537							break;
2538						}
2539					}
2540	
2541					// Type is valid for all data points in the column - use this
2542					// type
2543					if ( detectedType ) {
2544						col.sType = detectedType;
2545						break;
2546					}
2547				}
2548	
2549				// Fall back - if no type was detected, always use string
2550				if ( ! col.sType ) {
2551					col.sType = 'string';
2552				}
2553			}
2554		}
2555	}
2556	
2557	
2558	/**
2559	 * Take the column definitions and static columns arrays and calculate how
2560	 * they relate to column indexes. The callback function will then apply the
2561	 * definition found for a column to a suitable configuration object.
2562	 *  @param {object} oSettings dataTables settings object
2563	 *  @param {array} aoColDefs The aoColumnDefs array that is to be applied
2564	 *  @param {array} aoCols The aoColumns array that defines columns individually
2565	 *  @param {function} fn Callback function - takes two parameters, the calculated
2566	 *    column index and the definition for that column.
2567	 *  @memberof DataTable#oApi
2568	 */
2569	function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )
2570	{
2571		var i, iLen, j, jLen, k, kLen, def;
2572		var columns = oSettings.aoColumns;
2573	
2574		// Column definitions with aTargets
2575		if ( aoColDefs )
2576		{
2577			/* Loop over the definitions array - loop in reverse so first instance has priority */
2578			for ( i=aoColDefs.length-1 ; i>=0 ; i-- )
2579			{
2580				def = aoColDefs[i];
2581	
2582				/* Each definition can target multiple columns, as it is an array */
2583				var aTargets = def.target !== undefined
2584					? def.target
2585					: def.targets !== undefined
2586						? def.targets
2587						: def.aTargets;
2588	
2589				if ( ! Array.isArray( aTargets ) )
2590				{
2591					aTargets = [ aTargets ];
2592				}
2593	
2594				for ( j=0, jLen=aTargets.length ; j<jLen ; j++ )
2595				{
2596					if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 )
2597					{
2598						/* Add columns that we don't yet know about */
2599						while( columns.length <= aTargets[j] )
2600						{
2601							_fnAddColumn( oSettings );
2602						}
2603	
2604						/* Integer, basic index */
2605						fn( aTargets[j], def );
2606					}
2607					else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 )
2608					{
2609						/* Negative integer, right to left column counting */
2610						fn( columns.length+aTargets[j], def );
2611					}
2612					else if ( typeof aTargets[j] === 'string' )
2613					{
2614						/* Class name matching on TH element */
2615						for ( k=0, kLen=columns.length ; k<kLen ; k++ )
2616						{
2617							if ( aTargets[j] == "_all" ||
2618							     $(columns[k].nTh).hasClass( aTargets[j] ) )
2619							{
2620								fn( k, def );
2621							}
2622						}
2623					}
2624				}
2625			}
2626		}
2627	
2628		// Statically defined columns array
2629		if ( aoCols )
2630		{
2631			for ( i=0, iLen=aoCols.length ; i<iLen ; i++ )
2632			{
2633				fn( i, aoCols[i] );
2634			}
2635		}
2636	}
2637	
2638	/**
2639	 * Add a data array to the table, creating DOM node etc. This is the parallel to
2640	 * _fnGatherData, but for adding rows from a Javascript source, rather than a
2641	 * DOM source.
2642	 *  @param {object} oSettings dataTables settings object
2643	 *  @param {array} aData data array to be added
2644	 *  @param {node} [nTr] TR element to add to the table - optional. If not given,
2645	 *    DataTables will create a row automatically
2646	 *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
2647	 *    if nTr is.
2648	 *  @returns {int} >=0 if successful (index of new aoData entry), -1 if failed
2649	 *  @memberof DataTable#oApi
2650	 */
2651	function _fnAddData ( oSettings, aDataIn, nTr, anTds )
2652	{
2653		/* Create the object for storing information about this new row */
2654		var iRow = oSettings.aoData.length;
2655		var oData = $.extend( true, {}, DataTable.models.oRow, {
2656			src: nTr ? 'dom' : 'data',
2657			idx: iRow
2658		} );
2659	
2660		oData._aData = aDataIn;
2661		oSettings.aoData.push( oData );
2662	
2663		/* Create the cells */
2664		var nTd, sThisType;
2665		var columns = oSettings.aoColumns;
2666	
2667		// Invalidate the column types as the new data needs to be revalidated
2668		for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
2669		{
2670			columns[i].sType = null;
2671		}
2672	
2673		/* Add to the display array */
2674		oSettings.aiDisplayMaster.push( iRow );
2675	
2676		var id = oSettings.rowIdFn( aDataIn );
2677		if ( id !== undefined ) {
2678			oSettings.aIds[ id ] = oData;
2679		}
2680	
2681		/* Create the DOM information, or register it if already present */
2682		if ( nTr || ! oSettings.oFeatures.bDeferRender )
2683		{
2684			_fnCreateTr( oSettings, iRow, nTr, anTds );
2685		}
2686	
2687		return iRow;
2688	}
2689	
2690	
2691	/**
2692	 * Add one or more TR elements to the table. Generally we'd expect to
2693	 * use this for reading data from a DOM sourced table, but it could be
2694	 * used for an TR element. Note that if a TR is given, it is used (i.e.
2695	 * it is not cloned).
2696	 *  @param {object} settings dataTables settings object
2697	 *  @param {array|node|jQuery} trs The TR element(s) to add to the table
2698	 *  @returns {array} Array of indexes for the added rows
2699	 *  @memberof DataTable#oApi
2700	 */
2701	function _fnAddTr( settings, trs )
2702	{
2703		var row;
2704	
2705		// Allow an individual node to be passed in
2706		if ( ! (trs instanceof $) ) {
2707			trs = $(trs);
2708		}
2709	
2710		return trs.map( function (i, el) {
2711			row = _fnGetRowElements( settings, el );
2712			return _fnAddData( settings, row.data, el, row.cells );
2713		} );
2714	}
2715	
2716	
2717	/**
2718	 * Take a TR element and convert it to an index in aoData
2719	 *  @param {object} oSettings dataTables settings object
2720	 *  @param {node} n the TR element to find
2721	 *  @returns {int} index if the node is found, null if not
2722	 *  @memberof DataTable#oApi
2723	 */
2724	function _fnNodeToDataIndex( oSettings, n )
2725	{
2726		return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null;
2727	}
2728	
2729	
2730	/**
2731	 * Take a TD element and convert it into a column data index (not the visible index)
2732	 *  @param {object} oSettings dataTables settings object
2733	 *  @param {int} iRow The row number the TD/TH can be found in
2734	 *  @param {node} n The TD/TH element to find
2735	 *  @returns {int} index if the node is found, -1 if not
2736	 *  @memberof DataTable#oApi
2737	 */
2738	function _fnNodeToColumnIndex( oSettings, iRow, n )
2739	{
2740		return $.inArray( n, oSettings.aoData[ iRow ].anCells );
2741	}
2742	
2743	
2744	/**
2745	 * Get the data for a given cell from the internal cache, taking into account data mapping
2746	 *  @param {object} settings dataTables settings object
2747	 *  @param {int} rowIdx aoData row id
2748	 *  @param {int} colIdx Column index
2749	 *  @param {string} type data get type ('display', 'type' 'filter|search' 'sort|order')
2750	 *  @returns {*} Cell data
2751	 *  @memberof DataTable#oApi
2752	 */
2753	function _fnGetCellData( settings, rowIdx, colIdx, type )
2754	{
2755		if (type === 'search') {
2756			type = 'filter';
2757		}
2758		else if (type === 'order') {
2759			type = 'sort';
2760		}
2761	
2762		var draw           = settings.iDraw;
2763		var col            = settings.aoColumns[colIdx];
2764		var rowData        = settings.aoData[rowIdx]._aData;
2765		var defaultContent = col.sDefaultContent;
2766		var cellData       = col.fnGetData( rowData, type, {
2767			settings: settings,
2768			row:      rowIdx,
2769			col:      colIdx
2770		} );
2771	
2772		if ( cellData === undefined ) {
2773			if ( settings.iDrawError != draw && defaultContent === null ) {
2774				_fnLog( settings, 0, "Requested unknown parameter "+
2775					(typeof col.mData=='function' ? '{function}' : "'"+col.mData+"'")+
2776					" for row "+rowIdx+", column "+colIdx, 4 );
2777				settings.iDrawError = draw;
2778			}
2779			return defaultContent;
2780		}
2781	
2782		// When the data source is null and a specific data type is requested (i.e.
2783		// not the original data), we can use default column data
2784		if ( (cellData === rowData || cellData === null) && defaultContent !== null && type !== undefined ) {
2785			cellData = defaultContent;
2786		}
2787		else if ( typeof cellData === 'function' ) {
2788			// If the data source is a function, then we run it and use the return,
2789			// executing in the scope of the data object (for instances)
2790			return cellData.call( rowData );
2791		}
2792	
2793		if ( cellData === null && type === 'display' ) {
2794			return '';
2795		}
2796	
2797		if ( type === 'filter' ) {
2798			var fomatters = DataTable.ext.type.search;
2799	
2800			if ( fomatters[ col.sType ] ) {
2801				cellData = fomatters[ col.sType ]( cellData );
2802			}
2803		}
2804	
2805		return cellData;
2806	}
2807	
2808	
2809	/**
2810	 * Set the value for a specific cell, into the internal data cache
2811	 *  @param {object} settings dataTables settings object
2812	 *  @param {int} rowIdx aoData row id
2813	 *  @param {int} colIdx Column index
2814	 *  @param {*} val Value to set
2815	 *  @memberof DataTable#oApi
2816	 */
2817	function _fnSetCellData( settings, rowIdx, colIdx, val )
2818	{
2819		var col     = settings.aoColumns[colIdx];
2820		var rowData = settings.aoData[rowIdx]._aData;
2821	
2822		col.fnSetData( rowData, val, {
2823			settings: settings,
2824			row:      rowIdx,
2825			col:      colIdx
2826		}  );
2827	}
2828	
2829	
2830	// Private variable that is used to match action syntax in the data property object
2831	var __reArray = /\[.*?\]$/;
2832	var __reFn = /\(\)$/;
2833	
2834	/**
2835	 * Split string on periods, taking into account escaped periods
2836	 * @param  {string} str String to split
2837	 * @return {array} Split string
2838	 */
2839	function _fnSplitObjNotation( str )
2840	{
2841		return $.map( str.match(/(\\.|[^\.])+/g) || [''], function ( s ) {
2842			return s.replace(/\\\./g, '.');
2843		} );
2844	}
2845	
2846	
2847	/**
2848	 * Return a function that can be used to get data from a source object, taking
2849	 * into account the ability to use nested objects as a source
2850	 *  @param {string|int|function} mSource The data source for the object
2851	 *  @returns {function} Data get function
2852	 *  @memberof DataTable#oApi
2853	 */
2854	var _fnGetObjectDataFn = DataTable.util.get;
2855	
2856	
2857	/**
2858	 * Return a function that can be used to set data from a source object, taking
2859	 * into account the ability to use nested objects as a source
2860	 *  @param {string|int|function} mSource The data source for the object
2861	 *  @returns {function} Data set function
2862	 *  @memberof DataTable#oApi
2863	 */
2864	var _fnSetObjectDataFn = DataTable.util.set;
2865	
2866	
2867	/**
2868	 * Return an array with the full table data
2869	 *  @param {object} oSettings dataTables settings object
2870	 *  @returns array {array} aData Master data array
2871	 *  @memberof DataTable#oApi
2872	 */
2873	function _fnGetDataMaster ( settings )
2874	{
2875		return _pluck( settings.aoData, '_aData' );
2876	}
2877	
2878	
2879	/**
2880	 * Nuke the table
2881	 *  @param {object} oSettings dataTables settings object
2882	 *  @memberof DataTable#oApi
2883	 */
2884	function _fnClearTable( settings )
2885	{
2886		settings.aoData.length = 0;
2887		settings.aiDisplayMaster.length = 0;
2888		settings.aiDisplay.length = 0;
2889		settings.aIds = {};
2890	}
2891	
2892	
2893	 /**
2894	 * Take an array of integers (index array) and remove a target integer (value - not
2895	 * the key!)
2896	 *  @param {array} a Index array to target
2897	 *  @param {int} iTarget value to find
2898	 *  @memberof DataTable#oApi
2899	 */
2900	function _fnDeleteIndex( a, iTarget, splice )
2901	{
2902		var iTargetIndex = -1;
2903	
2904		for ( var i=0, iLen=a.length ; i<iLen ; i++ )
2905		{
2906			if ( a[i] == iTarget )
2907			{
2908				iTargetIndex = i;
2909			}
2910			else if ( a[i] > iTarget )
2911			{
2912				a[i]--;
2913			}
2914		}
2915	
2916		if ( iTargetIndex != -1 && splice === undefined )
2917		{
2918			a.splice( iTargetIndex, 1 );
2919		}
2920	}
2921	
2922	
2923	/**
2924	 * Mark cached data as invalid such that a re-read of the data will occur when
2925	 * the cached data is next requested. Also update from the data source object.
2926	 *
2927	 * @param {object} settings DataTables settings object
2928	 * @param {int}    rowIdx   Row index to invalidate
2929	 * @param {string} [src]    Source to invalidate from: undefined, 'auto', 'dom'
2930	 *     or 'data'
2931	 * @param {int}    [colIdx] Column index to invalidate. If undefined the whole
2932	 *     row will be invalidated
2933	 * @memberof DataTable#oApi
2934	 *
2935	 * @todo For the modularisation of v1.11 this will need to become a callback, so
2936	 *   the sort and filter methods can subscribe to it. That will required
2937	 *   initialisation options for sorting, which is why it is not already baked in
2938	 */
2939	function _fnInvalidate( settings, rowIdx, src, colIdx )
2940	{
2941		var row = settings.aoData[ rowIdx ];
2942		var i, ien;
2943		var cellWrite = function ( cell, col ) {
2944			// This is very frustrating, but in IE if you just write directly
2945			// to innerHTML, and elements that are overwritten are GC'ed,
2946			// even if there is a reference to them elsewhere
2947			while ( cell.childNodes.length ) {
2948				cell.removeChild( cell.firstChild );
2949			}
2950	
2951			cell.innerHTML = _fnGetCellData( settings, rowIdx, col, 'display' );
2952		};
2953	
2954		// Are we reading last data from DOM or the data object?
2955		if ( src === 'dom' || ((! src || src === 'auto') && row.src === 'dom') ) {
2956			// Read the data from the DOM
2957			row._aData = _fnGetRowElements(
2958					settings, row, colIdx, colIdx === undefined ? undefined : row._aData
2959				)
2960				.data;
2961		}
2962		else {
2963			// Reading from data object, update the DOM
2964			var cells = row.anCells;
2965	
2966			if ( cells ) {
2967				if ( colIdx !== undefined ) {
2968					cellWrite( cells[colIdx], colIdx );
2969				}
2970				else {
2971					for ( i=0, ien=cells.length ; i<ien ; i++ ) {
2972						cellWrite( cells[i], i );
2973					}
2974				}
2975			}
2976		}
2977	
2978		// For both row and cell invalidation, the cached data for sorting and
2979		// filtering is nulled out
2980		row._aSortData = null;
2981		row._aFilterData = null;
2982	
2983		// Invalidate the type for a specific column (if given) or all columns since
2984		// the data might have changed
2985		var cols = settings.aoColumns;
2986		if ( colIdx !== undefined ) {
2987			cols[ colIdx ].sType = null;
2988		}
2989		else {
2990			for ( i=0, ien=cols.length ; i<ien ; i++ ) {
2991				cols[i].sType = null;
2992			}
2993	
2994			// Update DataTables special `DT_*` attributes for the row
2995			_fnRowAttributes( settings, row );
2996		}
2997	}
2998	
2999	
3000	/**
3001	 * Build a data source object from an HTML row, reading the contents of the
3002	 * cells that are in the row.
3003	 *
3004	 * @param {object} settings DataTables settings object
3005	 * @param {node|object} TR element from which to read data or existing row
3006	 *   object from which to re-read the data from the cells
3007	 * @param {int} [colIdx] Optional column index
3008	 * @param {array|object} [d] Data source object. If `colIdx` is given then this
3009	 *   parameter should also be given and will be used to write the data into.
3010	 *   Only the column in question will be written
3011	 * @returns {object} Object with two parameters: `data` the data read, in
3012	 *   document order, and `cells` and array of nodes (they can be useful to the
3013	 *   caller, so rather than needing a second traversal to get them, just return
3014	 *   them from here).
3015	 * @memberof DataTable#oApi
3016	 */
3017	function _fnGetRowElements( settings, row, colIdx, d )
3018	{
3019		var
3020			tds = [],
3021			td = row.firstChild,
3022			name, col, o, i=0, contents,
3023			columns = settings.aoColumns,
3024			objectRead = settings._rowReadObject;
3025	
3026		// Allow the data object to be passed in, or construct
3027		d = d !== undefined ?
3028			d :
3029			objectRead ?
3030				{} :
3031				[];
3032	
3033		var attr = function ( str, td  ) {
3034			if ( typeof str === 'string' ) {
3035				var idx = str.indexOf('@');
3036	
3037				if ( idx !== -1 ) {
3038					var attr = str.substring( idx+1 );
3039					var setter = _fnSetObjectDataFn( str );
3040					setter( d, td.getAttribute( attr ) );
3041				}
3042			}
3043		};
3044	
3045		// Read data from a cell and store into the data object
3046		var cellProcess = function ( cell ) {
3047			if ( colIdx === undefined || colIdx === i ) {
3048				col = columns[i];
3049				contents = (cell.innerHTML).trim();
3050	
3051				if ( col && col._bAttrSrc ) {
3052					var setter = _fnSetObjectDataFn( col.mData._ );
3053					setter( d, contents );
3054	
3055					attr( col.mData.sort, cell );
3056					attr( col.mData.type, cell );
3057					attr( col.mData.filter, cell );
3058				}
3059				else {
3060					// Depending on the `data` option for the columns the data can
3061					// be read to either an object or an array.
3062					if ( objectRead ) {
3063						if ( ! col._setter ) {
3064							// Cache the setter function
3065							col._setter = _fnSetObjectDataFn( col.mData );
3066						}
3067						col._setter( d, contents );
3068					}
3069					else {
3070						d[i] = contents;
3071					}
3072				}
3073			}
3074	
3075			i++;
3076		};
3077	
3078		if ( td ) {
3079			// `tr` element was passed in
3080			while ( td ) {
3081				name = td.nodeName.toUpperCase();
3082	
3083				if ( name == "TD" || name == "TH" ) {
3084					cellProcess( td );
3085					tds.push( td );
3086				}
3087	
3088				td = td.nextSibling;
3089			}
3090		}
3091		else {
3092			// Existing row object passed in
3093			tds = row.anCells;
3094	
3095			for ( var j=0, jen=tds.length ; j<jen ; j++ ) {
3096				cellProcess( tds[j] );
3097			}
3098		}
3099	
3100		// Read the ID from the DOM if present
3101		var rowNode = row.firstChild ? row : row.nTr;
3102	
3103		if ( rowNode ) {
3104			var id = rowNode.getAttribute( 'id' );
3105	
3106			if ( id ) {
3107				_fnSetObjectDataFn( settings.rowId )( d, id );
3108			}
3109		}
3110	
3111		return {
3112			data: d,
3113			cells: tds
3114		};
3115	}
3116	/**
3117	 * Create a new TR element (and it's TD children) for a row
3118	 *  @param {object} oSettings dataTables settings object
3119	 *  @param {int} iRow Row to consider
3120	 *  @param {node} [nTrIn] TR element to add to the table - optional. If not given,
3121	 *    DataTables will create a row automatically
3122	 *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
3123	 *    if nTr is.
3124	 *  @memberof DataTable#oApi
3125	 */
3126	function _fnCreateTr ( oSettings, iRow, nTrIn, anTds )
3127	{
3128		var
3129			row = oSettings.aoData[iRow],
3130			rowData = row._aData,
3131			cells = [],
3132			nTr, nTd, oCol,
3133			i, iLen, create;
3134	
3135		if ( row.nTr === null )
3136		{
3137			nTr = nTrIn || document.createElement('tr');
3138	
3139			row.nTr = nTr;
3140			row.anCells = cells;
3141	
3142			/* Use a private property on the node to allow reserve mapping from the node
3143			 * to the aoData array for fast look up
3144			 */
3145			nTr._DT_RowIndex = iRow;
3146	
3147			/* Special parameters can be given by the data source to be used on the row */
3148			_fnRowAttributes( oSettings, row );
3149	
3150			/* Process each column */
3151			for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
3152			{
3153				oCol = oSettings.aoColumns[i];
3154				create = nTrIn ? false : true;
3155	
3156				nTd = create ? document.createElement( oCol.sCellType ) : anTds[i];
3157				nTd._DT_CellIndex = {
3158					row: iRow,
3159					column: i
3160				};
3161				
3162				cells.push( nTd );
3163	
3164				// Need to create the HTML if new, or if a rendering function is defined
3165				if ( create || ((oCol.mRender || oCol.mData !== i) &&
3166					 (!$.isPlainObject(oCol.mData) || oCol.mData._ !== i+'.display')
3167				)) {
3168					nTd.innerHTML = _fnGetCellData( oSettings, iRow, i, 'display' );
3169				}
3170	
3171				/* Add user defined class */
3172				if ( oCol.sClass )
3173				{
3174					nTd.className += ' '+oCol.sClass;
3175				}
3176	
3177				// Visibility - add or remove as required
3178				if ( oCol.bVisible && ! nTrIn )
3179				{
3180					nTr.appendChild( nTd );
3181				}
3182				else if ( ! oCol.bVisible && nTrIn )
3183				{
3184					nTd.parentNode.removeChild( nTd );
3185				}
3186	
3187				if ( oCol.fnCreatedCell )
3188				{
3189					oCol.fnCreatedCell.call( oSettings.oInstance,
3190						nTd, _fnGetCellData( oSettings, iRow, i ), rowData, iRow, i
3191					);
3192				}
3193			}
3194	
3195			_fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow, cells] );
3196		}
3197	}
3198	
3199	
3200	/**
3201	 * Add attributes to a row based on the special `DT_*` parameters in a data
3202	 * source object.
3203	 *  @param {object} settings DataTables settings object
3204	 *  @param {object} DataTables row object for the row to be modified
3205	 *  @memberof DataTable#oApi
3206	 */
3207	function _fnRowAttributes( settings, row )
3208	{
3209		var tr = row.nTr;
3210		var data = row._aData;
3211	
3212		if ( tr ) {
3213			var id = settings.rowIdFn( data );
3214	
3215			if ( id ) {
3216				tr.id = id;
3217			}
3218	
3219			if ( data.DT_RowClass ) {
3220				// Remove any classes added by DT_RowClass before
3221				var a = data.DT_RowClass.split(' ');
3222				row.__rowc = row.__rowc ?
3223					_unique( row.__rowc.concat( a ) ) :
3224					a;
3225	
3226				$(tr)
3227					.removeClass( row.__rowc.join(' ') )
3228					.addClass( data.DT_RowClass );
3229			}
3230	
3231			if ( data.DT_RowAttr ) {
3232				$(tr).attr( data.DT_RowAttr );
3233			}
3234	
3235			if ( data.DT_RowData ) {
3236				$(tr).data( data.DT_RowData );
3237			}
3238		}
3239	}
3240	
3241	
3242	/**
3243	 * Create the HTML header for the table
3244	 *  @param {object} oSettings dataTables settings object
3245	 *  @memberof DataTable#oApi
3246	 */
3247	function _fnBuildHead( oSettings )
3248	{
3249		var i, ien, cell, row, column;
3250		var thead = oSettings.nTHead;
3251		var tfoot = oSettings.nTFoot;
3252		var createHeader = $('th, td', thead).length === 0;
3253		var classes = oSettings.oClasses;
3254		var columns = oSettings.aoColumns;
3255	
3256		if ( createHeader ) {
3257			row = $('<tr/>').appendTo( thead );
3258		}
3259	
3260		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
3261			column = columns[i];
3262			cell = $( column.nTh ).addClass( column.sClass );
3263	
3264			if ( createHeader ) {
3265				cell.appendTo( row );
3266			}
3267	
3268			// 1.11 move into sorting
3269			if ( oSettings.oFeatures.bSort ) {
3270				cell.addClass( column.sSortingClass );
3271	
3272				if ( column.bSortable !== false ) {
3273					cell
3274						.attr( 'tabindex', oSettings.iTabIndex )
3275						.attr( 'aria-controls', oSettings.sTableId );
3276	
3277					_fnSortAttachListener( oSettings, column.nTh, i );
3278				}
3279			}
3280	
3281			if ( column.sTitle != cell[0].innerHTML ) {
3282				cell.html( column.sTitle );
3283			}
3284	
3285			_fnRenderer( oSettings, 'header' )(
3286				oSettings, cell, column, classes
3287			);
3288		}
3289	
3290		if ( createHeader ) {
3291			_fnDetectHeader( oSettings.aoHeader, thead );
3292		}
3293	
3294		/* Deal with the footer - add classes if required */
3295		$(thead).children('tr').children('th, td').addClass( classes.sHeaderTH );
3296		$(tfoot).children('tr').children('th, td').addClass( classes.sFooterTH );
3297	
3298		// Cache the footer cells. Note that we only take the cells from the first
3299		// row in the footer. If there is more than one row the user wants to
3300		// interact with, they need to use the table().foot() method. Note also this
3301		// allows cells to be used for multiple columns using colspan
3302		if ( tfoot !== null ) {
3303			var cells = oSettings.aoFooter[0];
3304	
3305			for ( i=0, ien=cells.length ; i<ien ; i++ ) {
3306				column = columns[i];
3307				column.nTf = cells[i].cell;
3308	
3309				if ( column.sClass ) {
3310					$(column.nTf).addClass( column.sClass );
3311				}
3312			}
3313		}
3314	}
3315	
3316	
3317	/**
3318	 * Draw the header (or footer) element based on the column visibility states. The
3319	 * methodology here is to use the layout array from _fnDetectHeader, modified for
3320	 * the instantaneous column visibility, to construct the new layout. The grid is
3321	 * traversed over cell at a time in a rows x columns grid fashion, although each
3322	 * cell insert can cover multiple elements in the grid - which is tracks using the
3323	 * aApplied array. Cell inserts in the grid will only occur where there isn't
3324	 * already a cell in that position.
3325	 *  @param {object} oSettings dataTables settings object
3326	 *  @param array {objects} aoSource Layout array from _fnDetectHeader
3327	 *  @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,
3328	 *  @memberof DataTable#oApi
3329	 */
3330	function _fnDrawHead( oSettings, aoSource, bIncludeHidden )
3331	{
3332		var i, iLen, j, jLen, k, kLen, n, nLocalTr;
3333		var aoLocal = [];
3334		var aApplied = [];
3335		var iColumns = oSettings.aoColumns.length;
3336		var iRowspan, iColspan;
3337	
3338		if ( ! aoSource )
3339		{
3340			return;
3341		}
3342	
3343		if (  bIncludeHidden === undefined )
3344		{
3345			bIncludeHidden = false;
3346		}
3347	
3348		/* Make a copy of the master layout array, but without the visible columns in it */
3349		for ( i=0, iLen=aoSource.length ; i<iLen ; i++ )
3350		{
3351			aoLocal[i] = aoSource[i].slice();
3352			aoLocal[i].nTr = aoSource[i].nTr;
3353	
3354			/* Remove any columns which are currently hidden */
3355			for ( j=iColumns-1 ; j>=0 ; j-- )
3356			{
3357				if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden )
3358				{
3359					aoLocal[i].splice( j, 1 );
3360				}
3361			}
3362	
3363			/* Prep the applied array - it needs an element for each row */
3364			aApplied.push( [] );
3365		}
3366	
3367		for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ )
3368		{
3369			nLocalTr = aoLocal[i].nTr;
3370	
3371			/* All cells are going to be replaced, so empty out the row */
3372			if ( nLocalTr )
3373			{
3374				while( (n = nLocalTr.firstChild) )
3375				{
3376					nLocalTr.removeChild( n );
3377				}
3378			}
3379	
3380			for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ )
3381			{
3382				iRowspan = 1;
3383				iColspan = 1;
3384	
3385				/* Check to see if there is already a cell (row/colspan) covering our target
3386				 * insert point. If there is, then there is nothing to do.
3387				 */
3388				if ( aApplied[i][j] === undefined )
3389				{
3390					nLocalTr.appendChild( aoLocal[i][j].cell );
3391					aApplied[i][j] = 1;
3392	
3393					/* Expand the cell to cover as many rows as needed */
3394					while ( aoLocal[i+iRowspan] !== undefined &&
3395					        aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell )
3396					{
3397						aApplied[i+iRowspan][j] = 1;
3398						iRowspan++;
3399					}
3400	
3401					/* Expand the cell to cover as many columns as needed */
3402					while ( aoLocal[i][j+iColspan] !== undefined &&
3403					        aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell )
3404					{
3405						/* Must update the applied array over the rows for the columns */
3406						for ( k=0 ; k<iRowspan ; k++ )
3407						{
3408							aApplied[i+k][j+iColspan] = 1;
3409						}
3410						iColspan++;
3411					}
3412	
3413					/* Do the actual expansion in the DOM */
3414					$(aoLocal[i][j].cell)
3415						.attr('rowspan', iRowspan)
3416						.attr('colspan', iColspan);
3417				}
3418			}
3419		}
3420	}
3421	
3422	
3423	/**
3424	 * Insert the required TR nodes into the table for display
3425	 *  @param {object} oSettings dataTables settings object
3426	 *  @param ajaxComplete true after ajax call to complete rendering
3427	 *  @memberof DataTable#oApi
3428	 */
3429	function _fnDraw( oSettings, ajaxComplete )
3430	{
3431		// Allow for state saving and a custom start position
3432		_fnStart( oSettings );
3433	
3434		/* Provide a pre-callback function which can be used to cancel the draw is false is returned */
3435		var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] );
3436		if ( $.inArray( false, aPreDraw ) !== -1 )
3437		{
3438			_fnProcessingDisplay( oSettings, false );
3439			return;
3440		}
3441	
3442		var anRows = [];
3443		var iRowCount = 0;
3444		var asStripeClasses = oSettings.asStripeClasses;
3445		var iStripes = asStripeClasses.length;
3446		var oLang = oSettings.oLanguage;
3447		var bServerSide = _fnDataSource( oSettings ) == 'ssp';
3448		var aiDisplay = oSettings.aiDisplay;
3449		var iDisplayStart = oSettings._iDisplayStart;
3450		var iDisplayEnd = oSettings.fnDisplayEnd();
3451	
3452		oSettings.bDrawing = true;
3453	
3454		/* Server-side processing draw intercept */
3455		if ( oSettings.bDeferLoading )
3456		{
3457			oSettings.bDeferLoading = false;
3458			oSettings.iDraw++;
3459			_fnProcessingDisplay( oSettings, false );
3460		}
3461		else if ( !bServerSide )
3462		{
3463			oSettings.iDraw++;
3464		}
3465		else if ( !oSettings.bDestroying && !ajaxComplete)
3466		{
3467			_fnAjaxUpdate( oSettings );
3468			return;
3469		}
3470	
3471		if ( aiDisplay.length !== 0 )
3472		{
3473			var iStart = bServerSide ? 0 : iDisplayStart;
3474			var iEnd = bServerSide ? oSettings.aoData.length : iDisplayEnd;
3475	
3476			for ( var j=iStart ; j<iEnd ; j++ )
3477			{
3478				var iDataIndex = aiDisplay[j];
3479				var aoData = oSettings.aoData[ iDataIndex ];
3480				if ( aoData.nTr === null )
3481				{
3482					_fnCreateTr( oSettings, iDataIndex );
3483				}
3484	
3485				var nRow = aoData.nTr;
3486	
3487				/* Remove the old striping classes and then add the new one */
3488				if ( iStripes !== 0 )
3489				{
3490					var sStripe = asStripeClasses[ iRowCount % iStripes ];
3491					if ( aoData._sRowStripe != sStripe )
3492					{
3493						$(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe );
3494						aoData._sRowStripe = sStripe;
3495					}
3496				}
3497	
3498				// Row callback functions - might want to manipulate the row
3499				// iRowCount and j are not currently documented. Are they at all
3500				// useful?
3501				_fnCallbackFire( oSettings, 'aoRowCallback', null,
3502					[nRow, aoData._aData, iRowCount, j, iDataIndex] );
3503	
3504				anRows.push( nRow );
3505				iRowCount++;
3506			}
3507		}
3508		else
3509		{
3510			/* Table is empty - create a row with an empty message in it */
3511			var sZero = oLang.sZeroRecords;
3512			if ( oSettings.iDraw == 1 &&  _fnDataSource( oSettings ) == 'ajax' )
3513			{
3514				sZero = oLang.sLoadingRecords;
3515			}
3516			else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 )
3517			{
3518				sZero = oLang.sEmptyTable;
3519			}
3520	
3521			anRows[ 0 ] = $( '<tr/>', { 'class': iStripes ? asStripeClasses[0] : '' } )
3522				.append( $('<td />', {
3523					'valign':  'top',
3524					'colSpan': _fnVisbleColumns( oSettings ),
3525					'class':   oSettings.oClasses.sRowEmpty
3526				} ).html( sZero ) )[0];
3527		}
3528	
3529		/* Header and footer callbacks */
3530		_fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0],
3531			_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
3532	
3533		_fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0],
3534			_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
3535	
3536		var body = $(oSettings.nTBody);
3537	
3538		body.children().detach();
3539		body.append( $(anRows) );
3540	
3541		/* Call all required callback functions for the end of a draw */
3542		_fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] );
3543	
3544		/* Draw is complete, sorting and filtering must be as well */
3545		oSettings.bSorted = false;
3546		oSettings.bFiltered = false;
3547		oSettings.bDrawing = false;
3548	}
3549	
3550	
3551	/**
3552	 * Redraw the table - taking account of the various features which are enabled
3553	 *  @param {object} oSettings dataTables settings object
3554	 *  @param {boolean} [holdPosition] Keep the current paging position. By default
3555	 *    the paging is reset to the first page
3556	 *  @memberof DataTable#oApi
3557	 */
3558	function _fnReDraw( settings, holdPosition )
3559	{
3560		var
3561			features = settings.oFeatures,
3562			sort     = features.bSort,
3563			filter   = features.bFilter;
3564	
3565		if ( sort ) {
3566			_fnSort( settings );
3567		}
3568	
3569		if ( filter ) {
3570			_fnFilterComplete( settings, settings.oPreviousSearch );
3571		}
3572		else {
3573			// No filtering, so we want to just use the display master
3574			settings.aiDisplay = settings.aiDisplayMaster.slice();
3575		}
3576	
3577		if ( holdPosition !== true ) {
3578			settings._iDisplayStart = 0;
3579		}
3580	
3581		// Let any modules know about the draw hold position state (used by
3582		// scrolling internally)
3583		settings._drawHold = holdPosition;
3584	
3585		_fnDraw( settings );
3586	
3587		settings._drawHold = false;
3588	}
3589	
3590	
3591	/**
3592	 * Add the options to the page HTML for the table
3593	 *  @param {object} oSettings dataTables settings object
3594	 *  @memberof DataTable#oApi
3595	 */
3596	function _fnAddOptionsHtml ( oSettings )
3597	{
3598		var classes = oSettings.oClasses;
3599		var table = $(oSettings.nTable);
3600		var holding = $('<div/>').insertBefore( table ); // Holding element for speed
3601		var features = oSettings.oFeatures;
3602	
3603		// All DataTables are wrapped in a div
3604		var insert = $('<div/>', {
3605			id:      oSettings.sTableId+'_wrapper',
3606			'class': classes.sWrapper + (oSettings.nTFoot ? '' : ' '+classes.sNoFooter)
3607		} );
3608	
3609		oSettings.nHolding = holding[0];
3610		oSettings.nTableWrapper = insert[0];
3611		oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;
3612	
3613		/* Loop over the user set positioning and place the elements as needed */
3614		var aDom = oSettings.sDom.split('');
3615		var featureNode, cOption, nNewNode, cNext, sAttr, j;
3616		for ( var i=0 ; i<aDom.length ; i++ )
3617		{
3618			featureNode = null;
3619			cOption = aDom[i];
3620	
3621			if ( cOption == '<' )
3622			{
3623				/* New container div */
3624				nNewNode = $('<div/>')[0];
3625	
3626				/* Check to see if we should append an id and/or a class name to the container */
3627				cNext = aDom[i+1];
3628				if ( cNext == "'" || cNext == '"' )
3629				{
3630					sAttr = "";
3631					j = 2;
3632					while ( aDom[i+j] != cNext )
3633					{
3634						sAttr += aDom[i+j];
3635						j++;
3636					}
3637	
3638					/* Replace jQuery UI constants @todo depreciated */
3639					if ( sAttr == "H" )
3640					{
3641						sAttr = classes.sJUIHeader;
3642					}
3643					else if ( sAttr == "F" )
3644					{
3645						sAttr = classes.sJUIFooter;
3646					}
3647	
3648					/* The attribute can be in the format of "#id.class", "#id" or "class" This logic
3649					 * breaks the string into parts and applies them as needed
3650					 */
3651					if ( sAttr.indexOf('.') != -1 )
3652					{
3653						var aSplit = sAttr.split('.');
3654						nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);
3655						nNewNode.className = aSplit[1];
3656					}
3657					else if ( sAttr.charAt(0) == "#" )
3658					{
3659						nNewNode.id = sAttr.substr(1, sAttr.length-1);
3660					}
3661					else
3662					{
3663						nNewNode.className = sAttr;
3664					}
3665	
3666					i += j; /* Move along the position array */
3667				}
3668	
3669				insert.append( nNewNode );
3670				insert = $(nNewNode);
3671			}
3672			else if ( cOption == '>' )
3673			{
3674				/* End container div */
3675				insert = insert.parent();
3676			}
3677			// @todo Move options into their own plugins?
3678			else if ( cOption == 'l' && features.bPaginate && features.bLengthChange )
3679			{
3680				/* Length */
3681				featureNode = _fnFeatureHtmlLength( oSettings );
3682			}
3683			else if ( cOption == 'f' && features.bFilter )
3684			{
3685				/* Filter */
3686				featureNode = _fnFeatureHtmlFilter( oSettings );
3687			}
3688			else if ( cOption == 'r' && features.bProcessing )
3689			{
3690				/* pRocessing */
3691				featureNode = _fnFeatureHtmlProcessing( oSettings );
3692			}
3693			else if ( cOption == 't' )
3694			{
3695				/* Table */
3696				featureNode = _fnFeatureHtmlTable( oSettings );
3697			}
3698			else if ( cOption ==  'i' && features.bInfo )
3699			{
3700				/* Info */
3701				featureNode = _fnFeatureHtmlInfo( oSettings );
3702			}
3703			else if ( cOption == 'p' && features.bPaginate )
3704			{
3705				/* Pagination */
3706				featureNode = _fnFeatureHtmlPaginate( oSettings );
3707			}
3708			else if ( DataTable.ext.feature.length !== 0 )
3709			{
3710				/* Plug-in features */
3711				var aoFeatures = DataTable.ext.feature;
3712				for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )
3713				{
3714					if ( cOption == aoFeatures[k].cFeature )
3715					{
3716						featureNode = aoFeatures[k].fnInit( oSettings );
3717						break;
3718					}
3719				}
3720			}
3721	
3722			/* Add to the 2D features array */
3723			if ( featureNode )
3724			{
3725				var aanFeatures = oSettings.aanFeatures;
3726	
3727				if ( ! aanFeatures[cOption] )
3728				{
3729					aanFeatures[cOption] = [];
3730				}
3731	
3732				aanFeatures[cOption].push( featureNode );
3733				insert.append( featureNode );
3734			}
3735		}
3736	
3737		/* Built our DOM structure - replace the holding div with what we want */
3738		holding.replaceWith( insert );
3739		oSettings.nHolding = null;
3740	}
3741	
3742	
3743	/**
3744	 * Use the DOM source to create up an array of header cells. The idea here is to
3745	 * create a layout grid (array) of rows x columns, which contains a reference
3746	 * to the cell that that point in the grid (regardless of col/rowspan), such that
3747	 * any column / row could be removed and the new grid constructed
3748	 *  @param array {object} aLayout Array to store the calculated layout in
3749	 *  @param {node} nThead The header/footer element for the table
3750	 *  @memberof DataTable#oApi
3751	 */
3752	function _fnDetectHeader ( aLayout, nThead )
3753	{
3754		var nTrs = $(nThead).children('tr');
3755		var nTr, nCell;
3756		var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan;
3757		var bUnique;
3758		var fnShiftCol = function ( a, i, j ) {
3759			var k = a[i];
3760	                while ( k[j] ) {
3761				j++;
3762			}
3763			return j;
3764		};
3765	
3766		aLayout.splice( 0, aLayout.length );
3767	
3768		/* We know how many rows there are in the layout - so prep it */
3769		for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
3770		{
3771			aLayout.push( [] );
3772		}
3773	
3774		/* Calculate a layout array */
3775		for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
3776		{
3777			nTr = nTrs[i];
3778			iColumn = 0;
3779	
3780			/* For every cell in the row... */
3781			nCell = nTr.firstChild;
3782			while ( nCell ) {
3783				if ( nCell.nodeName.toUpperCase() == "TD" ||
3784				     nCell.nodeName.toUpperCase() == "TH" )
3785				{
3786					/* Get the col and rowspan attributes from the DOM and sanitise them */
3787					iColspan = nCell.getAttribute('colspan') * 1;
3788					iRowspan = nCell.getAttribute('rowspan') * 1;
3789					iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan;
3790					iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan;
3791	
3792					/* There might be colspan cells already in this row, so shift our target
3793					 * accordingly
3794					 */
3795					iColShifted = fnShiftCol( aLayout, i, iColumn );
3796	
3797					/* Cache calculation for unique columns */
3798					bUnique = iColspan === 1 ? true : false;
3799	
3800					/* If there is col / rowspan, copy the information into the layout grid */
3801					for ( l=0 ; l<iColspan ; l++ )
3802					{
3803						for ( k=0 ; k<iRowspan ; k++ )
3804						{
3805							aLayout[i+k][iColShifted+l] = {
3806								"cell": nCell,
3807								"unique": bUnique
3808							};
3809							aLayout[i+k].nTr = nTr;
3810						}
3811					}
3812				}
3813				nCell = nCell.nextSibling;
3814			}
3815		}
3816	}
3817	
3818	
3819	/**
3820	 * Get an array of unique th elements, one for each column
3821	 *  @param {object} oSettings dataTables settings object
3822	 *  @param {node} nHeader automatically detect the layout from this node - optional
3823	 *  @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional
3824	 *  @returns array {node} aReturn list of unique th's
3825	 *  @memberof DataTable#oApi
3826	 */
3827	function _fnGetUniqueThs ( oSettings, nHeader, aLayout )
3828	{
3829		var aReturn = [];
3830		if ( !aLayout )
3831		{
3832			aLayout = oSettings.aoHeader;
3833			if ( nHeader )
3834			{
3835				aLayout = [];
3836				_fnDetectHeader( aLayout, nHeader );
3837			}
3838		}
3839	
3840		for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ )
3841		{
3842			for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ )
3843			{
3844				if ( aLayout[i][j].unique &&
3845					 (!aReturn[j] || !oSettings.bSortCellsTop) )
3846				{
3847					aReturn[j] = aLayout[i][j].cell;
3848				}
3849			}
3850		}
3851	
3852		return aReturn;
3853	}
3854	
3855	/**
3856	 * Set the start position for draw
3857	 *  @param {object} oSettings dataTables settings object
3858	 */
3859	function _fnStart( oSettings )
3860	{
3861		var bServerSide = _fnDataSource( oSettings ) == 'ssp';
3862		var iInitDisplayStart = oSettings.iInitDisplayStart;
3863	
3864		// Check and see if we have an initial draw position from state saving
3865		if ( iInitDisplayStart !== undefined && iInitDisplayStart !== -1 )
3866		{
3867			oSettings._iDisplayStart = bServerSide ?
3868				iInitDisplayStart :
3869				iInitDisplayStart >= oSettings.fnRecordsDisplay() ?
3870					0 :
3871					iInitDisplayStart;
3872	
3873			oSettings.iInitDisplayStart = -1;
3874		}
3875	}
3876	
3877	/**
3878	 * Create an Ajax call based on the table's settings, taking into account that
3879	 * parameters can have multiple forms, and backwards compatibility.
3880	 *
3881	 * @param {object} oSettings dataTables settings object
3882	 * @param {array} data Data to send to the server, required by
3883	 *     DataTables - may be augmented by developer callbacks
3884	 * @param {function} fn Callback function to run when data is obtained
3885	 */
3886	function _fnBuildAjax( oSettings, data, fn )
3887	{
3888		// Compatibility with 1.9-, allow fnServerData and event to manipulate
3889		_fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [data] );
3890	
3891		// Convert to object based for 1.10+ if using the old array scheme which can
3892		// come from server-side processing or serverParams
3893		if ( data && Array.isArray(data) ) {
3894			var tmp = {};
3895			var rbracket = /(.*?)\[\]$/;
3896	
3897			$.each( data, function (key, val) {
3898				var match = val.name.match(rbracket);
3899	
3900				if ( match ) {
3901					// Support for arrays
3902					var name = match[0];
3903	
3904					if ( ! tmp[ name ] ) {
3905						tmp[ name ] = [];
3906					}
3907					tmp[ name ].push( val.value );
3908				}
3909				else {
3910					tmp[val.name] = val.value;
3911				}
3912			} );
3913			data = tmp;
3914		}
3915	
3916		var ajaxData;
3917		var ajax = oSettings.ajax;
3918		var instance = oSettings.oInstance;
3919		var callback = function ( json ) {
3920			var status = oSettings.jqXHR
3921				? oSettings.jqXHR.status
3922				: null;
3923	
3924			if ( json === null || (typeof status === 'number' && status == 204 ) ) {
3925				json = {};
3926				_fnAjaxDataSrc( oSettings, json, [] );
3927			}
3928	
3929			var error = json.error || json.sError;
3930			if ( error ) {
3931				_fnLog( oSettings, 0, error );
3932			}
3933	
3934			oSettings.json = json;
3935	
3936			_fnCallbackFire( oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR] );
3937			fn( json );
3938		};
3939	
3940		if ( $.isPlainObject( ajax ) && ajax.data )
3941		{
3942			ajaxData = ajax.data;
3943	
3944			var newData = typeof ajaxData === 'function' ?
3945				ajaxData( data, oSettings ) :  // fn can manipulate data or return
3946				ajaxData;                      // an object object or array to merge
3947	
3948			// If the function returned something, use that alone
3949			data = typeof ajaxData === 'function' && newData ?
3950				newData :
3951				$.extend( true, data, newData );
3952	
3953			// Remove the data property as we've resolved it already and don't want
3954			// jQuery to do it again (it is restored at the end of the function)
3955			delete ajax.data;
3956		}
3957	
3958		var baseAjax = {
3959			"data": data,
3960			"success": callback,
3961			"dataType": "json",
3962			"cache": false,
3963			"type": oSettings.sServerMethod,
3964			"error": function (xhr, error, thrown) {
3965				var ret = _fnCallbackFire( oSettings, null, 'xhr', [oSettings, null, oSettings.jqXHR] );
3966	
3967				if ( $.inArray( true, ret ) === -1 ) {
3968					if ( error == "parsererror" ) {
3969						_fnLog( oSettings, 0, 'Invalid JSON response', 1 );
3970					}
3971					else if ( xhr.readyState === 4 ) {
3972						_fnLog( oSettings, 0, 'Ajax error', 7 );
3973					}
3974				}
3975	
3976				_fnProcessingDisplay( oSettings, false );
3977			}
3978		};
3979	
3980		// Store the data submitted for the API
3981		oSettings.oAjaxData = data;
3982	
3983		// Allow plug-ins and external processes to modify the data
3984		_fnCallbackFire( oSettings, null, 'preXhr', [oSettings, data] );
3985	
3986		if ( oSettings.fnServerData )
3987		{
3988			// DataTables 1.9- compatibility
3989			oSettings.fnServerData.call( instance,
3990				oSettings.sAjaxSource,
3991				$.map( data, function (val, key) { // Need to convert back to 1.9 trad format
3992					return { name: key, value: val };
3993				} ),
3994				callback,
3995				oSettings
3996			);
3997		}
3998		else if ( oSettings.sAjaxSource || typeof ajax === 'string' )
3999		{
4000			// DataTables 1.9- compatibility
4001			oSettings.jqXHR = $.ajax( $.extend( baseAjax, {
4002				url: ajax || oSettings.sAjaxSource
4003			} ) );
4004		}
4005		else if ( typeof ajax === 'function' )
4006		{
4007			// Is a function - let the caller define what needs to be done
4008			oSettings.jqXHR = ajax.call( instance, data, callback, oSettings );
4009		}
4010		else
4011		{
4012			// Object to extend the base settings
4013			oSettings.jqXHR = $.ajax( $.extend( baseAjax, ajax ) );
4014	
4015			// Restore for next time around
4016			ajax.data = ajaxData;
4017		}
4018	}
4019	
4020	
4021	/**
4022	 * Update the table using an Ajax call
4023	 *  @param {object} settings dataTables settings object
4024	 *  @returns {boolean} Block the table drawing or not
4025	 *  @memberof DataTable#oApi
4026	 */
4027	function _fnAjaxUpdate( settings )
4028	{
4029		settings.iDraw++;
4030		_fnProcessingDisplay( settings, true );
4031	
4032		_fnBuildAjax(
4033			settings,
4034			_fnAjaxParameters( settings ),
4035			function(json) {
4036				_fnAjaxUpdateDraw( settings, json );
4037			}
4038		);
4039	}
4040	
4041	
4042	/**
4043	 * Build up the parameters in an object needed for a server-side processing
4044	 * request. Note that this is basically done twice, is different ways - a modern
4045	 * method which is used by default in DataTables 1.10 which uses objects and
4046	 * arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if
4047	 * the sAjaxSource option is used in the initialisation, or the legacyAjax
4048	 * option is set.
4049	 *  @param {object} oSettings dataTables settings object
4050	 *  @returns {bool} block the table drawing or not
4051	 *  @memberof DataTable#oApi
4052	 */
4053	function _fnAjaxParameters( settings )
4054	{
4055		var
4056			columns = settings.aoColumns,
4057			columnCount = columns.length,
4058			features = settings.oFeatures,
4059			preSearch = settings.oPreviousSearch,
4060			preColSearch = settings.aoPreSearchCols,
4061			i, data = [], dataProp, column, columnSearch,
4062			sort = _fnSortFlatten( settings ),
4063			displayStart = settings._iDisplayStart,
4064			displayLength = features.bPaginate !== false ?
4065				settings._iDisplayLength :
4066				-1;
4067	
4068		var param = function ( name, value ) {
4069			data.push( { 'name': name, 'value': value } );
4070		};
4071	
4072		// DataTables 1.9- compatible method
4073		param( 'sEcho',          settings.iDraw );
4074		param( 'iColumns',       columnCount );
4075		param( 'sColumns',       _pluck( columns, 'sName' ).join(',') );
4076		param( 'iDisplayStart',  displayStart );
4077		param( 'iDisplayLength', displayLength );
4078	
4079		// DataTables 1.10+ method
4080		var d = {
4081			draw:    settings.iDraw,
4082			columns: [],
4083			order:   [],
4084			start:   displayStart,
4085			length:  displayLength,
4086			search:  {
4087				value: preSearch.sSearch,
4088				regex: preSearch.bRegex
4089			}
4090		};
4091	
4092		for ( i=0 ; i<columnCount ; i++ ) {
4093			column = columns[i];
4094			columnSearch = preColSearch[i];
4095			dataProp = typeof column.mData=="function" ? 'function' : column.mData ;
4096	
4097			d.columns.push( {
4098				data:       dataProp,
4099				name:       column.sName,
4100				searchable: column.bSearchable,
4101				orderable:  column.bSortable,
4102				search:     {
4103					value: columnSearch.sSearch,
4104					regex: columnSearch.bRegex
4105				}
4106			} );
4107	
4108			param( "mDataProp_"+i, dataProp );
4109	
4110			if ( features.bFilter ) {
4111				param( 'sSearch_'+i,     columnSearch.sSearch );
4112				param( 'bRegex_'+i,      columnSearch.bRegex );
4113				param( 'bSearchable_'+i, column.bSearchable );
4114			}
4115	
4116			if ( features.bSort ) {
4117				param( 'bSortable_'+i, column.bSortable );
4118			}
4119		}
4120	
4121		if ( features.bFilter ) {
4122			param( 'sSearch', preSearch.sSearch );
4123			param( 'bRegex', preSearch.bRegex );
4124		}
4125	
4126		if ( features.bSort ) {
4127			$.each( sort, function ( i, val ) {
4128				d.order.push( { column: val.col, dir: val.dir } );
4129	
4130				param( 'iSortCol_'+i, val.col );
4131				param( 'sSortDir_'+i, val.dir );
4132			} );
4133	
4134			param( 'iSortingCols', sort.length );
4135		}
4136	
4137		// If the legacy.ajax parameter is null, then we automatically decide which
4138		// form to use, based on sAjaxSource
4139		var legacy = DataTable.ext.legacy.ajax;
4140		if ( legacy === null ) {
4141			return settings.sAjaxSource ? data : d;
4142		}
4143	
4144		// Otherwise, if legacy has been specified then we use that to decide on the
4145		// form
4146		return legacy ? data : d;
4147	}
4148	
4149	
4150	/**
4151	 * Data the data from the server (nuking the old) and redraw the table
4152	 *  @param {object} oSettings dataTables settings object
4153	 *  @param {object} json json data return from the server.
4154	 *  @param {string} json.sEcho Tracking flag for DataTables to match requests
4155	 *  @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering
4156	 *  @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering
4157	 *  @param {array} json.aaData The data to display on this page
4158	 *  @param {string} [json.sColumns] Column ordering (sName, comma separated)
4159	 *  @memberof DataTable#oApi
4160	 */
4161	function _fnAjaxUpdateDraw ( settings, json )
4162	{
4163		// v1.10 uses camelCase variables, while 1.9 uses Hungarian notation.
4164		// Support both
4165		var compat = function ( old, modern ) {
4166			return json[old] !== undefined ? json[old] : json[modern];
4167		};
4168	
4169		var data = _fnAjaxDataSrc( settings, json );
4170		var draw            = compat( 'sEcho',                'draw' );
4171		var recordsTotal    = compat( 'iTotalRecords',        'recordsTotal' );
4172		var recordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' );
4173	
4174		if ( draw !== undefined ) {
4175			// Protect against out of sequence returns
4176			if ( draw*1 < settings.iDraw ) {
4177				return;
4178			}
4179			settings.iDraw = draw * 1;
4180		}
4181	
4182		// No data in returned object, so rather than an array, we show an empty table
4183		if ( ! data ) {
4184			data = [];
4185		}
4186	
4187		_fnClearTable( settings );
4188		settings._iRecordsTotal   = parseInt(recordsTotal, 10);
4189		settings._iRecordsDisplay = parseInt(recordsFiltered, 10);
4190	
4191		for ( var i=0, ien=data.length ; i<ien ; i++ ) {
4192			_fnAddData( settings, data[i] );
4193		}
4194		settings.aiDisplay = settings.aiDisplayMaster.slice();
4195	
4196		_fnDraw( settings, true );
4197	
4198		if ( ! settings._bInitComplete ) {
4199			_fnInitComplete( settings, json );
4200		}
4201	
4202		_fnProcessingDisplay( settings, false );
4203	}
4204	
4205	
4206	/**
4207	 * Get the data from the JSON data source to use for drawing a table. Using
4208	 * `_fnGetObjectDataFn` allows the data to be sourced from a property of the
4209	 * source object, or from a processing function.
4210	 *  @param {object} oSettings dataTables settings object
4211	 *  @param  {object} json Data source object / array from the server
4212	 *  @return {array} Array of data to use
4213	 */
4214	 function _fnAjaxDataSrc ( oSettings, json, write )
4215	 {
4216		var dataSrc = $.isPlainObject( oSettings.ajax ) && oSettings.ajax.dataSrc !== undefined ?
4217			oSettings.ajax.dataSrc :
4218			oSettings.sAjaxDataProp; // Compatibility with 1.9-.
4219	
4220		if ( ! write ) {
4221			if ( dataSrc === 'data' ) {
4222				// If the default, then we still want to support the old style, and safely ignore
4223				// it if possible
4224				return json.aaData || json[dataSrc];
4225			}
4226	
4227			return dataSrc !== "" ?
4228				_fnGetObjectDataFn( dataSrc )( json ) :
4229				json;
4230		}
4231	
4232		// set
4233		_fnSetObjectDataFn( dataSrc )( json, write );
4234	}
4235	
4236	/**
4237	 * Generate the node required for filtering text
4238	 *  @returns {node} Filter control element
4239	 *  @param {object} oSettings dataTables settings object
4240	 *  @memberof DataTable#oApi
4241	 */
4242	function _fnFeatureHtmlFilter ( settings )
4243	{
4244		var classes = settings.oClasses;
4245		var tableId = settings.sTableId;
4246		var language = settings.oLanguage;
4247		var previousSearch = settings.oPreviousSearch;
4248		var features = settings.aanFeatures;
4249		var input = '<input type="search" class="'+classes.sFilterInput+'"/>';
4250	
4251		var str = language.sSearch;
4252		str = str.match(/_INPUT_/) ?
4253			str.replace('_INPUT_', input) :
4254			str+input;
4255	
4256		var filter = $('<div/>', {
4257				'id': ! features.f ? tableId+'_filter' : null,
4258				'class': classes.sFilter
4259			} )
4260			.append( $('<label/>' ).append( str ) );
4261	
4262		var searchFn = function(event) {
4263			/* Update all other filter input elements for the new display */
4264			var n = features.f;
4265			var val = !this.value ? "" : this.value; // mental IE8 fix :-(
4266			if(previousSearch.return && event.key !== "Enter") {
4267				return;
4268			}
4269			/* Now do the filter */
4270			if ( val != previousSearch.sSearch ) {
4271				_fnFilterComplete( settings, {
4272					"sSearch": val,
4273					"bRegex": previousSearch.bRegex,
4274					"bSmart": previousSearch.bSmart ,
4275					"bCaseInsensitive": previousSearch.bCaseInsensitive,
4276					"return": previousSearch.return
4277				} );
4278	
4279				// Need to redraw, without resorting
4280				settings._iDisplayStart = 0;
4281				_fnDraw( settings );
4282			}
4283		};
4284	
4285		var searchDelay = settings.searchDelay !== null ?
4286			settings.searchDelay :
4287			_fnDataSource( settings ) === 'ssp' ?
4288				400 :
4289				0;
4290	
4291		var jqFilter = $('input', filter)
4292			.val( previousSearch.sSearch )
4293			.attr( 'placeholder', language.sSearchPlaceholder )
4294			.on(
4295				'keyup.DT search.DT input.DT paste.DT cut.DT',
4296				searchDelay ?
4297					_fnThrottle( searchFn, searchDelay ) :
4298					searchFn
4299			)
4300			.on( 'mouseup', function(e) {
4301				// Edge fix! Edge 17 does not trigger anything other than mouse events when clicking
4302				// on the clear icon (Edge bug 17584515). This is safe in other browsers as `searchFn`
4303				// checks the value to see if it has changed. In other browsers it won't have.
4304				setTimeout( function () {
4305					searchFn.call(jqFilter[0], e);
4306				}, 10);
4307			} )
4308			.on( 'keypress.DT', function(e) {
4309				/* Prevent form submission */
4310				if ( e.keyCode == 13 ) {
4311					return false;
4312				}
4313			} )
4314			.attr('aria-controls', tableId);
4315	
4316		// Update the input elements whenever the table is filtered
4317		$(settings.nTable).on( 'search.dt.DT', function ( ev, s ) {
4318			if ( settings === s ) {
4319				// IE9 throws an 'unknown error' if document.activeElement is used
4320				// inside an iframe or frame...
4321				try {
4322					if ( jqFilter[0] !== document.activeElement ) {
4323						jqFilter.val( previousSearch.sSearch );
4324					}
4325				}
4326				catch ( e ) {}
4327			}
4328		} );
4329	
4330		return filter[0];
4331	}
4332	
4333	
4334	/**
4335	 * Filter the table using both the global filter and column based filtering
4336	 *  @param {object} oSettings dataTables settings object
4337	 *  @param {object} oSearch search information
4338	 *  @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)
4339	 *  @memberof DataTable#oApi
4340	 */
4341	function _fnFilterComplete ( oSettings, oInput, iForce )
4342	{
4343		var oPrevSearch = oSettings.oPreviousSearch;
4344		var aoPrevSearch = oSettings.aoPreSearchCols;
4345		var fnSaveFilter = function ( oFilter ) {
4346			/* Save the filtering values */
4347			oPrevSearch.sSearch = oFilter.sSearch;
4348			oPrevSearch.bRegex = oFilter.bRegex;
4349			oPrevSearch.bSmart = oFilter.bSmart;
4350			oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive;
4351			oPrevSearch.return = oFilter.return;
4352		};
4353		var fnRegex = function ( o ) {
4354			// Backwards compatibility with the bEscapeRegex option
4355			return o.bEscapeRegex !== undefined ? !o.bEscapeRegex : o.bRegex;
4356		};
4357	
4358		// Resolve any column types that are unknown due to addition or invalidation
4359		// @todo As per sort - can this be moved into an event handler?
4360		_fnColumnTypes( oSettings );
4361	
4362		/* In server-side processing all filtering is done by the server, so no point hanging around here */
4363		if ( _fnDataSource( oSettings ) != 'ssp' )
4364		{
4365			/* Global filter */
4366			_fnFilter( oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive, oInput.return );
4367			fnSaveFilter( oInput );
4368	
4369			/* Now do the individual column filter */
4370			for ( var i=0 ; i<aoPrevSearch.length ; i++ )
4371			{
4372				_fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, fnRegex(aoPrevSearch[i]),
4373					aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive );
4374			}
4375	
4376			/* Custom filtering */
4377			_fnFilterCustom( oSettings );
4378		}
4379		else
4380		{
4381			fnSaveFilter( oInput );
4382		}
4383	
4384		/* Tell the draw function we have been filtering */
4385		oSettings.bFiltered = true;
4386		_fnCallbackFire( oSettings, null, 'search', [oSettings] );
4387	}
4388	
4389	
4390	/**
4391	 * Apply custom filtering functions
4392	 *  @param {object} oSettings dataTables settings object
4393	 *  @memberof DataTable#oApi
4394	 */
4395	function _fnFilterCustom( settings )
4396	{
4397		var filters = DataTable.ext.search;
4398		var displayRows = settings.aiDisplay;
4399		var row, rowIdx;
4400	
4401		for ( var i=0, ien=filters.length ; i<ien ; i++ ) {
4402			var rows = [];
4403	
4404			// Loop over each row and see if it should be included
4405			for ( var j=0, jen=displayRows.length ; j<jen ; j++ ) {
4406				rowIdx = displayRows[ j ];
4407				row = settings.aoData[ rowIdx ];
4408	
4409				if ( filters[i]( settings, row._aFilterData, rowIdx, row._aData, j ) ) {
4410					rows.push( rowIdx );
4411				}
4412			}
4413	
4414			// So the array reference doesn't break set the results into the
4415			// existing array
4416			displayRows.length = 0;
4417			$.merge( displayRows, rows );
4418		}
4419	}
4420	
4421	
4422	/**
4423	 * Filter the table on a per-column basis
4424	 *  @param {object} oSettings dataTables settings object
4425	 *  @param {string} sInput string to filter on
4426	 *  @param {int} iColumn column to filter
4427	 *  @param {bool} bRegex treat search string as a regular expression or not
4428	 *  @param {bool} bSmart use smart filtering or not
4429	 *  @param {bool} bCaseInsensitive Do case insensitive matching or not
4430	 *  @memberof DataTable#oApi
4431	 */
4432	function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, caseInsensitive )
4433	{
4434		if ( searchStr === '' ) {
4435			return;
4436		}
4437	
4438		var data;
4439		var out = [];
4440		var display = settings.aiDisplay;
4441		var rpSearch = _fnFilterCreateSearch( searchStr, regex, smart, caseInsensitive );
4442	
4443		for ( var i=0 ; i<display.length ; i++ ) {
4444			data = settings.aoData[ display[i] ]._aFilterData[ colIdx ];
4445	
4446			if ( rpSearch.test( data ) ) {
4447				out.push( display[i] );
4448			}
4449		}
4450	
4451		settings.aiDisplay = out;
4452	}
4453	
4454	
4455	/**
4456	 * Filter the data table based on user input and draw the table
4457	 *  @param {object} settings dataTables settings object
4458	 *  @param {string} input string to filter on
4459	 *  @param {int} force optional - force a research of the master array (1) or not (undefined or 0)
4460	 *  @param {bool} regex treat as a regular expression or not
4461	 *  @param {bool} smart perform smart filtering or not
4462	 *  @param {bool} caseInsensitive Do case insensitive matching or not
4463	 *  @memberof DataTable#oApi
4464	 */
4465	function _fnFilter( settings, input, force, regex, smart, caseInsensitive )
4466	{
4467		var rpSearch = _fnFilterCreateSearch( input, regex, smart, caseInsensitive );
4468		var prevSearch = settings.oPreviousSearch.sSearch;
4469		var displayMaster = settings.aiDisplayMaster;
4470		var display, invalidated, i;
4471		var filtered = [];
4472	
4473		// Need to take account of custom filtering functions - always filter
4474		if ( DataTable.ext.search.length !== 0 ) {
4475			force = true;
4476		}
4477	
4478		// Check if any of the rows were invalidated
4479		invalidated = _fnFilterData( settings );
4480	
4481		// If the input is blank - we just want the full data set
4482		if ( input.length <= 0 ) {
4483			settings.aiDisplay = displayMaster.slice();
4484		}
4485		else {
4486			// New search - start from the master array
4487			if ( invalidated ||
4488				 force ||
4489				 regex ||
4490				 prevSearch.length > input.length ||
4491				 input.indexOf(prevSearch) !== 0 ||
4492				 settings.bSorted // On resort, the display master needs to be
4493				                  // re-filtered since indexes will have changed
4494			) {
4495				settings.aiDisplay = displayMaster.slice();
4496			}
4497	
4498			// Search the display array
4499			display = settings.aiDisplay;
4500	
4501			for ( i=0 ; i<display.length ; i++ ) {
4502				if ( rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) {
4503					filtered.push( display[i] );
4504				}
4505			}
4506	
4507			settings.aiDisplay = filtered;
4508		}
4509	}
4510	
4511	
4512	/**
4513	 * Build a regular expression object suitable for searching a table
4514	 *  @param {string} sSearch string to search for
4515	 *  @param {bool} bRegex treat as a regular expression or not
4516	 *  @param {bool} bSmart perform smart filtering or not
4517	 *  @param {bool} bCaseInsensitive Do case insensitive matching or not
4518	 *  @returns {RegExp} constructed object
4519	 *  @memberof DataTable#oApi
4520	 */
4521	function _fnFilterCreateSearch( search, regex, smart, caseInsensitive )
4522	{
4523		search = regex ?
4524			search :
4525			_fnEscapeRegex( search );
4526		
4527		if ( smart ) {
4528			/* For smart filtering we want to allow the search to work regardless of
4529			 * word order. We also want double quoted text to be preserved, so word
4530			 * order is important - a la google. So this is what we want to
4531			 * generate:
4532			 * 
4533			 * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$
4534			 */
4535			var a = $.map( search.match( /"[^"]+"|[^ ]+/g ) || [''], function ( word ) {
4536				if ( word.charAt(0) === '"' ) {
4537					var m = word.match( /^"(.*)"$/ );
4538					word = m ? m[1] : word;
4539				}
4540	
4541				return word.replace('"', '');
4542			} );
4543	
4544			search = '^(?=.*?'+a.join( ')(?=.*?' )+').*$';
4545		}
4546	
4547		return new RegExp( search, caseInsensitive ? 'i' : '' );
4548	}
4549	
4550	
4551	/**
4552	 * Escape a string such that it can be used in a regular expression
4553	 *  @param {string} sVal string to escape
4554	 *  @returns {string} escaped string
4555	 *  @memberof DataTable#oApi
4556	 */
4557	var _fnEscapeRegex = DataTable.util.escapeRegex;
4558	
4559	var __filter_div = $('<div>')[0];
4560	var __filter_div_textContent = __filter_div.textContent !== undefined;
4561	
4562	// Update the filtering data for each row if needed (by invalidation or first run)
4563	function _fnFilterData ( settings )
4564	{
4565		var columns = settings.aoColumns;
4566		var column;
4567		var i, j, ien, jen, filterData, cellData, row;
4568		var wasInvalidated = false;
4569	
4570		for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
4571			row = settings.aoData[i];
4572	
4573			if ( ! row._aFilterData ) {
4574				filterData = [];
4575	
4576				for ( j=0, jen=columns.length ; j<jen ; j++ ) {
4577					column = columns[j];
4578	
4579					if ( column.bSearchable ) {
4580						cellData = _fnGetCellData( settings, i, j, 'filter' );
4581	
4582						// Search in DataTables 1.10 is string based. In 1.11 this
4583						// should be altered to also allow strict type checking.
4584						if ( cellData === null ) {
4585							cellData = '';
4586						}
4587	
4588						if ( typeof cellData !== 'string' && cellData.toString ) {
4589							cellData = cellData.toString();
4590						}
4591					}
4592					else {
4593						cellData = '';
4594					}
4595	
4596					// If it looks like there is an HTML entity in the string,
4597					// attempt to decode it so sorting works as expected. Note that
4598					// we could use a single line of jQuery to do this, but the DOM
4599					// method used here is much faster http://jsperf.com/html-decode
4600					if ( cellData.indexOf && cellData.indexOf('&') !== -1 ) {
4601						__filter_div.innerHTML = cellData;
4602						cellData = __filter_div_textContent ?
4603							__filter_div.textContent :
4604							__filter_div.innerText;
4605					}
4606	
4607					if ( cellData.replace ) {
4608						cellData = cellData.replace(/[\r\n\u2028]/g, '');
4609					}
4610	
4611					filterData.push( cellData );
4612				}
4613	
4614				row._aFilterData = filterData;
4615				row._sFilterRow = filterData.join('  ');
4616				wasInvalidated = true;
4617			}
4618		}
4619	
4620		return wasInvalidated;
4621	}
4622	
4623	
4624	/**
4625	 * Convert from the internal Hungarian notation to camelCase for external
4626	 * interaction
4627	 *  @param {object} obj Object to convert
4628	 *  @returns {object} Inverted object
4629	 *  @memberof DataTable#oApi
4630	 */
4631	function _fnSearchToCamel ( obj )
4632	{
4633		return {
4634			search:          obj.sSearch,
4635			smart:           obj.bSmart,
4636			regex:           obj.bRegex,
4637			caseInsensitive: obj.bCaseInsensitive
4638		};
4639	}
4640	
4641	
4642	
4643	/**
4644	 * Convert from camelCase notation to the internal Hungarian. We could use the
4645	 * Hungarian convert function here, but this is cleaner
4646	 *  @param {object} obj Object to convert
4647	 *  @returns {object} Inverted object
4648	 *  @memberof DataTable#oApi
4649	 */
4650	function _fnSearchToHung ( obj )
4651	{
4652		return {
4653			sSearch:          obj.search,
4654			bSmart:           obj.smart,
4655			bRegex:           obj.regex,
4656			bCaseInsensitive: obj.caseInsensitive
4657		};
4658	}
4659	
4660	/**
4661	 * Generate the node required for the info display
4662	 *  @param {object} oSettings dataTables settings object
4663	 *  @returns {node} Information element
4664	 *  @memberof DataTable#oApi
4665	 */
4666	function _fnFeatureHtmlInfo ( settings )
4667	{
4668		var
4669			tid = settings.sTableId,
4670			nodes = settings.aanFeatures.i,
4671			n = $('<div/>', {
4672				'class': settings.oClasses.sInfo,
4673				'id': ! nodes ? tid+'_info' : null
4674			} );
4675	
4676		if ( ! nodes ) {
4677			// Update display on each draw
4678			settings.aoDrawCallback.push( {
4679				"fn": _fnUpdateInfo,
4680				"sName": "information"
4681			} );
4682	
4683			n
4684				.attr( 'role', 'status' )
4685				.attr( 'aria-live', 'polite' );
4686	
4687			// Table is described by our info div
4688			$(settings.nTable).attr( 'aria-describedby', tid+'_info' );
4689		}
4690	
4691		return n[0];
4692	}
4693	
4694	
4695	/**
4696	 * Update the information elements in the display
4697	 *  @param {object} settings dataTables settings object
4698	 *  @memberof DataTable#oApi
4699	 */
4700	function _fnUpdateInfo ( settings )
4701	{
4702		/* Show information about the table */
4703		var nodes = settings.aanFeatures.i;
4704		if ( nodes.length === 0 ) {
4705			return;
4706		}
4707	
4708		var
4709			lang  = settings.oLanguage,
4710			start = settings._iDisplayStart+1,
4711			end   = settings.fnDisplayEnd(),
4712			max   = settings.fnRecordsTotal(),
4713			total = settings.fnRecordsDisplay(),
4714			out   = total ?
4715				lang.sInfo :
4716				lang.sInfoEmpty;
4717	
4718		if ( total !== max ) {
4719			/* Record set after filtering */
4720			out += ' ' + lang.sInfoFiltered;
4721		}
4722	
4723		// Convert the macros
4724		out += lang.sInfoPostFix;
4725		out = _fnInfoMacros( settings, out );
4726	
4727		var callback = lang.fnInfoCallback;
4728		if ( callback !== null ) {
4729			out = callback.call( settings.oInstance,
4730				settings, start, end, max, total, out
4731			);
4732		}
4733	
4734		$(nodes).html( out );
4735	}
4736	
4737	
4738	function _fnInfoMacros ( settings, str )
4739	{
4740		// When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
4741		// internally
4742		var
4743			formatter  = settings.fnFormatNumber,
4744			start      = settings._iDisplayStart+1,
4745			len        = settings._iDisplayLength,
4746			vis        = settings.fnRecordsDisplay(),
4747			all        = len === -1;
4748	
4749		return str.
4750			replace(/_START_/g, formatter.call( settings, start ) ).
4751			replace(/_END_/g,   formatter.call( settings, settings.fnDisplayEnd() ) ).
4752			replace(/_MAX_/g,   formatter.call( settings, settings.fnRecordsTotal() ) ).
4753			replace(/_TOTAL_/g, formatter.call( settings, vis ) ).
4754			replace(/_PAGE_/g,  formatter.call( settings, all ? 1 : Math.ceil( start / len ) ) ).
4755			replace(/_PAGES_/g, formatter.call( settings, all ? 1 : Math.ceil( vis / len ) ) );
4756	}
4757	
4758	
4759	
4760	/**
4761	 * Draw the table for the first time, adding all required features
4762	 *  @param {object} settings dataTables settings object
4763	 *  @memberof DataTable#oApi
4764	 */
4765	function _fnInitialise ( settings )
4766	{
4767		var i, iLen, iAjaxStart=settings.iInitDisplayStart;
4768		var columns = settings.aoColumns, column;
4769		var features = settings.oFeatures;
4770		var deferLoading = settings.bDeferLoading; // value modified by the draw
4771	
4772		/* Ensure that the table data is fully initialised */
4773		if ( ! settings.bInitialised ) {
4774			setTimeout( function(){ _fnInitialise( settings ); }, 200 );
4775			return;
4776		}
4777	
4778		/* Show the display HTML options */
4779		_fnAddOptionsHtml( settings );
4780	
4781		/* Build and draw the header / footer for the table */
4782		_fnBuildHead( settings );
4783		_fnDrawHead( settings, settings.aoHeader );
4784		_fnDrawHead( settings, settings.aoFooter );
4785	
4786		/* Okay to show that something is going on now */
4787		_fnProcessingDisplay( settings, true );
4788	
4789		/* Calculate sizes for columns */
4790		if ( features.bAutoWidth ) {
4791			_fnCalculateColumnWidths( settings );
4792		}
4793	
4794		for ( i=0, iLen=columns.length ; i<iLen ; i++ ) {
4795			column = columns[i];
4796	
4797			if ( column.sWidth ) {
4798				column.nTh.style.width = _fnStringToCss( column.sWidth );
4799			}
4800		}
4801	
4802		_fnCallbackFire( settings, null, 'preInit', [settings] );
4803	
4804		// If there is default sorting required - let's do it. The sort function
4805		// will do the drawing for us. Otherwise we draw the table regardless of the
4806		// Ajax source - this allows the table to look initialised for Ajax sourcing
4807		// data (show 'loading' message possibly)
4808		_fnReDraw( settings );
4809	
4810		// Server-side processing init complete is done by _fnAjaxUpdateDraw
4811		var dataSrc = _fnDataSource( settings );
4812		if ( dataSrc != 'ssp' || deferLoading ) {
4813			// if there is an ajax source load the data
4814			if ( dataSrc == 'ajax' ) {
4815				_fnBuildAjax( settings, [], function(json) {
4816					var aData = _fnAjaxDataSrc( settings, json );
4817	
4818					// Got the data - add it to the table
4819					for ( i=0 ; i<aData.length ; i++ ) {
4820						_fnAddData( settings, aData[i] );
4821					}
4822	
4823					// Reset the init display for cookie saving. We've already done
4824					// a filter, and therefore cleared it before. So we need to make
4825					// it appear 'fresh'
4826					settings.iInitDisplayStart = iAjaxStart;
4827	
4828					_fnReDraw( settings );
4829	
4830					_fnProcessingDisplay( settings, false );
4831					_fnInitComplete( settings, json );
4832				}, settings );
4833			}
4834			else {
4835				_fnProcessingDisplay( settings, false );
4836				_fnInitComplete( settings );
4837			}
4838		}
4839	}
4840	
4841	
4842	/**
4843	 * Draw the table for the first time, adding all required features
4844	 *  @param {object} oSettings dataTables settings object
4845	 *  @param {object} [json] JSON from the server that completed the table, if using Ajax source
4846	 *    with client-side processing (optional)
4847	 *  @memberof DataTable#oApi
4848	 */
4849	function _fnInitComplete ( settings, json )
4850	{
4851		settings._bInitComplete = true;
4852	
4853		// When data was added after the initialisation (data or Ajax) we need to
4854		// calculate the column sizing
4855		if ( json || settings.oInit.aaData ) {
4856			_fnAdjustColumnSizing( settings );
4857		}
4858	
4859		_fnCallbackFire( settings, null, 'plugin-init', [settings, json] );
4860		_fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] );
4861	}
4862	
4863	
4864	function _fnLengthChange ( settings, val )
4865	{
4866		var len = parseInt( val, 10 );
4867		settings._iDisplayLength = len;
4868	
4869		_fnLengthOverflow( settings );
4870	
4871		// Fire length change event
4872		_fnCallbackFire( settings, null, 'length', [settings, len] );
4873	}
4874	
4875	
4876	/**
4877	 * Generate the node required for user display length changing
4878	 *  @param {object} settings dataTables settings object
4879	 *  @returns {node} Display length feature node
4880	 *  @memberof DataTable#oApi
4881	 */
4882	function _fnFeatureHtmlLength ( settings )
4883	{
4884		var
4885			classes  = settings.oClasses,
4886			tableId  = settings.sTableId,
4887			menu     = settings.aLengthMenu,
4888			d2       = Array.isArray( menu[0] ),
4889			lengths  = d2 ? menu[0] : menu,
4890			language = d2 ? menu[1] : menu;
4891	
4892		var select = $('<select/>', {
4893			'name':          tableId+'_length',
4894			'aria-controls': tableId,
4895			'class':         classes.sLengthSelect
4896		} );
4897	
4898		for ( var i=0, ien=lengths.length ; i<ien ; i++ ) {
4899			select[0][ i ] = new Option(
4900				typeof language[i] === 'number' ?
4901					settings.fnFormatNumber( language[i] ) :
4902					language[i],
4903				lengths[i]
4904			);
4905		}
4906	
4907		var div = $('<div><label/></div>').addClass( classes.sLength );
4908		if ( ! settings.aanFeatures.l ) {
4909			div[0].id = tableId+'_length';
4910		}
4911	
4912		div.children().append(
4913			settings.oLanguage.sLengthMenu.replace( '_MENU_', select[0].outerHTML )
4914		);
4915	
4916		// Can't use `select` variable as user might provide their own and the
4917		// reference is broken by the use of outerHTML
4918		$('select', div)
4919			.val( settings._iDisplayLength )
4920			.on( 'change.DT', function(e) {
4921				_fnLengthChange( settings, $(this).val() );
4922				_fnDraw( settings );
4923			} );
4924	
4925		// Update node value whenever anything changes the table's length
4926		$(settings.nTable).on( 'length.dt.DT', function (e, s, len) {
4927			if ( settings === s ) {
4928				$('select', div).val( len );
4929			}
4930		} );
4931	
4932		return div[0];
4933	}
4934	
4935	
4936	
4937	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
4938	 * Note that most of the paging logic is done in
4939	 * DataTable.ext.pager
4940	 */
4941	
4942	/**
4943	 * Generate the node required for default pagination
4944	 *  @param {object} oSettings dataTables settings object
4945	 *  @returns {node} Pagination feature node
4946	 *  @memberof DataTable#oApi
4947	 */
4948	function _fnFeatureHtmlPaginate ( settings )
4949	{
4950		var
4951			type   = settings.sPaginationType,
4952			plugin = DataTable.ext.pager[ type ],
4953			modern = typeof plugin === 'function',
4954			redraw = function( settings ) {
4955				_fnDraw( settings );
4956			},
4957			node = $('<div/>').addClass( settings.oClasses.sPaging + type )[0],
4958			features = settings.aanFeatures;
4959	
4960		if ( ! modern ) {
4961			plugin.fnInit( settings, node, redraw );
4962		}
4963	
4964		/* Add a draw callback for the pagination on first instance, to update the paging display */
4965		if ( ! features.p )
4966		{
4967			node.id = settings.sTableId+'_paginate';
4968	
4969			settings.aoDrawCallback.push( {
4970				"fn": function( settings ) {
4971					if ( modern ) {
4972						var
4973							start      = settings._iDisplayStart,
4974							len        = settings._iDisplayLength,
4975							visRecords = settings.fnRecordsDisplay(),
4976							all        = len === -1,
4977							page = all ? 0 : Math.ceil( start / len ),
4978							pages = all ? 1 : Math.ceil( visRecords / len ),
4979							buttons = plugin(page, pages),
4980							i, ien;
4981	
4982						for ( i=0, ien=features.p.length ; i<ien ; i++ ) {
4983							_fnRenderer( settings, 'pageButton' )(
4984								settings, features.p[i], i, buttons, page, pages
4985							);
4986						}
4987					}
4988					else {
4989						plugin.fnUpdate( settings, redraw );
4990					}
4991				},
4992				"sName": "pagination"
4993			} );
4994		}
4995	
4996		return node;
4997	}
4998	
4999	
5000	/**
5001	 * Alter the display settings to change the page
5002	 *  @param {object} settings DataTables settings object
5003	 *  @param {string|int} action Paging action to take: "first", "previous",
5004	 *    "next" or "last" or page number to jump to (integer)
5005	 *  @param [bool] redraw Automatically draw the update or not
5006	 *  @returns {bool} true page has changed, false - no change
5007	 *  @memberof DataTable#oApi
5008	 */
5009	function _fnPageChange ( settings, action, redraw )
5010	{
5011		var
5012			start     = settings._iDisplayStart,
5013			len       = settings._iDisplayLength,
5014			records   = settings.fnRecordsDisplay();
5015	
5016		if ( records === 0 || len === -1 )
5017		{
5018			start = 0;
5019		}
5020		else if ( typeof action === "number" )
5021		{
5022			start = action * len;
5023	
5024			if ( start > records )
5025			{
5026				start = 0;
5027			}
5028		}
5029		else if ( action == "first" )
5030		{
5031			start = 0;
5032		}
5033		else if ( action == "previous" )
5034		{
5035			start = len >= 0 ?
5036				start - len :
5037				0;
5038	
5039			if ( start < 0 )
5040			{
5041			  start = 0;
5042			}
5043		}
5044		else if ( action == "next" )
5045		{
5046			if ( start + len < records )
5047			{
5048				start += len;
5049			}
5050		}
5051		else if ( action == "last" )
5052		{
5053			start = Math.floor( (records-1) / len) * len;
5054		}
5055		else
5056		{
5057			_fnLog( settings, 0, "Unknown paging action: "+action, 5 );
5058		}
5059	
5060		var changed = settings._iDisplayStart !== start;
5061		settings._iDisplayStart = start;
5062	
5063		if ( changed ) {
5064			_fnCallbackFire( settings, null, 'page', [settings] );
5065	
5066			if ( redraw ) {
5067				_fnDraw( settings );
5068			}
5069		}
5070	
5071		return changed;
5072	}
5073	
5074	
5075	
5076	/**
5077	 * Generate the node required for the processing node
5078	 *  @param {object} settings dataTables settings object
5079	 *  @returns {node} Processing element
5080	 *  @memberof DataTable#oApi
5081	 */
5082	function _fnFeatureHtmlProcessing ( settings )
5083	{
5084		return $('<div/>', {
5085				'id': ! settings.aanFeatures.r ? settings.sTableId+'_processing' : null,
5086				'class': settings.oClasses.sProcessing
5087			} )
5088			.html( settings.oLanguage.sProcessing )
5089			.append('<div><div></div><div></div><div></div><div></div></div>')
5090			.insertBefore( settings.nTable )[0];
5091	}
5092	
5093	
5094	/**
5095	 * Display or hide the processing indicator
5096	 *  @param {object} settings dataTables settings object
5097	 *  @param {bool} show Show the processing indicator (true) or not (false)
5098	 *  @memberof DataTable#oApi
5099	 */
5100	function _fnProcessingDisplay ( settings, show )
5101	{
5102		if ( settings.oFeatures.bProcessing ) {
5103			$(settings.aanFeatures.r).css( 'display', show ? 'block' : 'none' );
5104		}
5105	
5106		_fnCallbackFire( settings, null, 'processing', [settings, show] );
5107	}
5108	
5109	/**
5110	 * Add any control elements for the table - specifically scrolling
5111	 *  @param {object} settings dataTables settings object
5112	 *  @returns {node} Node to add to the DOM
5113	 *  @memberof DataTable#oApi
5114	 */
5115	function _fnFeatureHtmlTable ( settings )
5116	{
5117		var table = $(settings.nTable);
5118	
5119		// Scrolling from here on in
5120		var scroll = settings.oScroll;
5121	
5122		if ( scroll.sX === '' && scroll.sY === '' ) {
5123			return settings.nTable;
5124		}
5125	
5126		var scrollX = scroll.sX;
5127		var scrollY = scroll.sY;
5128		var classes = settings.oClasses;
5129		var caption = table.children('caption');
5130		var captionSide = caption.length ? caption[0]._captionSide : null;
5131		var headerClone = $( table[0].cloneNode(false) );
5132		var footerClone = $( table[0].cloneNode(false) );
5133		var footer = table.children('tfoot');
5134		var _div = '<div/>';
5135		var size = function ( s ) {
5136			return !s ? null : _fnStringToCss( s );
5137		};
5138	
5139		if ( ! footer.length ) {
5140			footer = null;
5141		}
5142	
5143		/*
5144		 * The HTML structure that we want to generate in this function is:
5145		 *  div - scroller
5146		 *    div - scroll head
5147		 *      div - scroll head inner
5148		 *        table - scroll head table
5149		 *          thead - thead
5150		 *    div - scroll body
5151		 *      table - table (master table)
5152		 *        thead - thead clone for sizing
5153		 *        tbody - tbody
5154		 *    div - scroll foot
5155		 *      div - scroll foot inner
5156		 *        table - scroll foot table
5157		 *          tfoot - tfoot
5158		 */
5159		var scroller = $( _div, { 'class': classes.sScrollWrapper } )
5160			.append(
5161				$(_div, { 'class': classes.sScrollHead } )
5162					.css( {
5163						overflow: 'hidden',
5164						position: 'relative',
5165						border: 0,
5166						width: scrollX ? size(scrollX) : '100%'
5167					} )
5168					.append(
5169						$(_div, { 'class': classes.sScrollHeadInner } )
5170							.css( {
5171								'box-sizing': 'content-box',
5172								width: scroll.sXInner || '100%'
5173							} )
5174							.append(
5175								headerClone
5176									.removeAttr('id')
5177									.css( 'margin-left', 0 )
5178									.append( captionSide === 'top' ? caption : null )
5179									.append(
5180										table.children('thead')
5181									)
5182							)
5183					)
5184			)
5185			.append(
5186				$(_div, { 'class': classes.sScrollBody } )
5187					.css( {
5188						position: 'relative',
5189						overflow: 'auto',
5190						width: size( scrollX )
5191					} )
5192					.append( table )
5193			);
5194	
5195		if ( footer ) {
5196			scroller.append(
5197				$(_div, { 'class': classes.sScrollFoot } )
5198					.css( {
5199						overflow: 'hidden',
5200						border: 0,
5201						width: scrollX ? size(scrollX) : '100%'
5202					} )
5203					.append(
5204						$(_div, { 'class': classes.sScrollFootInner } )
5205							.append(
5206								footerClone
5207									.removeAttr('id')
5208									.css( 'margin-left', 0 )
5209									.append( captionSide === 'bottom' ? caption : null )
5210									.append(
5211										table.children('tfoot')
5212									)
5213							)
5214					)
5215			);
5216		}
5217	
5218		var children = scroller.children();
5219		var scrollHead = children[0];
5220		var scrollBody = children[1];
5221		var scrollFoot = footer ? children[2] : null;
5222	
5223		// When the body is scrolled, then we also want to scroll the headers
5224		if ( scrollX ) {
5225			$(scrollBody).on( 'scroll.DT', function (e) {
5226				var scrollLeft = this.scrollLeft;
5227	
5228				scrollHead.scrollLeft = scrollLeft;
5229	
5230				if ( footer ) {
5231					scrollFoot.scrollLeft = scrollLeft;
5232				}
5233			} );
5234		}
5235	
5236		$(scrollBody).css('max-height', scrollY);
5237		if (! scroll.bCollapse) {
5238			$(scrollBody).css('height', scrollY);
5239		}
5240	
5241		settings.nScrollHead = scrollHead;
5242		settings.nScrollBody = scrollBody;
5243		settings.nScrollFoot = scrollFoot;
5244	
5245		// On redraw - align columns
5246		settings.aoDrawCallback.push( {
5247			"fn": _fnScrollDraw,
5248			"sName": "scrolling"
5249		} );
5250	
5251		return scroller[0];
5252	}
5253	
5254	
5255	
5256	/**
5257	 * Update the header, footer and body tables for resizing - i.e. column
5258	 * alignment.
5259	 *
5260	 * Welcome to the most horrible function DataTables. The process that this
5261	 * function follows is basically:
5262	 *   1. Re-create the table inside the scrolling div
5263	 *   2. Take live measurements from the DOM
5264	 *   3. Apply the measurements to align the columns
5265	 *   4. Clean up
5266	 *
5267	 *  @param {object} settings dataTables settings object
5268	 *  @memberof DataTable#oApi
5269	 */
5270	function _fnScrollDraw ( settings )
5271	{
5272		// Given that this is such a monster function, a lot of variables are use
5273		// to try and keep the minimised size as small as possible
5274		var
5275			scroll         = settings.oScroll,
5276			scrollX        = scroll.sX,
5277			scrollXInner   = scroll.sXInner,
5278			scrollY        = scroll.sY,
5279			barWidth       = scroll.iBarWidth,
5280			divHeader      = $(settings.nScrollHead),
5281			divHeaderStyle = divHeader[0].style,
5282			divHeaderInner = divHeader.children('div'),
5283			divHeaderInnerStyle = divHeaderInner[0].style,
5284			divHeaderTable = divHeaderInner.children('table'),
5285			divBodyEl      = settings.nScrollBody,
5286			divBody        = $(divBodyEl),
5287			divBodyStyle   = divBodyEl.style,
5288			divFooter      = $(settings.nScrollFoot),
5289			divFooterInner = divFooter.children('div'),
5290			divFooterTable = divFooterInner.children('table'),
5291			header         = $(settings.nTHead),
5292			table          = $(settings.nTable),
5293			tableEl        = table[0],
5294			tableStyle     = tableEl.style,
5295			footer         = settings.nTFoot ? $(settings.nTFoot) : null,
5296			browser        = settings.oBrowser,
5297			ie67           = browser.bScrollOversize,
5298			dtHeaderCells  = _pluck( settings.aoColumns, 'nTh' ),
5299			headerTrgEls, footerTrgEls,
5300			headerSrcEls, footerSrcEls,
5301			headerCopy, footerCopy,
5302			headerWidths=[], footerWidths=[],
5303			headerContent=[], footerContent=[],
5304			idx, correction, sanityWidth,
5305			zeroOut = function(nSizer) {
5306				var style = nSizer.style;
5307				style.paddingTop = "0";
5308				style.paddingBottom = "0";
5309				style.borderTopWidth = "0";
5310				style.borderBottomWidth = "0";
5311				style.height = 0;
5312			};
5313	
5314		// If the scrollbar visibility has changed from the last draw, we need to
5315		// adjust the column sizes as the table width will have changed to account
5316		// for the scrollbar
5317		var scrollBarVis = divBodyEl.scrollHeight > divBodyEl.clientHeight;
5318		
5319		if ( settings.scrollBarVis !== scrollBarVis && settings.scrollBarVis !== undefined ) {
5320			settings.scrollBarVis = scrollBarVis;
5321			_fnAdjustColumnSizing( settings );
5322			return; // adjust column sizing will call this function again
5323		}
5324		else {
5325			settings.scrollBarVis = scrollBarVis;
5326		}
5327	
5328		/*
5329		 * 1. Re-create the table inside the scrolling div
5330		 */
5331	
5332		// Remove the old minimised thead and tfoot elements in the inner table
5333		table.children('thead, tfoot').remove();
5334	
5335		if ( footer ) {
5336			footerCopy = footer.clone().prependTo( table );
5337			footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized
5338			footerSrcEls = footerCopy.find('tr');
5339			footerCopy.find('[id]').removeAttr('id');
5340		}
5341	
5342		// Clone the current header and footer elements and then place it into the inner table
5343		headerCopy = header.clone().prependTo( table );
5344		headerTrgEls = header.find('tr'); // original header is in its own table
5345		headerSrcEls = headerCopy.find('tr');
5346		headerCopy.find('th, td').removeAttr('tabindex');
5347		headerCopy.find('[id]').removeAttr('id');
5348	
5349	
5350		/*
5351		 * 2. Take live measurements from the DOM - do not alter the DOM itself!
5352		 */
5353	
5354		// Remove old sizing and apply the calculated column widths
5355		// Get the unique column headers in the newly created (cloned) header. We want to apply the
5356		// calculated sizes to this header
5357		if ( ! scrollX )
5358		{
5359			divBodyStyle.width = '100%';
5360			divHeader[0].style.width = '100%';
5361		}
5362	
5363		$.each( _fnGetUniqueThs( settings, headerCopy ), function ( i, el ) {
5364			idx = _fnVisibleToColumnIndex( settings, i );
5365			el.style.width = settings.aoColumns[idx].sWidth;
5366		} );
5367	
5368		if ( footer ) {
5369			_fnApplyToChildren( function(n) {
5370				n.style.width = "";
5371			}, footerSrcEls );
5372		}
5373	
5374		// Size the table as a whole
5375		sanityWidth = table.outerWidth();
5376		if ( scrollX === "" ) {
5377			// No x scrolling
5378			tableStyle.width = "100%";
5379	
5380			// IE7 will make the width of the table when 100% include the scrollbar
5381			// - which is shouldn't. When there is a scrollbar we need to take this
5382			// into account.
5383			if ( ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight ||
5384				divBody.css('overflow-y') == "scroll")
5385			) {
5386				tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth);
5387			}
5388	
5389			// Recalculate the sanity width
5390			sanityWidth = table.outerWidth();
5391		}
5392		else if ( scrollXInner !== "" ) {
5393			// legacy x scroll inner has been given - use it
5394			tableStyle.width = _fnStringToCss(scrollXInner);
5395	
5396			// Recalculate the sanity width
5397			sanityWidth = table.outerWidth();
5398		}
5399	
5400		// Hidden header should have zero height, so remove padding and borders. Then
5401		// set the width based on the real headers
5402	
5403		// Apply all styles in one pass
5404		_fnApplyToChildren( zeroOut, headerSrcEls );
5405	
5406		// Read all widths in next pass
5407		_fnApplyToChildren( function(nSizer) {
5408			var style = window.getComputedStyle ?
5409				window.getComputedStyle(nSizer).width :
5410				_fnStringToCss( $(nSizer).width() );
5411	
5412			headerContent.push( nSizer.innerHTML );
5413			headerWidths.push( style );
5414		}, headerSrcEls );
5415	
5416		// Apply all widths in final pass
5417		_fnApplyToChildren( function(nToSize, i) {
5418			nToSize.style.width = headerWidths[i];
5419		}, headerTrgEls );
5420	
5421		$(headerSrcEls).css('height', 0);
5422	
5423		/* Same again with the footer if we have one */
5424		if ( footer )
5425		{
5426			_fnApplyToChildren( zeroOut, footerSrcEls );
5427	
5428			_fnApplyToChildren( function(nSizer) {
5429				footerContent.push( nSizer.innerHTML );
5430				footerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
5431			}, footerSrcEls );
5432	
5433			_fnApplyToChildren( function(nToSize, i) {
5434				nToSize.style.width = footerWidths[i];
5435			}, footerTrgEls );
5436	
5437			$(footerSrcEls).height(0);
5438		}
5439	
5440	
5441		/*
5442		 * 3. Apply the measurements
5443		 */
5444	
5445		// "Hide" the header and footer that we used for the sizing. We need to keep
5446		// the content of the cell so that the width applied to the header and body
5447		// both match, but we want to hide it completely. We want to also fix their
5448		// width to what they currently are
5449		_fnApplyToChildren( function(nSizer, i) {
5450			nSizer.innerHTML = '<div class="dataTables_sizing">'+headerContent[i]+'</div>';
5451			nSizer.childNodes[0].style.height = "0";
5452			nSizer.childNodes[0].style.overflow = "hidden";
5453			nSizer.style.width = headerWidths[i];
5454		}, headerSrcEls );
5455	
5456		if ( footer )
5457		{
5458			_fnApplyToChildren( function(nSizer, i) {
5459				nSizer.innerHTML = '<div class="dataTables_sizing">'+footerContent[i]+'</div>';
5460				nSizer.childNodes[0].style.height = "0";
5461				nSizer.childNodes[0].style.overflow = "hidden";
5462				nSizer.style.width = footerWidths[i];
5463			}, footerSrcEls );
5464		}
5465	
5466		// Sanity check that the table is of a sensible width. If not then we are going to get
5467		// misalignment - try to prevent this by not allowing the table to shrink below its min width
5468		if ( Math.round(table.outerWidth()) < Math.round(sanityWidth) )
5469		{
5470			// The min width depends upon if we have a vertical scrollbar visible or not */
5471			correction = ((divBodyEl.scrollHeight > divBodyEl.offsetHeight ||
5472				divBody.css('overflow-y') == "scroll")) ?
5473					sanityWidth+barWidth :
5474					sanityWidth;
5475	
5476			// IE6/7 are a law unto themselves...
5477			if ( ie67 && (divBodyEl.scrollHeight >
5478				divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll")
5479			) {
5480				tableStyle.width = _fnStringToCss( correction-barWidth );
5481			}
5482	
5483			// And give the user a warning that we've stopped the table getting too small
5484			if ( scrollX === "" || scrollXInner !== "" ) {
5485				_fnLog( settings, 1, 'Possible column misalignment', 6 );
5486			}
5487		}
5488		else
5489		{
5490			correction = '100%';
5491		}
5492	
5493		// Apply to the container elements
5494		divBodyStyle.width = _fnStringToCss( correction );
5495		divHeaderStyle.width = _fnStringToCss( correction );
5496	
5497		if ( footer ) {
5498			settings.nScrollFoot.style.width = _fnStringToCss( correction );
5499		}
5500	
5501	
5502		/*
5503		 * 4. Clean up
5504		 */
5505		if ( ! scrollY ) {
5506			/* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
5507			 * the scrollbar height from the visible display, rather than adding it on. We need to
5508			 * set the height in order to sort this. Don't want to do it in any other browsers.
5509			 */
5510			if ( ie67 ) {
5511				divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+barWidth );
5512			}
5513		}
5514	
5515		/* Finally set the width's of the header and footer tables */
5516		var iOuterWidth = table.outerWidth();
5517		divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth );
5518		divHeaderInnerStyle.width = _fnStringToCss( iOuterWidth );
5519	
5520		// Figure out if there are scrollbar present - if so then we need a the header and footer to
5521		// provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
5522		var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll";
5523		var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' );
5524		divHeaderInnerStyle[ padding ] = bScrolling ? barWidth+"px" : "0px";
5525	
5526		if ( footer ) {
5527			divFooterTable[0].style.width = _fnStringToCss( iOuterWidth );
5528			divFooterInner[0].style.width = _fnStringToCss( iOuterWidth );
5529			divFooterInner[0].style[padding] = bScrolling ? barWidth+"px" : "0px";
5530		}
5531	
5532		// Correct DOM ordering for colgroup - comes before the thead
5533		table.children('colgroup').insertBefore( table.children('thead') );
5534	
5535		/* Adjust the position of the header in case we loose the y-scrollbar */
5536		divBody.trigger('scroll');
5537	
5538		// If sorting or filtering has occurred, jump the scrolling back to the top
5539		// only if we aren't holding the position
5540		if ( (settings.bSorted || settings.bFiltered) && ! settings._drawHold ) {
5541			divBodyEl.scrollTop = 0;
5542		}
5543	}
5544	
5545	
5546	
5547	/**
5548	 * Apply a given function to the display child nodes of an element array (typically
5549	 * TD children of TR rows
5550	 *  @param {function} fn Method to apply to the objects
5551	 *  @param array {nodes} an1 List of elements to look through for display children
5552	 *  @param array {nodes} an2 Another list (identical structure to the first) - optional
5553	 *  @memberof DataTable#oApi
5554	 */
5555	function _fnApplyToChildren( fn, an1, an2 )
5556	{
5557		var index=0, i=0, iLen=an1.length;
5558		var nNode1, nNode2;
5559	
5560		while ( i < iLen ) {
5561			nNode1 = an1[i].firstChild;
5562			nNode2 = an2 ? an2[i].firstChild : null;
5563	
5564			while ( nNode1 ) {
5565				if ( nNode1.nodeType === 1 ) {
5566					if ( an2 ) {
5567						fn( nNode1, nNode2, index );
5568					}
5569					else {
5570						fn( nNode1, index );
5571					}
5572	
5573					index++;
5574				}
5575	
5576				nNode1 = nNode1.nextSibling;
5577				nNode2 = an2 ? nNode2.nextSibling : null;
5578			}
5579	
5580			i++;
5581		}
5582	}
5583	
5584	
5585	
5586	var __re_html_remove = /<.*?>/g;
5587	
5588	
5589	/**
5590	 * Calculate the width of columns for the table
5591	 *  @param {object} oSettings dataTables settings object
5592	 *  @memberof DataTable#oApi
5593	 */
5594	function _fnCalculateColumnWidths ( oSettings )
5595	{
5596		var
5597			table = oSettings.nTable,
5598			columns = oSettings.aoColumns,
5599			scroll = oSettings.oScroll,
5600			scrollY = scroll.sY,
5601			scrollX = scroll.sX,
5602			scrollXInner = scroll.sXInner,
5603			columnCount = columns.length,
5604			visibleColumns = _fnGetColumns( oSettings, 'bVisible' ),
5605			headerCells = $('th', oSettings.nTHead),
5606			tableWidthAttr = table.getAttribute('width'), // from DOM element
5607			tableContainer = table.parentNode,
5608			userInputs = false,
5609			i, column, columnIdx, width, outerWidth,
5610			browser = oSettings.oBrowser,
5611			ie67 = browser.bScrollOversize;
5612	
5613		var styleWidth = table.style.width;
5614		if ( styleWidth && styleWidth.indexOf('%') !== -1 ) {
5615			tableWidthAttr = styleWidth;
5616		}
5617	
5618		/* Convert any user input sizes into pixel sizes */
5619		for ( i=0 ; i<visibleColumns.length ; i++ ) {
5620			column = columns[ visibleColumns[i] ];
5621	
5622			if ( column.sWidth !== null ) {
5623				column.sWidth = _fnConvertToWidth( column.sWidthOrig, tableContainer );
5624	
5625				userInputs = true;
5626			}
5627		}
5628	
5629		/* If the number of columns in the DOM equals the number that we have to
5630		 * process in DataTables, then we can use the offsets that are created by
5631		 * the web- browser. No custom sizes can be set in order for this to happen,
5632		 * nor scrolling used
5633		 */
5634		if ( ie67 || ! userInputs && ! scrollX && ! scrollY &&
5635		     columnCount == _fnVisbleColumns( oSettings ) &&
5636		     columnCount == headerCells.length
5637		) {
5638			for ( i=0 ; i<columnCount ; i++ ) {
5639				var colIdx = _fnVisibleToColumnIndex( oSettings, i );
5640	
5641				if ( colIdx !== null ) {
5642					columns[ colIdx ].sWidth = _fnStringToCss( headerCells.eq(i).width() );
5643				}
5644			}
5645		}
5646		else
5647		{
5648			// Otherwise construct a single row, worst case, table with the widest
5649			// node in the data, assign any user defined widths, then insert it into
5650			// the DOM and allow the browser to do all the hard work of calculating
5651			// table widths
5652			var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table
5653				.css( 'visibility', 'hidden' )
5654				.removeAttr( 'id' );
5655	
5656			// Clean up the table body
5657			tmpTable.find('tbody tr').remove();
5658			var tr = $('<tr/>').appendTo( tmpTable.find('tbody') );
5659	
5660			// Clone the table header and footer - we can't use the header / footer
5661			// from the cloned table, since if scrolling is active, the table's
5662			// real header and footer are contained in different table tags
5663			tmpTable.find('thead, tfoot').remove();
5664			tmpTable
5665				.append( $(oSettings.nTHead).clone() )
5666				.append( $(oSettings.nTFoot).clone() );
5667	
5668			// Remove any assigned widths from the footer (from scrolling)
5669			tmpTable.find('tfoot th, tfoot td').css('width', '');
5670	
5671			// Apply custom sizing to the cloned header
5672			headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] );
5673	
5674			for ( i=0 ; i<visibleColumns.length ; i++ ) {
5675				column = columns[ visibleColumns[i] ];
5676	
5677				headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ?
5678					_fnStringToCss( column.sWidthOrig ) :
5679					'';
5680	
5681				// For scrollX we need to force the column width otherwise the
5682				// browser will collapse it. If this width is smaller than the
5683				// width the column requires, then it will have no effect
5684				if ( column.sWidthOrig && scrollX ) {
5685					$( headerCells[i] ).append( $('<div/>').css( {
5686						width: column.sWidthOrig,
5687						margin: 0,
5688						padding: 0,
5689						border: 0,
5690						height: 1
5691					} ) );
5692				}
5693			}
5694	
5695			// Find the widest cell for each column and put it into the table
5696			if ( oSettings.aoData.length ) {
5697				for ( i=0 ; i<visibleColumns.length ; i++ ) {
5698					columnIdx = visibleColumns[i];
5699					column = columns[ columnIdx ];
5700	
5701					$( _fnGetWidestNode( oSettings, columnIdx ) )
5702						.clone( false )
5703						.append( column.sContentPadding )
5704						.appendTo( tr );
5705				}
5706			}
5707	
5708			// Tidy the temporary table - remove name attributes so there aren't
5709			// duplicated in the dom (radio elements for example)
5710			$('[name]', tmpTable).removeAttr('name');
5711	
5712			// Table has been built, attach to the document so we can work with it.
5713			// A holding element is used, positioned at the top of the container
5714			// with minimal height, so it has no effect on if the container scrolls
5715			// or not. Otherwise it might trigger scrolling when it actually isn't
5716			// needed
5717			var holder = $('<div/>').css( scrollX || scrollY ?
5718					{
5719						position: 'absolute',
5720						top: 0,
5721						left: 0,
5722						height: 1,
5723						right: 0,
5724						overflow: 'hidden'
5725					} :
5726					{}
5727				)
5728				.append( tmpTable )
5729				.appendTo( tableContainer );
5730	
5731			// When scrolling (X or Y) we want to set the width of the table as 
5732			// appropriate. However, when not scrolling leave the table width as it
5733			// is. This results in slightly different, but I think correct behaviour
5734			if ( scrollX && scrollXInner ) {
5735				tmpTable.width( scrollXInner );
5736			}
5737			else if ( scrollX ) {
5738				tmpTable.css( 'width', 'auto' );
5739				tmpTable.removeAttr('width');
5740	
5741				// If there is no width attribute or style, then allow the table to
5742				// collapse
5743				if ( tmpTable.width() < tableContainer.clientWidth && tableWidthAttr ) {
5744					tmpTable.width( tableContainer.clientWidth );
5745				}
5746			}
5747			else if ( scrollY ) {
5748				tmpTable.width( tableContainer.clientWidth );
5749			}
5750			else if ( tableWidthAttr ) {
5751				tmpTable.width( tableWidthAttr );
5752			}
5753	
5754			// Get the width of each column in the constructed table - we need to
5755			// know the inner width (so it can be assigned to the other table's
5756			// cells) and the outer width so we can calculate the full width of the
5757			// table. This is safe since DataTables requires a unique cell for each
5758			// column, but if ever a header can span multiple columns, this will
5759			// need to be modified.
5760			var total = 0;
5761			for ( i=0 ; i<visibleColumns.length ; i++ ) {
5762				var cell = $(headerCells[i]);
5763				var border = cell.outerWidth() - cell.width();
5764	
5765				// Use getBounding... where possible (not IE8-) because it can give
5766				// sub-pixel accuracy, which we then want to round up!
5767				var bounding = browser.bBounding ?
5768					Math.ceil( headerCells[i].getBoundingClientRect().width ) :
5769					cell.outerWidth();
5770	
5771				// Total is tracked to remove any sub-pixel errors as the outerWidth
5772				// of the table might not equal the total given here (IE!).
5773				total += bounding;
5774	
5775				// Width for each column to use
5776				columns[ visibleColumns[i] ].sWidth = _fnStringToCss( bounding - border );
5777			}
5778	
5779			table.style.width = _fnStringToCss( total );
5780	
5781			// Finished with the table - ditch it
5782			holder.remove();
5783		}
5784	
5785		// If there is a width attr, we want to attach an event listener which
5786		// allows the table sizing to automatically adjust when the window is
5787		// resized. Use the width attr rather than CSS, since we can't know if the
5788		// CSS is a relative value or absolute - DOM read is always px.
5789		if ( tableWidthAttr ) {
5790			table.style.width = _fnStringToCss( tableWidthAttr );
5791		}
5792	
5793		if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) {
5794			var bindResize = function () {
5795				$(window).on('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {
5796					_fnAdjustColumnSizing( oSettings );
5797				} ) );
5798			};
5799	
5800			// IE6/7 will crash if we bind a resize event handler on page load.
5801			// To be removed in 1.11 which drops IE6/7 support
5802			if ( ie67 ) {
5803				setTimeout( bindResize, 1000 );
5804			}
5805			else {
5806				bindResize();
5807			}
5808	
5809			oSettings._reszEvt = true;
5810		}
5811	}
5812	
5813	
5814	/**
5815	 * Throttle the calls to a function. Arguments and context are maintained for
5816	 * the throttled function
5817	 *  @param {function} fn Function to be called
5818	 *  @param {int} [freq=200] call frequency in mS
5819	 *  @returns {function} wrapped function
5820	 *  @memberof DataTable#oApi
5821	 */
5822	var _fnThrottle = DataTable.util.throttle;
5823	
5824	
5825	/**
5826	 * Convert a CSS unit width to pixels (e.g. 2em)
5827	 *  @param {string} width width to be converted
5828	 *  @param {node} parent parent to get the with for (required for relative widths) - optional
5829	 *  @returns {int} width in pixels
5830	 *  @memberof DataTable#oApi
5831	 */
5832	function _fnConvertToWidth ( width, parent )
5833	{
5834		if ( ! width ) {
5835			return 0;
5836		}
5837	
5838		var n = $('<div/>')
5839			.css( 'width', _fnStringToCss( width ) )
5840			.appendTo( parent || document.body );
5841	
5842		var val = n[0].offsetWidth;
5843		n.remove();
5844	
5845		return val;
5846	}
5847	
5848	
5849	/**
5850	 * Get the widest node
5851	 *  @param {object} settings dataTables settings object
5852	 *  @param {int} colIdx column of interest
5853	 *  @returns {node} widest table node
5854	 *  @memberof DataTable#oApi
5855	 */
5856	function _fnGetWidestNode( settings, colIdx )
5857	{
5858		var idx = _fnGetMaxLenString( settings, colIdx );
5859		if ( idx < 0 ) {
5860			return null;
5861		}
5862	
5863		var data = settings.aoData[ idx ];
5864		return ! data.nTr ? // Might not have been created when deferred rendering
5865			$('<td/>').html( _fnGetCellData( settings, idx, colIdx, 'display' ) )[0] :
5866			data.anCells[ colIdx ];
5867	}
5868	
5869	
5870	/**
5871	 * Get the maximum strlen for each data column
5872	 *  @param {object} settings dataTables settings object
5873	 *  @param {int} colIdx column of interest
5874	 *  @returns {string} max string length for each column
5875	 *  @memberof DataTable#oApi
5876	 */
5877	function _fnGetMaxLenString( settings, colIdx )
5878	{
5879		var s, max=-1, maxIdx = -1;
5880	
5881		for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
5882			s = _fnGetCellData( settings, i, colIdx, 'display' )+'';
5883			s = s.replace( __re_html_remove, '' );
5884			s = s.replace( /&nbsp;/g, ' ' );
5885	
5886			if ( s.length > max ) {
5887				max = s.length;
5888				maxIdx = i;
5889			}
5890		}
5891	
5892		return maxIdx;
5893	}
5894	
5895	
5896	/**
5897	 * Append a CSS unit (only if required) to a string
5898	 *  @param {string} value to css-ify
5899	 *  @returns {string} value with css unit
5900	 *  @memberof DataTable#oApi
5901	 */
5902	function _fnStringToCss( s )
5903	{
5904		if ( s === null ) {
5905			return '0px';
5906		}
5907	
5908		if ( typeof s == 'number' ) {
5909			return s < 0 ?
5910				'0px' :
5911				s+'px';
5912		}
5913	
5914		// Check it has a unit character already
5915		return s.match(/\d$/) ?
5916			s+'px' :
5917			s;
5918	}
5919	
5920	
5921	
5922	function _fnSortFlatten ( settings )
5923	{
5924		var
5925			i, iLen, k, kLen,
5926			aSort = [],
5927			aiOrig = [],
5928			aoColumns = settings.aoColumns,
5929			aDataSort, iCol, sType, srcCol,
5930			fixed = settings.aaSortingFixed,
5931			fixedObj = $.isPlainObject( fixed ),
5932			nestedSort = [],
5933			add = function ( a ) {
5934				if ( a.length && ! Array.isArray( a[0] ) ) {
5935					// 1D array
5936					nestedSort.push( a );
5937				}
5938				else {
5939					// 2D array
5940					$.merge( nestedSort, a );
5941				}
5942			};
5943	
5944		// Build the sort array, with pre-fix and post-fix options if they have been
5945		// specified
5946		if ( Array.isArray( fixed ) ) {
5947			add( fixed );
5948		}
5949	
5950		if ( fixedObj && fixed.pre ) {
5951			add( fixed.pre );
5952		}
5953	
5954		add( settings.aaSorting );
5955	
5956		if (fixedObj && fixed.post ) {
5957			add( fixed.post );
5958		}
5959	
5960		for ( i=0 ; i<nestedSort.length ; i++ )
5961		{
5962			srcCol = nestedSort[i][0];
5963			aDataSort = aoColumns[ srcCol ].aDataSort;
5964	
5965			for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ )
5966			{
5967				iCol = aDataSort[k];
5968				sType = aoColumns[ iCol ].sType || 'string';
5969	
5970				if ( nestedSort[i]._idx === undefined ) {
5971					nestedSort[i]._idx = $.inArray( nestedSort[i][1], aoColumns[iCol].asSorting );
5972				}
5973	
5974				aSort.push( {
5975					src:       srcCol,
5976					col:       iCol,
5977					dir:       nestedSort[i][1],
5978					index:     nestedSort[i]._idx,
5979					type:      sType,
5980					formatter: DataTable.ext.type.order[ sType+"-pre" ]
5981				} );
5982			}
5983		}
5984	
5985		return aSort;
5986	}
5987	
5988	/**
5989	 * Change the order of the table
5990	 *  @param {object} oSettings dataTables settings object
5991	 *  @memberof DataTable#oApi
5992	 *  @todo This really needs split up!
5993	 */
5994	function _fnSort ( oSettings )
5995	{
5996		var
5997			i, ien, iLen, j, jLen, k, kLen,
5998			sDataType, nTh,
5999			aiOrig = [],
6000			oExtSort = DataTable.ext.type.order,
6001			aoData = oSettings.aoData,
6002			aoColumns = oSettings.aoColumns,
6003			aDataSort, data, iCol, sType, oSort,
6004			formatters = 0,
6005			sortCol,
6006			displayMaster = oSettings.aiDisplayMaster,
6007			aSort;
6008	
6009		// Resolve any column types that are unknown due to addition or invalidation
6010		// @todo Can this be moved into a 'data-ready' handler which is called when
6011		//   data is going to be used in the table?
6012		_fnColumnTypes( oSettings );
6013	
6014		aSort = _fnSortFlatten( oSettings );
6015	
6016		for ( i=0, ien=aSort.length ; i<ien ; i++ ) {
6017			sortCol = aSort[i];
6018	
6019			// Track if we can use the fast sort algorithm
6020			if ( sortCol.formatter ) {
6021				formatters++;
6022			}
6023	
6024			// Load the data needed for the sort, for each cell
6025			_fnSortData( oSettings, sortCol.col );
6026		}
6027	
6028		/* No sorting required if server-side or no sorting array */
6029		if ( _fnDataSource( oSettings ) != 'ssp' && aSort.length !== 0 )
6030		{
6031			// Create a value - key array of the current row positions such that we can use their
6032			// current position during the sort, if values match, in order to perform stable sorting
6033			for ( i=0, iLen=displayMaster.length ; i<iLen ; i++ ) {
6034				aiOrig[ displayMaster[i] ] = i;
6035			}
6036	
6037			/* Do the sort - here we want multi-column sorting based on a given data source (column)
6038			 * and sorting function (from oSort) in a certain direction. It's reasonably complex to
6039			 * follow on it's own, but this is what we want (example two column sorting):
6040			 *  fnLocalSorting = function(a,b){
6041			 *    var iTest;
6042			 *    iTest = oSort['string-asc']('data11', 'data12');
6043			 *      if (iTest !== 0)
6044			 *        return iTest;
6045			 *    iTest = oSort['numeric-desc']('data21', 'data22');
6046			 *    if (iTest !== 0)
6047			 *      return iTest;
6048			 *    return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
6049			 *  }
6050			 * Basically we have a test for each sorting column, if the data in that column is equal,
6051			 * test the next column. If all columns match, then we use a numeric sort on the row
6052			 * positions in the original data array to provide a stable sort.
6053			 *
6054			 * Note - I know it seems excessive to have two sorting methods, but the first is around
6055			 * 15% faster, so the second is only maintained for backwards compatibility with sorting
6056			 * methods which do not have a pre-sort formatting function.
6057			 */
6058			if ( formatters === aSort.length ) {
6059				// All sort types have formatting functions
6060				displayMaster.sort( function ( a, b ) {
6061					var
6062						x, y, k, test, sort,
6063						len=aSort.length,
6064						dataA = aoData[a]._aSortData,
6065						dataB = aoData[b]._aSortData;
6066	
6067					for ( k=0 ; k<len ; k++ ) {
6068						sort = aSort[k];
6069	
6070						x = dataA[ sort.col ];
6071						y = dataB[ sort.col ];
6072	
6073						test = x<y ? -1 : x>y ? 1 : 0;
6074						if ( test !== 0 ) {
6075							return sort.dir === 'asc' ? test : -test;
6076						}
6077					}
6078	
6079					x = aiOrig[a];
6080					y = aiOrig[b];
6081					return x<y ? -1 : x>y ? 1 : 0;
6082				} );
6083			}
6084			else {
6085				// Depreciated - remove in 1.11 (providing a plug-in option)
6086				// Not all sort types have formatting methods, so we have to call their sorting
6087				// methods.
6088				displayMaster.sort( function ( a, b ) {
6089					var
6090						x, y, k, l, test, sort, fn,
6091						len=aSort.length,
6092						dataA = aoData[a]._aSortData,
6093						dataB = aoData[b]._aSortData;
6094	
6095					for ( k=0 ; k<len ; k++ ) {
6096						sort = aSort[k];
6097	
6098						x = dataA[ sort.col ];
6099						y = dataB[ sort.col ];
6100	
6101						fn = oExtSort[ sort.type+"-"+sort.dir ] || oExtSort[ "string-"+sort.dir ];
6102						test = fn( x, y );
6103						if ( test !== 0 ) {
6104							return test;
6105						}
6106					}
6107	
6108					x = aiOrig[a];
6109					y = aiOrig[b];
6110					return x<y ? -1 : x>y ? 1 : 0;
6111				} );
6112			}
6113		}
6114	
6115		/* Tell the draw function that we have sorted the data */
6116		oSettings.bSorted = true;
6117	}
6118	
6119	
6120	function _fnSortAria ( settings )
6121	{
6122		var label;
6123		var nextSort;
6124		var columns = settings.aoColumns;
6125		var aSort = _fnSortFlatten( settings );
6126		var oAria = settings.oLanguage.oAria;
6127	
6128		// ARIA attributes - need to loop all columns, to update all (removing old
6129		// attributes as needed)
6130		for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
6131		{
6132			var col = columns[i];
6133			var asSorting = col.asSorting;
6134			var sTitle = col.ariaTitle || col.sTitle.replace( /<.*?>/g, "" );
6135			var th = col.nTh;
6136	
6137			// IE7 is throwing an error when setting these properties with jQuery's
6138			// attr() and removeAttr() methods...
6139			th.removeAttribute('aria-sort');
6140	
6141			/* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
6142			if ( col.bSortable ) {
6143				if ( aSort.length > 0 && aSort[0].col == i ) {
6144					th.setAttribute('aria-sort', aSort[0].dir=="asc" ? "ascending" : "descending" );
6145					nextSort = asSorting[ aSort[0].index+1 ] || asSorting[0];
6146				}
6147				else {
6148					nextSort = asSorting[0];
6149				}
6150	
6151				label = sTitle + ( nextSort === "asc" ?
6152					oAria.sSortAscending :
6153					oAria.sSortDescending
6154				);
6155			}
6156			else {
6157				label = sTitle;
6158			}
6159	
6160			th.setAttribute('aria-label', label);
6161		}
6162	}
6163	
6164	
6165	/**
6166	 * Function to run on user sort request
6167	 *  @param {object} settings dataTables settings object
6168	 *  @param {node} attachTo node to attach the handler to
6169	 *  @param {int} colIdx column sorting index
6170	 *  @param {boolean} [append=false] Append the requested sort to the existing
6171	 *    sort if true (i.e. multi-column sort)
6172	 *  @param {function} [callback] callback function
6173	 *  @memberof DataTable#oApi
6174	 */
6175	function _fnSortListener ( settings, colIdx, append, callback )
6176	{
6177		var col = settings.aoColumns[ colIdx ];
6178		var sorting = settings.aaSorting;
6179		var asSorting = col.asSorting;
6180		var nextSortIdx;
6181		var next = function ( a, overflow ) {
6182			var idx = a._idx;
6183			if ( idx === undefined ) {
6184				idx = $.inArray( a[1], asSorting );
6185			}
6186	
6187			return idx+1 < asSorting.length ?
6188				idx+1 :
6189				overflow ?
6190					null :
6191					0;
6192		};
6193	
6194		// Convert to 2D array if needed
6195		if ( typeof sorting[0] === 'number' ) {
6196			sorting = settings.aaSorting = [ sorting ];
6197		}
6198	
6199		// If appending the sort then we are multi-column sorting
6200		if ( append && settings.oFeatures.bSortMulti ) {
6201			// Are we already doing some kind of sort on this column?
6202			var sortIdx = $.inArray( colIdx, _pluck(sorting, '0') );
6203	
6204			if ( sortIdx !== -1 ) {
6205				// Yes, modify the sort
6206				nextSortIdx = next( sorting[sortIdx], true );
6207	
6208				if ( nextSortIdx === null && sorting.length === 1 ) {
6209					nextSortIdx = 0; // can't remove sorting completely
6210				}
6211	
6212				if ( nextSortIdx === null ) {
6213					sorting.splice( sortIdx, 1 );
6214				}
6215				else {
6216					sorting[sortIdx][1] = asSorting[ nextSortIdx ];
6217					sorting[sortIdx]._idx = nextSortIdx;
6218				}
6219			}
6220			else {
6221				// No sort on this column yet
6222				sorting.push( [ colIdx, asSorting[0], 0 ] );
6223				sorting[sorting.length-1]._idx = 0;
6224			}
6225		}
6226		else if ( sorting.length && sorting[0][0] == colIdx ) {
6227			// Single column - already sorting on this column, modify the sort
6228			nextSortIdx = next( sorting[0] );
6229	
6230			sorting.length = 1;
6231			sorting[0][1] = asSorting[ nextSortIdx ];
6232			sorting[0]._idx = nextSortIdx;
6233		}
6234		else {
6235			// Single column - sort only on this column
6236			sorting.length = 0;
6237			sorting.push( [ colIdx, asSorting[0] ] );
6238			sorting[0]._idx = 0;
6239		}
6240	
6241		// Run the sort by calling a full redraw
6242		_fnReDraw( settings );
6243	
6244		// callback used for async user interaction
6245		if ( typeof callback == 'function' ) {
6246			callback( settings );
6247		}
6248	}
6249	
6250	
6251	/**
6252	 * Attach a sort handler (click) to a node
6253	 *  @param {object} settings dataTables settings object
6254	 *  @param {node} attachTo node to attach the handler to
6255	 *  @param {int} colIdx column sorting index
6256	 *  @param {function} [callback] callback function
6257	 *  @memberof DataTable#oApi
6258	 */
6259	function _fnSortAttachListener ( settings, attachTo, colIdx, callback )
6260	{
6261		var col = settings.aoColumns[ colIdx ];
6262	
6263		_fnBindAction( attachTo, {}, function (e) {
6264			/* If the column is not sortable - don't to anything */
6265			if ( col.bSortable === false ) {
6266				return;
6267			}
6268	
6269			// If processing is enabled use a timeout to allow the processing
6270			// display to be shown - otherwise to it synchronously
6271			if ( settings.oFeatures.bProcessing ) {
6272				_fnProcessingDisplay( settings, true );
6273	
6274				setTimeout( function() {
6275					_fnSortListener( settings, colIdx, e.shiftKey, callback );
6276	
6277					// In server-side processing, the draw callback will remove the
6278					// processing display
6279					if ( _fnDataSource( settings ) !== 'ssp' ) {
6280						_fnProcessingDisplay( settings, false );
6281					}
6282				}, 0 );
6283			}
6284			else {
6285				_fnSortListener( settings, colIdx, e.shiftKey, callback );
6286			}
6287		} );
6288	}
6289	
6290	
6291	/**
6292	 * Set the sorting classes on table's body, Note: it is safe to call this function
6293	 * when bSort and bSortClasses are false
6294	 *  @param {object} oSettings dataTables settings object
6295	 *  @memberof DataTable#oApi
6296	 */
6297	function _fnSortingClasses( settings )
6298	{
6299		var oldSort = settings.aLastSort;
6300		var sortClass = settings.oClasses.sSortColumn;
6301		var sort = _fnSortFlatten( settings );
6302		var features = settings.oFeatures;
6303		var i, ien, colIdx;
6304	
6305		if ( features.bSort && features.bSortClasses ) {
6306			// Remove old sorting classes
6307			for ( i=0, ien=oldSort.length ; i<ien ; i++ ) {
6308				colIdx = oldSort[i].src;
6309	
6310				// Remove column sorting
6311				$( _pluck( settings.aoData, 'anCells', colIdx ) )
6312					.removeClass( sortClass + (i<2 ? i+1 : 3) );
6313			}
6314	
6315			// Add new column sorting
6316			for ( i=0, ien=sort.length ; i<ien ; i++ ) {
6317				colIdx = sort[i].src;
6318	
6319				$( _pluck( settings.aoData, 'anCells', colIdx ) )
6320					.addClass( sortClass + (i<2 ? i+1 : 3) );
6321			}
6322		}
6323	
6324		settings.aLastSort = sort;
6325	}
6326	
6327	
6328	// Get the data to sort a column, be it from cache, fresh (populating the
6329	// cache), or from a sort formatter
6330	function _fnSortData( settings, idx )
6331	{
6332		// Custom sorting function - provided by the sort data type
6333		var column = settings.aoColumns[ idx ];
6334		var customSort = DataTable.ext.order[ column.sSortDataType ];
6335		var customData;
6336	
6337		if ( customSort ) {
6338			customData = customSort.call( settings.oInstance, settings, idx,
6339				_fnColumnIndexToVisible( settings, idx )
6340			);
6341		}
6342	
6343		// Use / populate cache
6344		var row, cellData;
6345		var formatter = DataTable.ext.type.order[ column.sType+"-pre" ];
6346	
6347		for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
6348			row = settings.aoData[i];
6349	
6350			if ( ! row._aSortData ) {
6351				row._aSortData = [];
6352			}
6353	
6354			if ( ! row._aSortData[idx] || customSort ) {
6355				cellData = customSort ?
6356					customData[i] : // If there was a custom sort function, use data from there
6357					_fnGetCellData( settings, i, idx, 'sort' );
6358	
6359				row._aSortData[ idx ] = formatter ?
6360					formatter( cellData ) :
6361					cellData;
6362			}
6363		}
6364	}
6365	
6366	
6367	
6368	/**
6369	 * Save the state of a table
6370	 *  @param {object} oSettings dataTables settings object
6371	 *  @memberof DataTable#oApi
6372	 */
6373	function _fnSaveState ( settings )
6374	{
6375		if (settings._bLoadingState) {
6376			return;
6377		}
6378	
6379		/* Store the interesting variables */
6380		var state = {
6381			time:    +new Date(),
6382			start:   settings._iDisplayStart,
6383			length:  settings._iDisplayLength,
6384			order:   $.extend( true, [], settings.aaSorting ),
6385			search:  _fnSearchToCamel( settings.oPreviousSearch ),
6386			columns: $.map( settings.aoColumns, function ( col, i ) {
6387				return {
6388					visible: col.bVisible,
6389					search: _fnSearchToCamel( settings.aoPreSearchCols[i] )
6390				};
6391			} )
6392		};
6393	
6394		settings.oSavedState = state;
6395		_fnCallbackFire( settings, "aoStateSaveParams", 'stateSaveParams', [settings, state] );
6396		
6397		if ( settings.oFeatures.bStateSave && !settings.bDestroying )
6398		{
6399			settings.fnStateSaveCallback.call( settings.oInstance, settings, state );
6400		}	
6401	}
6402	
6403	
6404	/**
6405	 * Attempt to load a saved table state
6406	 *  @param {object} oSettings dataTables settings object
6407	 *  @param {object} oInit DataTables init object so we can override settings
6408	 *  @param {function} callback Callback to execute when the state has been loaded
6409	 *  @memberof DataTable#oApi
6410	 */
6411	function _fnLoadState ( settings, oInit, callback )
6412	{
6413		if ( ! settings.oFeatures.bStateSave ) {
6414			callback();
6415			return;
6416		}
6417	
6418		var loaded = function(state) {
6419			_fnImplementState(settings, state, callback);
6420		}
6421	
6422		var state = settings.fnStateLoadCallback.call( settings.oInstance, settings, loaded );
6423	
6424		if ( state !== undefined ) {
6425			_fnImplementState( settings, state, callback );
6426		}
6427		// otherwise, wait for the loaded callback to be executed
6428	
6429		return true;
6430	}
6431	
6432	function _fnImplementState ( settings, s, callback) {
6433		var i, ien;
6434		var columns = settings.aoColumns;
6435		settings._bLoadingState = true;
6436	
6437		// When StateRestore was introduced the state could now be implemented at any time
6438		// Not just initialisation. To do this an api instance is required in some places
6439		var api = settings._bInitComplete ? new DataTable.Api(settings) : null;
6440	
6441		if ( ! s || ! s.time ) {
6442			settings._bLoadingState = false;
6443			callback();
6444			return;
6445		}
6446	
6447		// Allow custom and plug-in manipulation functions to alter the saved data set and
6448		// cancelling of loading by returning false
6449		var abStateLoad = _fnCallbackFire( settings, 'aoStateLoadParams', 'stateLoadParams', [settings, s] );
6450		if ( $.inArray( false, abStateLoad ) !== -1 ) {
6451			settings._bLoadingState = false;
6452			callback();
6453			return;
6454		}
6455	
6456		// Reject old data
6457		var duration = settings.iStateDuration;
6458		if ( duration > 0 && s.time < +new Date() - (duration*1000) ) {
6459			settings._bLoadingState = false;
6460			callback();
6461			return;
6462		}
6463	
6464		// Number of columns have changed - all bets are off, no restore of settings
6465		if ( s.columns && columns.length !== s.columns.length ) {
6466			settings._bLoadingState = false;
6467			callback();
6468			return;
6469		}
6470	
6471		// Store the saved state so it might be accessed at any time
6472		settings.oLoadedState = $.extend( true, {}, s );
6473	
6474		// Page Length
6475		if ( s.length !== undefined ) {
6476			// If already initialised just set the value directly so that the select element is also updated
6477			if (api) {
6478				api.page.len(s.length)
6479			}
6480			else {
6481				settings._iDisplayLength   = s.length;
6482			}
6483		}
6484	
6485		// Restore key features - todo - for 1.11 this needs to be done by
6486		// subscribed events
6487		if ( s.start !== undefined ) {
6488			if(api === null) {
6489				settings._iDisplayStart    = s.start;
6490				settings.iInitDisplayStart = s.start;
6491			}
6492			else {
6493				_fnPageChange(settings, s.start/settings._iDisplayLength);
6494			}
6495		}
6496	
6497		// Order
6498		if ( s.order !== undefined ) {
6499			settings.aaSorting = [];
6500			$.each( s.order, function ( i, col ) {
6501				settings.aaSorting.push( col[0] >= columns.length ?
6502					[ 0, col[1] ] :
6503					col
6504				);
6505			} );
6506		}
6507	
6508		// Search
6509		if ( s.search !== undefined ) {
6510			$.extend( settings.oPreviousSearch, _fnSearchToHung( s.search ) );
6511		}
6512	
6513		// Columns
6514		if ( s.columns ) {
6515			for ( i=0, ien=s.columns.length ; i<ien ; i++ ) {
6516				var col = s.columns[i];
6517	
6518				// Visibility
6519				if ( col.visible !== undefined ) {
6520					// If the api is defined, the table has been initialised so we need to use it rather than internal settings
6521					if (api) {
6522						// Don't redraw the columns on every iteration of this loop, we will do this at the end instead
6523						api.column(i).visible(col.visible, false);
6524					}
6525					else {
6526						columns[i].bVisible = col.visible;
6527					}
6528				}
6529	
6530				// Search
6531				if ( col.search !== undefined ) {
6532					$.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) );
6533				}
6534			}
6535			
6536			// If the api is defined then we need to adjust the columns once the visibility has been changed
6537			if (api) {
6538				api.columns.adjust();
6539			}
6540		}
6541	
6542		settings._bLoadingState = false;
6543		_fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, s] );
6544		callback();
6545	};
6546	
6547	
6548	/**
6549	 * Return the settings object for a particular table
6550	 *  @param {node} table table we are using as a dataTable
6551	 *  @returns {object} Settings object - or null if not found
6552	 *  @memberof DataTable#oApi
6553	 */
6554	function _fnSettingsFromNode ( table )
6555	{
6556		var settings = DataTable.settings;
6557		var idx = $.inArray( table, _pluck( settings, 'nTable' ) );
6558	
6559		return idx !== -1 ?
6560			settings[ idx ] :
6561			null;
6562	}
6563	
6564	
6565	/**
6566	 * Log an error message
6567	 *  @param {object} settings dataTables settings object
6568	 *  @param {int} level log error messages, or display them to the user
6569	 *  @param {string} msg error message
6570	 *  @param {int} tn Technical note id to get more information about the error.
6571	 *  @memberof DataTable#oApi
6572	 */
6573	function _fnLog( settings, level, msg, tn )
6574	{
6575		msg = 'DataTables warning: '+
6576			(settings ? 'table id='+settings.sTableId+' - ' : '')+msg;
6577	
6578		if ( tn ) {
6579			msg += '. For more information about this error, please see '+
6580			'http://datatables.net/tn/'+tn;
6581		}
6582	
6583		if ( ! level  ) {
6584			// Backwards compatibility pre 1.10
6585			var ext = DataTable.ext;
6586			var type = ext.sErrMode || ext.errMode;
6587	
6588			if ( settings ) {
6589				_fnCallbackFire( settings, null, 'error', [ settings, tn, msg ] );
6590			}
6591	
6592			if ( type == 'alert' ) {
6593				alert( msg );
6594			}
6595			else if ( type == 'throw' ) {
6596				throw new Error(msg);
6597			}
6598			else if ( typeof type == 'function' ) {
6599				type( settings, tn, msg );
6600			}
6601		}
6602		else if ( window.console && console.log ) {
6603			console.log( msg );
6604		}
6605	}
6606	
6607	
6608	/**
6609	 * See if a property is defined on one object, if so assign it to the other object
6610	 *  @param {object} ret target object
6611	 *  @param {object} src source object
6612	 *  @param {string} name property
6613	 *  @param {string} [mappedName] name to map too - optional, name used if not given
6614	 *  @memberof DataTable#oApi
6615	 */
6616	function _fnMap( ret, src, name, mappedName )
6617	{
6618		if ( Array.isArray( name ) ) {
6619			$.each( name, function (i, val) {
6620				if ( Array.isArray( val ) ) {
6621					_fnMap( ret, src, val[0], val[1] );
6622				}
6623				else {
6624					_fnMap( ret, src, val );
6625				}
6626			} );
6627	
6628			return;
6629		}
6630	
6631		if ( mappedName === undefined ) {
6632			mappedName = name;
6633		}
6634	
6635		if ( src[name] !== undefined ) {
6636			ret[mappedName] = src[name];
6637		}
6638	}
6639	
6640	
6641	/**
6642	 * Extend objects - very similar to jQuery.extend, but deep copy objects, and
6643	 * shallow copy arrays. The reason we need to do this, is that we don't want to
6644	 * deep copy array init values (such as aaSorting) since the dev wouldn't be
6645	 * able to override them, but we do want to deep copy arrays.
6646	 *  @param {object} out Object to extend
6647	 *  @param {object} extender Object from which the properties will be applied to
6648	 *      out
6649	 *  @param {boolean} breakRefs If true, then arrays will be sliced to take an
6650	 *      independent copy with the exception of the `data` or `aaData` parameters
6651	 *      if they are present. This is so you can pass in a collection to
6652	 *      DataTables and have that used as your data source without breaking the
6653	 *      references
6654	 *  @returns {object} out Reference, just for convenience - out === the return.
6655	 *  @memberof DataTable#oApi
6656	 *  @todo This doesn't take account of arrays inside the deep copied objects.
6657	 */
6658	function _fnExtend( out, extender, breakRefs )
6659	{
6660		var val;
6661	
6662		for ( var prop in extender ) {
6663			if ( extender.hasOwnProperty(prop) ) {
6664				val = extender[prop];
6665	
6666				if ( $.isPlainObject( val ) ) {
6667					if ( ! $.isPlainObject( out[prop] ) ) {
6668						out[prop] = {};
6669					}
6670					$.extend( true, out[prop], val );
6671				}
6672				else if ( breakRefs && prop !== 'data' && prop !== 'aaData' && Array.isArray(val) ) {
6673					out[prop] = val.slice();
6674				}
6675				else {
6676					out[prop] = val;
6677				}
6678			}
6679		}
6680	
6681		return out;
6682	}
6683	
6684	
6685	/**
6686	 * Bind an event handers to allow a click or return key to activate the callback.
6687	 * This is good for accessibility since a return on the keyboard will have the
6688	 * same effect as a click, if the element has focus.
6689	 *  @param {element} n Element to bind the action to
6690	 *  @param {object} oData Data object to pass to the triggered function
6691	 *  @param {function} fn Callback function for when the event is triggered
6692	 *  @memberof DataTable#oApi
6693	 */
6694	function _fnBindAction( n, oData, fn )
6695	{
6696		$(n)
6697			.on( 'click.DT', oData, function (e) {
6698					$(n).trigger('blur'); // Remove focus outline for mouse users
6699					fn(e);
6700				} )
6701			.on( 'keypress.DT', oData, function (e){
6702					if ( e.which === 13 ) {
6703						e.preventDefault();
6704						fn(e);
6705					}
6706				} )
6707			.on( 'selectstart.DT', function () {
6708					/* Take the brutal approach to cancelling text selection */
6709					return false;
6710				} );
6711	}
6712	
6713	
6714	/**
6715	 * Register a callback function. Easily allows a callback function to be added to
6716	 * an array store of callback functions that can then all be called together.
6717	 *  @param {object} oSettings dataTables settings object
6718	 *  @param {string} sStore Name of the array storage for the callbacks in oSettings
6719	 *  @param {function} fn Function to be called back
6720	 *  @param {string} sName Identifying name for the callback (i.e. a label)
6721	 *  @memberof DataTable#oApi
6722	 */
6723	function _fnCallbackReg( oSettings, sStore, fn, sName )
6724	{
6725		if ( fn )
6726		{
6727			oSettings[sStore].push( {
6728				"fn": fn,
6729				"sName": sName
6730			} );
6731		}
6732	}
6733	
6734	
6735	/**
6736	 * Fire callback functions and trigger events. Note that the loop over the
6737	 * callback array store is done backwards! Further note that you do not want to
6738	 * fire off triggers in time sensitive applications (for example cell creation)
6739	 * as its slow.
6740	 *  @param {object} settings dataTables settings object
6741	 *  @param {string} callbackArr Name of the array storage for the callbacks in
6742	 *      oSettings
6743	 *  @param {string} eventName Name of the jQuery custom event to trigger. If
6744	 *      null no trigger is fired
6745	 *  @param {array} args Array of arguments to pass to the callback function /
6746	 *      trigger
6747	 *  @memberof DataTable#oApi
6748	 */
6749	function _fnCallbackFire( settings, callbackArr, eventName, args )
6750	{
6751		var ret = [];
6752	
6753		if ( callbackArr ) {
6754			ret = $.map( settings[callbackArr].slice().reverse(), function (val, i) {
6755				return val.fn.apply( settings.oInstance, args );
6756			} );
6757		}
6758	
6759		if ( eventName !== null ) {
6760			var e = $.Event( eventName+'.dt' );
6761	
6762			$(settings.nTable).trigger( e, args );
6763	
6764			ret.push( e.result );
6765		}
6766	
6767		return ret;
6768	}
6769	
6770	
6771	function _fnLengthOverflow ( settings )
6772	{
6773		var
6774			start = settings._iDisplayStart,
6775			end = settings.fnDisplayEnd(),
6776			len = settings._iDisplayLength;
6777	
6778		/* If we have space to show extra rows (backing up from the end point - then do so */
6779		if ( start >= end )
6780		{
6781			start = end - len;
6782		}
6783	
6784		// Keep the start record on the current page
6785		start -= (start % len);
6786	
6787		if ( len === -1 || start < 0 )
6788		{
6789			start = 0;
6790		}
6791	
6792		settings._iDisplayStart = start;
6793	}
6794	
6795	
6796	function _fnRenderer( settings, type )
6797	{
6798		var renderer = settings.renderer;
6799		var host = DataTable.ext.renderer[type];
6800	
6801		if ( $.isPlainObject( renderer ) && renderer[type] ) {
6802			// Specific renderer for this type. If available use it, otherwise use
6803			// the default.
6804			return host[renderer[type]] || host._;
6805		}
6806		else if ( typeof renderer === 'string' ) {
6807			// Common renderer - if there is one available for this type use it,
6808			// otherwise use the default
6809			return host[renderer] || host._;
6810		}
6811	
6812		// Use the default
6813		return host._;
6814	}
6815	
6816	
6817	/**
6818	 * Detect the data source being used for the table. Used to simplify the code
6819	 * a little (ajax) and to make it compress a little smaller.
6820	 *
6821	 *  @param {object} settings dataTables settings object
6822	 *  @returns {string} Data source
6823	 *  @memberof DataTable#oApi
6824	 */
6825	function _fnDataSource ( settings )
6826	{
6827		if ( settings.oFeatures.bServerSide ) {
6828			return 'ssp';
6829		}
6830		else if ( settings.ajax || settings.sAjaxSource ) {
6831			return 'ajax';
6832		}
6833		return 'dom';
6834	}
6835	
6836	
6837	
6838	
6839	/**
6840	 * Computed structure of the DataTables API, defined by the options passed to
6841	 * `DataTable.Api.register()` when building the API.
6842	 *
6843	 * The structure is built in order to speed creation and extension of the Api
6844	 * objects since the extensions are effectively pre-parsed.
6845	 *
6846	 * The array is an array of objects with the following structure, where this
6847	 * base array represents the Api prototype base:
6848	 *
6849	 *     [
6850	 *       {
6851	 *         name:      'data'                -- string   - Property name
6852	 *         val:       function () {},       -- function - Api method (or undefined if just an object
6853	 *         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
6854	 *         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
6855	 *       },
6856	 *       {
6857	 *         name:     'row'
6858	 *         val:       {},
6859	 *         methodExt: [ ... ],
6860	 *         propExt:   [
6861	 *           {
6862	 *             name:      'data'
6863	 *             val:       function () {},
6864	 *             methodExt: [ ... ],
6865	 *             propExt:   [ ... ]
6866	 *           },
6867	 *           ...
6868	 *         ]
6869	 *       }
6870	 *     ]
6871	 *
6872	 * @type {Array}
6873	 * @ignore
6874	 */
6875	var __apiStruct = [];
6876	
6877	
6878	/**
6879	 * `Array.prototype` reference.
6880	 *
6881	 * @type object
6882	 * @ignore
6883	 */
6884	var __arrayProto = Array.prototype;
6885	
6886	
6887	/**
6888	 * Abstraction for `context` parameter of the `Api` constructor to allow it to
6889	 * take several different forms for ease of use.
6890	 *
6891	 * Each of the input parameter types will be converted to a DataTables settings
6892	 * object where possible.
6893	 *
6894	 * @param  {string|node|jQuery|object} mixed DataTable identifier. Can be one
6895	 *   of:
6896	 *
6897	 *   * `string` - jQuery selector. Any DataTables' matching the given selector
6898	 *     with be found and used.
6899	 *   * `node` - `TABLE` node which has already been formed into a DataTable.
6900	 *   * `jQuery` - A jQuery object of `TABLE` nodes.
6901	 *   * `object` - DataTables settings object
6902	 *   * `DataTables.Api` - API instance
6903	 * @return {array|null} Matching DataTables settings objects. `null` or
6904	 *   `undefined` is returned if no matching DataTable is found.
6905	 * @ignore
6906	 */
6907	var _toSettings = function ( mixed )
6908	{
6909		var idx, jq;
6910		var settings = DataTable.settings;
6911		var tables = $.map( settings, function (el, i) {
6912			return el.nTable;
6913		} );
6914	
6915		if ( ! mixed ) {
6916			return [];
6917		}
6918		else if ( mixed.nTable && mixed.oApi ) {
6919			// DataTables settings object
6920			return [ mixed ];
6921		}
6922		else if ( mixed.nodeName && mixed.nodeName.toLowerCase() === 'table' ) {
6923			// Table node
6924			idx = $.inArray( mixed, tables );
6925			return idx !== -1 ? [ settings[idx] ] : null;
6926		}
6927		else if ( mixed && typeof mixed.settings === 'function' ) {
6928			return mixed.settings().toArray();
6929		}
6930		else if ( typeof mixed === 'string' ) {
6931			// jQuery selector
6932			jq = $(mixed);
6933		}
6934		else if ( mixed instanceof $ ) {
6935			// jQuery object (also DataTables instance)
6936			jq = mixed;
6937		}
6938	
6939		if ( jq ) {
6940			return jq.map( function(i) {
6941				idx = $.inArray( this, tables );
6942				return idx !== -1 ? settings[idx] : null;
6943			} ).toArray();
6944		}
6945	};
6946	
6947	
6948	/**
6949	 * DataTables API class - used to control and interface with  one or more
6950	 * DataTables enhanced tables.
6951	 *
6952	 * The API class is heavily based on jQuery, presenting a chainable interface
6953	 * that you can use to interact with tables. Each instance of the API class has
6954	 * a "context" - i.e. the tables that it will operate on. This could be a single
6955	 * table, all tables on a page or a sub-set thereof.
6956	 *
6957	 * Additionally the API is designed to allow you to easily work with the data in
6958	 * the tables, retrieving and manipulating it as required. This is done by
6959	 * presenting the API class as an array like interface. The contents of the
6960	 * array depend upon the actions requested by each method (for example
6961	 * `rows().nodes()` will return an array of nodes, while `rows().data()` will
6962	 * return an array of objects or arrays depending upon your table's
6963	 * configuration). The API object has a number of array like methods (`push`,
6964	 * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`,
6965	 * `unique` etc) to assist your working with the data held in a table.
6966	 *
6967	 * Most methods (those which return an Api instance) are chainable, which means
6968	 * the return from a method call also has all of the methods available that the
6969	 * top level object had. For example, these two calls are equivalent:
6970	 *
6971	 *     // Not chained
6972	 *     api.row.add( {...} );
6973	 *     api.draw();
6974	 *
6975	 *     // Chained
6976	 *     api.row.add( {...} ).draw();
6977	 *
6978	 * @class DataTable.Api
6979	 * @param {array|object|string|jQuery} context DataTable identifier. This is
6980	 *   used to define which DataTables enhanced tables this API will operate on.
6981	 *   Can be one of:
6982	 *
6983	 *   * `string` - jQuery selector. Any DataTables' matching the given selector
6984	 *     with be found and used.
6985	 *   * `node` - `TABLE` node which has already been formed into a DataTable.
6986	 *   * `jQuery` - A jQuery object of `TABLE` nodes.
6987	 *   * `object` - DataTables settings object
6988	 * @param {array} [data] Data to initialise the Api instance with.
6989	 *
6990	 * @example
6991	 *   // Direct initialisation during DataTables construction
6992	 *   var api = $('#example').DataTable();
6993	 *
6994	 * @example
6995	 *   // Initialisation using a DataTables jQuery object
6996	 *   var api = $('#example').dataTable().api();
6997	 *
6998	 * @example
6999	 *   // Initialisation as a constructor
7000	 *   var api = new $.fn.DataTable.Api( 'table.dataTable' );
7001	 */
7002	_Api = function ( context, data )
7003	{
7004		if ( ! (this instanceof _Api) ) {
7005			return new _Api( context, data );
7006		}
7007	
7008		var settings = [];
7009		var ctxSettings = function ( o ) {
7010			var a = _toSettings( o );
7011			if ( a ) {
7012				settings.push.apply( settings, a );
7013			}
7014		};
7015	
7016		if ( Array.isArray( context ) ) {
7017			for ( var i=0, ien=context.length ; i<ien ; i++ ) {
7018				ctxSettings( context[i] );
7019			}
7020		}
7021		else {
7022			ctxSettings( context );
7023		}
7024	
7025		// Remove duplicates
7026		this.context = _unique( settings );
7027	
7028		// Initial data
7029		if ( data ) {
7030			$.merge( this, data );
7031		}
7032	
7033		// selector
7034		this.selector = {
7035			rows: null,
7036			cols: null,
7037			opts: null
7038		};
7039	
7040		_Api.extend( this, this, __apiStruct );
7041	};
7042	
7043	DataTable.Api = _Api;
7044	
7045	// Don't destroy the existing prototype, just extend it. Required for jQuery 2's
7046	// isPlainObject.
7047	$.extend( _Api.prototype, {
7048		any: function ()
7049		{
7050			return this.count() !== 0;
7051		},
7052	
7053	
7054		concat:  __arrayProto.concat,
7055	
7056	
7057		context: [], // array of table settings objects
7058	
7059	
7060		count: function ()
7061		{
7062			return this.flatten().length;
7063		},
7064	
7065	
7066		each: function ( fn )
7067		{
7068			for ( var i=0, ien=this.length ; i<ien; i++ ) {
7069				fn.call( this, this[i], i, this );
7070			}
7071	
7072			return this;
7073		},
7074	
7075	
7076		eq: function ( idx )
7077		{
7078			var ctx = this.context;
7079	
7080			return ctx.length > idx ?
7081				new _Api( ctx[idx], this[idx] ) :
7082				null;
7083		},
7084	
7085	
7086		filter: function ( fn )
7087		{
7088			var a = [];
7089	
7090			if ( __arrayProto.filter ) {
7091				a = __arrayProto.filter.call( this, fn, this );
7092			}
7093			else {
7094				// Compatibility for browsers without EMCA-252-5 (JS 1.6)
7095				for ( var i=0, ien=this.length ; i<ien ; i++ ) {
7096					if ( fn.call( this, this[i], i, this ) ) {
7097						a.push( this[i] );
7098					}
7099				}
7100			}
7101	
7102			return new _Api( this.context, a );
7103		},
7104	
7105	
7106		flatten: function ()
7107		{
7108			var a = [];
7109			return new _Api( this.context, a.concat.apply( a, this.toArray() ) );
7110		},
7111	
7112	
7113		join:    __arrayProto.join,
7114	
7115	
7116		indexOf: __arrayProto.indexOf || function (obj, start)
7117		{
7118			for ( var i=(start || 0), ien=this.length ; i<ien ; i++ ) {
7119				if ( this[i] === obj ) {
7120					return i;
7121				}
7122			}
7123			return -1;
7124		},
7125	
7126		iterator: function ( flatten, type, fn, alwaysNew ) {
7127			var
7128				a = [], ret,
7129				i, ien, j, jen,
7130				context = this.context,
7131				rows, items, item,
7132				selector = this.selector;
7133	
7134			// Argument shifting
7135			if ( typeof flatten === 'string' ) {
7136				alwaysNew = fn;
7137				fn = type;
7138				type = flatten;
7139				flatten = false;
7140			}
7141	
7142			for ( i=0, ien=context.length ; i<ien ; i++ ) {
7143				var apiInst = new _Api( context[i] );
7144	
7145				if ( type === 'table' ) {
7146					ret = fn.call( apiInst, context[i], i );
7147	
7148					if ( ret !== undefined ) {
7149						a.push( ret );
7150					}
7151				}
7152				else if ( type === 'columns' || type === 'rows' ) {
7153					// this has same length as context - one entry for each table
7154					ret = fn.call( apiInst, context[i], this[i], i );
7155	
7156					if ( ret !== undefined ) {
7157						a.push( ret );
7158					}
7159				}
7160				else if ( type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell' ) {
7161					// columns and rows share the same structure.
7162					// 'this' is an array of column indexes for each context
7163					items = this[i];
7164	
7165					if ( type === 'column-rows' ) {
7166						rows = _selector_row_indexes( context[i], selector.opts );
7167					}
7168	
7169					for ( j=0, jen=items.length ; j<jen ; j++ ) {
7170						item = items[j];
vendor: 73,613 bytes, lines 7171-9856
7171	
7172						if ( type === 'cell' ) {
7173							ret = fn.call( apiInst, context[i], item.row, item.column, i, j );
7174						}
7175						else {
7176							ret = fn.call( apiInst, context[i], item, i, j, rows );
7177						}
7178	
7179						if ( ret !== undefined ) {
7180							a.push( ret );
7181						}
7182					}
7183				}
7184			}
7185	
7186			if ( a.length || alwaysNew ) {
7187				var api = new _Api( context, flatten ? a.concat.apply( [], a ) : a );
7188				var apiSelector = api.selector;
7189				apiSelector.rows = selector.rows;
7190				apiSelector.cols = selector.cols;
7191				apiSelector.opts = selector.opts;
7192				return api;
7193			}
7194			return this;
7195		},
7196	
7197	
7198		lastIndexOf: __arrayProto.lastIndexOf || function (obj, start)
7199		{
7200			// Bit cheeky...
7201			return this.indexOf.apply( this.toArray.reverse(), arguments );
7202		},
7203	
7204	
7205		length:  0,
7206	
7207	
7208		map: function ( fn )
7209		{
7210			var a = [];
7211	
7212			if ( __arrayProto.map ) {
7213				a = __arrayProto.map.call( this, fn, this );
7214			}
7215			else {
7216				// Compatibility for browsers without EMCA-252-5 (JS 1.6)
7217				for ( var i=0, ien=this.length ; i<ien ; i++ ) {
7218					a.push( fn.call( this, this[i], i ) );
7219				}
7220			}
7221	
7222			return new _Api( this.context, a );
7223		},
7224	
7225	
7226		pluck: function ( prop )
7227		{
7228			let fn = DataTable.util.get(prop);
7229	
7230			return this.map( function ( el ) {
7231				return fn(el);
7232			} );
7233		},
7234	
7235		pop:     __arrayProto.pop,
7236	
7237	
7238		push:    __arrayProto.push,
7239	
7240	
7241		// Does not return an API instance
7242		reduce: __arrayProto.reduce || function ( fn, init )
7243		{
7244			return _fnReduce( this, fn, init, 0, this.length, 1 );
7245		},
7246	
7247	
7248		reduceRight: __arrayProto.reduceRight || function ( fn, init )
7249		{
7250			return _fnReduce( this, fn, init, this.length-1, -1, -1 );
7251		},
7252	
7253	
7254		reverse: __arrayProto.reverse,
7255	
7256	
7257		// Object with rows, columns and opts
7258		selector: null,
7259	
7260	
7261		shift:   __arrayProto.shift,
7262	
7263	
7264		slice: function () {
7265			return new _Api( this.context, this );
7266		},
7267	
7268	
7269		sort:    __arrayProto.sort, // ? name - order?
7270	
7271	
7272		splice:  __arrayProto.splice,
7273	
7274	
7275		toArray: function ()
7276		{
7277			return __arrayProto.slice.call( this );
7278		},
7279	
7280	
7281		to$: function ()
7282		{
7283			return $( this );
7284		},
7285	
7286	
7287		toJQuery: function ()
7288		{
7289			return $( this );
7290		},
7291	
7292	
7293		unique: function ()
7294		{
7295			return new _Api( this.context, _unique(this) );
7296		},
7297	
7298	
7299		unshift: __arrayProto.unshift
7300	} );
7301	
7302	
7303	_Api.extend = function ( scope, obj, ext )
7304	{
7305		// Only extend API instances and static properties of the API
7306		if ( ! ext.length || ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) {
7307			return;
7308		}
7309	
7310		var
7311			i, ien,
7312			struct,
7313			methodScoping = function ( scope, fn, struc ) {
7314				return function () {
7315					var ret = fn.apply( scope, arguments );
7316	
7317					// Method extension
7318					_Api.extend( ret, ret, struc.methodExt );
7319					return ret;
7320				};
7321			};
7322	
7323		for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7324			struct = ext[i];
7325	
7326			// Value
7327			obj[ struct.name ] = struct.type === 'function' ?
7328				methodScoping( scope, struct.val, struct ) :
7329				struct.type === 'object' ?
7330					{} :
7331					struct.val;
7332	
7333			obj[ struct.name ].__dt_wrapper = true;
7334	
7335			// Property extension
7336			_Api.extend( scope, obj[ struct.name ], struct.propExt );
7337		}
7338	};
7339	
7340	
7341	// @todo - Is there need for an augment function?
7342	// _Api.augment = function ( inst, name )
7343	// {
7344	// 	// Find src object in the structure from the name
7345	// 	var parts = name.split('.');
7346	
7347	// 	_Api.extend( inst, obj );
7348	// };
7349	
7350	
7351	//     [
7352	//       {
7353	//         name:      'data'                -- string   - Property name
7354	//         val:       function () {},       -- function - Api method (or undefined if just an object
7355	//         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
7356	//         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
7357	//       },
7358	//       {
7359	//         name:     'row'
7360	//         val:       {},
7361	//         methodExt: [ ... ],
7362	//         propExt:   [
7363	//           {
7364	//             name:      'data'
7365	//             val:       function () {},
7366	//             methodExt: [ ... ],
7367	//             propExt:   [ ... ]
7368	//           },
7369	//           ...
7370	//         ]
7371	//       }
7372	//     ]
7373	
7374	_Api.register = _api_register = function ( name, val )
7375	{
7376		if ( Array.isArray( name ) ) {
7377			for ( var j=0, jen=name.length ; j<jen ; j++ ) {
7378				_Api.register( name[j], val );
7379			}
7380			return;
7381		}
7382	
7383		var
7384			i, ien,
7385			heir = name.split('.'),
7386			struct = __apiStruct,
7387			key, method;
7388	
7389		var find = function ( src, name ) {
7390			for ( var i=0, ien=src.length ; i<ien ; i++ ) {
7391				if ( src[i].name === name ) {
7392					return src[i];
7393				}
7394			}
7395			return null;
7396		};
7397	
7398		for ( i=0, ien=heir.length ; i<ien ; i++ ) {
7399			method = heir[i].indexOf('()') !== -1;
7400			key = method ?
7401				heir[i].replace('()', '') :
7402				heir[i];
7403	
7404			var src = find( struct, key );
7405			if ( ! src ) {
7406				src = {
7407					name:      key,
7408					val:       {},
7409					methodExt: [],
7410					propExt:   [],
7411					type:      'object'
7412				};
7413				struct.push( src );
7414			}
7415	
7416			if ( i === ien-1 ) {
7417				src.val = val;
7418				src.type = typeof val === 'function' ?
7419					'function' :
7420					$.isPlainObject( val ) ?
7421						'object' :
7422						'other';
7423			}
7424			else {
7425				struct = method ?
7426					src.methodExt :
7427					src.propExt;
7428			}
7429		}
7430	};
7431	
7432	_Api.registerPlural = _api_registerPlural = function ( pluralName, singularName, val ) {
7433		_Api.register( pluralName, val );
7434	
7435		_Api.register( singularName, function () {
7436			var ret = val.apply( this, arguments );
7437	
7438			if ( ret === this ) {
7439				// Returned item is the API instance that was passed in, return it
7440				return this;
7441			}
7442			else if ( ret instanceof _Api ) {
7443				// New API instance returned, want the value from the first item
7444				// in the returned array for the singular result.
7445				return ret.length ?
7446					Array.isArray( ret[0] ) ?
7447						new _Api( ret.context, ret[0] ) : // Array results are 'enhanced'
7448						ret[0] :
7449					undefined;
7450			}
7451	
7452			// Non-API return - just fire it back
7453			return ret;
7454		} );
7455	};
7456	
7457	
7458	/**
7459	 * Selector for HTML tables. Apply the given selector to the give array of
7460	 * DataTables settings objects.
7461	 *
7462	 * @param {string|integer} [selector] jQuery selector string or integer
7463	 * @param  {array} Array of DataTables settings objects to be filtered
7464	 * @return {array}
7465	 * @ignore
7466	 */
7467	var __table_selector = function ( selector, a )
7468	{
7469		if ( Array.isArray(selector) ) {
7470			return $.map( selector, function (item) {
7471				return __table_selector(item, a);
7472			} );
7473		}
7474	
7475		// Integer is used to pick out a table by index
7476		if ( typeof selector === 'number' ) {
7477			return [ a[ selector ] ];
7478		}
7479	
7480		// Perform a jQuery selector on the table nodes
7481		var nodes = $.map( a, function (el, i) {
7482			return el.nTable;
7483		} );
7484	
7485		return $(nodes)
7486			.filter( selector )
7487			.map( function (i) {
7488				// Need to translate back from the table node to the settings
7489				var idx = $.inArray( this, nodes );
7490				return a[ idx ];
7491			} )
7492			.toArray();
7493	};
7494	
7495	
7496	
7497	/**
7498	 * Context selector for the API's context (i.e. the tables the API instance
7499	 * refers to.
7500	 *
7501	 * @name    DataTable.Api#tables
7502	 * @param {string|integer} [selector] Selector to pick which tables the iterator
7503	 *   should operate on. If not given, all tables in the current context are
7504	 *   used. This can be given as a jQuery selector (for example `':gt(0)'`) to
7505	 *   select multiple tables or as an integer to select a single table.
7506	 * @returns {DataTable.Api} Returns a new API instance if a selector is given.
7507	 */
7508	_api_register( 'tables()', function ( selector ) {
7509		// A new instance is created if there was a selector specified
7510		return selector !== undefined && selector !== null ?
7511			new _Api( __table_selector( selector, this.context ) ) :
7512			this;
7513	} );
7514	
7515	
7516	_api_register( 'table()', function ( selector ) {
7517		var tables = this.tables( selector );
7518		var ctx = tables.context;
7519	
7520		// Truncate to the first matched table
7521		return ctx.length ?
7522			new _Api( ctx[0] ) :
7523			tables;
7524	} );
7525	
7526	
7527	_api_registerPlural( 'tables().nodes()', 'table().node()' , function () {
7528		return this.iterator( 'table', function ( ctx ) {
7529			return ctx.nTable;
7530		}, 1 );
7531	} );
7532	
7533	
7534	_api_registerPlural( 'tables().body()', 'table().body()' , function () {
7535		return this.iterator( 'table', function ( ctx ) {
7536			return ctx.nTBody;
7537		}, 1 );
7538	} );
7539	
7540	
7541	_api_registerPlural( 'tables().header()', 'table().header()' , function () {
7542		return this.iterator( 'table', function ( ctx ) {
7543			return ctx.nTHead;
7544		}, 1 );
7545	} );
7546	
7547	
7548	_api_registerPlural( 'tables().footer()', 'table().footer()' , function () {
7549		return this.iterator( 'table', function ( ctx ) {
7550			return ctx.nTFoot;
7551		}, 1 );
7552	} );
7553	
7554	
7555	_api_registerPlural( 'tables().containers()', 'table().container()' , function () {
7556		return this.iterator( 'table', function ( ctx ) {
7557			return ctx.nTableWrapper;
7558		}, 1 );
7559	} );
7560	
7561	
7562	
7563	/**
7564	 * Redraw the tables in the current context.
7565	 */
7566	_api_register( 'draw()', function ( paging ) {
7567		return this.iterator( 'table', function ( settings ) {
7568			if ( paging === 'page' ) {
7569				_fnDraw( settings );
7570			}
7571			else {
7572				if ( typeof paging === 'string' ) {
7573					paging = paging === 'full-hold' ?
7574						false :
7575						true;
7576				}
7577	
7578				_fnReDraw( settings, paging===false );
7579			}
7580		} );
7581	} );
7582	
7583	
7584	
7585	/**
7586	 * Get the current page index.
7587	 *
7588	 * @return {integer} Current page index (zero based)
7589	 *//**
7590	 * Set the current page.
7591	 *
7592	 * Note that if you attempt to show a page which does not exist, DataTables will
7593	 * not throw an error, but rather reset the paging.
7594	 *
7595	 * @param {integer|string} action The paging action to take. This can be one of:
7596	 *  * `integer` - The page index to jump to
7597	 *  * `string` - An action to take:
7598	 *    * `first` - Jump to first page.
7599	 *    * `next` - Jump to the next page
7600	 *    * `previous` - Jump to previous page
7601	 *    * `last` - Jump to the last page.
7602	 * @returns {DataTables.Api} this
7603	 */
7604	_api_register( 'page()', function ( action ) {
7605		if ( action === undefined ) {
7606			return this.page.info().page; // not an expensive call
7607		}
7608	
7609		// else, have an action to take on all tables
7610		return this.iterator( 'table', function ( settings ) {
7611			_fnPageChange( settings, action );
7612		} );
7613	} );
7614	
7615	
7616	/**
7617	 * Paging information for the first table in the current context.
7618	 *
7619	 * If you require paging information for another table, use the `table()` method
7620	 * with a suitable selector.
7621	 *
7622	 * @return {object} Object with the following properties set:
7623	 *  * `page` - Current page index (zero based - i.e. the first page is `0`)
7624	 *  * `pages` - Total number of pages
7625	 *  * `start` - Display index for the first record shown on the current page
7626	 *  * `end` - Display index for the last record shown on the current page
7627	 *  * `length` - Display length (number of records). Note that generally `start
7628	 *    + length = end`, but this is not always true, for example if there are
7629	 *    only 2 records to show on the final page, with a length of 10.
7630	 *  * `recordsTotal` - Full data set length
7631	 *  * `recordsDisplay` - Data set length once the current filtering criterion
7632	 *    are applied.
7633	 */
7634	_api_register( 'page.info()', function ( action ) {
7635		if ( this.context.length === 0 ) {
7636			return undefined;
7637		}
7638	
7639		var
7640			settings   = this.context[0],
7641			start      = settings._iDisplayStart,
7642			len        = settings.oFeatures.bPaginate ? settings._iDisplayLength : -1,
7643			visRecords = settings.fnRecordsDisplay(),
7644			all        = len === -1;
7645	
7646		return {
7647			"page":           all ? 0 : Math.floor( start / len ),
7648			"pages":          all ? 1 : Math.ceil( visRecords / len ),
7649			"start":          start,
7650			"end":            settings.fnDisplayEnd(),
7651			"length":         len,
7652			"recordsTotal":   settings.fnRecordsTotal(),
7653			"recordsDisplay": visRecords,
7654			"serverSide":     _fnDataSource( settings ) === 'ssp'
7655		};
7656	} );
7657	
7658	
7659	/**
7660	 * Get the current page length.
7661	 *
7662	 * @return {integer} Current page length. Note `-1` indicates that all records
7663	 *   are to be shown.
7664	 *//**
7665	 * Set the current page length.
7666	 *
7667	 * @param {integer} Page length to set. Use `-1` to show all records.
7668	 * @returns {DataTables.Api} this
7669	 */
7670	_api_register( 'page.len()', function ( len ) {
7671		// Note that we can't call this function 'length()' because `length`
7672		// is a Javascript property of functions which defines how many arguments
7673		// the function expects.
7674		if ( len === undefined ) {
7675			return this.context.length !== 0 ?
7676				this.context[0]._iDisplayLength :
7677				undefined;
7678		}
7679	
7680		// else, set the page length
7681		return this.iterator( 'table', function ( settings ) {
7682			_fnLengthChange( settings, len );
7683		} );
7684	} );
7685	
7686	
7687	
7688	var __reload = function ( settings, holdPosition, callback ) {
7689		// Use the draw event to trigger a callback
7690		if ( callback ) {
7691			var api = new _Api( settings );
7692	
7693			api.one( 'draw', function () {
7694				callback( api.ajax.json() );
7695			} );
7696		}
7697	
7698		if ( _fnDataSource( settings ) == 'ssp' ) {
7699			_fnReDraw( settings, holdPosition );
7700		}
7701		else {
7702			_fnProcessingDisplay( settings, true );
7703	
7704			// Cancel an existing request
7705			var xhr = settings.jqXHR;
7706			if ( xhr && xhr.readyState !== 4 ) {
7707				xhr.abort();
7708			}
7709	
7710			// Trigger xhr
7711			_fnBuildAjax( settings, [], function( json ) {
7712				_fnClearTable( settings );
7713	
7714				var data = _fnAjaxDataSrc( settings, json );
7715				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7716					_fnAddData( settings, data[i] );
7717				}
7718	
7719				_fnReDraw( settings, holdPosition );
7720				_fnProcessingDisplay( settings, false );
7721			} );
7722		}
7723	};
7724	
7725	
7726	/**
7727	 * Get the JSON response from the last Ajax request that DataTables made to the
7728	 * server. Note that this returns the JSON from the first table in the current
7729	 * context.
7730	 *
7731	 * @return {object} JSON received from the server.
7732	 */
7733	_api_register( 'ajax.json()', function () {
7734		var ctx = this.context;
7735	
7736		if ( ctx.length > 0 ) {
7737			return ctx[0].json;
7738		}
7739	
7740		// else return undefined;
7741	} );
7742	
7743	
7744	/**
7745	 * Get the data submitted in the last Ajax request
7746	 */
7747	_api_register( 'ajax.params()', function () {
7748		var ctx = this.context;
7749	
7750		if ( ctx.length > 0 ) {
7751			return ctx[0].oAjaxData;
7752		}
7753	
7754		// else return undefined;
7755	} );
7756	
7757	
7758	/**
7759	 * Reload tables from the Ajax data source. Note that this function will
7760	 * automatically re-draw the table when the remote data has been loaded.
7761	 *
7762	 * @param {boolean} [reset=true] Reset (default) or hold the current paging
7763	 *   position. A full re-sort and re-filter is performed when this method is
7764	 *   called, which is why the pagination reset is the default action.
7765	 * @returns {DataTables.Api} this
7766	 */
7767	_api_register( 'ajax.reload()', function ( callback, resetPaging ) {
7768		return this.iterator( 'table', function (settings) {
7769			__reload( settings, resetPaging===false, callback );
7770		} );
7771	} );
7772	
7773	
7774	/**
7775	 * Get the current Ajax URL. Note that this returns the URL from the first
7776	 * table in the current context.
7777	 *
7778	 * @return {string} Current Ajax source URL
7779	 *//**
7780	 * Set the Ajax URL. Note that this will set the URL for all tables in the
7781	 * current context.
7782	 *
7783	 * @param {string} url URL to set.
7784	 * @returns {DataTables.Api} this
7785	 */
7786	_api_register( 'ajax.url()', function ( url ) {
7787		var ctx = this.context;
7788	
7789		if ( url === undefined ) {
7790			// get
7791			if ( ctx.length === 0 ) {
7792				return undefined;
7793			}
7794			ctx = ctx[0];
7795	
7796			return ctx.ajax ?
7797				$.isPlainObject( ctx.ajax ) ?
7798					ctx.ajax.url :
7799					ctx.ajax :
7800				ctx.sAjaxSource;
7801		}
7802	
7803		// set
7804		return this.iterator( 'table', function ( settings ) {
7805			if ( $.isPlainObject( settings.ajax ) ) {
7806				settings.ajax.url = url;
7807			}
7808			else {
7809				settings.ajax = url;
7810			}
7811			// No need to consider sAjaxSource here since DataTables gives priority
7812			// to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any
7813			// value of `sAjaxSource` redundant.
7814		} );
7815	} );
7816	
7817	
7818	/**
7819	 * Load data from the newly set Ajax URL. Note that this method is only
7820	 * available when `ajax.url()` is used to set a URL. Additionally, this method
7821	 * has the same effect as calling `ajax.reload()` but is provided for
7822	 * convenience when setting a new URL. Like `ajax.reload()` it will
7823	 * automatically redraw the table once the remote data has been loaded.
7824	 *
7825	 * @returns {DataTables.Api} this
7826	 */
7827	_api_register( 'ajax.url().load()', function ( callback, resetPaging ) {
7828		// Same as a reload, but makes sense to present it for easy access after a
7829		// url change
7830		return this.iterator( 'table', function ( ctx ) {
7831			__reload( ctx, resetPaging===false, callback );
7832		} );
7833	} );
7834	
7835	
7836	
7837	
7838	var _selector_run = function ( type, selector, selectFn, settings, opts )
7839	{
7840		var
7841			out = [], res,
7842			a, i, ien, j, jen,
7843			selectorType = typeof selector;
7844	
7845		// Can't just check for isArray here, as an API or jQuery instance might be
7846		// given with their array like look
7847		if ( ! selector || selectorType === 'string' || selectorType === 'function' || selector.length === undefined ) {
7848			selector = [ selector ];
7849		}
7850	
7851		for ( i=0, ien=selector.length ; i<ien ; i++ ) {
7852			// Only split on simple strings - complex expressions will be jQuery selectors
7853			a = selector[i] && selector[i].split && ! selector[i].match(/[\[\(:]/) ?
7854				selector[i].split(',') :
7855				[ selector[i] ];
7856	
7857			for ( j=0, jen=a.length ; j<jen ; j++ ) {
7858				res = selectFn( typeof a[j] === 'string' ? (a[j]).trim() : a[j] );
7859	
7860				if ( res && res.length ) {
7861					out = out.concat( res );
7862				}
7863			}
7864		}
7865	
7866		// selector extensions
7867		var ext = _ext.selector[ type ];
7868		if ( ext.length ) {
7869			for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7870				out = ext[i]( settings, opts, out );
7871			}
7872		}
7873	
7874		return _unique( out );
7875	};
7876	
7877	
7878	var _selector_opts = function ( opts )
7879	{
7880		if ( ! opts ) {
7881			opts = {};
7882		}
7883	
7884		// Backwards compatibility for 1.9- which used the terminology filter rather
7885		// than search
7886		if ( opts.filter && opts.search === undefined ) {
7887			opts.search = opts.filter;
7888		}
7889	
7890		return $.extend( {
7891			search: 'none',
7892			order: 'current',
7893			page: 'all'
7894		}, opts );
7895	};
7896	
7897	
7898	var _selector_first = function ( inst )
7899	{
7900		// Reduce the API instance to the first item found
7901		for ( var i=0, ien=inst.length ; i<ien ; i++ ) {
7902			if ( inst[i].length > 0 ) {
7903				// Assign the first element to the first item in the instance
7904				// and truncate the instance and context
7905				inst[0] = inst[i];
7906				inst[0].length = 1;
7907				inst.length = 1;
7908				inst.context = [ inst.context[i] ];
7909	
7910				return inst;
7911			}
7912		}
7913	
7914		// Not found - return an empty instance
7915		inst.length = 0;
7916		return inst;
7917	};
7918	
7919	
7920	var _selector_row_indexes = function ( settings, opts )
7921	{
7922		var
7923			i, ien, tmp, a=[],
7924			displayFiltered = settings.aiDisplay,
7925			displayMaster = settings.aiDisplayMaster;
7926	
7927		var
7928			search = opts.search,  // none, applied, removed
7929			order  = opts.order,   // applied, current, index (original - compatibility with 1.9)
7930			page   = opts.page;    // all, current
7931	
7932		if ( _fnDataSource( settings ) == 'ssp' ) {
7933			// In server-side processing mode, most options are irrelevant since
7934			// rows not shown don't exist and the index order is the applied order
7935			// Removed is a special case - for consistency just return an empty
7936			// array
7937			return search === 'removed' ?
7938				[] :
7939				_range( 0, displayMaster.length );
7940		}
7941		else if ( page == 'current' ) {
7942			// Current page implies that order=current and filter=applied, since it is
7943			// fairly senseless otherwise, regardless of what order and search actually
7944			// are
7945			for ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i<ien ; i++ ) {
7946				a.push( displayFiltered[i] );
7947			}
7948		}
7949		else if ( order == 'current' || order == 'applied' ) {
7950			if ( search == 'none') {
7951				a = displayMaster.slice();
7952			}
7953			else if ( search == 'applied' ) {
7954				a = displayFiltered.slice();
7955			}
7956			else if ( search == 'removed' ) {
7957				// O(n+m) solution by creating a hash map
7958				var displayFilteredMap = {};
7959	
7960				for ( var i=0, ien=displayFiltered.length ; i<ien ; i++ ) {
7961					displayFilteredMap[displayFiltered[i]] = null;
7962				}
7963	
7964				a = $.map( displayMaster, function (el) {
7965					return ! displayFilteredMap.hasOwnProperty(el) ?
7966						el :
7967						null;
7968				} );
7969			}
7970		}
7971		else if ( order == 'index' || order == 'original' ) {
7972			for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
7973				if ( search == 'none' ) {
7974					a.push( i );
7975				}
7976				else { // applied | removed
7977					tmp = $.inArray( i, displayFiltered );
7978	
7979					if ((tmp === -1 && search == 'removed') ||
7980						(tmp >= 0   && search == 'applied') )
7981					{
7982						a.push( i );
7983					}
7984				}
7985			}
7986		}
7987	
7988		return a;
7989	};
7990	
7991	
7992	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
7993	 * Rows
7994	 *
7995	 * {}          - no selector - use all available rows
7996	 * {integer}   - row aoData index
7997	 * {node}      - TR node
7998	 * {string}    - jQuery selector to apply to the TR elements
7999	 * {array}     - jQuery array of nodes, or simply an array of TR nodes
8000	 *
8001	 */
8002	var __row_selector = function ( settings, selector, opts )
8003	{
8004		var rows;
8005		var run = function ( sel ) {
8006			var selInt = _intVal( sel );
8007			var i, ien;
8008			var aoData = settings.aoData;
8009	
8010			// Short cut - selector is a number and no options provided (default is
8011			// all records, so no need to check if the index is in there, since it
8012			// must be - dev error if the index doesn't exist).
8013			if ( selInt !== null && ! opts ) {
8014				return [ selInt ];
8015			}
8016	
8017			if ( ! rows ) {
8018				rows = _selector_row_indexes( settings, opts );
8019			}
8020	
8021			if ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) {
8022				// Selector - integer
8023				return [ selInt ];
8024			}
8025			else if ( sel === null || sel === undefined || sel === '' ) {
8026				// Selector - none
8027				return rows;
8028			}
8029	
8030			// Selector - function
8031			if ( typeof sel === 'function' ) {
8032				return $.map( rows, function (idx) {
8033					var row = aoData[ idx ];
8034					return sel( idx, row._aData, row.nTr ) ? idx : null;
8035				} );
8036			}
8037	
8038			// Selector - node
8039			if ( sel.nodeName ) {
8040				var rowIdx = sel._DT_RowIndex;  // Property added by DT for fast lookup
8041				var cellIdx = sel._DT_CellIndex;
8042	
8043				if ( rowIdx !== undefined ) {
8044					// Make sure that the row is actually still present in the table
8045					return aoData[ rowIdx ] && aoData[ rowIdx ].nTr === sel ?
8046						[ rowIdx ] :
8047						[];
8048				}
8049				else if ( cellIdx ) {
8050					return aoData[ cellIdx.row ] && aoData[ cellIdx.row ].nTr === sel.parentNode ?
8051						[ cellIdx.row ] :
8052						[];
8053				}
8054				else {
8055					var host = $(sel).closest('*[data-dt-row]');
8056					return host.length ?
8057						[ host.data('dt-row') ] :
8058						[];
8059				}
8060			}
8061	
8062			// ID selector. Want to always be able to select rows by id, regardless
8063			// of if the tr element has been created or not, so can't rely upon
8064			// jQuery here - hence a custom implementation. This does not match
8065			// Sizzle's fast selector or HTML4 - in HTML5 the ID can be anything,
8066			// but to select it using a CSS selector engine (like Sizzle or
8067			// querySelect) it would need to need to be escaped for some characters.
8068			// DataTables simplifies this for row selectors since you can select
8069			// only a row. A # indicates an id any anything that follows is the id -
8070			// unescaped.
8071			if ( typeof sel === 'string' && sel.charAt(0) === '#' ) {
8072				// get row index from id
8073				var rowObj = settings.aIds[ sel.replace( /^#/, '' ) ];
8074				if ( rowObj !== undefined ) {
8075					return [ rowObj.idx ];
8076				}
8077	
8078				// need to fall through to jQuery in case there is DOM id that
8079				// matches
8080			}
8081			
8082			// Get nodes in the order from the `rows` array with null values removed
8083			var nodes = _removeEmpty(
8084				_pluck_order( settings.aoData, rows, 'nTr' )
8085			);
8086	
8087			// Selector - jQuery selector string, array of nodes or jQuery object/
8088			// As jQuery's .filter() allows jQuery objects to be passed in filter,
8089			// it also allows arrays, so this will cope with all three options
8090			return $(nodes)
8091				.filter( sel )
8092				.map( function () {
8093					return this._DT_RowIndex;
8094				} )
8095				.toArray();
8096		};
8097	
8098		return _selector_run( 'row', selector, run, settings, opts );
8099	};
8100	
8101	
8102	_api_register( 'rows()', function ( selector, opts ) {
8103		// argument shifting
8104		if ( selector === undefined ) {
8105			selector = '';
8106		}
8107		else if ( $.isPlainObject( selector ) ) {
8108			opts = selector;
8109			selector = '';
8110		}
8111	
8112		opts = _selector_opts( opts );
8113	
8114		var inst = this.iterator( 'table', function ( settings ) {
8115			return __row_selector( settings, selector, opts );
8116		}, 1 );
8117	
8118		// Want argument shifting here and in __row_selector?
8119		inst.selector.rows = selector;
8120		inst.selector.opts = opts;
8121	
8122		return inst;
8123	} );
8124	
8125	_api_register( 'rows().nodes()', function () {
8126		return this.iterator( 'row', function ( settings, row ) {
8127			return settings.aoData[ row ].nTr || undefined;
8128		}, 1 );
8129	} );
8130	
8131	_api_register( 'rows().data()', function () {
8132		return this.iterator( true, 'rows', function ( settings, rows ) {
8133			return _pluck_order( settings.aoData, rows, '_aData' );
8134		}, 1 );
8135	} );
8136	
8137	_api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) {
8138		return this.iterator( 'row', function ( settings, row ) {
8139			var r = settings.aoData[ row ];
8140			return type === 'search' ? r._aFilterData : r._aSortData;
8141		}, 1 );
8142	} );
8143	
8144	_api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) {
8145		return this.iterator( 'row', function ( settings, row ) {
8146			_fnInvalidate( settings, row, src );
8147		} );
8148	} );
8149	
8150	_api_registerPlural( 'rows().indexes()', 'row().index()', function () {
8151		return this.iterator( 'row', function ( settings, row ) {
8152			return row;
8153		}, 1 );
8154	} );
8155	
8156	_api_registerPlural( 'rows().ids()', 'row().id()', function ( hash ) {
8157		var a = [];
8158		var context = this.context;
8159	
8160		// `iterator` will drop undefined values, but in this case we want them
8161		for ( var i=0, ien=context.length ; i<ien ; i++ ) {
8162			for ( var j=0, jen=this[i].length ; j<jen ; j++ ) {
8163				var id = context[i].rowIdFn( context[i].aoData[ this[i][j] ]._aData );
8164				a.push( (hash === true ? '#' : '' )+ id );
8165			}
8166		}
8167	
8168		return new _Api( context, a );
8169	} );
8170	
8171	_api_registerPlural( 'rows().remove()', 'row().remove()', function () {
8172		var that = this;
8173	
8174		this.iterator( 'row', function ( settings, row, thatIdx ) {
8175			var data = settings.aoData;
8176			var rowData = data[ row ];
8177			var i, ien, j, jen;
8178			var loopRow, loopCells;
8179	
8180			data.splice( row, 1 );
8181	
8182			// Update the cached indexes
8183			for ( i=0, ien=data.length ; i<ien ; i++ ) {
8184				loopRow = data[i];
8185				loopCells = loopRow.anCells;
8186	
8187				// Rows
8188				if ( loopRow.nTr !== null ) {
8189					loopRow.nTr._DT_RowIndex = i;
8190				}
8191	
8192				// Cells
8193				if ( loopCells !== null ) {
8194					for ( j=0, jen=loopCells.length ; j<jen ; j++ ) {
8195						loopCells[j]._DT_CellIndex.row = i;
8196					}
8197				}
8198			}
8199	
8200			// Delete from the display arrays
8201			_fnDeleteIndex( settings.aiDisplayMaster, row );
8202			_fnDeleteIndex( settings.aiDisplay, row );
8203			_fnDeleteIndex( that[ thatIdx ], row, false ); // maintain local indexes
8204	
8205			// For server-side processing tables - subtract the deleted row from the count
8206			if ( settings._iRecordsDisplay > 0 ) {
8207				settings._iRecordsDisplay--;
8208			}
8209	
8210			// Check for an 'overflow' they case for displaying the table
8211			_fnLengthOverflow( settings );
8212	
8213			// Remove the row's ID reference if there is one
8214			var id = settings.rowIdFn( rowData._aData );
8215			if ( id !== undefined ) {
8216				delete settings.aIds[ id ];
8217			}
8218		} );
8219	
8220		this.iterator( 'table', function ( settings ) {
8221			for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
8222				settings.aoData[i].idx = i;
8223			}
8224		} );
8225	
8226		return this;
8227	} );
8228	
8229	
8230	_api_register( 'rows.add()', function ( rows ) {
8231		var newRows = this.iterator( 'table', function ( settings ) {
8232				var row, i, ien;
8233				var out = [];
8234	
8235				for ( i=0, ien=rows.length ; i<ien ; i++ ) {
8236					row = rows[i];
8237	
8238					if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
8239						out.push( _fnAddTr( settings, row )[0] );
8240					}
8241					else {
8242						out.push( _fnAddData( settings, row ) );
8243					}
8244				}
8245	
8246				return out;
8247			}, 1 );
8248	
8249		// Return an Api.rows() extended instance, so rows().nodes() etc can be used
8250		var modRows = this.rows( -1 );
8251		modRows.pop();
8252		$.merge( modRows, newRows );
8253	
8254		return modRows;
8255	} );
8256	
8257	
8258	
8259	
8260	
8261	/**
8262	 *
8263	 */
8264	_api_register( 'row()', function ( selector, opts ) {
8265		return _selector_first( this.rows( selector, opts ) );
8266	} );
8267	
8268	
8269	_api_register( 'row().data()', function ( data ) {
8270		var ctx = this.context;
8271	
8272		if ( data === undefined ) {
8273			// Get
8274			return ctx.length && this.length ?
8275				ctx[0].aoData[ this[0] ]._aData :
8276				undefined;
8277		}
8278	
8279		// Set
8280		var row = ctx[0].aoData[ this[0] ];
8281		row._aData = data;
8282	
8283		// If the DOM has an id, and the data source is an array
8284		if ( Array.isArray( data ) && row.nTr && row.nTr.id ) {
8285			_fnSetObjectDataFn( ctx[0].rowId )( data, row.nTr.id );
8286		}
8287	
8288		// Automatically invalidate
8289		_fnInvalidate( ctx[0], this[0], 'data' );
8290	
8291		return this;
8292	} );
8293	
8294	
8295	_api_register( 'row().node()', function () {
8296		var ctx = this.context;
8297	
8298		return ctx.length && this.length ?
8299			ctx[0].aoData[ this[0] ].nTr || null :
8300			null;
8301	} );
8302	
8303	
8304	_api_register( 'row.add()', function ( row ) {
8305		// Allow a jQuery object to be passed in - only a single row is added from
8306		// it though - the first element in the set
8307		if ( row instanceof $ && row.length ) {
8308			row = row[0];
8309		}
8310	
8311		var rows = this.iterator( 'table', function ( settings ) {
8312			if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
8313				return _fnAddTr( settings, row )[0];
8314			}
8315			return _fnAddData( settings, row );
8316		} );
8317	
8318		// Return an Api.rows() extended instance, with the newly added row selected
8319		return this.row( rows[0] );
8320	} );
8321	
8322	
8323	$(document).on('plugin-init.dt', function (e, context) {
8324		var api = new _Api( context );
8325	
8326		api.on( 'stateSaveParams', function ( e, settings, d ) {
8327			// This could be more compact with the API, but it is a lot faster as a simple
8328			// internal loop
8329			var idFn = settings.rowIdFn;
8330			var data = settings.aoData;
8331			var ids = [];
8332	
8333			for (var i=0 ; i<data.length ; i++) {
8334				if (data[i]._detailsShow) {
8335					ids.push( '#' + idFn(data[i]._aData) );
8336				}
8337			}
8338	
8339			d.childRows = ids;
8340		})
8341	
8342		var loaded = api.state.loaded();
8343	
8344		if ( loaded && loaded.childRows ) {
8345			api
8346				.rows( $.map(loaded.childRows, function (id){
8347					return id.replace(/:/g, '\\:')
8348				}) )
8349				.every( function () {
8350					_fnCallbackFire( context, null, 'requestChild', [ this ] )
8351				});
8352		}
8353	});
8354	
8355	var __details_add = function ( ctx, row, data, klass )
8356	{
8357		// Convert to array of TR elements
8358		var rows = [];
8359		var addRow = function ( r, k ) {
8360			// Recursion to allow for arrays of jQuery objects
8361			if ( Array.isArray( r ) || r instanceof $ ) {
8362				for ( var i=0, ien=r.length ; i<ien ; i++ ) {
8363					addRow( r[i], k );
8364				}
8365				return;
8366			}
8367	
8368			// If we get a TR element, then just add it directly - up to the dev
8369			// to add the correct number of columns etc
8370			if ( r.nodeName && r.nodeName.toLowerCase() === 'tr' ) {
8371				rows.push( r );
8372			}
8373			else {
8374				// Otherwise create a row with a wrapper
8375				var created = $('<tr><td></td></tr>').addClass( k );
8376				$('td', created)
8377					.addClass( k )
8378					.html( r )
8379					[0].colSpan = _fnVisbleColumns( ctx );
8380	
8381				rows.push( created[0] );
8382			}
8383		};
8384	
8385		addRow( data, klass );
8386	
8387		if ( row._details ) {
8388			row._details.detach();
8389		}
8390	
8391		row._details = $(rows);
8392	
8393		// If the children were already shown, that state should be retained
8394		if ( row._detailsShow ) {
8395			row._details.insertAfter( row.nTr );
8396		}
8397	};
8398	
8399	
8400	// Make state saving of child row details async to allow them to be batch processed
8401	var __details_state = DataTable.util.throttle(
8402		function (ctx) {
8403			_fnSaveState( ctx[0] )
8404		},
8405		500
8406	);
8407	
8408	
8409	var __details_remove = function ( api, idx )
8410	{
8411		var ctx = api.context;
8412	
8413		if ( ctx.length ) {
8414			var row = ctx[0].aoData[ idx !== undefined ? idx : api[0] ];
8415	
8416			if ( row && row._details ) {
8417				row._details.remove();
8418	
8419				row._detailsShow = undefined;
8420				row._details = undefined;
8421				$( row.nTr ).removeClass( 'dt-hasChild' );
8422				__details_state( ctx );
8423			}
8424		}
8425	};
8426	
8427	
8428	var __details_display = function ( api, show ) {
8429		var ctx = api.context;
8430	
8431		if ( ctx.length && api.length ) {
8432			var row = ctx[0].aoData[ api[0] ];
8433	
8434			if ( row._details ) {
8435				row._detailsShow = show;
8436	
8437				if ( show ) {
8438					row._details.insertAfter( row.nTr );
8439					$( row.nTr ).addClass( 'dt-hasChild' );
8440				}
8441				else {
8442					row._details.detach();
8443					$( row.nTr ).removeClass( 'dt-hasChild' );
8444				}
8445	
8446				_fnCallbackFire( ctx[0], null, 'childRow', [ show, api.row( api[0] ) ] )
8447	
8448				__details_events( ctx[0] );
8449				__details_state( ctx );
8450			}
8451		}
8452	};
8453	
8454	
8455	var __details_events = function ( settings )
8456	{
8457		var api = new _Api( settings );
8458		var namespace = '.dt.DT_details';
8459		var drawEvent = 'draw'+namespace;
8460		var colvisEvent = 'column-sizing'+namespace;
8461		var destroyEvent = 'destroy'+namespace;
8462		var data = settings.aoData;
8463	
8464		api.off( drawEvent +' '+ colvisEvent +' '+ destroyEvent );
8465	
8466		if ( _pluck( data, '_details' ).length > 0 ) {
8467			// On each draw, insert the required elements into the document
8468			api.on( drawEvent, function ( e, ctx ) {
8469				if ( settings !== ctx ) {
8470					return;
8471				}
8472	
8473				api.rows( {page:'current'} ).eq(0).each( function (idx) {
8474					// Internal data grab
8475					var row = data[ idx ];
8476	
8477					if ( row._detailsShow ) {
8478						row._details.insertAfter( row.nTr );
8479					}
8480				} );
8481			} );
8482	
8483			// Column visibility change - update the colspan
8484			api.on( colvisEvent, function ( e, ctx, idx, vis ) {
8485				if ( settings !== ctx ) {
8486					return;
8487				}
8488	
8489				// Update the colspan for the details rows (note, only if it already has
8490				// a colspan)
8491				var row, visible = _fnVisbleColumns( ctx );
8492	
8493				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
8494					row = data[i];
8495	
8496					if ( row._details ) {
8497						row._details.children('td[colspan]').attr('colspan', visible );
8498					}
8499				}
8500			} );
8501	
8502			// Table destroyed - nuke any child rows
8503			api.on( destroyEvent, function ( e, ctx ) {
8504				if ( settings !== ctx ) {
8505					return;
8506				}
8507	
8508				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
8509					if ( data[i]._details ) {
8510						__details_remove( api, i );
8511					}
8512				}
8513			} );
8514		}
8515	};
8516	
8517	// Strings for the method names to help minification
8518	var _emp = '';
8519	var _child_obj = _emp+'row().child';
8520	var _child_mth = _child_obj+'()';
8521	
8522	// data can be:
8523	//  tr
8524	//  string
8525	//  jQuery or array of any of the above
8526	_api_register( _child_mth, function ( data, klass ) {
8527		var ctx = this.context;
8528	
8529		if ( data === undefined ) {
8530			// get
8531			return ctx.length && this.length ?
8532				ctx[0].aoData[ this[0] ]._details :
8533				undefined;
8534		}
8535		else if ( data === true ) {
8536			// show
8537			this.child.show();
8538		}
8539		else if ( data === false ) {
8540			// remove
8541			__details_remove( this );
8542		}
8543		else if ( ctx.length && this.length ) {
8544			// set
8545			__details_add( ctx[0], ctx[0].aoData[ this[0] ], data, klass );
8546		}
8547	
8548		return this;
8549	} );
8550	
8551	
8552	_api_register( [
8553		_child_obj+'.show()',
8554		_child_mth+'.show()' // only when `child()` was called with parameters (without
8555	], function ( show ) {   // it returns an object and this method is not executed)
8556		__details_display( this, true );
8557		return this;
8558	} );
8559	
8560	
8561	_api_register( [
8562		_child_obj+'.hide()',
8563		_child_mth+'.hide()' // only when `child()` was called with parameters (without
8564	], function () {         // it returns an object and this method is not executed)
8565		__details_display( this, false );
8566		return this;
8567	} );
8568	
8569	
8570	_api_register( [
8571		_child_obj+'.remove()',
8572		_child_mth+'.remove()' // only when `child()` was called with parameters (without
8573	], function () {           // it returns an object and this method is not executed)
8574		__details_remove( this );
8575		return this;
8576	} );
8577	
8578	
8579	_api_register( _child_obj+'.isShown()', function () {
8580		var ctx = this.context;
8581	
8582		if ( ctx.length && this.length ) {
8583			// _detailsShown as false or undefined will fall through to return false
8584			return ctx[0].aoData[ this[0] ]._detailsShow || false;
8585		}
8586		return false;
8587	} );
8588	
8589	
8590	
8591	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
8592	 * Columns
8593	 *
8594	 * {integer}           - column index (>=0 count from left, <0 count from right)
8595	 * "{integer}:visIdx"  - visible column index (i.e. translate to column index)  (>=0 count from left, <0 count from right)
8596	 * "{integer}:visible" - alias for {integer}:visIdx  (>=0 count from left, <0 count from right)
8597	 * "{string}:name"     - column name
8598	 * "{string}"          - jQuery selector on column header nodes
8599	 *
8600	 */
8601	
8602	// can be an array of these items, comma separated list, or an array of comma
8603	// separated lists
8604	
8605	var __re_column_selector = /^([^:]+):(name|visIdx|visible)$/;
8606	
8607	
8608	// r1 and r2 are redundant - but it means that the parameters match for the
8609	// iterator callback in columns().data()
8610	var __columnData = function ( settings, column, r1, r2, rows ) {
8611		var a = [];
8612		for ( var row=0, ien=rows.length ; row<ien ; row++ ) {
8613			a.push( _fnGetCellData( settings, rows[row], column ) );
8614		}
8615		return a;
8616	};
8617	
8618	
8619	var __column_selector = function ( settings, selector, opts )
8620	{
8621		var
8622			columns = settings.aoColumns,
8623			names = _pluck( columns, 'sName' ),
8624			nodes = _pluck( columns, 'nTh' );
8625	
8626		var run = function ( s ) {
8627			var selInt = _intVal( s );
8628	
8629			// Selector - all
8630			if ( s === '' ) {
8631				return _range( columns.length );
8632			}
8633	
8634			// Selector - index
8635			if ( selInt !== null ) {
8636				return [ selInt >= 0 ?
8637					selInt : // Count from left
8638					columns.length + selInt // Count from right (+ because its a negative value)
8639				];
8640			}
8641	
8642			// Selector = function
8643			if ( typeof s === 'function' ) {
8644				var rows = _selector_row_indexes( settings, opts );
8645	
8646				return $.map( columns, function (col, idx) {
8647					return s(
8648							idx,
8649							__columnData( settings, idx, 0, 0, rows ),
8650							nodes[ idx ]
8651						) ? idx : null;
8652				} );
8653			}
8654	
8655			// jQuery or string selector
8656			var match = typeof s === 'string' ?
8657				s.match( __re_column_selector ) :
8658				'';
8659	
8660			if ( match ) {
8661				switch( match[2] ) {
8662					case 'visIdx':
8663					case 'visible':
8664						var idx = parseInt( match[1], 10 );
8665						// Visible index given, convert to column index
8666						if ( idx < 0 ) {
8667							// Counting from the right
8668							var visColumns = $.map( columns, function (col,i) {
8669								return col.bVisible ? i : null;
8670							} );
8671							return [ visColumns[ visColumns.length + idx ] ];
8672						}
8673						// Counting from the left
8674						return [ _fnVisibleToColumnIndex( settings, idx ) ];
8675	
8676					case 'name':
8677						// match by name. `names` is column index complete and in order
8678						return $.map( names, function (name, i) {
8679							return name === match[1] ? i : null;
8680						} );
8681	
8682					default:
8683						return [];
8684				}
8685			}
8686	
8687			// Cell in the table body
8688			if ( s.nodeName && s._DT_CellIndex ) {
8689				return [ s._DT_CellIndex.column ];
8690			}
8691	
8692			// jQuery selector on the TH elements for the columns
8693			var jqResult = $( nodes )
8694				.filter( s )
8695				.map( function () {
8696					return $.inArray( this, nodes ); // `nodes` is column index complete and in order
8697				} )
8698				.toArray();
8699	
8700			if ( jqResult.length || ! s.nodeName ) {
8701				return jqResult;
8702			}
8703	
8704			// Otherwise a node which might have a `dt-column` data attribute, or be
8705			// a child or such an element
8706			var host = $(s).closest('*[data-dt-column]');
8707			return host.length ?
8708				[ host.data('dt-column') ] :
8709				[];
8710		};
8711	
8712		return _selector_run( 'column', selector, run, settings, opts );
8713	};
8714	
8715	
8716	var __setColumnVis = function ( settings, column, vis ) {
8717		var
8718			cols = settings.aoColumns,
8719			col  = cols[ column ],
8720			data = settings.aoData,
8721			row, cells, i, ien, tr;
8722	
8723		// Get
8724		if ( vis === undefined ) {
8725			return col.bVisible;
8726		}
8727	
8728		// Set
8729		// No change
8730		if ( col.bVisible === vis ) {
8731			return;
8732		}
8733	
8734		if ( vis ) {
8735			// Insert column
8736			// Need to decide if we should use appendChild or insertBefore
8737			var insertBefore = $.inArray( true, _pluck(cols, 'bVisible'), column+1 );
8738	
8739			for ( i=0, ien=data.length ; i<ien ; i++ ) {
8740				tr = data[i].nTr;
8741				cells = data[i].anCells;
8742	
8743				if ( tr ) {
8744					// insertBefore can act like appendChild if 2nd arg is null
8745					tr.insertBefore( cells[ column ], cells[ insertBefore ] || null );
8746				}
8747			}
8748		}
8749		else {
8750			// Remove column
8751			$( _pluck( settings.aoData, 'anCells', column ) ).detach();
8752		}
8753	
8754		// Common actions
8755		col.bVisible = vis;
8756	};
8757	
8758	
8759	_api_register( 'columns()', function ( selector, opts ) {
8760		// argument shifting
8761		if ( selector === undefined ) {
8762			selector = '';
8763		}
8764		else if ( $.isPlainObject( selector ) ) {
8765			opts = selector;
8766			selector = '';
8767		}
8768	
8769		opts = _selector_opts( opts );
8770	
8771		var inst = this.iterator( 'table', function ( settings ) {
8772			return __column_selector( settings, selector, opts );
8773		}, 1 );
8774	
8775		// Want argument shifting here and in _row_selector?
8776		inst.selector.cols = selector;
8777		inst.selector.opts = opts;
8778	
8779		return inst;
8780	} );
8781	
8782	_api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) {
8783		return this.iterator( 'column', function ( settings, column ) {
8784			return settings.aoColumns[column].nTh;
8785		}, 1 );
8786	} );
8787	
8788	_api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) {
8789		return this.iterator( 'column', function ( settings, column ) {
8790			return settings.aoColumns[column].nTf;
8791		}, 1 );
8792	} );
8793	
8794	_api_registerPlural( 'columns().data()', 'column().data()', function () {
8795		return this.iterator( 'column-rows', __columnData, 1 );
8796	} );
8797	
8798	_api_registerPlural( 'columns().dataSrc()', 'column().dataSrc()', function () {
8799		return this.iterator( 'column', function ( settings, column ) {
8800			return settings.aoColumns[column].mData;
8801		}, 1 );
8802	} );
8803	
8804	_api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) {
8805		return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8806			return _pluck_order( settings.aoData, rows,
8807				type === 'search' ? '_aFilterData' : '_aSortData', column
8808			);
8809		}, 1 );
8810	} );
8811	
8812	_api_registerPlural( 'columns().nodes()', 'column().nodes()', function () {
8813		return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8814			return _pluck_order( settings.aoData, rows, 'anCells', column ) ;
8815		}, 1 );
8816	} );
8817	
8818	_api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis, calc ) {
8819		var that = this;
8820		var ret = this.iterator( 'column', function ( settings, column ) {
8821			if ( vis === undefined ) {
8822				return settings.aoColumns[ column ].bVisible;
8823			} // else
8824			__setColumnVis( settings, column, vis );
8825		} );
8826	
8827		// Group the column visibility changes
8828		if ( vis !== undefined ) {
8829			this.iterator( 'table', function ( settings ) {
8830				// Redraw the header after changes
8831				_fnDrawHead( settings, settings.aoHeader );
8832				_fnDrawHead( settings, settings.aoFooter );
8833		
8834				// Update colspan for no records display. Child rows and extensions will use their own
8835				// listeners to do this - only need to update the empty table item here
8836				if ( ! settings.aiDisplay.length ) {
8837					$(settings.nTBody).find('td[colspan]').attr('colspan', _fnVisbleColumns(settings));
8838				}
8839		
8840				_fnSaveState( settings );
8841	
8842				// Second loop once the first is done for events
8843				that.iterator( 'column', function ( settings, column ) {
8844					_fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis, calc] );
8845				} );
8846	
8847				if ( calc === undefined || calc ) {
8848					that.columns.adjust();
8849				}
8850			});
8851		}
8852	
8853		return ret;
8854	} );
8855	
8856	_api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) {
8857		return this.iterator( 'column', function ( settings, column ) {
8858			return type === 'visible' ?
8859				_fnColumnIndexToVisible( settings, column ) :
8860				column;
8861		}, 1 );
8862	} );
8863	
8864	_api_register( 'columns.adjust()', function () {
8865		return this.iterator( 'table', function ( settings ) {
8866			_fnAdjustColumnSizing( settings );
8867		}, 1 );
8868	} );
8869	
8870	_api_register( 'column.index()', function ( type, idx ) {
8871		if ( this.context.length !== 0 ) {
8872			var ctx = this.context[0];
8873	
8874			if ( type === 'fromVisible' || type === 'toData' ) {
8875				return _fnVisibleToColumnIndex( ctx, idx );
8876			}
8877			else if ( type === 'fromData' || type === 'toVisible' ) {
8878				return _fnColumnIndexToVisible( ctx, idx );
8879			}
8880		}
8881	} );
8882	
8883	_api_register( 'column()', function ( selector, opts ) {
8884		return _selector_first( this.columns( selector, opts ) );
8885	} );
8886	
8887	var __cell_selector = function ( settings, selector, opts )
8888	{
8889		var data = settings.aoData;
8890		var rows = _selector_row_indexes( settings, opts );
8891		var cells = _removeEmpty( _pluck_order( data, rows, 'anCells' ) );
8892		var allCells = $(_flatten( [], cells ));
8893		var row;
8894		var columns = settings.aoColumns.length;
8895		var a, i, ien, j, o, host;
8896	
8897		var run = function ( s ) {
8898			var fnSelector = typeof s === 'function';
8899	
8900			if ( s === null || s === undefined || fnSelector ) {
8901				// All cells and function selectors
8902				a = [];
8903	
8904				for ( i=0, ien=rows.length ; i<ien ; i++ ) {
8905					row = rows[i];
8906	
8907					for ( j=0 ; j<columns ; j++ ) {
8908						o = {
8909							row: row,
8910							column: j
8911						};
8912	
8913						if ( fnSelector ) {
8914							// Selector - function
8915							host = data[ row ];
8916	
8917							if ( s( o, _fnGetCellData(settings, row, j), host.anCells ? host.anCells[j] : null ) ) {
8918								a.push( o );
8919							}
8920						}
8921						else {
8922							// Selector - all
8923							a.push( o );
8924						}
8925					}
8926				}
8927	
8928				return a;
8929			}
8930			
8931			// Selector - index
8932			if ( $.isPlainObject( s ) ) {
8933				// Valid cell index and its in the array of selectable rows
8934				return s.column !== undefined && s.row !== undefined && $.inArray( s.row, rows ) !== -1 ?
8935					[s] :
8936					[];
8937			}
8938	
8939			// Selector - jQuery filtered cells
8940			var jqResult = allCells
8941				.filter( s )
8942				.map( function (i, el) {
8943					return { // use a new object, in case someone changes the values
8944						row:    el._DT_CellIndex.row,
8945						column: el._DT_CellIndex.column
8946	 				};
8947				} )
8948				.toArray();
8949	
8950			if ( jqResult.length || ! s.nodeName ) {
8951				return jqResult;
8952			}
8953	
8954			// Otherwise the selector is a node, and there is one last option - the
8955			// element might be a child of an element which has dt-row and dt-column
8956			// data attributes
8957			host = $(s).closest('*[data-dt-row]');
8958			return host.length ?
8959				[ {
8960					row: host.data('dt-row'),
8961					column: host.data('dt-column')
8962				} ] :
8963				[];
8964		};
8965	
8966		return _selector_run( 'cell', selector, run, settings, opts );
8967	};
8968	
8969	
8970	
8971	
8972	_api_register( 'cells()', function ( rowSelector, columnSelector, opts ) {
8973		// Argument shifting
8974		if ( $.isPlainObject( rowSelector ) ) {
8975			// Indexes
8976			if ( rowSelector.row === undefined ) {
8977				// Selector options in first parameter
8978				opts = rowSelector;
8979				rowSelector = null;
8980			}
8981			else {
8982				// Cell index objects in first parameter
8983				opts = columnSelector;
8984				columnSelector = null;
8985			}
8986		}
8987		if ( $.isPlainObject( columnSelector ) ) {
8988			opts = columnSelector;
8989			columnSelector = null;
8990		}
8991	
8992		// Cell selector
8993		if ( columnSelector === null || columnSelector === undefined ) {
8994			return this.iterator( 'table', function ( settings ) {
8995				return __cell_selector( settings, rowSelector, _selector_opts( opts ) );
8996			} );
8997		}
8998	
8999		// The default built in options need to apply to row and columns
9000		var internalOpts = opts ? {
9001			page: opts.page,
9002			order: opts.order,
9003			search: opts.search
9004		} : {};
9005	
9006		// Row + column selector
9007		var columns = this.columns( columnSelector, internalOpts );
9008		var rows = this.rows( rowSelector, internalOpts );
9009		var i, ien, j, jen;
9010	
9011		var cellsNoOpts = this.iterator( 'table', function ( settings, idx ) {
9012			var a = [];
9013	
9014			for ( i=0, ien=rows[idx].length ; i<ien ; i++ ) {
9015				for ( j=0, jen=columns[idx].length ; j<jen ; j++ ) {
9016					a.push( {
9017						row:    rows[idx][i],
9018						column: columns[idx][j]
9019					} );
9020				}
9021			}
9022	
9023			return a;
9024		}, 1 );
9025	
9026		// There is currently only one extension which uses a cell selector extension
9027		// It is a _major_ performance drag to run this if it isn't needed, so this is
9028		// an extension specific check at the moment
9029		var cells = opts && opts.selected ?
9030			this.cells( cellsNoOpts, opts ) :
9031			cellsNoOpts;
9032	
9033		$.extend( cells.selector, {
9034			cols: columnSelector,
9035			rows: rowSelector,
9036			opts: opts
9037		} );
9038	
9039		return cells;
9040	} );
9041	
9042	
9043	_api_registerPlural( 'cells().nodes()', 'cell().node()', function () {
9044		return this.iterator( 'cell', function ( settings, row, column ) {
9045			var data = settings.aoData[ row ];
9046	
9047			return data && data.anCells ?
9048				data.anCells[ column ] :
9049				undefined;
9050		}, 1 );
9051	} );
9052	
9053	
9054	_api_register( 'cells().data()', function () {
9055		return this.iterator( 'cell', function ( settings, row, column ) {
9056			return _fnGetCellData( settings, row, column );
9057		}, 1 );
9058	} );
9059	
9060	
9061	_api_registerPlural( 'cells().cache()', 'cell().cache()', function ( type ) {
9062		type = type === 'search' ? '_aFilterData' : '_aSortData';
9063	
9064		return this.iterator( 'cell', function ( settings, row, column ) {
9065			return settings.aoData[ row ][ type ][ column ];
9066		}, 1 );
9067	} );
9068	
9069	
9070	_api_registerPlural( 'cells().render()', 'cell().render()', function ( type ) {
9071		return this.iterator( 'cell', function ( settings, row, column ) {
9072			return _fnGetCellData( settings, row, column, type );
9073		}, 1 );
9074	} );
9075	
9076	
9077	_api_registerPlural( 'cells().indexes()', 'cell().index()', function () {
9078		return this.iterator( 'cell', function ( settings, row, column ) {
9079			return {
9080				row: row,
9081				column: column,
9082				columnVisible: _fnColumnIndexToVisible( settings, column )
9083			};
9084		}, 1 );
9085	} );
9086	
9087	
9088	_api_registerPlural( 'cells().invalidate()', 'cell().invalidate()', function ( src ) {
9089		return this.iterator( 'cell', function ( settings, row, column ) {
9090			_fnInvalidate( settings, row, src, column );
9091		} );
9092	} );
9093	
9094	
9095	
9096	_api_register( 'cell()', function ( rowSelector, columnSelector, opts ) {
9097		return _selector_first( this.cells( rowSelector, columnSelector, opts ) );
9098	} );
9099	
9100	
9101	_api_register( 'cell().data()', function ( data ) {
9102		var ctx = this.context;
9103		var cell = this[0];
9104	
9105		if ( data === undefined ) {
9106			// Get
9107			return ctx.length && cell.length ?
9108				_fnGetCellData( ctx[0], cell[0].row, cell[0].column ) :
9109				undefined;
9110		}
9111	
9112		// Set
9113		_fnSetCellData( ctx[0], cell[0].row, cell[0].column, data );
9114		_fnInvalidate( ctx[0], cell[0].row, 'data', cell[0].column );
9115	
9116		return this;
9117	} );
9118	
9119	
9120	
9121	/**
9122	 * Get current ordering (sorting) that has been applied to the table.
9123	 *
9124	 * @returns {array} 2D array containing the sorting information for the first
9125	 *   table in the current context. Each element in the parent array represents
9126	 *   a column being sorted upon (i.e. multi-sorting with two columns would have
9127	 *   2 inner arrays). The inner arrays may have 2 or 3 elements. The first is
9128	 *   the column index that the sorting condition applies to, the second is the
9129	 *   direction of the sort (`desc` or `asc`) and, optionally, the third is the
9130	 *   index of the sorting order from the `column.sorting` initialisation array.
9131	 *//**
9132	 * Set the ordering for the table.
9133	 *
9134	 * @param {integer} order Column index to sort upon.
9135	 * @param {string} direction Direction of the sort to be applied (`asc` or `desc`)
9136	 * @returns {DataTables.Api} this
9137	 *//**
9138	 * Set the ordering for the table.
9139	 *
9140	 * @param {array} order 1D array of sorting information to be applied.
9141	 * @param {array} [...] Optional additional sorting conditions
9142	 * @returns {DataTables.Api} this
9143	 *//**
9144	 * Set the ordering for the table.
9145	 *
9146	 * @param {array} order 2D array of sorting information to be applied.
9147	 * @returns {DataTables.Api} this
9148	 */
9149	_api_register( 'order()', function ( order, dir ) {
9150		var ctx = this.context;
9151	
9152		if ( order === undefined ) {
9153			// get
9154			return ctx.length !== 0 ?
9155				ctx[0].aaSorting :
9156				undefined;
9157		}
9158	
9159		// set
9160		if ( typeof order === 'number' ) {
9161			// Simple column / direction passed in
9162			order = [ [ order, dir ] ];
9163		}
9164		else if ( order.length && ! Array.isArray( order[0] ) ) {
9165			// Arguments passed in (list of 1D arrays)
9166			order = Array.prototype.slice.call( arguments );
9167		}
9168		// otherwise a 2D array was passed in
9169	
9170		return this.iterator( 'table', function ( settings ) {
9171			settings.aaSorting = order.slice();
9172		} );
9173	} );
9174	
9175	
9176	/**
9177	 * Attach a sort listener to an element for a given column
9178	 *
9179	 * @param {node|jQuery|string} node Identifier for the element(s) to attach the
9180	 *   listener to. This can take the form of a single DOM node, a jQuery
9181	 *   collection of nodes or a jQuery selector which will identify the node(s).
9182	 * @param {integer} column the column that a click on this node will sort on
9183	 * @param {function} [callback] callback function when sort is run
9184	 * @returns {DataTables.Api} this
9185	 */
9186	_api_register( 'order.listener()', function ( node, column, callback ) {
9187		return this.iterator( 'table', function ( settings ) {
9188			_fnSortAttachListener( settings, node, column, callback );
9189		} );
9190	} );
9191	
9192	
9193	_api_register( 'order.fixed()', function ( set ) {
9194		if ( ! set ) {
9195			var ctx = this.context;
9196			var fixed = ctx.length ?
9197				ctx[0].aaSortingFixed :
9198				undefined;
9199	
9200			return Array.isArray( fixed ) ?
9201				{ pre: fixed } :
9202				fixed;
9203		}
9204	
9205		return this.iterator( 'table', function ( settings ) {
9206			settings.aaSortingFixed = $.extend( true, {}, set );
9207		} );
9208	} );
9209	
9210	
9211	// Order by the selected column(s)
9212	_api_register( [
9213		'columns().order()',
9214		'column().order()'
9215	], function ( dir ) {
9216		var that = this;
9217	
9218		return this.iterator( 'table', function ( settings, i ) {
9219			var sort = [];
9220	
9221			$.each( that[i], function (j, col) {
9222				sort.push( [ col, dir ] );
9223			} );
9224	
9225			settings.aaSorting = sort;
9226		} );
9227	} );
9228	
9229	
9230	
9231	_api_register( 'search()', function ( input, regex, smart, caseInsen ) {
9232		var ctx = this.context;
9233	
9234		if ( input === undefined ) {
9235			// get
9236			return ctx.length !== 0 ?
9237				ctx[0].oPreviousSearch.sSearch :
9238				undefined;
9239		}
9240	
9241		// set
9242		return this.iterator( 'table', function ( settings ) {
9243			if ( ! settings.oFeatures.bFilter ) {
9244				return;
9245			}
9246	
9247			_fnFilterComplete( settings, $.extend( {}, settings.oPreviousSearch, {
9248				"sSearch": input+"",
9249				"bRegex":  regex === null ? false : regex,
9250				"bSmart":  smart === null ? true  : smart,
9251				"bCaseInsensitive": caseInsen === null ? true : caseInsen
9252			} ), 1 );
9253		} );
9254	} );
9255	
9256	
9257	_api_registerPlural(
9258		'columns().search()',
9259		'column().search()',
9260		function ( input, regex, smart, caseInsen ) {
9261			return this.iterator( 'column', function ( settings, column ) {
9262				var preSearch = settings.aoPreSearchCols;
9263	
9264				if ( input === undefined ) {
9265					// get
9266					return preSearch[ column ].sSearch;
9267				}
9268	
9269				// set
9270				if ( ! settings.oFeatures.bFilter ) {
9271					return;
9272				}
9273	
9274				$.extend( preSearch[ column ], {
9275					"sSearch": input+"",
9276					"bRegex":  regex === null ? false : regex,
9277					"bSmart":  smart === null ? true  : smart,
9278					"bCaseInsensitive": caseInsen === null ? true : caseInsen
9279				} );
9280	
9281				_fnFilterComplete( settings, settings.oPreviousSearch, 1 );
9282			} );
9283		}
9284	);
9285	
9286	/*
9287	 * State API methods
9288	 */
9289	
9290	_api_register( 'state()', function () {
9291		return this.context.length ?
9292			this.context[0].oSavedState :
9293			null;
9294	} );
9295	
9296	
9297	_api_register( 'state.clear()', function () {
9298		return this.iterator( 'table', function ( settings ) {
9299			// Save an empty object
9300			settings.fnStateSaveCallback.call( settings.oInstance, settings, {} );
9301		} );
9302	} );
9303	
9304	
9305	_api_register( 'state.loaded()', function () {
9306		return this.context.length ?
9307			this.context[0].oLoadedState :
9308			null;
9309	} );
9310	
9311	
9312	_api_register( 'state.save()', function () {
9313		return this.iterator( 'table', function ( settings ) {
9314			_fnSaveState( settings );
9315		} );
9316	} );
9317	
9318	
9319	
9320	/**
9321	 * Provide a common method for plug-ins to check the version of DataTables being
9322	 * used, in order to ensure compatibility.
9323	 *
9324	 *  @param {string} version Version string to check for, in the format "X.Y.Z".
9325	 *    Note that the formats "X" and "X.Y" are also acceptable.
9326	 *  @returns {boolean} true if this version of DataTables is greater or equal to
9327	 *    the required version, or false if this version of DataTales is not
9328	 *    suitable
9329	 *  @static
9330	 *  @dtopt API-Static
9331	 *
9332	 *  @example
9333	 *    alert( $.fn.dataTable.versionCheck( '1.9.0' ) );
9334	 */
9335	DataTable.versionCheck = DataTable.fnVersionCheck = function( version )
9336	{
9337		var aThis = DataTable.version.split('.');
9338		var aThat = version.split('.');
9339		var iThis, iThat;
9340	
9341		for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) {
9342			iThis = parseInt( aThis[i], 10 ) || 0;
9343			iThat = parseInt( aThat[i], 10 ) || 0;
9344	
9345			// Parts are the same, keep comparing
9346			if (iThis === iThat) {
9347				continue;
9348			}
9349	
9350			// Parts are different, return immediately
9351			return iThis > iThat;
9352		}
9353	
9354		return true;
9355	};
9356	
9357	
9358	/**
9359	 * Check if a `<table>` node is a DataTable table already or not.
9360	 *
9361	 *  @param {node|jquery|string} table Table node, jQuery object or jQuery
9362	 *      selector for the table to test. Note that if more than more than one
9363	 *      table is passed on, only the first will be checked
9364	 *  @returns {boolean} true the table given is a DataTable, or false otherwise
9365	 *  @static
9366	 *  @dtopt API-Static
9367	 *
9368	 *  @example
9369	 *    if ( ! $.fn.DataTable.isDataTable( '#example' ) ) {
9370	 *      $('#example').dataTable();
9371	 *    }
9372	 */
9373	DataTable.isDataTable = DataTable.fnIsDataTable = function ( table )
9374	{
9375		var t = $(table).get(0);
9376		var is = false;
9377	
9378		if ( table instanceof DataTable.Api ) {
9379			return true;
9380		}
9381	
9382		$.each( DataTable.settings, function (i, o) {
9383			var head = o.nScrollHead ? $('table', o.nScrollHead)[0] : null;
9384			var foot = o.nScrollFoot ? $('table', o.nScrollFoot)[0] : null;
9385	
9386			if ( o.nTable === t || head === t || foot === t ) {
9387				is = true;
9388			}
9389		} );
9390	
9391		return is;
9392	};
9393	
9394	
9395	/**
9396	 * Get all DataTable tables that have been initialised - optionally you can
9397	 * select to get only currently visible tables.
9398	 *
9399	 *  @param {boolean} [visible=false] Flag to indicate if you want all (default)
9400	 *    or visible tables only.
9401	 *  @returns {array} Array of `table` nodes (not DataTable instances) which are
9402	 *    DataTables
9403	 *  @static
9404	 *  @dtopt API-Static
9405	 *
9406	 *  @example
9407	 *    $.each( $.fn.dataTable.tables(true), function () {
9408	 *      $(table).DataTable().columns.adjust();
9409	 *    } );
9410	 */
9411	DataTable.tables = DataTable.fnTables = function ( visible )
9412	{
9413		var api = false;
9414	
9415		if ( $.isPlainObject( visible ) ) {
9416			api = visible.api;
9417			visible = visible.visible;
9418		}
9419	
9420		var a = $.map( DataTable.settings, function (o) {
9421			if ( !visible || (visible && $(o.nTable).is(':visible')) ) {
9422				return o.nTable;
9423			}
9424		} );
9425	
9426		return api ?
9427			new _Api( a ) :
9428			a;
9429	};
9430	
9431	
9432	/**
9433	 * Convert from camel case parameters to Hungarian notation. This is made public
9434	 * for the extensions to provide the same ability as DataTables core to accept
9435	 * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase
9436	 * parameters.
9437	 *
9438	 *  @param {object} src The model object which holds all parameters that can be
9439	 *    mapped.
9440	 *  @param {object} user The object to convert from camel case to Hungarian.
9441	 *  @param {boolean} force When set to `true`, properties which already have a
9442	 *    Hungarian value in the `user` object will be overwritten. Otherwise they
9443	 *    won't be.
9444	 */
9445	DataTable.camelToHungarian = _fnCamelToHungarian;
9446	
9447	
9448	
9449	/**
9450	 *
9451	 */
9452	_api_register( '$()', function ( selector, opts ) {
9453		var
9454			rows   = this.rows( opts ).nodes(), // Get all rows
9455			jqRows = $(rows);
9456	
9457		return $( [].concat(
9458			jqRows.filter( selector ).toArray(),
9459			jqRows.find( selector ).toArray()
9460		) );
9461	} );
9462	
9463	
9464	// jQuery functions to operate on the tables
9465	$.each( [ 'on', 'one', 'off' ], function (i, key) {
9466		_api_register( key+'()', function ( /* event, handler */ ) {
9467			var args = Array.prototype.slice.call(arguments);
9468	
9469			// Add the `dt` namespace automatically if it isn't already present
9470			args[0] = $.map( args[0].split( /\s/ ), function ( e ) {
9471				return ! e.match(/\.dt\b/) ?
9472					e+'.dt' :
9473					e;
9474				} ).join( ' ' );
9475	
9476			var inst = $( this.tables().nodes() );
9477			inst[key].apply( inst, args );
9478			return this;
9479		} );
9480	} );
9481	
9482	
9483	_api_register( 'clear()', function () {
9484		return this.iterator( 'table', function ( settings ) {
9485			_fnClearTable( settings );
9486		} );
9487	} );
9488	
9489	
9490	_api_register( 'settings()', function () {
9491		return new _Api( this.context, this.context );
9492	} );
9493	
9494	
9495	_api_register( 'init()', function () {
9496		var ctx = this.context;
9497		return ctx.length ? ctx[0].oInit : null;
9498	} );
9499	
9500	
9501	_api_register( 'data()', function () {
9502		return this.iterator( 'table', function ( settings ) {
9503			return _pluck( settings.aoData, '_aData' );
9504		} ).flatten();
9505	} );
9506	
9507	
9508	_api_register( 'destroy()', function ( remove ) {
9509		remove = remove || false;
9510	
9511		return this.iterator( 'table', function ( settings ) {
9512			var classes   = settings.oClasses;
9513			var table     = settings.nTable;
9514			var tbody     = settings.nTBody;
9515			var thead     = settings.nTHead;
9516			var tfoot     = settings.nTFoot;
9517			var jqTable   = $(table);
9518			var jqTbody   = $(tbody);
9519			var jqWrapper = $(settings.nTableWrapper);
9520			var rows      = $.map( settings.aoData, function (r) { return r.nTr; } );
9521			var i, ien;
9522	
9523			// Flag to note that the table is currently being destroyed - no action
9524			// should be taken
9525			settings.bDestroying = true;
9526	
9527			// Fire off the destroy callbacks for plug-ins etc
9528			_fnCallbackFire( settings, "aoDestroyCallback", "destroy", [settings] );
9529	
9530			// If not being removed from the document, make all columns visible
9531			if ( ! remove ) {
9532				new _Api( settings ).columns().visible( true );
9533			}
9534	
9535			// Blitz all `DT` namespaced events (these are internal events, the
9536			// lowercase, `dt` events are user subscribed and they are responsible
9537			// for removing them
9538			jqWrapper.off('.DT').find(':not(tbody *)').off('.DT');
9539			$(window).off('.DT-'+settings.sInstance);
9540	
9541			// When scrolling we had to break the table up - restore it
9542			if ( table != thead.parentNode ) {
9543				jqTable.children('thead').detach();
9544				jqTable.append( thead );
9545			}
9546	
9547			if ( tfoot && table != tfoot.parentNode ) {
9548				jqTable.children('tfoot').detach();
9549				jqTable.append( tfoot );
9550			}
9551	
9552			settings.aaSorting = [];
9553			settings.aaSortingFixed = [];
9554			_fnSortingClasses( settings );
9555	
9556			$( rows ).removeClass( settings.asStripeClasses.join(' ') );
9557	
9558			$('th, td', thead).removeClass( classes.sSortable+' '+
9559				classes.sSortableAsc+' '+classes.sSortableDesc+' '+classes.sSortableNone
9560			);
9561	
9562			// Add the TR elements back into the table in their original order
9563			jqTbody.children().detach();
9564			jqTbody.append( rows );
9565	
9566			var orig = settings.nTableWrapper.parentNode;
9567	
9568			// Remove the DataTables generated nodes, events and classes
9569			var removedMethod = remove ? 'remove' : 'detach';
9570			jqTable[ removedMethod ]();
9571			jqWrapper[ removedMethod ]();
9572	
9573			// If we need to reattach the table to the document
9574			if ( ! remove && orig ) {
9575				// insertBefore acts like appendChild if !arg[1]
9576				orig.insertBefore( table, settings.nTableReinsertBefore );
9577	
9578				// Restore the width of the original table - was read from the style property,
9579				// so we can restore directly to that
9580				jqTable
9581					.css( 'width', settings.sDestroyWidth )
9582					.removeClass( classes.sTable );
9583	
9584				// If the were originally stripe classes - then we add them back here.
9585				// Note this is not fool proof (for example if not all rows had stripe
9586				// classes - but it's a good effort without getting carried away
9587				ien = settings.asDestroyStripes.length;
9588	
9589				if ( ien ) {
9590					jqTbody.children().each( function (i) {
9591						$(this).addClass( settings.asDestroyStripes[i % ien] );
9592					} );
9593				}
9594			}
9595	
9596			/* Remove the settings object from the settings array */
9597			var idx = $.inArray( settings, DataTable.settings );
9598			if ( idx !== -1 ) {
9599				DataTable.settings.splice( idx, 1 );
9600			}
9601		} );
9602	} );
9603	
9604	
9605	// Add the `every()` method for rows, columns and cells in a compact form
9606	$.each( [ 'column', 'row', 'cell' ], function ( i, type ) {
9607		_api_register( type+'s().every()', function ( fn ) {
9608			var opts = this.selector.opts;
9609			var api = this;
9610	
9611			return this.iterator( type, function ( settings, arg1, arg2, arg3, arg4 ) {
9612				// Rows and columns:
9613				//  arg1 - index
9614				//  arg2 - table counter
9615				//  arg3 - loop counter
9616				//  arg4 - undefined
9617				// Cells:
9618				//  arg1 - row index
9619				//  arg2 - column index
9620				//  arg3 - table counter
9621				//  arg4 - loop counter
9622				fn.call(
9623					api[ type ](
9624						arg1,
9625						type==='cell' ? arg2 : opts,
9626						type==='cell' ? opts : undefined
9627					),
9628					arg1, arg2, arg3, arg4
9629				);
9630			} );
9631		} );
9632	} );
9633	
9634	
9635	// i18n method for extensions to be able to use the language object from the
9636	// DataTable
9637	_api_register( 'i18n()', function ( token, def, plural ) {
9638		var ctx = this.context[0];
9639		var resolved = _fnGetObjectDataFn( token )( ctx.oLanguage );
9640	
9641		if ( resolved === undefined ) {
9642			resolved = def;
9643		}
9644	
9645		if ( plural !== undefined && $.isPlainObject( resolved ) ) {
9646			resolved = resolved[ plural ] !== undefined ?
9647				resolved[ plural ] :
9648				resolved._;
9649		}
9650	
9651		return resolved.replace( '%d', plural ); // nb: plural might be undefined,
9652	} );	
9653	/**
9654	 * Version string for plug-ins to check compatibility. Allowed format is
9655	 * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used
9656	 * only for non-release builds. See http://semver.org/ for more information.
9657	 *  @member
9658	 *  @type string
9659	 *  @default Version number
9660	 */
9661	DataTable.version = "1.12.1";
9662	
9663	/**
9664	 * Private data store, containing all of the settings objects that are
9665	 * created for the tables on a given page.
9666	 *
9667	 * Note that the `DataTable.settings` object is aliased to
9668	 * `jQuery.fn.dataTableExt` through which it may be accessed and
9669	 * manipulated, or `jQuery.fn.dataTable.settings`.
9670	 *  @member
9671	 *  @type array
9672	 *  @default []
9673	 *  @private
9674	 */
9675	DataTable.settings = [];
9676	
9677	/**
9678	 * Object models container, for the various models that DataTables has
9679	 * available to it. These models define the objects that are used to hold
9680	 * the active state and configuration of the table.
9681	 *  @namespace
9682	 */
9683	DataTable.models = {};
9684	
9685	
9686	
9687	/**
9688	 * Template object for the way in which DataTables holds information about
9689	 * search information for the global filter and individual column filters.
9690	 *  @namespace
9691	 */
9692	DataTable.models.oSearch = {
9693		/**
9694		 * Flag to indicate if the filtering should be case insensitive or not
9695		 *  @type boolean
9696		 *  @default true
9697		 */
9698		"bCaseInsensitive": true,
9699	
9700		/**
9701		 * Applied search term
9702		 *  @type string
9703		 *  @default <i>Empty string</i>
9704		 */
9705		"sSearch": "",
9706	
9707		/**
9708		 * Flag to indicate if the search term should be interpreted as a
9709		 * regular expression (true) or not (false) and therefore and special
9710		 * regex characters escaped.
9711		 *  @type boolean
9712		 *  @default false
9713		 */
9714		"bRegex": false,
9715	
9716		/**
9717		 * Flag to indicate if DataTables is to use its smart filtering or not.
9718		 *  @type boolean
9719		 *  @default true
9720		 */
9721		"bSmart": true,
9722	
9723		/**
9724		 * Flag to indicate if DataTables should only trigger a search when
9725		 * the return key is pressed.
9726		 *  @type boolean
9727		 *  @default false
9728		 */
9729		"return": false
9730	};
9731	
9732	
9733	
9734	
9735	/**
9736	 * Template object for the way in which DataTables holds information about
9737	 * each individual row. This is the object format used for the settings
9738	 * aoData array.
9739	 *  @namespace
9740	 */
9741	DataTable.models.oRow = {
9742		/**
9743		 * TR element for the row
9744		 *  @type node
9745		 *  @default null
9746		 */
9747		"nTr": null,
9748	
9749		/**
9750		 * Array of TD elements for each row. This is null until the row has been
9751		 * created.
9752		 *  @type array nodes
9753		 *  @default []
9754		 */
9755		"anCells": null,
9756	
9757		/**
9758		 * Data object from the original data source for the row. This is either
9759		 * an array if using the traditional form of DataTables, or an object if
9760		 * using mData options. The exact type will depend on the passed in
9761		 * data from the data source, or will be an array if using DOM a data
9762		 * source.
9763		 *  @type array|object
9764		 *  @default []
9765		 */
9766		"_aData": [],
9767	
9768		/**
9769		 * Sorting data cache - this array is ostensibly the same length as the
9770		 * number of columns (although each index is generated only as it is
9771		 * needed), and holds the data that is used for sorting each column in the
9772		 * row. We do this cache generation at the start of the sort in order that
9773		 * the formatting of the sort data need be done only once for each cell
9774		 * per sort. This array should not be read from or written to by anything
9775		 * other than the master sorting methods.
9776		 *  @type array
9777		 *  @default null
9778		 *  @private
9779		 */
9780		"_aSortData": null,
9781	
9782		/**
9783		 * Per cell filtering data cache. As per the sort data cache, used to
9784		 * increase the performance of the filtering in DataTables
9785		 *  @type array
9786		 *  @default null
9787		 *  @private
9788		 */
9789		"_aFilterData": null,
9790	
9791		/**
9792		 * Filtering data cache. This is the same as the cell filtering cache, but
9793		 * in this case a string rather than an array. This is easily computed with
9794		 * a join on `_aFilterData`, but is provided as a cache so the join isn't
9795		 * needed on every search (memory traded for performance)
9796		 *  @type array
9797		 *  @default null
9798		 *  @private
9799		 */
9800		"_sFilterRow": null,
9801	
9802		/**
9803		 * Cache of the class name that DataTables has applied to the row, so we
9804		 * can quickly look at this variable rather than needing to do a DOM check
9805		 * on className for the nTr property.
9806		 *  @type string
9807		 *  @default <i>Empty string</i>
9808		 *  @private
9809		 */
9810		"_sRowStripe": "",
9811	
9812		/**
9813		 * Denote if the original data source was from the DOM, or the data source
9814		 * object. This is used for invalidating data, so DataTables can
9815		 * automatically read data from the original source, unless uninstructed
9816		 * otherwise.
9817		 *  @type string
9818		 *  @default null
9819		 *  @private
9820		 */
9821		"src": null,
9822	
9823		/**
9824		 * Index in the aoData array. This saves an indexOf lookup when we have the
9825		 * object, but want to know the index
9826		 *  @type integer
9827		 *  @default -1
9828		 *  @private
9829		 */
9830		"idx": -1
9831	};
9832	
9833	
9834	/**
9835	 * Template object for the column information object in DataTables. This object
9836	 * is held in the settings aoColumns array and contains all the information that
9837	 * DataTables needs about each individual column.
9838	 *
9839	 * Note that this object is related to {@link DataTable.defaults.column}
9840	 * but this one is the internal data store for DataTables's cache of columns.
9841	 * It should NOT be manipulated outside of DataTables. Any configuration should
9842	 * be done through the initialisation options.
9843	 *  @namespace
9844	 */
9845	DataTable.models.oColumn = {
9846		/**
9847		 * Column index. This could be worked out on-the-fly with $.inArray, but it
9848		 * is faster to just hold it as a variable
9849		 *  @type integer
9850		 *  @default null
9851		 */
9852		"idx": null,
9853	
9854		/**
9855		 * A list of the columns that sorting should occur on when this column
9856		 * is sorted. That this property is an array allows multi-column s
9856orting
9857		 * to be defined for a column (for example first name / last name columns
9858		 * would benefit from this). The values are integers pointing to the
9859		 * columns to be sorted on (typically it will be a single integer pointing
9860		 * at itself, but that doesn't need to be the case).
9861		 *  @type array
9862		 */
9863		"aDataSort": null,
9864	
9865		/**
9866		 * Define the sorting directions that are applied to the column, in sequence
9867		 * as the column is repeatedly sorted upon - i.e. the first value is used
9868		 * as the sorting direction when the column if first sorted (clicked on).
9869		 * Sort it again (click again) and it will move on to the next index.
9870		 * Repeat until loop.
9871		 *  @type array
9872		 */
9873		"asSorting": null,
9874	
9875		/**
9876		 * Flag to indicate if the column is searchable, and thus should be included
9877		 * in the filtering or not.
9878		 *  @type boolean
9879		 */
9880		"bSearchable": null,
9881	
9882		/**
9883		 * Flag to indicate if the column is sortable or not.
9884		 *  @type boolean
9885		 */
9886		"bSortable": null,
9887	
9888		/**
9889		 * Flag to indicate if the column is currently visible in the table or not
9890		 *  @type boolean
9891		 */
9892		"bVisible": null,
9893	
9894		/**
9895		 * Store for manual type assignment using the `column.type` option. This
9896		 * is held in store so we can manipulate the column's `sType` property.
9897		 *  @type string
9898		 *  @default null
9899		 *  @private
9900		 */
9901		"_sManualType": null,
9902	
9903		/**
9904		 * Flag to indicate if HTML5 data attributes should be used as the data
9905		 * source for filtering or sorting. True is either are.
9906		 *  @type boolean
9907		 *  @default false
9908		 *  @private
9909		 */
9910		"_bAttrSrc": false,
9911	
9912		/**
9913		 * Developer definable function that is called whenever a cell is created (Ajax source,
9914		 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
9915		 * allowing you to modify the DOM element (add background colour for example) when the
9916		 * element is available.
9917		 *  @type function
9918		 *  @param {element} nTd The TD node that has been created
9919		 *  @param {*} sData The Data for the cell
9920		 *  @param {array|object} oData The data for the whole row
9921		 *  @param {int} iRow The row index for the aoData data store
9922		 *  @default null
9923		 */
9924		"fnCreatedCell": null,
9925	
9926		/**
9927		 * Function to get data from a cell in a column. You should <b>never</b>
9928		 * access data directly through _aData internally in DataTables - always use
9929		 * the method attached to this property. It allows mData to function as
9930		 * required. This function is automatically assigned by the column
9931		 * initialisation method
9932		 *  @type function
9933		 *  @param {array|object} oData The data array/object for the array
9934		 *    (i.e. aoData[]._aData)
9935		 *  @param {string} sSpecific The specific data type you want to get -
9936		 *    'display', 'type' 'filter' 'sort'
9937		 *  @returns {*} The data for the cell from the given row's data
9938		 *  @default null
9939		 */
9940		"fnGetData": null,
9941	
9942		/**
9943		 * Function to set data for a cell in the column. You should <b>never</b>
9944		 * set the data directly to _aData internally in DataTables - always use
9945		 * this method. It allows mData to function as required. This function
9946		 * is automatically assigned by the column initialisation method
9947		 *  @type function
9948		 *  @param {array|object} oData The data array/object for the array
9949		 *    (i.e. aoData[]._aData)
9950		 *  @param {*} sValue Value to set
9951		 *  @default null
9952		 */
9953		"fnSetData": null,
9954	
9955		/**
9956		 * Property to read the value for the cells in the column from the data
9957		 * source array / object. If null, then the default content is used, if a
9958		 * function is given then the return from the function is used.
9959		 *  @type function|int|string|null
9960		 *  @default null
9961		 */
9962		"mData": null,
9963	
9964		/**
9965		 * Partner property to mData which is used (only when defined) to get
9966		 * the data - i.e. it is basically the same as mData, but without the
9967		 * 'set' option, and also the data fed to it is the result from mData.
9968		 * This is the rendering method to match the data method of mData.
9969		 *  @type function|int|string|null
9970		 *  @default null
9971		 */
9972		"mRender": null,
9973	
9974		/**
9975		 * Unique header TH/TD element for this column - this is what the sorting
9976		 * listener is attached to (if sorting is enabled.)
9977		 *  @type node
9978		 *  @default null
9979		 */
9980		"nTh": null,
9981	
9982		/**
9983		 * Unique footer TH/TD element for this column (if there is one). Not used
9984		 * in DataTables as such, but can be used for plug-ins to reference the
9985		 * footer for each column.
9986		 *  @type node
9987		 *  @default null
9988		 */
9989		"nTf": null,
9990	
9991		/**
9992		 * The class to apply to all TD elements in the table's TBODY for the column
9993		 *  @type string
9994		 *  @default null
9995		 */
9996		"sClass": null,
9997	
9998		/**
9999		 * When DataTables calculates the column widths to assign to each column,
10000		 * it finds the longest string in each column and then constructs a
10001		 * temporary table and reads the widths from that. The problem with this
10002		 * is that "mmm" is much wider then "iiii", but the latter is a longer
10003		 * string - thus the calculation can go wrong (doing it properly and putting
10004		 * it into an DOM object and measuring that is horribly(!) slow). Thus as
10005		 * a "work around" we provide this option. It will append its value to the
10006		 * text that is found to be the longest string for the column - i.e. padding.
10007		 *  @type string
10008		 */
10009		"sContentPadding": null,
10010	
10011		/**
10012		 * Allows a default value to be given for a column's data, and will be used
10013		 * whenever a null data source is encountered (this can be because mData
10014		 * is set to null, or because the data source itself is null).
10015		 *  @type string
10016		 *  @default null
10017		 */
10018		"sDefaultContent": null,
10019	
10020		/**
10021		 * Name for the column, allowing reference to the column by name as well as
10022		 * by index (needs a lookup to work by name).
10023		 *  @type string
10024		 */
10025		"sName": null,
10026	
10027		/**
10028		 * Custom sorting data type - defines which of the available plug-ins in
10029		 * afnSortData the custom sorting will use - if any is defined.
10030		 *  @type string
10031		 *  @default std
10032		 */
10033		"sSortDataType": 'std',
10034	
10035		/**
10036		 * Class to be applied to the header element when sorting on this column
10037		 *  @type string
10038		 *  @default null
10039		 */
10040		"sSortingClass": null,
10041	
10042		/**
10043		 * Class to be applied to the header element when sorting on this column -
10044		 * when jQuery UI theming is used.
10045		 *  @type string
10046		 *  @default null
10047		 */
10048		"sSortingClassJUI": null,
10049	
10050		/**
10051		 * Title of the column - what is seen in the TH element (nTh).
10052		 *  @type string
10053		 */
10054		"sTitle": null,
10055	
10056		/**
10057		 * Column sorting and filtering type
10058		 *  @type string
10059		 *  @default null
10060		 */
10061		"sType": null,
10062	
10063		/**
10064		 * Width of the column
10065		 *  @type string
10066		 *  @default null
10067		 */
10068		"sWidth": null,
10069	
10070		/**
10071		 * Width of the column when it was first "encountered"
10072		 *  @type string
10073		 *  @default null
10074		 */
10075		"sWidthOrig": null
10076	};
10077	
10078	
10079	/*
10080	 * Developer note: The properties of the object below are given in Hungarian
10081	 * notation, that was used as the interface for DataTables prior to v1.10, however
10082	 * from v1.10 onwards the primary interface is camel case. In order to avoid
10083	 * breaking backwards compatibility utterly with this change, the Hungarian
10084	 * version is still, internally the primary interface, but is is not documented
10085	 * - hence the @name tags in each doc comment. This allows a Javascript function
10086	 * to create a map from Hungarian notation to camel case (going the other direction
10087	 * would require each property to be listed, which would add around 3K to the size
10088	 * of DataTables, while this method is about a 0.5K hit).
10089	 *
10090	 * Ultimately this does pave the way for Hungarian notation to be dropped
10091	 * completely, but that is a massive amount of work and will break current
10092	 * installs (therefore is on-hold until v2).
10093	 */
10094	
10095	/**
10096	 * Initialisation options that can be given to DataTables at initialisation
10097	 * time.
10098	 *  @namespace
10099	 */
10100	DataTable.defaults = {
10101		/**
10102		 * An array of data to use for the table, passed in at initialisation which
10103		 * will be used in preference to any data which is already in the DOM. This is
10104		 * particularly useful for constructing tables purely in Javascript, for
10105		 * example with a custom Ajax call.
10106		 *  @type array
10107		 *  @default null
10108		 *
10109		 *  @dtopt Option
10110		 *  @name DataTable.defaults.data
10111		 *
10112		 *  @example
10113		 *    // Using a 2D array data source
10114		 *    $(document).ready( function () {
10115		 *      $('#example').dataTable( {
10116		 *        "data": [
10117		 *          ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
10118		 *          ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
10119		 *        ],
10120		 *        "columns": [
10121		 *          { "title": "Engine" },
10122		 *          { "title": "Browser" },
10123		 *          { "title": "Platform" },
10124		 *          { "title": "Version" },
10125		 *          { "title": "Grade" }
10126		 *        ]
10127		 *      } );
10128		 *    } );
10129		 *
10130		 *  @example
10131		 *    // Using an array of objects as a data source (`data`)
10132		 *    $(document).ready( function () {
10133		 *      $('#example').dataTable( {
10134		 *        "data": [
10135		 *          {
10136		 *            "engine":   "Trident",
10137		 *            "browser":  "Internet Explorer 4.0",
10138		 *            "platform": "Win 95+",
10139		 *            "version":  4,
10140		 *            "grade":    "X"
10141		 *          },
10142		 *          {
10143		 *            "engine":   "Trident",
10144		 *            "browser":  "Internet Explorer 5.0",
10145		 *            "platform": "Win 95+",
10146		 *            "version":  5,
10147		 *            "grade":    "C"
10148		 *          }
10149		 *        ],
10150		 *        "columns": [
10151		 *          { "title": "Engine",   "data": "engine" },
10152		 *          { "title": "Browser",  "data": "browser" },
10153		 *          { "title": "Platform", "data": "platform" },
10154		 *          { "title": "Version",  "data": "version" },
10155		 *          { "title": "Grade",    "data": "grade" }
10156		 *        ]
10157		 *      } );
10158		 *    } );
10159		 */
10160		"aaData": null,
10161	
10162	
10163		/**
10164		 * If ordering is enabled, then DataTables will perform a first pass sort on
10165		 * initialisation. You can define which column(s) the sort is performed
10166		 * upon, and the sorting direction, with this variable. The `sorting` array
10167		 * should contain an array for each column to be sorted initially containing
10168		 * the column's index and a direction string ('asc' or 'desc').
10169		 *  @type array
10170		 *  @default [[0,'asc']]
10171		 *
10172		 *  @dtopt Option
10173		 *  @name DataTable.defaults.order
10174		 *
10175		 *  @example
10176		 *    // Sort by 3rd column first, and then 4th column
10177		 *    $(document).ready( function() {
10178		 *      $('#example').dataTable( {
10179		 *        "order": [[2,'asc'], [3,'desc']]
10180		 *      } );
10181		 *    } );
10182		 *
10183		 *    // No initial sorting
10184		 *    $(document).ready( function() {
10185		 *      $('#example').dataTable( {
10186		 *        "order": []
10187		 *      } );
10188		 *    } );
10189		 */
10190		"aaSorting": [[0,'asc']],
10191	
10192	
10193		/**
10194		 * This parameter is basically identical to the `sorting` parameter, but
10195		 * cannot be overridden by user interaction with the table. What this means
10196		 * is that you could have a column (visible or hidden) which the sorting
10197		 * will always be forced on first - any sorting after that (from the user)
10198		 * will then be performed as required. This can be useful for grouping rows
10199		 * together.
10200		 *  @type array
10201		 *  @default null
10202		 *
10203		 *  @dtopt Option
10204		 *  @name DataTable.defaults.orderFixed
10205		 *
10206		 *  @example
10207		 *    $(document).ready( function() {
10208		 *      $('#example').dataTable( {
10209		 *        "orderFixed": [[0,'asc']]
10210		 *      } );
10211		 *    } )
10212		 */
10213		"aaSortingFixed": [],
10214	
10215	
10216		/**
10217		 * DataTables can be instructed to load data to display in the table from a
10218		 * Ajax source. This option defines how that Ajax call is made and where to.
10219		 *
10220		 * The `ajax` property has three different modes of operation, depending on
10221		 * how it is defined. These are:
10222		 *
10223		 * * `string` - Set the URL from where the data should be loaded from.
10224		 * * `object` - Define properties for `jQuery.ajax`.
10225		 * * `function` - Custom data get function
10226		 *
10227		 * `string`
10228		 * --------
10229		 *
10230		 * As a string, the `ajax` property simply defines the URL from which
10231		 * DataTables will load data.
10232		 *
10233		 * `object`
10234		 * --------
10235		 *
10236		 * As an object, the parameters in the object are passed to
10237		 * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control
10238		 * of the Ajax request. DataTables has a number of default parameters which
10239		 * you can override using this option. Please refer to the jQuery
10240		 * documentation for a full description of the options available, although
10241		 * the following parameters provide additional options in DataTables or
10242		 * require special consideration:
10243		 *
10244		 * * `data` - As with jQuery, `data` can be provided as an object, but it
10245		 *   can also be used as a function to manipulate the data DataTables sends
10246		 *   to the server. The function takes a single parameter, an object of
10247		 *   parameters with the values that DataTables has readied for sending. An
10248		 *   object may be returned which will be merged into the DataTables
10249		 *   defaults, or you can add the items to the object that was passed in and
10250		 *   not return anything from the function. This supersedes `fnServerParams`
10251		 *   from DataTables 1.9-.
10252		 *
10253		 * * `dataSrc` - By default DataTables will look for the property `data` (or
10254		 *   `aaData` for compatibility with DataTables 1.9-) when obtaining data
10255		 *   from an Ajax source or for server-side processing - this parameter
10256		 *   allows that property to be changed. You can use Javascript dotted
10257		 *   object notation to get a data source for multiple levels of nesting, or
10258		 *   it my be used as a function. As a function it takes a single parameter,
10259		 *   the JSON returned from the server, which can be manipulated as
10260		 *   required, with the returned value being that used by DataTables as the
10261		 *   data source for the table. This supersedes `sAjaxDataProp` from
10262		 *   DataTables 1.9-.
10263		 *
10264		 * * `success` - Should not be overridden it is used internally in
10265		 *   DataTables. To manipulate / transform the data returned by the server
10266		 *   use `ajax.dataSrc`, or use `ajax` as a function (see below).
10267		 *
10268		 * `function`
10269		 * ----------
10270		 *
10271		 * As a function, making the Ajax call is left up to yourself allowing
10272		 * complete control of the Ajax request. Indeed, if desired, a method other
10273		 * than Ajax could be used to obtain the required data, such as Web storage
10274		 * or an AIR database.
10275		 *
10276		 * The function is given four parameters and no return is required. The
10277		 * parameters are:
10278		 *
10279		 * 1. _object_ - Data to send to the server
10280		 * 2. _function_ - Callback function that must be executed when the required
10281		 *    data has been obtained. That data should be passed into the callback
10282		 *    as the only parameter
10283		 * 3. _object_ - DataTables settings object for the table
10284		 *
10285		 * Note that this supersedes `fnServerData` from DataTables 1.9-.
10286		 *
10287		 *  @type string|object|function
10288		 *  @default null
10289		 *
10290		 *  @dtopt Option
10291		 *  @name DataTable.defaults.ajax
10292		 *  @since 1.10.0
10293		 *
10294		 * @example
10295		 *   // Get JSON data from a file via Ajax.
10296		 *   // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default).
10297		 *   $('#example').dataTable( {
10298		 *     "ajax": "data.json"
10299		 *   } );
10300		 *
10301		 * @example
10302		 *   // Get JSON data from a file via Ajax, using `dataSrc` to change
10303		 *   // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`)
10304		 *   $('#example').dataTable( {
10305		 *     "ajax": {
10306		 *       "url": "data.json",
10307		 *       "dataSrc": "tableData"
10308		 *     }
10309		 *   } );
10310		 *
10311		 * @example
10312		 *   // Get JSON data from a file via Ajax, using `dataSrc` to read data
10313		 *   // from a plain array rather than an array in an object
10314		 *   $('#example').dataTable( {
10315		 *     "ajax": {
10316		 *       "url": "data.json",
10317		 *       "dataSrc": ""
10318		 *     }
10319		 *   } );
10320		 *
10321		 * @example
10322		 *   // Manipulate the data returned from the server - add a link to data
10323		 *   // (note this can, should, be done using `render` for the column - this
10324		 *   // is just a simple example of how the data can be manipulated).
10325		 *   $('#example').dataTable( {
10326		 *     "ajax": {
10327		 *       "url": "data.json",
10328		 *       "dataSrc": function ( json ) {
10329		 *         for ( var i=0, ien=json.length ; i<ien ; i++ ) {
10330		 *           json[i][0] = '<a href="/message/'+json[i][0]+'>View message</a>';
10331		 *         }
10332		 *         return json;
10333		 *       }
10334		 *     }
10335		 *   } );
10336		 *
10337		 * @example
10338		 *   // Add data to the request
10339		 *   $('#example').dataTable( {
10340		 *     "ajax": {
10341		 *       "url": "data.json",
10342		 *       "data": function ( d ) {
10343		 *         return {
10344		 *           "extra_search": $('#extra').val()
10345		 *         };
10346		 *       }
10347		 *     }
10348		 *   } );
10349		 *
10350		 * @example
10351		 *   // Send request as POST
10352		 *   $('#example').dataTable( {
10353		 *     "ajax": {
10354		 *       "url": "data.json",
10355		 *       "type": "POST"
10356		 *     }
10357		 *   } );
10358		 *
10359		 * @example
10360		 *   // Get the data from localStorage (could interface with a form for
10361		 *   // adding, editing and removing rows).
10362		 *   $('#example').dataTable( {
10363		 *     "ajax": function (data, callback, settings) {
10364		 *       callback(
10365		 *         JSON.parse( localStorage.getItem('dataTablesData') )
10366		 *       );
10367		 *     }
10368		 *   } );
10369		 */
10370		"ajax": null,
10371	
10372	
10373		/**
10374		 * This parameter allows you to readily specify the entries in the length drop
10375		 * down menu that DataTables shows when pagination is enabled. It can be
10376		 * either a 1D array of options which will be used for both the displayed
10377		 * option and the value, or a 2D array which will use the array in the first
10378		 * position as the value, and the array in the second position as the
10379		 * displayed options (useful for language strings such as 'All').
10380		 *
10381		 * Note that the `pageLength` property will be automatically set to the
10382		 * first value given in this array, unless `pageLength` is also provided.
10383		 *  @type array
10384		 *  @default [ 10, 25, 50, 100 ]
10385		 *
10386		 *  @dtopt Option
10387		 *  @name DataTable.defaults.lengthMenu
10388		 *
10389		 *  @example
10390		 *    $(document).ready( function() {
10391		 *      $('#example').dataTable( {
10392		 *        "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
10393		 *      } );
10394		 *    } );
10395		 */
10396		"aLengthMenu": [ 10, 25, 50, 100 ],
10397	
10398	
10399		/**
10400		 * The `columns` option in the initialisation parameter allows you to define
10401		 * details about the way individual columns behave. For a full list of
10402		 * column options that can be set, please see
10403		 * {@link DataTable.defaults.column}. Note that if you use `columns` to
10404		 * define your columns, you must have an entry in the array for every single
10405		 * column that you have in your table (these can be null if you don't which
10406		 * to specify any options).
10407		 *  @member
10408		 *
10409		 *  @name DataTable.defaults.column
10410		 */
10411		"aoColumns": null,
10412	
10413		/**
10414		 * Very similar to `columns`, `columnDefs` allows you to target a specific
10415		 * column, multiple columns, or all columns, using the `targets` property of
10416		 * each object in the array. This allows great flexibility when creating
10417		 * tables, as the `columnDefs` arrays can be of any length, targeting the
10418		 * columns you specifically want. `columnDefs` may use any of the column
10419		 * options available: {@link DataTable.defaults.column}, but it _must_
10420		 * have `targets` defined in each object in the array. Values in the `targets`
10421		 * array may be:
10422		 *   <ul>
10423		 *     <li>
10423a string - class name will be matched on the TH for the column</li>
10424		 *     <li>0 or a positive integer - column index counting from the left</li>
10425		 *     <li>a negative integer - column index counting from the right</li>
10426		 *     <li>the string "_all" - all columns (i.e. assign a default)</li>
10427		 *   </ul>
10428		 *  @member
10429		 *
10430		 *  @name DataTable.defaults.columnDefs
10431		 */
10432		"aoColumnDefs": null,
10433	
10434	
10435		/**
10436		 * Basically the same as `search`, this parameter defines the individual column
10437		 * filtering state at initialisation time. The array must be of the same size
10438		 * as the number of columns, and each element be an object with the parameters
10439		 * `search` and `escapeRegex` (the latter is optional). 'null' is also
10440		 * accepted and the default will be used.
10441		 *  @type array
10442		 *  @default []
10443		 *
10444		 *  @dtopt Option
10445		 *  @name DataTable.defaults.searchCols
10446		 *
10447		 *  @example
10448		 *    $(document).ready( function() {
10449		 *      $('#example').dataTable( {
10450		 *        "searchCols": [
10451		 *          null,
10452		 *          { "search": "My filter" },
10453		 *          null,
10454		 *          { "search": "^[0-9]", "escapeRegex": false }
10455		 *        ]
10456		 *      } );
10457		 *    } )
10458		 */
10459		"aoSearchCols": [],
10460	
10461	
10462		/**
10463		 * An array of CSS classes that should be applied to displayed rows. This
10464		 * array may be of any length, and DataTables will apply each class
10465		 * sequentially, looping when required.
10466		 *  @type array
10467		 *  @default null <i>
10467Will take the values determined by the `oClasses.stripe*`
10468		 *    options</i>
10469		 *
10470		 *  @dtopt Option
10471		 *  @name DataTable.defaults.stripeClasses
10472		 *
10473		 *  @example
10474		 *    $(document).ready( function() {
10475		 *      $('#example').dataTable( {
10476		 *        "stripeClasses": [ 'strip1', 'strip2', 'strip3' ]
10477		 *      } );
10478		 *    } )
10479		 */
10480		"asStripeClasses": null,
10481	
10482	
10483		/**
10484		 * Enable or disable automatic column width calculation. This can be disabled
10485		 * as an optimisation (it takes some time to calculate the widths) if the
10486		 * tables widths are passed in using `columns`.
10487		 *  @type boolean
10488		 *  @default true
10489		 *
10490		 *  @dtopt Features
10491		 *  @name DataTable.defaults.autoWidth
10492		 *
10493		 *  @example
10494		 *    $(document).ready( function () {
10495		 *      $('#example').dataTable( {
10496		 *        "autoWidth": false
10497		 *      } );
10498		 *    } );
10499		 */
10500		"bAutoWidth": true,
10501	
10502	
10503		/**
10504		 * Deferred rendering can provide DataTables with a huge speed boost when you
10505		 * are using an Ajax or JS data source for the table. This option, when set to
10506		 * true, will cause DataTables to defer the creation of the table elements for
10507		 * each row until they are needed for a draw - saving a significant amount of
10508		 * time.
10509		 *  @type boolean
10510		 *  @default false
10511		 *
10512		 *  @dtopt Features
10513		 *  @name DataTable.defaults.deferRender
10514		 *
10515		 *  @example
10516		 *    $(document).ready( function() {
10517		 *      $('#example').dataTable( {
10518		 *        "ajax": "sources/arrays.txt",
10519		 *        "deferRender": true
10520		 *      } );
10521		 *    } );
10522		 */
10523		"bDeferRender": false,
10524	
10525	
10526		/**
10527		 * Replace a DataTable which matches the given selector and replace it with
10528		 * one which has the properties of the new initialisation object passed. If no
10529		 * table matches the selector, then the new DataTable will be constructed as
10530		 * per normal.
10531		 *  @type boolean
10532		 *  @default false
10533		 *
10534		 *  @dtopt Options
10535		 *  @name DataTable.defaults.destroy
10536		 *
10537		 *  @example
10538		 *    $(document).ready( function() {
10539		 *      $('#example').dataTable( {
10540		 *        "srollY": "200px",
10541		 *        "paginate": false
10542		 *      } );
10543		 *
10544		 *      // Some time later....
10545		 *      $('#example').dataTable( {
10546		 *        "filter": false,
10547		 *        "destroy": true
10548		 *      } );
10549		 *    } );
10550		 */
10551		"bDestroy": false,
10552	
10553	
10554		/**
10555		 * Enable or disable filtering of data. Filtering in DataTables is "smart" in
10556		 * that it allows the end user to input multiple words (space separated) and
10557		 * will match a row containing those words, even if not in the order that was
10558		 * specified (this allow matching across multiple columns). Note that if you
10559		 * wish to use filtering in DataTables this must remain 'true' - to remove the
10560		 * default filtering input box and retain filtering abilities, please use
10561		 * {@link DataTable.defaults.dom}.
10562		 *  @type boolean
10563		 *  @default true
10564		 *
10565		 *  @dtopt Features
10566		 *  @name DataTable.defaults.searching
10567		 *
10568		 *  @example
10569		 *    $(document).ready( function () {
10570		 *      $('#example').dataTable( {
10571		 *        "searching": false
10572		 *      } );
10573		 *    } );
10574		 */
10575		"bFilter": true,
10576	
10577	
10578		/**
10579		 * Enable or disable the table information display. This shows information
10580		 * about the data that is currently visible on the page, including information
10581		 * about filtered data if that action is being performed.
10582		 *  @type boolean
10583		 *  @default true
10584		 *
10585		 *  @dtopt Features
10586		 *  @name DataTable.defaults.info
10587		 *
10588		 *  @example
10589		 *    $(document).ready( function () {
10590		 *      $('#example').dataTable( {
10591		 *        "info": false
10592		 *      } );
10593		 *    } );
10594		 */
10595		"bInfo": true,
10596	
10597	
10598		/**
10599		 * Allows the end user to select the size of a formatted page from a select
10600		 * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`).
10601		 *  @type boolean
10602		 *  @default true
10603		 *
10604		 *  @dtopt Features
10605		 *  @name DataTable.defaults.lengthChange
10606		 *
10607		 *  @example
10608		 *    $(document).ready( function () {
10609		 *      $('#example').dataTable( {
10610		 *        "lengthChange": false
10611		 *      } );
10612		 *    } );
10613		 */
10614		"bLengthChange": true,
10615	
10616	
10617		/**
10618		 * Enable or disable pagination.
10619		 *  @type boolean
10620		 *  @default true
10621		 *
10622		 *  @dtopt Features
10623		 *  @name DataTable.defaults.paging
10624		 *
10625		 *  @example
10626		 *    $(document).ready( function () {
10627		 *      $('#example').dataTable( {
10628		 *        "paging": false
10629		 *      } );
10630		 *    } );
10631		 */
10632		"bPaginate": true,
10633	
10634	
10635		/**
10636		 * Enable or disable the display of a 'processing' indicator when the table is
10637		 * being processed (e.g. a sort). This is particularly useful for tables with
10638		 * large amounts of data where it can take a noticeable amount of time to sort
10639		 * the entries.
10640		 *  @type boolean
10641		 *  @default false
10642		 *
10643		 *  @dtopt Features
10644		 *  @name DataTable.defaults.processing
10645		 *
10646		 *  @example
10647		 *    $(document).ready( function () {
10648		 *      $('#example').dataTable( {
10649		 *        "processing": true
10650		 *      } );
10651		 *    } );
10652		 */
10653		"bProcessing": false,
10654	
10655	
10656		/**
10657		 * Retrieve the DataTables object for the given selector. Note that if the
10658		 * table has already been initialised, this parameter will cause DataTables
10659		 * to simply return the object that has already been set up - it will not take
10660		 * account of any changes you might have made to the initialisation object
10661		 * passed to DataTables (setting this parameter to true is an acknowledgement
10662		 * that you understand this). `destroy` can be used to reinitialise a table if
10663		 * you need.
10664		 *  @type boolean
10665		 *  @default false
10666		 *
10667		 *  @dtopt Options
10668		 *  @name DataTable.defaults.retrieve
10669		 *
10670		 *  @example
10671		 *    $(document).ready( function() {
10672		 *      initTable();
10673		 *      tableActions();
10674		 *    } );
10675		 *
10676		 *    function initTable ()
10677		 *    {
10678		 *      return $('#example').dataTable( {
10679		 *        "scrollY": "200px",
10680		 *        "paginate": false,
10681		 *        "retrieve": true
10682		 *      } );
10683		 *    }
10684		 *
10685		 *    function tableActions ()
10686		 *    {
10687		 *      var table = initTable();
10688		 *      // perform API operations with oTable
10689		 *    }
10690		 */
10691		"bRetrieve": false,
10692	
10693	
10694		/**
10695		 * When vertical (y) scrolling is enabled, DataTables will force the height of
10696		 * the table's viewport to the given height at all times (useful for layout).
10697		 * However, this can look odd when filtering data down to a small data set,
10698		 * and the footer is left "floating" further down. This parameter (when
10699		 * enabled) will cause DataTables to collapse the table's viewport down when
10700		 * the result set will fit within the given Y height.
10701		 *  @type boolean
10702		 *  @default false
10703		 *
10704		 *  @dtopt Options
10705		 *  @name DataTable.defaults.scrollCollapse
10706		 *
10707		 *  @example
10708		 *    $(document).ready( function() {
10709		 *      $('#example').dataTable( {
10710		 *        "scrollY": "200",
10711		 *        "scrollCollapse": true
10712		 *      } );
10713		 *    } );
10714		 */
10715		"bScrollCollapse": false,
10716	
10717	
10718		/**
10719		 * Configure DataTables to use server-side processing. Note that the
10720		 * `ajax` parameter must also be given in order to give DataTables a
10721		 * source to obtain the required data for each draw.
10722		 *  @type boolean
10723		 *  @default false
10724		 *
10725		 *  @dtopt Features
10726		 *  @dtopt Server-side
10727		 *  @name DataTable.defaults.serverSide
10728		 *
10729		 *  @example
10730		 *    $(document).ready( function () {
10731		 *      $('#example').dataTable( {
10732		 *        "serverSide": true,
10733		 *        "ajax": "xhr.php"
10734		 *      } );
10735		 *    } );
10736		 */
10737		"bServerSide": false,
10738	
10739	
10740		/**
10741		 * Enable or disable sorting of columns. Sorting of individual columns can be
10742		 * disabled by the `sortable` option for each column.
10743		 *  @type boolean
10744		 *  @default true
10745		 *
10746		 *  @dtopt Features
10747		 *  @name DataTable.defaults.ordering
10748		 *
10749		 *  @example
10750		 *    $(document).ready( function () {
10751		 *      $('#example').dataTable( {
10752		 *        "ordering": false
10753		 *      } );
10754		 *    } );
10755		 */
10756		"bSort": true,
10757	
10758	
10759		/**
10760		 * Enable or display DataTables' ability to sort multiple columns at the
10761		 * same time (activated by shift-click by the user).
10762		 *  @type boolean
10763		 *  @default true
10764		 *
10765		 *  @dtopt Options
10766		 *  @name DataTable.defaults.orderMulti
10767		 *
10768		 *  @example
10769		 *    // Disable multiple column sorting ability
10770		 *    $(document).ready( function () {
10771		 *      $('#example').dataTable( {
10772		 *        "orderMulti": false
10773		 *      } );
10774		 *    } );
10775		 */
10776		"bSortMulti": true,
10777	
10778	
10779		/**
10780		 * Allows control over whether DataTables should use the top (true) unique
10781		 * cell that is found for a single column, or the bottom (false - default).
10782		 * This is useful when using complex headers.
10783		 *  @type boolean
10784		 *  @default false
10785		 *
10786		 *  @dtopt Options
10787		 *  @name DataTable.defaults.orderCellsTop
10788		 *
10789		 *  @example
10790		 *    $(document).ready( function() {
10791		 *      $('#example').dataTable( {
10792		 *        "orderCellsTop": true
10793		 *      } );
10794		 *    } );
10795		 */
10796		"bSortCellsTop": false,
10797	
10798	
10799		/**
10800		 * Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and
10801		 * `sorting\_3` to the columns which are currently being sorted on. This is
10802		 * presented as a feature switch as it can increase processing time (while
10803		 * classes are removed and added) so for large data sets you might want to
10804		 * turn this off.
10805		 *  @type boolean
10806		 *  @default true
10807		 *
10808		 *  @dtopt Features
10809		 *  @name DataTable.defaults.orderClasses
10810		 *
10811		 *  @example
10812		 *    $(document).ready( function () {
10813		 *      $('#example').dataTable( {
10814		 *        "orderClasses": false
10815		 *      } );
10816		 *    } );
10817		 */
10818		"bSortClasses": true,
10819	
10820	
10821		/**
10822		 * Enable or disable state saving. When enabled HTML5 `localStorage` will be
10823		 * used to save table display information such as pagination information,
10824		 * display length, filtering and sorting. As such when the end user reloads
10825		 * the page the display display will match what thy had previously set up.
10826		 *
10827		 * Due to the use of `localStorage` the default state saving is not supported
10828		 * in IE6 or 7. If state saving is required in those browsers, use
10829		 * `stateSaveCallback` to provide a storage solution such as cookies.
10830		 *  @type boolean
10831		 *  @default false
10832		 *
10833		 *  @dtopt Features
10834		 *  @name DataTable.defaults.stateSave
10835		 *
10836		 *  @example
10837		 *    $(document).ready( function () {
10838		 *      $('#example').dataTable( {
10839		 *        "stateSave": true
10840		 *      } );
10841		 *    } );
10842		 */
10843		"bStateSave": false,
10844	
10845	
10846		/**
10847		 * This function is called when a TR element is created (and all TD child
10848		 * elements have been inserted), or registered if using a DOM source, allowing
10849		 * manipulation of the TR element (adding classes etc).
10850		 *  @type function
10851		 *  @param {node} row "TR" element for the current row
10852		 *  @param {array} data Raw data array for this row
10853		 *  @param {int} dataIndex The index of this row in the internal aoData array
10854		 *
10855		 *  @dtopt Callbacks
10856		 *  @name DataTable.defaults.createdRow
10857		 *
10858		 *  @example
10859		 *    $(document).ready( function() {
10860		 *      $('#example').dataTable( {
10861		 *        "createdRow": function( row, data, dataIndex ) {
10862		 *          // Bold the grade for all 'A' grade browsers
10863		 *          if ( data[4] == "A" )
10864		 *          {
10865		 *            $('td:eq(4)', row).html( '<b>A</b>' );
10866		 *          }
10867		 *        }
10868		 *      } );
10869		 *    } );
10870		 */
10871		"fnCreatedRow": null,
10872	
10873	
10874		/**
10875		 * This function is called on every 'draw' event, and allows you to
10876		 * dynamically modify any aspect you want about the created DOM.
10877		 *  @type function
10878		 *  @param {object} settings DataTables settings object
10879		 *
10880		 *  @dtopt Callbacks
10881		 *  @name DataTable.defaults.drawCallback
10882		 *
10883		 *  @example
10884		 *    $(document).ready( function() {
10885		 *      $('#example').dataTable( {
10886		 *        "drawCallback": function( settings ) {
10887		 *          alert( 'DataTables has redrawn the table' );
10888		 *        }
10889		 *      } );
10890		 *    } );
10891		 */
10892		"fnDrawCallback": null,
10893	
10894	
10895		/**
10896		 * Identical to fnHeaderCallback() but for the table footer this function
10897		 * allows you to modify the table footer on every 'draw' event.
10898		 *  @type function
10899		 *  @param {node} foot "TR" element for the footer
10900		 *  @param {array} data Full table data (as derived from the original HTML)
10901		 *  @param {int} start Index for the current display starting point in the
10902		 *    display array
10903		 *  @param {int} end Index for the current display ending point in the
10904		 *    display array
10905		 *  @param {array int} display Index array to translate the visual position
10906		 *    to the full data array
10907		 *
10908		 *  @dtopt Callbacks
10909		 *  @name DataTable.defaults.footerCallback
10910		 *
10911		 *  @example
10912		 *    $(document).ready( function() {
10913		 *      $('#example').dataTable( {
10914		 *        "footerCallback": function( tfoot, data, start, end, display ) {
10915		 *          tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start;
10916		 *        }
10917		 *      } );
10918		 *    } )
10919		 */
10920		"fnFooterCallback": null,
10921	
10922	
10923		/**
10924		 * When rendering large numbers in the information element for the table
10925		 * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
10926		 * to have a comma separator for the 'thousands' units (e.g. 1 million is
10927		 * rendered as "1,000,000") to help readability for the end user. This
10928		 * function will override the default method DataTables uses.
10929		 *  @type function
10930		 *  @member
10931		 *  @param {int} toFormat number to be formatted
10932		 *  @returns {string} formatted string for DataTables to show the number
10933		 *
10934		 *  @dtopt Callbacks
10935		 *  @name DataTable.defaults.formatNumber
10936		 *
10937		 *  @example
10938		 *    // Format a number using a single quote for the separator (note that
10939		 *    // this can also be done with the language.thousands option)
10940		 *    $(document).ready( function() {
10941		 *      $('#example').dataTable( {
10942		 *        "formatNumber": function ( toFormat ) {
10943		 *          return toFormat.toString().replace(
10944		 *            /\B(?=(\d{3})+(?!\d))/g, "'"
10945		 *          );
10946		 *        };
10947		 *      } );
10948		 *    } );
10949		 */
10950		"fnFormatNumber": function ( toFormat ) {
10951			return toFormat.toString().replace(
10952				/\B(?=(\d{3})+(?!\d))/g,
10953				this.oLanguage.sThousands
10954			);
10955		},
10956	
10957	
10958		/**
10959		 * This function is called on every 'draw' event, and allows you to
10960		 * dynamically modify the header row. This can be used to calculate and
10961		 * display useful information about the table.
10962		 *  @type function
10963		 *  @param {node} head "TR" element for the header
10964		 *  @param {array} data Full table data (as derived from the original HTML)
10965		 *  @param {int} start Index for the current display starting point in the
10966		 *    display array
10967		 *  @param {int} end Index for the current display ending point in the
10968		 *    display array
10969		 *  @param {array int} display Index array to translate the visual position
10970		 *    to the full data array
10971		 *
10972		 *  @dtopt Callbacks
10973		 *  @name DataTable.defaults.headerCallback
10974		 *
10975		 *  @example
10976		 *    $(document).ready( function() {
10977		 *      $('#example').dataTable( {
10978		 *        "fheaderCallback": function( head, data, start, end, display ) {
10979		 *          head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records";
10980		 *        }
10981		 *      } );
10982		 *    } )
10983		 */
10984		"fnHeaderCallback": null,
10985	
10986	
10987		/**
10988		 * The information element can be used to convey information about the current
10989		 * state of the table. Although the internationalisation options presented by
10990		 * DataTables are quite capable of dealing with most customisations, there may
10991		 * be times where you wish to customise the string further. This callback
10992		 * allows you to do exactly that.
10993		 *  @type function
10994		 *  @param {object} oSettings DataTables settings object
10995		 *  @param {int} start Starting position in data for the draw
10996		 *  @param {int} end End position in data for the draw
10997		 *  @param {int} max Total number of rows in the table (regardless of
10998		 *    filtering)
10999		 *  @param {int} total Total number of rows in the data set, after filtering
11000		 *  @param {string} pre The string that DataTables has formatted using it's
11001		 *    own rules
11002		 *  @returns {string} The string to be displayed in the information element.
11003		 *
11004		 *  @dtopt Callbacks
11005		 *  @name DataTable.defaults.infoCallback
11006		 *
11007		 *  @example
11008		 *    $('#example').dataTable( {
11009		 *      "infoCallback": function( settings, start, end, max, total, pre ) {
11010		 *        return start +" to "+ end;
11011		 *      }
11012		 *    } );
11013		 */
11014		"fnInfoCallback": null,
11015	
11016	
11017		/**
11018		 * Called when the table has been initialised. Normally DataTables will
11019		 * initialise sequentially and there will be no need for this function,
11020		 * however, this does not hold true when using external language information
11021		 * since that is obtained using an async XHR call.
11022		 *  @type function
11023		 *  @param {object} settings DataTables settings object
11024		 *  @param {object} json The JSON object request from the server - only
11025		 *    present if client-side Ajax sourced data is used
11026		 *
11027		 *  @dtopt Callbacks
11028		 *  @name DataTable.defaults.initComplete
11029		 *
11030		 *  @example
11031		 *    $(document).ready( function() {
11032		 *      $('#example').dataTable( {
11033		 *        "initComplete": function(settings, json) {
11034		 *          alert( 'DataTables has finished its initialisation.' );
11035		 *        }
11036		 *      } );
11037		 *    } )
11038		 */
11039		"fnInitComplete": null,
11040	
11041	
11042		/**
11043		 * Called at the very start of each table draw and can be used to cancel the
11044		 * draw by returning false, any other return (including undefined) results in
11045		 * the full draw occurring).
11046		 *  @type function
11047		 *  @param {object} settings DataTables settings object
11048		 *  @returns {boolean} False will cancel the draw, anything else (including no
11049		 *    return) will allow it to complete.
11050		 *
11051		 *  @dtopt Callbacks
11052		 *  @name DataTable.defaults.preDrawCallback
11053		 *
11054		 *  @example
11055		 *    $(document).ready( function() {
11056		 *      $('#example').dataTable( {
11057		 *        "preDrawCallback": function( settings ) {
11058		 *          if ( $('#test').val() == 1 ) {
11059		 *            return false;
11060		 *          }
11061		 *        }
11062		 *      } );
11063		 *    } );
11064		 */
11065		"fnPreDrawCallback": null,
11066	
11067	
11068		/**
11069		 * This function allows you to 'post process' each row after it have been
11070		 * generated for each table draw, but before it is rendered on screen. This
11071		 * function might be used for setting the row class name etc.
11072		 *  @type function
11073		 *  @param {node} row "TR" element for the current row
11074		 *  @param {array} data Raw data array for this row
11075		 *  @param {int} displayIndex The display index for the current table draw
11076		 *  @param {int} displayIndexFull The index of the data in the full list of
11077		 *    rows (after filtering)
11078		 *
11079		 *  @dtopt Callbacks
11080		 *  @name DataTable.defaults.rowCallback
11081		 *
11082		 *  @example
11083		 *    $(document).ready( function() {
11084		 *      $('#example').dataTable( {
11085		 *        "rowCallback": function( row, data, displayIndex, displayIndexFull ) {
11086		 *          // Bold the grade for all 'A' grade browsers
11087		 *          if ( data[4] == "A" ) {
11088		 *            $('td:eq(4)', row).html( '<b>A</b>' );
11089		 *          }
11090		 *        }
11091		 *      } );
11092		 *    } );
11093		 */
11094		"fnRowCallback": null,
11095	
11096	
11097		/**
11098		 * __Deprecated__ The functionality provided by this parameter has now been
11099		 * superseded by that provided through `ajax`, which should be used instead.
11100		 *
11101		 * This parameter allows you to override the default function which obtains
11102		 * the data from the server so something more suitable for your application.
11103		 * For example you could use POST data, or pull information from a Gears or
11104		 * AIR database.
11105		 *  @type function
11106		 *  @member
11107		 *  @param {string} source HTTP source to obtain the data from (`ajax`)
11108		 *  @param {array}
11108 data A key/value pair object containing the data to send
11109		 *    to the server
11110		 *  @param {function} callback to be called on completion of the data get
11111		 *    process that will draw the data on the page.
11112		 *  @param {object} settings DataTables settings object
11113		 *
11114		 *  @dtopt Callbacks
11115		 *  @dtopt Server-side
11116		 *  @name DataTable.defaults.serverData
11117		 *
11118		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11119		 */
11120		"fnServerData": null,
11121	
11122	
11123		/**
11124		 * __Deprecated__ The functionality provided by this parameter has now been
11125		 * superseded by that provided through `ajax`, which should be used instead.
11126		 *
11127		 *  It is often useful to send extra data to the server when making an Ajax
11128		 * request - for example custom filtering information, and this callback
11129		 * function makes it trivial to send extra information to the server. The
11130		 * passed in parameter is the data set that has been constructed by
11131		 * DataTables, and you can add to this or modify it as you require.
11132		 *  @type function
11133		 *  @param {array} data Data array (array of objects which are name/value
11134		 *    pairs) that has been constructed by DataTables and will be sent to the
11135		 *    server. In the case of Ajax sourced data with server-side processing
11136		 *    this will be an empty array, for server-side processing there will be a
11137		 *    significant number of parameters!
11138		 *  @returns {undefined} Ensure that you modify the data array passed in,
11139		 *    as this is passed by reference.
11140		 *
11141		 *  @dtopt Callbacks
11142		 *  @dtopt Server-side
11143		 *  @name DataTable.defaults.serverParams
11144		 *
11145		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11146		 */
11147		"fnServerParams": null,
11148	
11149	
11150		/**
11151		 * Load the table state. With this function you can define from where, and how, the
11152		 * state of a table is loaded. By default DataTables will load from `localStorage`
11153		 * but you might wish to use a server-side database or cookies.
11154		 *  @type function
11155		 *  @member
11156		 *  @param {object} settings DataTables settings object
11157		 *  @param {object} callback Callback that can be executed when done. It
11158		 *    should be passed the loaded state object.
11159		 *  @return {object} The DataTables state object to be loaded
11160		 *
11161		 *  @dtopt Callbacks
11162		 *  @name DataTable.defaults.stateLoadCallback
11163		 *
11164		 *  @example
11165		 *    $(document).ready( function() {
11166		 *      $('#example').dataTable( {
11167		 *        "stateSave": true,
11168		 *        "stateLoadCallback": function (settings, callback) {
11169		 *          $.ajax( {
11170		 *            "url": "/state_load",
11171		 *            "dataType": "json",
11172		 *            "success": function (json) {
11173		 *              callback( json );
11174		 *            }
11175		 *          } );
11176		 *        }
11177		 *      } );
11178		 *    } );
11179		 */
11180		"fnStateLoadCallback": function ( settings ) {
11181			try {
11182				return JSON.parse(
11183					(settings.iStateDuration === -1 ? sessionStorage : localStorage).getItem(
11184						'DataTables_'+settings.sInstance+'_'+location.pathname
11185					)
11186				);
11187			} catch (e) {
11188				return {};
11189			}
11190		},
11191	
11192	
11193		/**
11194		 * Callback which allows modification of the saved state prior to loading that state.
11195		 * This callback is called when the table is loading state from the stored data, but
11196		 * prior to the settings object being modified by the saved state. Note that for
11197		 * plug-in authors, you should use the `stateLoadParams` event to load parameters for
11198		 * a plug-in.
11199		 *  @type function
11200		 *  @param {object} settings DataTables settings object
11201		 *  @param {object} data The state object that is to be loaded
11202		 *
11203		 *  @dtopt Callbacks
11204		 *  @name DataTable.defaults.stateLoadParams
11205		 *
11206		 *  @example
11207		 *    // Remove a saved filter, so filtering is never loaded
11208		 *    $(document).ready( function() {
11209		 *      $('#example').dataTable( {
11210		 *        "stateSave": true,
11211		 *        "stateLoadParams": function (settings, data) {
11212		 *          data.oSearch.sSearch = "";
11213		 *        }
11214		 *      } );
11215		 *    } );
11216		 *
11217		 *  @example
11218		 *    // Disallow state loading by returning false
11219		 *    $(document).ready( function() {
11220		 *      $('#example').dataTable( {
11221		 *        "stateSave": true,
11222		 *        "stateLoadParams": function (settings, data) {
11223		 *          return false;
11224		 *        }
11225		 *      } );
11226		 *    } );
11227		 */
11228		"fnStateLoadParams": null,
11229	
11230	
11231		/**
11232		 * Callback that is called when the state has been loaded from the state saving method
11233		 * and the DataTables settings object has been modified as a result of the loaded state.
11234		 *  @type function
11235		 *  @param {object} settings DataTables settings object
11236		 *  @param {object} data The state object that was loaded
11237		 *
11238		 *  @dtopt Callbacks
11239		 *  @name DataTable.defaults.stateLoaded
11240		 *
11241		 *  @example
11242		 *    // Show an alert with the filtering value that was saved
11243		 *    $(document).ready( function() {
11244		 *      $('#example').dataTable( {
11245		 *        "stateSave": true,
11246		 *        "stateLoaded": function (settings, data) {
11247		 *          alert( 'Saved filter was: '+data.oSearch.sSearch );
11248		 *        }
11249		 *      } );
11250		 *    } );
11251		 */
11252		"fnStateLoaded": null,
11253	
11254	
11255		/**
11256		 * Save the table state. This function allows you to define where and how the state
11257		 * information for the table is stored By default DataTables will use `localStorage`
11258		 * but you might wish to use a server-side database or cookies.
11259		 *  @type function
11260		 *  @member
11261		 *  @param {object} settings DataTables settings object
11262		 *  @param {object} data The state object to be saved
11263		 *
11264		 *  @dtopt Callbacks
11265		 *  @name DataTable.defaults.stateSaveCallback
11266		 *
11267		 *  @example
11268		 *    $(document).ready( function() {
11269		 *      $('#example').dataTable( {
11270		 *        "stateSave": true,
11271		 *        "stateSaveCallback": function (settings, data) {
11272		 *          // Send an Ajax request to the server with the state object
11273		 *          $.ajax( {
11274		 *            "url": "/state_save",
11275		 *            "data": data,
11276		 *            "dataType": "json",
11277		 *            "method": "POST"
11278		 *            "success": function () {}
11279		 *          } );
11280		 *        }
11281		 *      } );
11282		 *    } );
11283		 */
11284		"fnStateSaveCallback": function ( settings, data ) {
11285			try {
11286				(settings.iStateDuration === -1 ? sessionStorage : localStorage).setItem(
11287					'DataTables_'+settings.sInstance+'_'+location.pathname,
11288					JSON.stringify( data )
11289				);
11290			} catch (e) {}
11291		},
11292	
11293	
11294		/**
11295		 * Callback which allows modification of the state to be saved. Called when the table
11296		 * has changed state a new state save is required. This method allows modification of
11297		 * the state saving object prior to actually doing the save, including addition or
11298		 * other state properties or modification. Note that for plug-in authors, you should
11299		 * use the `stateSaveParams` event to save parameters for a plug-in.
11300		 *  @type function
11301		 *  @param {object} settings DataTables settings object
11302		 *  @param {object} data The state object to be saved
11303		 *
11304		 *  @dtopt Callbacks
11305		 *  @name DataTable.defaults.stateSaveParams
11306		 *
11307		 *  @example
11308		 *    // Remove a saved filter, so filtering is never saved
11309		 *    $(document).ready( function() {
11310		 *      $('#example').dataTable( {
11311		 *        "stateSave": true,
11312		 *        "stateSaveParams": function (settings, data) {
11313		 *          data.oSearch.sSearch = "";
11314		 *        }
11315		 *      } );
11316		 *    } );
11317		 */
11318		"fnStateSaveParams": null,
11319	
11320	
11321		/**
11322		 * Duration for which the saved state information is considered valid. After this period
11323		 * has elapsed the state will be returned to the default.
11324		 * Value is given in seconds.
11325		 *  @type int
11326		 *  @default 7200 <i>(2 hours)</i>
11327		 *
11328		 *  @dtopt Options
11329		 *  @name DataTable.defaults.stateDuration
11330		 *
11331		 *  @example
11332		 *    $(document).ready( function() {
11333		 *      $('#example').dataTable( {
11334		 *        "stateDuration": 60*60*24; // 1 day
11335		 *      } );
11336		 *    } )
11337		 */
11338		"iStateDuration": 7200,
11339	
11340	
11341		/**
11342		 * When enabled DataTables will not make a request to the server for the first
11343		 * page draw - rather it will use the data already on the page (no sorting etc
11344		 * will be applied to it), thus saving on an XHR at load time. `deferLoading`
11345		 * is used to indicate that deferred loading is required, but it is also used
11346		 * to tell DataTables how many records there are in the full table (allowing
11347		 * the information element and pagination to be displayed correctly). In the case
11348		 * where a filtering is applied to the table on initial load, this can be
11349		 * indicated by giving the parameter as an array, where the first element is
11350		 * the number of records available after filtering and the second element is the
11351		 * number of records without filtering (allowing the table information element
11352		 * to be shown correctly).
11353		 *  @type int | array
11354		 *  @default null
11355		 *
11356		 *  @dtopt Options
11357		 *  @name DataTable.defaults.deferLoading
11358		 *
11359		 *  @example
11360		 *    // 57 records available in the table, no filtering applied
11361		 *    $(document).ready( function() {
11362		 *      $('#example').dataTable( {
11363		 *        "serverSide": true,
11364		 *        "ajax": "scripts/server_processing.php",
11365		 *        "deferLoading": 57
11366		 *      } );
11367		 *    } );
11368		 *
11369		 *  @example
11370		 *    // 57 records after filtering, 100 without filtering (an initial filter applied)
11371		 *    $(document).ready( function() {
11372		 *      $('#example').dataTable( {
11373		 *        "serverSide": true,
11374		 *        "ajax": "scripts/server_processing.php",
11375		 *        "deferLoading": [ 57, 100 ],
11376		 *        "search": {
11377		 *          "search": "my_filter"
11378		 *        }
11379		 *      } );
11380		 *    } );
11381		 */
11382		"iDeferLoading": null,
11383	
11384	
11385		/**
11386		 * Number of rows to display on a single page when using pagination. If
11387		 * feature enabled (`lengthChange`) then the end user will be able to override
11388		 * this to a custom setting using a pop-up menu.
11389		 *  @type int
11390		 *  @default 10
11391		 *
11392		 *  @dtopt Options
11393		 *  @name DataTable.defaults.pageLength
11394		 *
11395		 *  @example
11396		 *    $(document).ready( function() {
11397		 *      $('#example').dataTable( {
11398		 *        "pageLength": 50
11399		 *      } );
11400		 *    } )
11401		 */
11402		"iDisplayLength": 10,
11403	
11404	
11405		/**
11406		 * Define the starting point for data display when using DataTables with
11407		 * pagination. Note that this parameter is the number of records, rather than
11408		 * the page number, so if you have 10 records per page and want to start on
11409		 * the third page, it should be "20".
11410		 *  @type int
11411		 *  @default 0
11412		 *
11413		 *  @dtopt Options
11414		 *  @name DataTable.defaults.displayStart
11415		 *
11416		 *  @example
11417		 *    $(document).ready( function() {
11418		 *      $('#example').dataTable( {
11419		 *        "displayStart": 20
11420		 *      } );
11421		 *    } )
11422		 */
11423		"iDisplayStart": 0,
11424	
11425	
11426		/**
11427		 * By default DataTables allows keyboard navigation of the table (sorting, paging,
11428		 * and filtering) by adding a `tabindex` attribute to the required elements. This
11429		 * allows you to tab through the controls and press the enter key to activate them.
11430		 * The tabindex is default 0, meaning that the tab follows the flow of the document.
11431		 * You can overrule this using this parameter if you wish. Use a value of -1 to
11432		 * disable built-in keyboard navigation.
11433		 *  @type int
11434		 *  @default 0
11435		 *
11436		 *  @dtopt Options
11437		 *  @name DataTable.defaults.tabIndex
11438		 *
11439		 *  @example
11440		 *    $(document).ready( function() {
11441		 *      $('#example').dataTable( {
11442		 *        "tabIndex": 1
11443		 *      } );
11444		 *    } );
11445		 */
11446		"iTabIndex": 0,
11447	
11448	
11449		/**
11450		 * Classes that DataTables assigns to the various components and features
11451		 * that it adds to the HTML table. This allows classes to be configured
11452		 * during initialisation in addition to through the static
11453		 * {@link DataTable.ext.oStdClasses} object).
11454		 *  @namespace
11455		 *  @name DataTable.defaults.classes
11456		 */
11457		"oClasses": {},
11458	
11459	
11460		/**
11461		 * All strings that DataTables uses in the user interface that it creates
11462		 * are defined in this object, allowing you to modified them individually or
11463		 * completely replace them all as required.
11464		 *  @namespace
11465		 *  @name DataTable.defaults.language
11466		 */
11467		"oLanguage": {
11468			/**
11469			 * Strings that are used for WAI-ARIA labels and controls only (these are not
11470			 * actually visible on the page, but will be read by screenreaders, and thus
11471			 * must be internationalised as well).
11472			 *  @namespace
11473			 *  @name DataTable.defaults.language.aria
11474			 */
11475			"oAria": {
11476				/**
11477				 * ARIA label that is added to the table headers when the column may be
11478				 * sorted ascending by activing the column (click or return when focused).
11479				 * Note that the column header is prefixed to this string.
11480				 *  @type string
11481				 *  @default : activate to sort column ascending
11482				 *
11483				 *  @dtopt Language
11484				 *  @name DataTable.defaults.language.aria.sortAscending
11485				 *
11486				 *  @example
11487				 *    $(document).ready( function() {
11488				 *      $('#example').dataTable( {
11489				 *        "language": {
11490				 *          "aria": {
11491				 *            "sortAscending": " - click/return to sort ascending"
11492				 *          }
11493				 *        }
11494				 *      } );
11495				 *    } );
11496				 */
11497				"sSortAscending": ": activate to sort column ascending",
11498	
11499				/**
11500				 * ARIA label that is added to the table headers when the column may be
11501				 * sorted descending by activing the column (click or return when focused).
11502				 * Note that the column header is prefixed to this string.
11503				 *  @type string
11504				 *  @default : activate to sort column ascending
11505				 *
11506				 *  @dtopt Language
11507				 *  @name DataTable.defaults.language.aria.sortDescending
11508				 *
11509				 *  @example
11510				 *    $(document).ready( function() {
11511				 *      $('#example').dataTable( {
11512				 *        "language": {
11513				 *          "aria": {
11514				 *            "sortDescending": " - click/return to sort descending"
11515				 *          }
11516				 *        }
11517				 *      } );
11518				 *    } );
11519				 */
11520				"sSortDescending": ": activate to sort column descending"
11521			},
11522	
11523			/**
11524			 * Pagination string used by DataTables for the built-in pagination
11525			 * control types.
11526			 *  @namespace
11527			 *  @name DataTable.defaults.language.paginate
11528			 */
11529			"oPaginate": {
11530				/**
11531				 * Text to use when using the 'full_numbers' type of pagination for the
11532				 * button to take the user to the first page.
11533				 *  @type string
11534				 *  @default First
11535				 *
11536				 *  @dtopt Language
11537				 *  @name DataTable.defaults.language.paginate.first
11538				 *
11539				 *  @example
11540				 *    $(document).ready( function() {
11541				 *      $('#example').dataTable( {
11542				 *        "language": {
11543				 *          "paginate": {
11544				 *            "first": "First page"
11545				 *          }
11546				 *        }
11547				 *      } );
11548				 *    } );
11549				 */
11550				"sFirst": "First",
11551	
11552	
11553				/**
11554				 * Text to use when using the 'full_numbers' type of pagination for the
11555				 * button to take the user to the last page.
11556				 *  @type string
11557				 *  @default Last
11558				 *
11559				 *  @dtopt Language
11560				 *  @name DataTable.defaults.language.paginate.last
11561				 *
11562				 *  @example
11563				 *    $(document).ready( function() {
11564				 *      $('#example').dataTable( {
11565				 *        "language": {
11566				 *          "paginate": {
11567				 *            "last": "Last page"
11568				 *          }
11569				 *        }
11570				 *      } );
11571				 *    } );
11572				 */
11573				"sLast": "Last",
11574	
11575	
11576				/**
11577				 * Text to use for the 'next' pagination button (to take the user to the
11578				 * next page).
11579				 *  @type string
11580				 *  @default Next
11581				 *
11582				 *  @dtopt Language
11583				 *  @name DataTable.defaults.language.paginate.next
11584				 *
11585				 *  @example
11586				 *    $(document).ready( function() {
11587				 *      $('#example').dataTable( {
11588				 *        "language": {
11589				 *          "paginate": {
11590				 *            "next": "Next page"
11591				 *          }
11592				 *        }
11593				 *      } );
11594				 *    } );
11595				 */
11596				"sNext": "Next",
11597	
11598	
11599				/**
11600				 * Text to use for the 'previous' pagination button (to take the user to
11601				 * the previous page).
11602				 *  @type string
11603				 *  @default Previous
11604				 *
11605				 *  @dtopt Language
11606				 *  @name DataTable.defaults.language.paginate.previous
11607				 *
11608				 *  @example
11609				 *    $(document).ready( function() {
11610				 *      $('#example').dataTable( {
11611				 *        "language": {
11612				 *          "paginate": {
11613				 *            "previous": "Previous page"
11614				 *          }
11615				 *        }
11616				 *      } );
11617				 *    } );
11618				 */
11619				"sPrevious": "Previous"
11620			},
11621	
11622			/**
11623			 * This string is shown in preference to `zeroRecords` when the table is
11624			 * empty of data (regardless of filtering). Note that this is an optional
11625			 * parameter - if it is not given, the value of `zeroRecords` will be used
11626			 * instead (either the default or given value).
11627			 *  @type string
11628			 *  @default No data available in table
11629			 *
11630			 *  @dtopt Language
11631			 *  @name DataTable.defaults.language.emptyTable
11632			 *
11633			 *  @example
11634			 *    $(document).ready( function() {
11635			 *      $('#example').dataTable( {
11636			 *        "language": {
11637			 *          "emptyTable": "No data available in table"
11638			 *        }
11639			 *      } );
11640			 *    } );
11641			 */
11642			"sEmptyTable": "No data available in table",
11643	
11644	
11645			/**
11646			 * This string gives information to the end user about the information
11647			 * that is current on display on the page. The following tokens can be
11648			 * used in the string and will be dynamically replaced as the table
11649			 * display updates. This tokens can be placed anywhere in the string, or
11650			 * removed as needed by the language requires:
11651			 *
11652			 * * `\_START\_` - Display index of the first record on the current page
11653			 * * `\_END\_` - Display index of the last record on the current page
11654			 * * `\_TOTAL\_` - Number of records in the table after filtering
11655			 * * `\_MAX\_` - Number of records in the table without filtering
11656			 * * `\_PAGE\_` - Current page number
11657			 * * `\_PAGES\_` - Total number of pages of data in the table
11658			 *
11659			 *  @type string
11660			 *  @default Showing _START_ to _END_ of _TOTAL_ entries
11661			 *
11662			 *  @dtopt Language
11663			 *  @name DataTable.defaults.language.info
11664			 *
11665			 *  @example
11666			 *    $(document).ready( function() {
11667			 *      $('#example').dataTable( {
11668			 *        "language": {
11669			 *          "info": "Showing page _PAGE_ of _PAGES_"
11670			 *        }
11671			 *      } );
11672			 *    } );
11673			 */
11674			"sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
11675	
11676	
11677			/**
11678			 * Display information string for when the table is empty. Typically the
11679			 * format of this string should match `info`.
11680			 *  @type string
11681			 *  @default Showing 0 to 0 of 0 entries
11682			 *
11683			 *  @dtopt Language
11684			 *  @name DataTable.defaults.language.infoEmpty
11685			 *
11686			 *  @example
11687			 *    $(document).ready( function() {
11688			 *      $('#example').dataTable( {
11689			 *        "language": {
11690			 *          "infoEmpty": "No entries to show"
11691			 *        }
11692			 *      } );
11693			 *    } );
11694			 */
11695			"sInfoEmpty": "Showing 0 to 0 of 0 entries",
11696	
11697	
11698			/**
11699			 * When a user filters the information in a table, this string is appended
11700			 * to the information (`info`) to give an idea of how strong the filtering
11701			 * is. The variable _MAX_ is dynamically updated.
11702			 *  @type string
11703			 *  @default (filtered from _MAX_ total entries)
11704			 *
11705			 *  @dtopt Language
11706			 *  @name DataTable.defaults.language.infoFiltered
11707			 *
11708			 *  @example
11709			 *    $(document).ready( function() {
11710			 *      $('#example').dataTable( {
11711			 *        "language": {
11712			 *          "infoFiltered": " - filtering from _MAX_ records"
11713			 *        }
11714			 *      } );
11715			 *    } );
11716			 */
11717			"sInfoFiltered": "(filtered from _MAX_ total entries)",
11718	
11719	
11720			/**
11721			 * If can be useful to append extra information to the info string at times,
11722			 * and this variable does exactly that. This information will be appended to
11723			 * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are
11724			 * being used) at all times.
11725			 *  @type string
11726			 *  @default <i>Empty string</i>
11727			 *
11728			 *  @dtopt Language
11729			 *  @name DataTable.defaults.language.infoPostFix
11730			 *
11731			 *  @example
11732			 *    $(document).ready( function() {
11733			 *      $('#example').dataTable( {
11734			 *        "language": {
11735			 *          "infoPostFix": "All records shown are derived from real information."
11736			 *        }
11737			 *      } );
11738			 *    } );
11739			 */
11740			"sInfoPostFix": "",
11741	
11742	
11743			/**
11744			 * This decimal place operator is a little different from the other
11745			 * language options since DataTables doesn't output floating point
11746			 * numbers, so it won't ever use this for display of a number. Rather,
11747			 * what this parameter does is modify the sort methods of the table so
11748			 * that numbers which are in a format which has a character other than
11749			 * a period (`.`) as a decimal place will be sorted numerically.
11750			 *
11751			 * Note that numbers with different decimal places cannot be shown in
11752			 * the same table and still be sortable, the table must be consistent.
11753			 * However, multiple different tables on the page can use different
11754			 * decimal place characters.
11755			 *  @type string
11756			 *  @default 
11757			 *
11758			 *  @dtopt Language
11759			 *  @name DataTable.defaults.language.decimal
11760			 *
11761			 *  @example
11762			 *    $(document).ready( function() {
11763			 *      $('#example').dataTable( {
11764			 *        "language": {
11765			 *          "decimal": ","
11766			 *          "thousands": "."
11767			 *        }
11768			 *      } );
11769			 *    } );
11770			 */
11771			"sDecimal": "",
11772	
11773	
11774			/**
11775			 * DataTables has a build in number formatter (`formatNumber`) which is
11776			 * used to format large numbers that are used in the table information.
11777			 * By default a comma is used, but this can be trivially changed to any
11778			 * character you wish with this parameter.
11779			 *  @type string
11780			 *  @default ,
11781			 *
11782			 *  @dtopt Language
11783			 *  @name DataTable.defaults.language.thousands
11784			 *
11785			 *  @example
11786			 *    $(document).ready( function() {
11787			 *      $('#example').dataTable( {
11788			 *        "language": {
11789			 *          "thousands": "'"
11790			 *        }
11791			 *      } );
11792			 *    } );
11793			 */
11794			"sThousands": ",",
11795	
11796	
11797			/**
11798			 * Detail the action that will be taken when the drop down menu for the
11799			 * pagination length option is changed. The '_MENU_' variable is replaced
11800			 * with a default select list of 10, 25, 50 and 100, and can be replaced
11801			 * with a custom select box if required.
11802			 *  @type string
11803			 *  @default Show _MENU_ entries
11804			 *
11805			 *  @dtopt Language
11806			 *  @name DataTable.defaults.language.lengthMenu
11807			 *
11808			 *  @example
11809			 *    // Language change only
11810			 *    $(document).ready( function() {
11811			 *      $('#example').dataTable( {
11812			 *        "language": {
11813			 *          "lengthMenu": "Display _MENU_ records"
11814			 *        }
11815			 *      } );
11816			 *    } );
11817			 *
11818			 *  @example
11819			 *    // Language and options change
11820			 *    $(document).ready( function() {
11821			 *      $('#example').dataTable( {
11822			 *        "language": {
11823			 *          "lengthMenu": 'Display <select>'+
11824			 *            '<option value="10">10</option>'+
11825			 *            '<option value="20">20</option>'+
11826			 *            '<option value="30">30</option>'+
11827			 *            '<option value="40">40</option>'+
11828			 *            '<option value="50">50</option>'+
11829			 *            '<option value="-1">All</option>'+
11830			 *            '</select> records'
11831			 *        }
11832			 *      } );
11833			 *    } );
11834			 */
11835			"sLengthMenu": "Show _MENU_ entries",
11836	
11837	
11838			/**
11839			 * When using Ajax sourced data and during the first draw when DataTables is
11840			 * gathering the data, this message is shown in an empty row in the table to
11841			 * indicate to the end user the the data is being loaded. Note that this
11842			 * parameter is not used when loading data by server-side processing, just
11843			 * Ajax sourced data with client-side processing.
11844			 *  @type string
11845			 *  @default Loading...
11846			 *
11847			 *  @dtopt Language
11848			 *  @name DataTable.defaults.language.loadingRecords
11849			 *
11850			 *  @example
11851			 *    $(document).ready( function() {
11852			 *      $('#example').dataTable( {
11853			 *        "language": {
11854			 *          "loadingRecords": "Please wait - loading..."
11855			 *        }
11856			 *      } );
11857			 *    } );
11858			 */
11859			"sLoadingRecords": "Loading...",
11860	
11861	
11862			/**
11863			 * Text which is displayed when the table is processing a user action
11864			 * (usually a sort command or similar).
11865			 *  @type string
11866			 *
11867			 *  @dtopt Language
11868			 *  @name DataTable.defaults.language.processing
11869			 *
11870			 *  @example
11871			 *    $(document).ready( function() {
11872			 *      $('#example').dataTable( {
11873			 *        "language": {
11874			 *          "processing": "DataTables is currently busy"
11875			 *        }
11876			 *      } );
11877			 *    } );
11878			 */
11879			"sProcessing": "",
11880	
11881	
11882			/**
11883			 * Details the actions that will be taken when the user types into the
11884			 * filtering input text box. The variable "_INPUT_", if used in the string,
11885			 * is replaced with the HTML text box for the filtering input allowing
11886			 * control over where it appears in the string. If "_INPUT_" is not given
11887			 * then the input box is appended to the string automatically.
11888			 *  @type string
11889			 *  @default Search:
11890			 *
11891			 *  @dtopt Language
11892			 *  @name DataTable.defaults.language.search
11893			 *
11894			 *  @example
11895			 *    // Input text box will be appended at the end automatically
11896			 *    $(document).ready( function() {
11897			 *      $('#example').dataTable( {
11898			 *        "language": {
11899			 *          "search": "Filter records:"
11900			 *        }
11901			 *      } );
11902			 *    } );
11903			 *
11904			 *  @example
11905			 *    // Specify where the filter should appear
11906			 *    $(document).ready( function() {
11907			 *      $('#example').dataTable( {
11908			 *        "language": {
11909			 *          "search": "Apply filter _INPUT_ to table"
11910			 *        }
11911			 *      } );
11912			 *    } );
11913			 */
11914			"sSearch": "Search:",
11915	
11916	
11917			/**
11918			 * Assign a `placeholder` attribute to the search `input` element
11919			 *  @type string
11920			 *  @default 
11921			 *
11922			 *  @dtopt Language
11923			 *  @name DataTable.defaults.language.searchPlaceholder
11924			 */
11925			"sSearchPlaceholder": "",
11926	
11927	
11928			/**
11929			 * All of the language information can be stored in a file on the
11930			 * server-side, which DataTables will look up if this parameter is passed.
11931			 * It must store the URL of the language file, which is in a JSON format,
11932			 * and the object has the same properties as the oLanguage object in the
11933			 * initialiser object (i.e. the above parameters). Please refer to one of
11934			 * the example language files to see how this works in action.
11935			 *  @type string
11936			 *  @default <i>Empty string - i.e. disabled</i>
11937			 *
11938			 *  @dtopt Language
11939			 *  @name DataTable.defaults.language.url
11940			 *
11941			 *  @example
11942			 *    $(document).ready( function() {
11943			 *      $('#example').dataTable( {
11944			 *        "language": {
11945			 *          "url": "http://www.sprymedia.co.uk/dataTables/lang.txt"
11946			 *        }
11947			 *      } );
11948			 *    } );
11949			 */
11950			"sUrl": "",
11951	
11952	
11953			/**
11954			 * Text shown inside the table records when the is no information to be
11955			 * displayed after filtering. `emptyTable` is shown when there is simply no
11956			 * information in the table at all (regardless of filtering).
11957			 *  @type string
11958			 *  @default No matching records found
11959			 *
11960			 *  @dtopt Language
11961			 *  @name DataTable.defaults.language.zeroRecords
11962			 *
11963			 *  @example
11964			 *    $(document).ready( function() {
11965			 *      $('#example').dataTable( {
11966			 *        "language": {
11967			 *          "zeroRecords": "No records to display"
11968			 *        }
11969			 *      } );
11970			 *    } );
11971			 */
11972			"sZeroRecords": "No matching records found"
11973		},
11974	
11975	
11976		/**
11977		 * This parameter allows you to have define the global filtering state at
11978		 * initialisation time. As an object the `search` parameter must be
11979		 * defined, but all other parameters are optional. When `regex` is true,
11980		 * the search string will be treated as a regular expression, when false
11981		 * (default) it will be treated as a straight string. When `smart`
11982		 * DataTables will use it's smart filtering methods (to word match at
11983		 * any point in the data), when false this will not be done.
11984		 *  @namespace
11985		 *  @extends DataTable.models.oSearch
11986		 *
11987		 *  @dtopt Options
11988		 *  @name DataTable.defaults.search
11989		 *
11990		 *  @example
11991		 *    $(document).ready( function() {
11992		 *      $('#example').dataTable( {
11993		 *        "search": {"search": "Initial search"}
11994		 *      } );
11995		 *    } )
11996		 */
11997		"oSearch": $.extend( {}, DataTable.models.oSearch ),
11998	
11999	
12000		/**
12001		 * __Deprecated__ The functionality provided by this parameter has now been
12002		 * superseded by that provided through `ajax`, which should be used instead.
12003		 *
12004		 * By default DataTables will look for the property `data` (or `aaData` for
12005		 * compatibility with DataTables 1.9-) when obtaining data from an Ajax
12006		 * source or for server-side processing - this parameter allows that
12007		 * property to be changed. You can use Javascript dotted object notation to
12008		 * get a data source for multiple levels of nesting.
12009		 *  @type string
12010		 *  @default data
12011		 *
12012		 *  @dtopt Options
12013		 *  @dtopt Server-side
12014		 *  @name DataTable.defaults.ajaxDataProp
12015		 *
12016		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
12017		 */
12018		"sAjaxDataProp": "data",
12019	
12020	
12021		/**
12022		 * __Deprecated__ The functionality provided by this parameter has now been
12023		 * superseded by that provided through `ajax`, which should be used instead.
12024		 *
12025		 * You can instruct DataTables to load data from an external
12026		 * source using this parameter (use aData if you want to pass data in you
12027		 * already have). Simply provide a url a JSON object can be obtained from.
12028		 *  @type string
12029		 *  @default null
12030		 *
12031		 *  @dtopt Options
12032		 *  @dtopt Server-side
12033		 *  @name DataTable.defaults.ajaxSource
12034		 *
12035		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
12036		 */
12037		"sAjaxSource": null,
12038	
12039	
12040		/**
12041		 * This initialisation variable allows you to specify exactly where in the
12042		 * DOM you want DataTables to inject the various controls it adds to the page
12043		 * (for example you might want the pagination controls at the top of the
12044		 * table). DIV elements (with or without a custom class) can also be added to
12045		 * aid styling. The follow syntax is used:
12046		 *   <ul>
12047		 *     <li>The following options are allowed:
12048		 *       <ul>
12049		 *         <li>'l' - Length changing</li>
12050		 *         <li>'f' - Filtering input</li>
12051		 *         <li>'t' - The table!</li>
12052		 *         <li>'i' - Information</li>
12053		 *         <li>'p' - Pagination</li>
12054		 *         <li>'r' - pRocessing</li>
12055		 *       </ul>
12056		 *     </li>
12057		 *     <li>The following constants are allowed:
12058		 *       <ul>
12059		 *         <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>
12060		 *         <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>
12061		 *       </ul>
12062		 *     </li>
12063		 *     <li>The following syntax is expected:
12064		 *       <ul>
12065		 *         <li>'&lt;' and '&gt;' - div elements</li>
12066		 *         <li>'&lt;"class" and '&gt;' - div with a class</li>
12067		 *         <li>'&lt;"#id" and '&gt;' - div with an ID</li>
12068		 *       </ul>
12069		 *     </li>
12070		 *     <li>Examples:
12071		 *       <ul>
12072		 *         <li>'&lt;"wrapper"flipt&gt;'</li>
12073		 *         <li>'&lt;lf&lt;t&gt;ip&gt;'</li>
12074		 *       </ul>
12075		 *     </li>
12076		 *   </ul>
12077		 *  @type string
12078		 *  @default lfrtip <i>(when `jQueryUI` is false)</i> <b>or</b>
12079		 *    <"H"lfr>t<"F"ip> <i>(when `jQueryUI` is true)</i>
12080		 *
12081		 *  @dtopt Options
12082		 *  @name DataTable.defaults.dom
12083		 *
12084		 *  @example
12085		 *    $(document).ready( function() {
12086		 *      $('#example').dataTable( {
12087		 *        "dom": '&lt;"top"i&gt;rt&lt;"bottom"flp&gt;&lt;"clear"&gt;'
12088		 *      } );
12089		 *    } );
12090		 */
12091		"sDom": "lfrtip",
12092	
12093	
12094		/**
12095		 * Search delay option. This will throttle full table searches that use the
12096		 * DataTables provided search input element (it does not effect calls to
12097		 * `dt-api search()`, providing a delay before the search is made.
12098		 *  @type integer
12099		 *  @default 0
12100		 *
12101		 *  @dtopt Options
12102		 *  @name DataTable.defaults.searchDelay
12103		 *
12104		 *  @example
12105		 *    $(document).ready( function() {
12106		 *      $('#example').dataTable( {
12107		 *        "searchDelay": 200
12108		 *      } );
12109		 *    } )
12110		 */
12111		"searchDelay": null,
12112	
12113	
12114		/**
12115		 * DataTables features six different built-in options for the buttons to
12116		 * display for pagination control:
12117		 *
12118		 * * `numbers` - Page number buttons only
12119		 * * `simple` - 'Previous' and 'Next' buttons only
12120		 * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers
12121		 * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons
12122		 * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus page numbers
12123		 * * `first_last_numbers` - 'First' and 'Last' buttons, plus page numbers
12124		 *  
12125		 * Further methods can be added using {@link DataTable.ext.oPagination}.
12126		 *  @type string
12127		 *  @default simple_numbers
12128		 *
12129		 *  @dtopt Options
12130		 *  @name DataTable.defaults.pagingType
12131		 *
12132		 *  @example
12133		 *    $(document).ready( function() {
12134		 *      $('#example').dataTable( {
12135		 *        "pagingType": "full_numbers"
12136		 *      } );
12137		 *    } )
12138		 */
12139		"sPaginationType": "simple_numbers",
12140	
12141	
12142		/**
12143		 * Enable horizontal scrolling. When a table is too wide to fit into a
12144		 * certain layout, or you have a large number of columns in the table, you
12145		 * can enable x-scrolling to show the table in a viewport, which can be
12146		 * scrolled. This property can be `true` which will allow the table to
12147		 * scroll horizontally when needed, or any CSS unit, or a number (in which
12148		 * case it will be treated as a pixel measurement). Setting as simply `true`
12149		 * is recommended.
12150		 *  @type boolean|string
12151		 *  @default <i>blank string - i.e. disabled</i>
12152		 *
12153		 *  @dtopt Features
12154		 *  @name DataTable.defaults.scrollX
12155		 *
12156		 *  @example
12157		 *    $(document).ready( function() {
12158		 *      $('#example').dataTable( {
12159		 *        "scrollX": true,
12160		 *        "scrollCollapse": true
12161		 *      } );
12162		 *    } );
12163		 */
12164		"sScrollX": "",
12165	
12166	
12167		/**
12168		 * This property can be used to force a DataTable to use more width than it
12169		 * might otherwise do when x-scrolling is enabled. For example if you have a
12170		 * table which requires to be well spaced, this parameter is useful for
12171		 * "over-sizing" the table, and thus forcing scrolling. This property can by
12172		 * any CSS unit, or a number (in which case it will be treated as a pixel
12173		 * measurement).
12174		 *  @type string
12175		 *  @default <i>blank string - i.e. disabled</i>
12176		 *
12177		 *  @dtopt Options
12178		 *  @name DataTable.defaults.scrollXInner
12179		 *
12180		 *  @example
12181		 *    $(document).ready( function() {
12182		 *      $('#example').dataTable( {
12183		 *        "scrollX": "100%",
12184		 *        "scrollXInner": "110%"
12185		 *      } );
12186		 *    } );
12187		 */
12188		"sScrollXInner": "",
12189	
12190	
12191		/**
12192		 * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
12193		 * to the given height, and enable scrolling for any data which overflows the
12194		 * current viewport. This can be used as an alternative to paging to display
12195		 * a lot of data in a small area (although paging and scrolling can both be
12196		 * enabled at the same time). This property can be any CSS unit, or a number
12197		 * (in which case it will be treated as a pixel measurement).
12198		 *  @type string
12199		 *  @default <i>blank string - i.e. disabled</i>
12200		 *
12201		 *  @dtopt Features
12202		 *  @name DataTable.defaults.scrollY
12203		 *
12204		 *  @example
12205		 *    $(document).ready( function() {
12206		 *      $('#example').dataTable( {
12207		 *        "scrollY": "200px",
12208		 *        "paginate": false
12209		 *      } );
12210		 *    } );
12211		 */
12212		"sScrollY": "",
12213	
12214	
12215		/**
12216		 * __Deprecated__ The functionality provided by this parameter has now been
12217		 * superseded by that provided through `ajax`, which should be used instead.
12218		 *
12219		 * Set the HTTP method that is used to make the Ajax call for server-side
12220		 * processing or Ajax sourced data.
12221		 *  @type string
12222		 *  @default GET
12223		 *
12224		 *  @dtopt Options
12225		 *  @dtopt Server-side
12226		 *  @name DataTable.defaults.serverMethod
12227		 *
12228		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
12229		 */
12230		"sServerMethod": "GET",
12231	
12232	
12233		/**
12234		 * DataTables makes use of renderers when displaying HTML elements for
12235		 * a table. These renderers can be added or modified by plug-ins to
12236		 * generate suitable mark-up for a site. For example the Bootstrap
12237		 * integration plug-in for DataTables uses a paging button renderer to
12238		 * display pagination buttons in the mark-up required by Bootstrap.
12239		 *
12240		 * For further information about the renderers available see
12241		 * DataTable.ext.renderer
12242		 *  @type string|object
12243		 *  @default null
12244		 *
12245		 *  @name DataTable.defaults.renderer
12246		 *
12247		 */
12248		"renderer": null,
12249	
12250	
12251		/**
12252		 * Set the data property name that DataTables should use to get a row's id
12253		 * to set as the `id` property in the node.
12254		 *  @type string
12255		 *  @default DT_RowId
12256		 *
12257		 *  @name DataTable.defaults.rowId
12258		 */
12259		"rowId": "DT_RowId"
12260	};
12261	
12262	_fnHungarianMap( DataTable.defaults );
12263	
12264	
12265	
12266	/*
12267	 * Developer note - See note in model.defaults.js about the use of Hungarian
12268	 * notation and camel case.
12269	 */
12270	
12271	/**
12272	 * Column options that can be given to DataTables at initialisation time.
12273	 *  @namespace
12274	 */
12275	DataTable.defaults.column = {
12276		/**
12277		 * Define which column(s) an order will occur on for this column. This
12278		 * allows a column's ordering to take multiple columns into account when
12279		 * doing a sort or use the data from a different column. For example first
12280		 * name / last name columns make sense to do a multi-column sort over the
12281		 * two columns.
12282		 *  @type array|int
12283		 *  @default null <i>Takes the value of the column index automatically</i>
12284		 *
12285		 *  @name DataTable.defaults.column.orderData
12286		 *  @dtopt Columns
12287		 *
12288		 *  @example
12289		 *    // Using `columnDefs`
12290		 *    $(document).ready( function() {
12291		 *      $('#example').dataTable( {
12292		 *        "columnDefs": [
12293		 *          { "orderData": [ 0, 1 ], "targets": [ 0 ] },
12294		 *          { "orderData": [ 1, 0 ], "targets": [ 1 ] },
12295		 *          { "orderData": 2, "targets": [ 2 ] }
12296		 *        ]
12297		 *      } );
12298		 *    } );
12299		 *
12300		 *  @example
12301		 *    // Using `columns`
12302		 *    $(document).ready( function() {
12303		 *      $('#example').dataTable( {
12304		 *        "columns": [
12305		 *          { "orderData": [ 0, 1 ] },
12306		 *          { "orderData": [ 1, 0 ] },
12307		 *          { "orderData": 2 },
12308		 *          null,
12309		 *          null
12310		 *        ]
12311		 *      } );
12312		 *    } );
12313		 */
12314		"aDataSort": null,
12315		"iDataSort": -1,
12316	
12317	
12318		/**
12319		 * You can control the default ordering direction, and even alter the
12320		 * behaviour of the sort handler (i.e. only allow ascending ordering etc)
12321		 * using this parameter.
12322		 *  @type array
12323		 *  @default [ 'asc', 'desc' ]
12324		 *
12325		 *  @name DataTable.defaults.column.orderSequence
12326		 *  @dtopt Columns
12327		 *
12328		 *  @example
12329		 *    // Using `columnDefs`
12330		 *    $(document).ready( function() {
12331		 *      $('#example').dataTable( {
12332		 *        "columnDefs": [
12333		 *          { "orderSequence": [ "asc" ], "targets": [ 1 ] },
12334		 *          { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] },
12335		 *          { "orderSequence": [ "desc" ], "targets": [ 3 ] }
12336		 *        ]
12337		 *      } );
12338		 *    } );
12339		 *
12340		 *  @example
12341		 *    // Using `columns`
12342		 *    $(document).ready( function() {
12343		 *      $('#example').dataTable( {
12344		 *        "columns": [
12345		 *          null,
12346		 *          { "orderSequence": [ "asc" ] },
12347		 *          { "orderSequence": [ "desc", "asc", "asc" ] },
12348		 *          { "orderSequence": [ "desc" ] },
12349		 *          null
12350		 *        ]
12351		 *      } );
12352		 *    } );
12353		 */
12354		"asSorting": [ 'asc', 'desc' ],
12355	
12356	
12357		/**
12358		 * Enable or disable filtering on the data in this column.
12359		 *  @type boolean
12360		 *  @default true
12361		 *
12362		 *  @name DataTable.defaults.column.searchable
12363		 *  @dtopt Columns
12364		 *
12365		 *  @example
12366		 *    // Using `columnDefs`
12367		 *    $(document).ready( function() {
12368		 *      $('#example').dataTable( {
12369		 *        "columnDefs": [
12370		 *          { "searchable": false, "targets": [ 0 ] }
12371		 *        ] } );
12372		 *    } );
12373		 *
12374		 *  @example
12375		 *    // Using `columns`
12376		 *    $(document).ready( function() {
12377		 *      $('#example').dataTable( {
12378		 *        "columns": [
12379		 *          { "searchable": false },
12380		 *          null,
12381		 *          null,
12382		 *          null,
12383		 *          null
12384		 *        ] } );
12385		 *    } );
12386		 */
12387		"bSearchable": true,
12388	
12389	
12390		/**
12391		 * Enable or disable ordering on this column.
12392		 *  @type boolean
12393		 *  @default true
12394		 *
12395		 *  @name DataTable.defaults.column.orderable
12396		 *  @dtopt Columns
12397		 *
12398		 *  @example
12399		 *    // Using `columnDefs`
12400		 *    $(document).ready( function() {
12401		 *      $('#example').dataTable( {
12402		 *        "columnDefs": [
12403		 *          { "orderable": false, "targets": [ 0 ] }
12404		 *        ] } );
12405		 *    } );
12406		 *
12407		 *  @example
12408		 *    // Using `columns`
12409		 *    $(document).ready( function() {
12410		 *      $('#example').dataTable( {
12411		 *        "columns": [
12412		 *          { "orderable": false },
12413		 *          null,
12414		 *          null,
12415		 *          null,
12416		 *          null
12417		 *        ] } );
12418		 *    } );
12419		 */
12420		"bSortable": true,
12421	
12422	
12423		/**
12424		 * Enable or disable the display of this column.
12425		 *  @type boolean
12426		 *  @default true
12427		 *
12428		 *  @name DataTable.defaults.column.visible
12429		 *  @dtopt Columns
12430		 *
12431		 *  @example
12432		 *    // Using `columnDefs`
12433		 *    $(document).ready( function() {
12434		 *      $('#example').dataTable( {
12435		 *        "columnDefs": [
12436		 *          { "visible": false, "targets": [ 0 ] }
12437		 *        ] } );
12438		 *    } );
12439		 *
12440		 *  @example
12441		 *    // Using `columns`
12442		 *    $(document).ready( function() {
12443		 *      $('#example').dataTable( {
12444		 *        "columns": [
12445		 *          { "visible": false },
12446		 *          null,
12447		 *          null,
12448		 *          null,
12449		 *          null
12450		 *        ] } );
12451		 *    } );
12452		 */
12453		"bVisible": true,
12454	
12455	
12456		/**
12457		 * Developer definable function that is called whenever a cell is created (Ajax source,
12458		 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
12459		 * allowing you to modify the DOM element (add background colour for example) when the
12460		 * element is available.
12461		 *  @type function
12462		 *  @param {element} td The TD node that has been created
12463		 *  @param {*} cellData The Data for the cell
12464		 *  @param {array|object} rowData The data for the whole row
12465		 *  @param {int} row The row index for the aoData data store
12466		 *  @param {int} col The column index for aoColumns
12467		 *
12468		 *  @name DataTable.defaults.column.createdCell
12469		 *  @dtopt Columns
12470		 *
12471		 *  @example
12472		 *    $(document).ready( function() {
12473		 *      $('#example').dataTable( {
12474		 *        "columnDefs": [ {
12475		 *          "targets": [3],
12476		 *          "createdCell": function (td, cellData, rowData, row, c
12476ol) {
12477		 *            if ( cellData == "1.7" ) {
12478		 *              $(td).css('color', 'blue')
12479		 *            }
12480		 *          }
12481		 *        } ]
12482		 *      });
12483		 *    } );
12484		 */
12485		"fnCreatedCell": null,
12486	
12487	
12488		/**
12489		 * This parameter has been replaced by `data` in DataTables to ensure naming
12490		 * consistency. `dataProp` can still be used, as there is backwards
12491		 * compatibility in DataTables for this option, but it is strongly
12492		 * recommended that you use `data` in preference to `dataProp`.
12493		 *  @name DataTable.defaults.column.dataProp
12494		 */
12495	
12496	
12497		/**
12498		 * This property can be used to read data from any data source property,
12499		 * including deeply nested objects / properties. `data` can be given in a
12500		 * number of different ways which effect its behaviour:
12501		 *
12502		 * * `integer` - treated as an array index for the data source. This is the
12503		 *   default that DataTables uses (incrementally increased for each column).
12504		 * * `string` - read an object property from the data source. There are
12505		 *   three 'special' options that can be used in the string to alter how
12506		 *   DataTables reads the data from the source object:
12507		 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
12508		 *      Javascript to read from nested objects, so to can the options
12509		 *      specified in `data`. For example: `browser.version` or
12510		 *      `browser.name`. If your object parameter name contains a period, use
12511		 *      `\\` to escape it - i.e. `first\\.name`.
12512		 *    * `[]` - Array notation. DataTables can automatically combine data
12513		 *      from and array source, joining the data with the characters provided
12514		 *      between the two brackets. For example: `name[, ]` would provide a
12515		 *      comma-space separated list from the source array. If no characters
12516		 *      are provided between the brackets, the original array source is
12517		 *      returned.
12518		 *    * `()` - Function notation. Adding `()` to the end of a parameter will
12519		 *      execute a function of the name given. For example: `browser()` for a
12520		 *      simple function on the data source, `browser.version()` for a
12521		 *      function in a nested property or even `browser().version` to get an
12522		 *      object property if the function called returns an object. Note that
12523		 *      function notation is recommended for use in `render` rather than
12524		 *      `data` as it is much simpler to use as a renderer.
12525		 * * `null` - use the original data source for the row rather than plucking
12526		 *   data directly from it. This action has effects on two other
12527		 *   initialisation options:
12528		 *    * `defaultContent` - When null is given as the `data` option and
12529		 *      `defaultContent` is specified for the column, the value defined by
12530		 *      `defaultContent` will be used for the cell.
12531		 *    * `render` - When null is used for the `data` option and the `render`
12532		 *      option is specified for the column, the whole data source for the
12533		 *      row is used for the renderer.
12534		 * * `function` - the function given will be executed whenever DataTables
12535		 *   needs to set or get the data for a cell in the column. The function
12536		 *   takes three parameters:
12537		 *    * Parameters:
12538		 *      * `{array|object}` The data source for the row
12539		 *      * `{string}` The type call data requested - this will be 'set' when
12540		 *        setting data or 'filter', 'display', 'type', 'sort' or undefined
12541		 *        when gathering data. Note that when `undefined` is given for the
12542		 *        type DataTables expects to get the raw data for the object back<
12543		 *      * `{*}` Data to set when the second parameter is 'set'.
12544		 *    * Return:
12545		 *      * The return value from the function is not required when 'set' is
12546		 *        the type of call, but otherwise the return is what will be used
12547		 *        for the data requested.
12548		 *
12549		 * Note that `data` is a getter and setter option. If you just require
12550		 * formatting of data for output, you will likely want to use `render` which
12551		 * is simply a getter and thus simpler to use.
12552		 *
12553		 * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The
12554		 * name change reflects the flexibility of this property and is consistent
12555		 * with the naming of mRender. If 'mDataProp' is given, then it will still
12556		 * be used by DataTables, as it automatically maps the old name to the new
12557		 * if required.
12558		 *
12559		 *  @type string|int|function|null
12560		 *  @default null <i>Use automatically calculated column index</i>
12561		 *
12562		 *  @name DataTable.defaults.column.data
12563		 *  @dtopt Columns
12564		 *
12565		 *  @example
12566		 *    // Read table data from objects
12567		 *    // JSON structure for each row:
12568		 *    //   {
12569		 *    //      "engine": {value},
12570		 *    //      "browser": {value},
12571		 *    //      "platform": {value},
12572		 *    //      "version": {value},
12573		 *    //      "grade": {value}
12574		 *    //   }
12575		 *    $(document).ready( function() {
12576		 *      $('#example').dataTable( {
12577		 *        "ajaxSource": "sources/objects.txt",
12578		 *        "columns": [
12579		 *          { "data": "engine" },
12580		 *          { "data": "browser" },
12581		 *          { "data": "platform" },
12582		 *          { "data": "version" },
12583		 *          { "data": "grade" }
12584		 *        ]
12585		 *      } );
12586		 *    } );
12587		 *
12588		 *  @example
12589		 *    // Read information from deeply nested objects
12590		 *    // JSON structure for each row:
12591		 *    //   {
12592		 *    //      "engine": {value},
12593		 *    //      "browser": {value},
12594		 *    //      "platform": {
12595		 *    //         "inner": {value}
12596		 *    //      },
12597		 *    //      "details": [
12598		 *    //         {value}, {value}
12599		 *    //      ]
12600		 *    //   }
12601		 *    $(document).ready( function() {
12602		 *      $('#example').dataTable( {
12603		 *        "ajaxSource": "sources/deep.txt",
12604		 *        "columns": [
12605		 *          { "data": "engine" },
12606		 *          { "data": "browser" },
12607		 *          { "data": "platform.inner" },
12608		 *          { "data": "details.0" },
12609		 *          { "data": "details.1" }
12610		 *        ]
12611		 *      } );
12612		 *    } );
12613		 *
12614		 *  @example
12615		 *    // Using `data` as a function to provide different information for
12616		 *    // sorting, filtering and display. In this case, currency (price)
12617		 *    $(document).ready( function() {
12618		 *      $('#example').dataTable( {
12619		 *        "columnDefs": [ {
12620		 *          "targets": [ 0 ],
12621		 *          "data": function ( source, type, val ) {
12622		 *            if (type === 'set') {
12623		 *              source.price = val;
12624		 *              // Store the computed display and filter values for efficiency
12625		 *              source.price_display = val=="" ? "" : "$"+numberFormat(val);
12626		 *              source.price_filter  = val=="" ? "" : "$"+numberFormat(val)+" "+val;
12627		 *              return;
12628		 *            }
12629		 *            else if (type === 'display') {
12630		 *              return source.price_display;
12631		 *            }
12632		 *            else if (type === 'filter') {
12633		 *              return source.price_filter;
12634		 *            }
12635		 *            // 'sort', 'type' and undefined all just use the integer
12636		 *            return source.price;
12637		 *          }
12638		 *        } ]
12639		 *      } );
12640		 *    } );
12641		 *
12642		 *  @example
12643		 *    // Using default content
12644		 *    $(document).ready( function() {
12645		 *      $('#example').dataTable( {
12646		 *        "columnDefs": [ {
12647		 *          "targets": [ 0 ],
12648		 *          "data": null,
12649		 *          "defaultContent": "Click to edit"
12650		 *        } ]
12651		 *      } );
12652		 *    } );
12653		 *
12654		 *  @example
12655		 *    // Using array notation - outputting a list from an array
12656		 *    $(document).ready( function() {
12657		 *      $('#example').dataTable( {
12658		 *        "columnDefs": [ {
12659		 *          "targets": [ 0 ],
12660		 *          "data": "name[, ]"
12661		 *        } ]
12662		 *      } );
12663		 *    } );
12664		 *
12665		 */
12666		"mData": null,
12667	
12668	
12669		/**
12670		 * This property is the rendering partner to `data` and it is suggested that
12671		 * when you want to manipulate data for display (including filtering,
12672		 * sorting etc) without altering the underlying data for the table, use this
12673		 * property. `render` can be considered to be the the read only companion to
12674		 * `data` which is read / write (then as such more complex). Like `data`
12675		 * this option can be given in a number of different ways to effect its
12676		 * behaviour:
12677		 *
12678		 * * `integer` - treated as an array index for the data source. This is the
12679		 *   default that DataTables uses (incrementally increased for each column).
12680		 * * `string` - read an object property from the data source. There are
12681		 *   three 'special' options that can be used in the string to alter how
12682		 *   DataTables reads the data from the source object:
12683		 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
12684		 *      Javascript to read from nested objects, so to can the options
12685		 *      specified in `data`. For example: `browser.version` or
12686		 *      `browser.name`. If your object parameter name contains a period, use
12687		 *      `\\` to escape it - i.e. `first\\.name`.
12688		 *    * `[]` - Array notation. DataTables can automatically combine data
12689		 *      from and array source, joining the data with the characters provided
12690		 *      between the two brackets. For example: `name[, ]` would provide a
12691		 *      comma-space separated list from the source array. If no characters
12692		 *      are provided between the brackets, the original array source is
12693		 *      returned.
12694		 *    * `()` - Function notation. Adding `()` to the end of a parameter will
12695		 *      execute a function of the name given. For example: `browser()` for a
12696		 *      simple function on the data source, `browser.version()` for a
12697		 *      function in a nested property or even `browser().version` to get an
12698		 *      object property if the function called returns an object.
12699		 * * `object` - use different data for the different data types requested by
12700		 *   DataTables ('filter', 'display', 'type' or 'sort'). The property names
12701		 *   of the object is the data type the property refers to and the value can
12702		 *   defined using an integer, string or function using the same rules as
12703		 *   `render` normally does. Note that an `_` option _must_ be specified.
12704		 *   This is the default value to use if you haven't specified a value for
12705		 *   the data type requested by DataTables.
12706		 * * `function` - the function given will be executed whenever DataTables
12707		 *   needs to set or get the data for a cell in the column. The function
12708		 *   takes three parameters:
12709		 *    * Parameters:
12710		 *      * {array|object} The data source for the row (based on `data`)
12711		 *      * {string} The type call data requested - this will be 'filter',
12712		 *        'display', 'type' or 'sort'.
12713		 *      * {array|object} The full data source for the row (not based on
12714		 *        `data`)
12715		 *    * Return:
12716		 *      * The return value from the function is what will be used for the
12717		 *        data requested.
12718		 *
12719		 *  @type string|int|function|object|null
12720		 *  @default null Use the data source value.
12721		 *
12722		 *  @name DataTable.defaults.column.render
12723		 *  @dtopt Columns
12724		 *
12725		 *  @example
12726		 *    // Create a comma separated list from an array of objects
12727		 *    $(document).ready( function() {
12728		 *      $('#example').dataTable( {
12729		 *        "ajaxSource": "sources/deep.txt",
12730		 *        "columns": [
12731		 *          { "data": "engine" },
12732		 *          { "data": "browser" },
12733		 *          {
12734		 *            "data": "platform",
12735		 *            "render": "[, ].name"
12736		 *          }
12737		 *        ]
12738		 *      } );
12739		 *    } );
12740		 *
12741		 *  @example
12742		 *    // Execute a function to obtain data
12743		 *    $(document).ready( function() {
12744		 *      $('#example').dataTable( {
12745		 *        "columnDefs": [ {
12746		 *          "targets": [ 0 ],
12747		 *          "data": null, // Use the full data source object for the renderer's source
12748		 *          "render": "browserName()"
12749		 *        } ]
12750		 *      } );
12751		 *    } );
12752		 *
12753		 *  @example
12754		 *    // As an object, extracting different data for the different types
12755		 *    // This would be used with a data source such as:
12756		 *    //   { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" }
12757		 *    // Here the `phone` integer is used for sorting and type detection, while `phone_filter`
12758		 *    // (which has both forms) is used for filtering for if a user inputs either format, while
12759		 *    // the formatted phone number is the one that is shown in the table.
12760		 *    $(document).ready( function() {
12761		 *      $('#example').dataTable( {
12762		 *        "columnDefs": [ {
12763		 *          "targets": [ 0 ],
12764		 *          "data": null, // Use the full data source object for the renderer's source
12765		 *          "render": {
12766		 *            "_": "phone",
12767		 *            "filter": "phone_filter",
12768		 *            "display": "phone_display"
12769		 *          }
12770		 *        } ]
12771		 *      } );
12772		 *    } );
12773		 *
12774		 *  @example
12775		 *    // Use as a function to create a link from the data source
12776		 *    $(document).ready( function() {
12777		 *      $('#example').dataTable( {
12778		 *        "columnDefs": [ {
12779		 *          "targets": [ 0 ],
12780		 *          "data": "download_link",
12781		 *          "render": function ( data, type, full ) {
12782		 *            return '<a href="'+data+'">Download</a>';
12783		 *          }
12784		 *        } ]
12785		 *      } );
12786		 *    } );
12787		 */
12788		"mRender": null,
12789	
12790	
12791		/**
12792		 * Change the cell type created for the column - either TD cells or TH cells. This
12793		 * can be useful as TH cells have semantic meaning in the table body, allowing them
12794		 * to act as a header for a row (you may wish to add scope='row' to the TH elements).
12795		 *  @type string
12796		 *  @default td
12797		 *
12798		 *  @name DataTable.defaults.column.cellType
12799		 *  @dtopt Columns
12800		 *
12801		 *  @example
12802		 *    // Make the first column use TH cells
12803		 *    $(document).ready( function() {
12804		 *      $('#example').dataTable( {
12805		 *        "columnDefs": [ {
12806		 *          "targets": [ 0 ],
12807		 *          "cellType": "th"
12808		 *        } ]
12809		 *      } );
12810		 *    } );
12811		 */
12812		"sCellType": "td",
12813	
12814	
12815		/**
12816		 * Class to give to each cell in this column.
12817		 *  @type string
12818		 *  @default <i>Empty string</i>
12819		 *
12820		 *  @name DataTable.defaults.column.class
12821		 *  @dtopt Columns
12822		 *
12823		 *  @example
12824		 *    // Using `columnDefs`
12825		 *    $(document).ready( function() {
12826		 *      $('#example').dataTable( {
12827		 *        "columnDefs": [
12828		 *          { "class": "my_class", "targets": [ 0 ] }
12829		 *        ]
12830		 *      } );
12831		 *    } );
12832		 *
12833		 *  @example
12834		 *    // Using `columns`
12835		 *    $(document).ready( function() {
12836		 *      $('#example').dataTable( {
12837		 *        "columns": [
12838		 *          { "class": "my_class" },
12839		 *          null,
12840		 *          null,
12841		 *          null,
12842		 *          null
12843		 *        ]
12844		 *      } );
12845		 *    } );
12846		 */
12847		"sClass": "",
12848	
12849		/**
12850		 * When DataTables calculates the column widths to assign to each column,
12851		 * it finds the longest string in each column and then constructs a
12852		 * temporary table and reads the widths from that. The problem with this
12853		 * is that "mmm" is much wider then "iiii", but the latter is a longer
12854		 * string - thus the calculation can go wrong (doing it properly and putting
12855		 * it into an DOM object and measuring that is horribly(!) slow). Thus as
12856		 * a "work around" we provide this option. It will append its value to the
12857		 * text that is found to be the longest string for the column - i.e. padding.
12858		 * Generally you shouldn't need this!
12859		 *  @type string
12860		 *  @default <i>Empty string<i>
12861		 *
12862		 *  @name DataTable.defaults.column.contentPadding
12863		 *  @dtopt Columns
12864		 *
12865		 *  @example
12866		 *    // Using `columns`
12867		 *    $(document).ready( function() {
12868		 *      $('#example').dataTable( {
12869		 *        "columns": [
12870		 *          null,
12871		 *          null,
12872		 *          null,
12873		 *          {
12874		 *            "contentPadding": "mmm"
12875		 *          }
12876		 *        ]
12877		 *      } );
12878		 *    } );
12879		 */
12880		"sContentPadding": "",
12881	
12882	
12883		/**
12884		 * Allows a default value to be given for a column's data, and will be used
12885		 * whenever a null data source is encountered (this can be because `data`
12886		 * is set to null, or because the data source itself is null).
12887		 *  @type string
12888		 *  @default null
12889		 *
12890		 *  @name DataTable.defaults.column.defaultContent
12891		 *  @dtopt Columns
12892		 *
12893		 *  @example
12894		 *    // Using `columnDefs`
12895		 *    $(document).ready( function() {
12896		 *      $('#example').dataTable( {
12897		 *        "columnDefs": [
12898		 *          {
12899		 *            "data": null,
12900		 *            "defaultContent": "Edit",
12901		 *            "targets": [ -1 ]
12902		 *          }
12903		 *        ]
12904		 *      } );
12905		 *    } );
12906		 *
12907		 *  @example
12908		 *    // Using `columns`
12909		 *    $(document).ready( function() {
12910		 *      $('#example').dataTable( {
12911		 *        "columns": [
12912		 *          null,
12913		 *          null,
12914		 *          null,
12915		 *          {
12916		 *            "data": null,
12917		 *            "defaultContent": "Edit"
12918		 *          }
12919		 *        ]
12920		 *      } );
12921		 *    } );
12922		 */
12923		"sDefaultContent": null,
12924	
12925	
12926		/**
12927		 * This parameter is only used in DataTables' server-side processing. It can
12928		 * be exceptionally useful to know what columns are being displayed on the
12929		 * client side, and to map these to database fields. When defined, the names
12930		 * also allow DataTables to reorder information from the server if it comes
12931		 * back in an unexpected order (i.e. if you switch your columns around on the
12932		 * client-side, your server-side code does not also need updating).
12933		 *  @type string
12934		 *  @default <i>Empty string</i>
12935		 *
12936		 *  @name DataTable.defaults.column.name
12937		 *  @dtopt Columns
12938		 *
12939		 *  @example
12940		 *    // Using `columnDefs`
12941		 *    $(document).ready( function() {
12942		 *      $('#example').dataTable( {
12943		 *        "columnDefs": [
12944		 *          { "name": "engine", "targets": [ 0 ] },
12945		 *          { "name": "browser", "targets": [ 1 ] },
12946		 *          { "name": "platform", "targets": [ 2 ] },
12947		 *          { "name": "version", "targets": [ 3 ] },
12948		 *          { "name": "grade", "targets": [ 4 ] }
12949		 *        ]
12950		 *      } );
12951		 *    } );
12952		 *
12953		 *  @example
12954		 *    // Using `columns`
12955		 *    $(document).ready( function() {
12956		 *      $('#example').dataTable( {
12957		 *        "columns": [
12958		 *          { "name": "engine" },
12959		 *          { "name": "browser" },
12960		 *          { "name": "platform" },
12961		 *          { "name": "version" },
12962		 *          { "name": "grade" }
12963		 *        ]
12964		 *      } );
12965		 *    } );
12966		 */
12967		"sName": "",
12968	
12969	
12970		/**
12971		 * Defines a data source type for the ordering which can be used to read
12972		 * real-time information from the table (updating the internally cached
12973		 * version) prior to ordering. This allows ordering to occur on user
12974		 * editable elements such as form inputs.
12975		 *  @type string
12976		 *  @default std
12977		 *
12978		 *  @name DataTable.defaults.column.orderDataType
12979		 *  @dtopt Columns
12980		 *
12981		 *  @example
12982		 *    // Using `columnDefs`
12983		 *    $(document).ready( function() {
12984		 *      $('#example').dataTable( {
12985		 *        "columnDefs": [
12986		 *          { "orderDataType": "dom-text", "targets": [ 2, 3 ] },
12987		 *          { "type": "numeric", "targets": [ 3 ] },
12988		 *          { "orderDataType": "dom-select", "targets": [ 4 ] },
12989		 *          { "orderDataType": "dom-checkbox", "targets": [ 5 ] }
12990		 *        ]
12991		 *      } );
12992		 *    } );
12993		 *
12994		 *  @example
12995		 *    // Using `columns`
12996		 *    $(document).ready( function() {
12997		 *      $('#example').dataTable( {
12998		 *        "columns": [
12999		 *          null,
13000		 *          null,
13001		 *          { "orderDataType": "dom-text" },
13002		 *          { "orderDataType": "dom-text", "type": "numeric" },
13003		 *          { "orderDataType": "dom-select" },
13004		 *          { "orderDataType": "dom-checkbox" }
13005		 *        ]
13006		 *      } );
13007		 *    } );
13008		 */
13009		"sSortDataType": "std",
13010	
13011	
13012		/**
13013		 * The title of this column.
13014		 *  @type string
13015		 *  @default null <i>Derived from the 'TH' value for this column in the
13016		 *    original HTML table.</i>
13017		 *
13018		 *  @name DataTable.defaults.column.title
13019		 *  @dtopt Columns
13020		 *
13021		 *  @example
13022		 *    // Using `columnDefs`
13023		 *    $(document).ready( function() {
13024		 *      $('#example').dataTable( {
13025		 *        "columnDefs": [
13026		 *          { "title": "My column title", "targets": [ 0 ] }
13027		 *        ]
13028		 *      } );
13029		 *    } );
13030		 *
13031		 *  @example
13032		 *    // Using `columns`
13033		 *    $(document).ready( function() {
13034		 *      $('#example').dataTable( {
13035		 *        "columns": [
13036		 *          { "title": "My column title" },
13037		 *          null,
13038		 *          null,
13039		 *          null,
13040		 *          null
13041		 *        ]
13042		 *      } );
13043		 *    } );
13044		 */
13045		"sTitle": null,
13046	
13047	
13048		/**
13049		 * The type allows you to specify how the data for this column will be
13050		 * ordered. Four types (string, numeric, date and html (which will strip
13051		 * HTML tags before ordering)) are currently available. Note that only date
13052		 * formats understood by Javascript's Date() object will be accepted as type
13053		 * date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string',
13054		 * 'numeric', 'date' or 'html' (by default). Further types can be adding
13055		 * through plug-ins.
13056		 *  @type string
13057		 *  @default null <i>Auto-detected from raw data</i>
13058		 *
13059		 *  @name DataTable.defaults.column.type
13060		 *  @dtopt Columns
13061		 *
13062		 *  @example
13063		 *    // Using `columnDefs`
13064		 *    $(document).ready( function() {
13065		 *      $('#example').dataTable( {
13066		 *        "columnDefs": [
13067		 *          { "type": "html", "targets": [ 0 ] }
13068		 *        ]
13069		 *      } );
13070		 *    } );
13071		 *
13072		 *  @example
13073		 *    // Using `columns`
13074		 *    $(document).ready( function() {
13075		 *      $('#example').dataTable( {
13076		 *        "columns": [
13077		 *          { "type": "html" },
13078		 *          null,
13079		 *          null,
13080		 *          null,
13081		 *          null
13082		 *        ]
13083		 *      } );
13084		 *    } );
13085		 */
13086		"sType": null,
13087	
13088	
13089		/**
13090		 * Defining the width of the column, this parameter may take any CSS value
13091		 * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not
13092		 * been given a specific width through this interface ensuring that the table
13093		 * remains readable.
13094		 *  @type string
13095		 *  @default null <i>Automatic</i>
13096		 *
13097		 *  @name DataTable.defaults.column.width
13098		 *  @dtopt Columns
13099		 *
13100		 *  @example
13101		 *    // Using `columnDefs`
13102		 *    $(document).ready( function() {
13103		 *      $('#example').dataTable( {
13104		 *        "columnDefs": [
13105		 *          { "width": "20%", "targets": [ 0 ] }
13106		 *        ]
13107		 *      } );
13108		 *    } );
13109		 *
13110		 *  @example
13111		 *    // Using `columns`
13112		 *    $(document).ready( function() {
13113		 *      $('#example').dataTable( {
13114		 *        "columns": [
13115		 *          { "width": "20%" },
13116		 *          null,
13117		 *          null,
13118		 *          null,
13119		 *          null
13120		 *        ]
13121		 *      } );
13122		 *    } );
13123		 */
13124		"sWidth": null
13125	};
13126	
13127	_fnHungarianMap( DataTable.defaults.column );
13128	
13129	
13130	
13131	/**
13132	 * DataTables settings object - this holds all the information needed for a
13133	 * given table, including configuration, data and current application of the
13134	 * table options. DataTables does not have a single instance for each DataTable
13135	 * with the settings attached to that instance, but rather instances of the
13136	 * DataTable "class" are created on-the-fly as needed (typically by a
13137	 * $().dataTable() call) and the settings object is then applied to that
13138	 * instance.
13139	 *
13140	 * Note that this object is related to {@link DataTable.defaults} but this
13141	 * one is the internal data store for DataTables's cache of columns. It should
13142	 * NOT be manipulated outside of DataTables. Any configuration should be done
13143	 * through the initialisation options.
13144	 *  @namespace
13145	 *  @todo Really should attach the settings object to individual instances so we
13146	 *    don't need to create new instances on each $().dataTable() call (if the
13147	 *    table already exists). It would also save passing oSettings around and
13148	 *    into every single function. However, this is a very significant
13149	 *    architecture change for DataTables and will almost certainly break
13150	 *    backwards compatibility with older installations. This is something that
13151	 *    will be done in 2.0.
13152	 */
13153	DataTable.models.oSettings = {
13154		/**
13155		 * Primary features of DataTables and their enablement state.
13156		 *  @namespace
13157		 */
13158		"oFeatures": {
13159	
13160			/**
13161			 * Flag to say if DataTables should automatically try to calculate the
13162			 * optimum table and columns widths (true) or not (false).
13163			 * Note that this parameter will be set by the initialisation routine. To
13164			 * set a default use {@link DataTable.defaults}.
13165			 *  @type boolean
13166			 */
13167			"bAutoWidth": null,
13168	
13169			/**
13170			 * Delay the creation of TR and TD elements until they are actually
13171			 * needed by a driven page draw. This can give a significant speed
13172			 * increase for Ajax source and Javascript source data, but makes no
13173			 * difference at all for DOM and server-side processing tables.
13174			 * Note that this parameter will be set by the initialisation routine. To
13175			 * set a default use {@link DataTable.defaults}.
13176			 *  @type boolean
13177			 */
13178			"bDeferRender": null,
13179	
13180			/**
13181			 * Enable filtering on the table or not. Note that if this is disabled
13182			 * then there is no filtering at all on the table, including fnFilter.
13183			 * To just remove the filtering input use sDom and remove the 'f' option.
13184			 * Note that this parameter will be set by the initialisation routine. To
13185			 * set a default use {@link DataTable.defaults}.
13186			 *  @type boolean
13187			 */
13188			"bFilter": null,
13189	
13190			/**
13191			 * Table information element (the 'Showing x of y records' div) enable
13192			 * flag.
13193			 * Note that this parameter will be set by the initialisation routine. To
13194			 * set a default use {@link DataTable.defaults}.
13195			 *  @type boolean
13196			 */
13197			"bInfo": null,
13198	
13199			/**
13200			 * Present a user control allowing the end user to change the page size
13201			 * when pagination is enabled.
13202			 * Note that this parameter will be set by the initialisation routine. To
13203			 * set a default use {@link DataTable.defaults}.
13204			 *  @type boolean
13205			 */
13206			"bLengthChange": null,
13207	
13208			/**
13209			 * Pagination enabled or not. Note that if this is disabled then length
13210			 * changing must also be disabled.
13211			 * Note that this parameter will be set by the initialisation routine. To
13212			 * set a default use {@link DataTable.defaults}.
13213			 *  @type boolean
13214			 */
13215			"bPaginate": null,
13216	
13217			/**
13218			 * Processing indicator enable flag whenever DataTables is enacting a
13219			 * user request - typically an Ajax request for server-side processing.
13220			 * Note that this parameter will be set by the initialisation routine. To
13221			 * set a default use {@link DataTable.defaults}.
13222			 *  @type boolean
13223			 */
13224			"bProcessing": null,
13225	
13226			/**
13227			 * Server-side processing enabled flag - when enabled DataTables will
13228			 * get all data from the server for every draw - there is no filtering,
13229			 * sorting or paging done on the client-side.
13230			 * Note that this parameter will be set by the initialisation routine. To
13231			 * set a default use {@link DataTable.defaults}.
13232			 *  @type boolean
13233			 */
13234			"bServerSide": null,
13235	
13236			/**
13237			 * Sorting enablement flag.
13238			 * Note that this parameter will be set by the initialisation routine. To
13239			 * set a default use {@link DataTable.defaults}.
13240			 *  @type boolean
13241			 */
13242			"bSort": null,
13243	
13244			/**
vendor: 10,013 bytes, lines 13245-13653
13245			 * Multi-column sorting
13246			 * Note that this parameter will be set by the initialisation routine. To
13247			 * set a default use {@link DataTable.defaults}.
13248			 *  @type boolean
13249			 */
13250			"bSortMulti": null,
13251	
13252			/**
13253			 * Apply a class to the columns which are being sorted to provide a
13254			 * visual highlight or not. This can slow things down when enabled since
13255			 * there is a lot of DOM interaction.
13256			 * Note that this parameter will be set by the initialisation routine. To
13257			 * set a default use {@link DataTable.defaults}.
13258			 *  @type boolean
13259			 */
13260			"bSortClasses": null,
13261	
13262			/**
13263			 * State saving enablement flag.
13264			 * Note that this parameter will be set by the initialisation routine. To
13265			 * set a default use {@link DataTable.defaults}.
13266			 *  @type boolean
13267			 */
13268			"bStateSave": null
13269		},
13270	
13271	
13272		/**
13273		 * Scrolling settings for a table.
13274		 *  @namespace
13275		 */
13276		"oScroll": {
13277			/**
13278			 * When the table is shorter in height than sScrollY, collapse the
13279			 * table container down to the height of the table (when true).
13280			 * Note that this parameter will be set by the initialisation routine. To
13281			 * set a default use {@link DataTable.defaults}.
13282			 *  @type boolean
13283			 */
13284			"bCollapse": null,
13285	
13286			/**
13287			 * Width of the scrollbar for the web-browser's platform. Calculated
13288			 * during table initialisation.
13289			 *  @type int
13290			 *  @default 0
13291			 */
13292			"iBarWidth": 0,
13293	
13294			/**
13295			 * Viewport width for horizontal scrolling. Horizontal scrolling is
13296			 * disabled if an empty string.
13297			 * Note that this parameter will be set by the initialisation routine. To
13298			 * set a default use {@link DataTable.defaults}.
13299			 *  @type string
13300			 */
13301			"sX": null,
13302	
13303			/**
13304			 * Width to expand the table to when using x-scrolling. Typically you
13305			 * should not need to use this.
13306			 * Note that this parameter will be set by the initialisation routine. To
13307			 * set a default use {@link DataTable.defaults}.
13308			 *  @type string
13309			 *  @deprecated
13310			 */
13311			"sXInner": null,
13312	
13313			/**
13314			 * Viewport height for vertical scrolling. Vertical scrolling is disabled
13315			 * if an empty string.
13316			 * Note that this parameter will be set by the initialisation routine. To
13317			 * set a default use {@link DataTable.defaults}.
13318			 *  @type string
13319			 */
13320			"sY": null
13321		},
13322	
13323		/**
13324		 * Language information for the table.
13325		 *  @namespace
13326		 *  @extends DataTable.defaults.oLanguage
13327		 */
13328		"oLanguage": {
13329			/**
13330			 * Information callback function. See
13331			 * {@link DataTable.defaults.fnInfoCallback}
13332			 *  @type function
13333			 *  @default null
13334			 */
13335			"fnInfoCallback": null
13336		},
13337	
13338		/**
13339		 * Browser support parameters
13340		 *  @namespace
13341		 */
13342		"oBrowser": {
13343			/**
13344			 * Indicate if the browser incorrectly calculates width:100% inside a
13345			 * scrolling element (IE6/7)
13346			 *  @type boolean
13347			 *  @default false
13348			 */
13349			"bScrollOversize": false,
13350	
13351			/**
13352			 * Determine if the vertical scrollbar is on the right or left of the
13353			 * scrolling container - needed for rtl language layout, although not
13354			 * all browsers move the scrollbar (Safari).
13355			 *  @type boolean
13356			 *  @default false
13357			 */
13358			"bScrollbarLeft": false,
13359	
13360			/**
13361			 * Flag for if `getBoundingClientRect` is fully supported or not
13362			 *  @type boolean
13363			 *  @default false
13364			 */
13365			"bBounding": false,
13366	
13367			/**
13368			 * Browser scrollbar width
13369			 *  @type integer
13370			 *  @default 0
13371			 */
13372			"barWidth": 0
13373		},
13374	
13375	
13376		"ajax": null,
13377	
13378	
13379		/**
13380		 * Array referencing the nodes which are used for the features. The
13381		 * parameters of this object match what is allowed by sDom - i.e.
13382		 *   <ul>
13383		 *     <li>'l' - Length changing</li>
13384		 *     <li>'f' - Filtering input</li>
13385		 *     <li>'t' - The table!</li>
13386		 *     <li>'i' - Information</li>
13387		 *     <li>'p' - Pagination</li>
13388		 *     <li>'r' - pRocessing</li>
13389		 *   </ul>
13390		 *  @type array
13391		 *  @default []
13392		 */
13393		"aanFeatures": [],
13394	
13395		/**
13396		 * Store data information - see {@link DataTable.models.oRow} for detailed
13397		 * information.
13398		 *  @type array
13399		 *  @default []
13400		 */
13401		"aoData": [],
13402	
13403		/**
13404		 * Array of indexes which are in the current display (after filtering etc)
13405		 *  @type array
13406		 *  @default []
13407		 */
13408		"aiDisplay": [],
13409	
13410		/**
13411		 * Array of indexes for display - no filtering
13412		 *  @type array
13413		 *  @default []
13414		 */
13415		"aiDisplayMaster": [],
13416	
13417		/**
13418		 * Map of row ids to data indexes
13419		 *  @type object
13420		 *  @default {}
13421		 */
13422		"aIds": {},
13423	
13424		/**
13425		 * Store information about each column that is in use
13426		 *  @type array
13427		 *  @default []
13428		 */
13429		"aoColumns": [],
13430	
13431		/**
13432		 * Store information about the table's header
13433		 *  @type array
13434		 *  @default []
13435		 */
13436		"aoHeader": [],
13437	
13438		/**
13439		 * Store information about the table's footer
13440		 *  @type array
13441		 *  @default []
13442		 */
13443		"aoFooter": [],
13444	
13445		/**
13446		 * Store the applied global search information in case we want to force a
13447		 * research or compare the old search to a new one.
13448		 * Note that this parameter will be set by the initialisation routine. To
13449		 * set a default use {@link DataTable.defaults}.
13450		 *  @namespace
13451		 *  @extends DataTable.models.oSearch
13452		 */
13453		"oPreviousSearch": {},
13454	
13455		/**
13456		 * Store the applied search for each column - see
13457		 * {@link DataTable.models.oSearch} for the format that is used for the
13458		 * filtering information for each column.
13459		 *  @type array
13460		 *  @default []
13461		 */
13462		"aoPreSearchCols": [],
13463	
13464		/**
13465		 * Sorting that is applied to the table. Note that the inner arrays are
13466		 * used in the following manner:
13467		 * <ul>
13468		 *   <li>Index 0 - column number</li>
13469		 *   <li>Index 1 - current sorting direction</li>
13470		 * </ul>
13471		 * Note that this parameter will be set by the initialisation routine. To
13472		 * set a default use {@link DataTable.defaults}.
13473		 *  @type array
13474		 *  @todo These inner arrays should really be objects
13475		 */
13476		"aaSorting": null,
13477	
13478		/**
13479		 * Sorting that is always applied to the table (i.e. prefixed in front of
13480		 * aaSorting).
13481		 * Note that this parameter will be set by the initialisation routine. To
13482		 * set a default use {@link DataTable.defaults}.
13483		 *  @type array
13484		 *  @default []
13485		 */
13486		"aaSortingFixed": [],
13487	
13488		/**
13489		 * Classes to use for the striping of a table.
13490		 * Note that this parameter will be set by the initialisation routine. To
13491		 * set a default use {@link DataTable.defaults}.
13492		 *  @type array
13493		 *  @default []
13494		 */
13495		"asStripeClasses": null,
13496	
13497		/**
13498		 * If restoring a table - we should restore its striping classes as well
13499		 *  @type array
13500		 *  @default []
13501		 */
13502		"asDestroyStripes": [],
13503	
13504		/**
13505		 * If restoring a table - we should restore its width
13506		 *  @type int
13507		 *  @default 0
13508		 */
13509		"sDestroyWidth": 0,
13510	
13511		/**
13512		 * Callback functions array for every time a row is inserted (i.e. on a draw).
13513		 *  @type array
13514		 *  @default []
13515		 */
13516		"aoRowCallback": [],
13517	
13518		/**
13519		 * Callback functions for the header on each draw.
13520		 *  @type array
13521		 *  @default []
13522		 */
13523		"aoHeaderCallback": [],
13524	
13525		/**
13526		 * Callback function for the footer on each draw.
13527		 *  @type array
13528		 *  @default []
13529		 */
13530		"aoFooterCallback": [],
13531	
13532		/**
13533		 * Array of callback functions for draw callback functions
13534		 *  @type array
13535		 *  @default []
13536		 */
13537		"aoDrawCallback": [],
13538	
13539		/**
13540		 * Array of callback functions for row created function
13541		 *  @type array
13542		 *  @default []
13543		 */
13544		"aoRowCreatedCallback": [],
13545	
13546		/**
13547		 * Callback functions for just before the table is redrawn. A return of
13548		 * false will be used to cancel the draw.
13549		 *  @type array
13550		 *  @default []
13551		 */
13552		"aoPreDrawCallback": [],
13553	
13554		/**
13555		 * Callback functions for when the table has been initialised.
13556		 *  @type array
13557		 *  @default []
13558		 */
13559		"aoInitComplete": [],
13560	
13561	
13562		/**
13563		 * Callbacks for modifying the settings to be stored for state saving, prior to
13564		 * saving state.
13565		 *  @type array
13566		 *  @default []
13567		 */
13568		"aoStateSaveParams": [],
13569	
13570		/**
13571		 * Callbacks for modifying the settings that have been stored for state saving
13572		 * prior to using the stored values to restore the state.
13573		 *  @type array
13574		 *  @default []
13575		 */
13576		"aoStateLoadParams": [],
13577	
13578		/**
13579		 * Callbacks for operating on the settings object once the saved state has been
13580		 * loaded
13581		 *  @type array
13582		 *  @default []
13583		 */
13584		"aoStateLoaded": [],
13585	
13586		/**
13587		 * Cache the table ID for quick access
13588		 *  @type string
13589		 *  @default <i>Empty string</i>
13590		 */
13591		"sTableId": "",
13592	
13593		/**
13594		 * The TABLE node for the main table
13595		 *  @type node
13596		 *  @default null
13597		 */
13598		"nTable": null,
13599	
13600		/**
13601		 * Permanent ref to the thead element
13602		 *  @type node
13603		 *  @default null
13604		 */
13605		"nTHead": null,
13606	
13607		/**
13608		 * Permanent ref to the tfoot element - if it exists
13609		 *  @type node
13610		 *  @default null
13611		 */
13612		"nTFoot": null,
13613	
13614		/**
13615		 * Permanent ref to the tbody element
13616		 *  @type node
13617		 *  @default null
13618		 */
13619		"nTBody": null,
13620	
13621		/**
13622		 * Cache the wrapper node (contains all DataTables controlled elements)
13623		 *  @type node
13624		 *  @default null
13625		 */
13626		"nTableWrapper": null,
13627	
13628		/**
13629		 * Indicate if when using server-side processing the loading of data
13630		 * should be deferred until the second draw.
13631		 * Note that this parameter will be set by the initialisation routine. To
13632		 * set a default use {@link DataTable.defaults}.
13633		 *  @type boolean
13634		 *  @default false
13635		 */
13636		"bDeferLoading": false,
13637	
13638		/**
13639		 * Indicate if all required information has been read in
13640		 *  @type boolean
13641		 *  @default false
13642		 */
13643		"bInitialised": false,
13644	
13645		/**
13646		 * Information about open rows. Each object in the array has the parameters
13647		 * 'nTr' and 'nParent'
13648		 *  @type array
13649		 *  @default []
13650		 */
13651		"aoOpenRows": [],
13652	
13653		/**
13654		 * Dictate the positioning of DataTables' control elements - see
13655		 * {@link DataTable.model.oInit.sDom}.
13656		 * Note that this parameter will be set by the initialisation routine. To
13657		 * set a default use {@link DataTable.defaults}.
13658		 *  @type string
13659		 *  @default null
13660		 */
13661		"sDom": null,
13662	
13663		/**
13664		 * Search delay (in mS)
13665		 *  @type integer
13666		 *  @default null
13667		 */
13668		"searchDelay": null,
13669	
13670		/**
13671		 * Which type of pagination should be used.
13672		 * Note that this parameter will be set by the initialisation routine. To
13673		 * set a default use {@link DataTable.defaults}.
13674		 *  @type string
13675		 *  @default two_button
13676		 */
13677		"sPaginationType": "two_button",
13678	
13679		/**
13680		 * The state duration (for `stateSave`) in seconds.
13681		 * Note that this parameter will be set by the initialisation routine. To
13682		 * set a default use {@link DataTable.defaults}.
13683		 *  @type int
13684		 *  @default 0
13685		 */
13686		"iStateDuration": 0,
13687	
13688		/**
13689		 * Array of callback functions for state saving. Each array element is an
13690		 * object with the following parameters:
13691		 *   <ul>
13692		 *     <li>function:fn - function to call. Takes two parameters, oSettings
13693		 *       and the JSON string to save that has been thus far created. Returns
13694		 *       a JSON string to be inserted into a json object
13695		 *       (i.e. '"param": [ 0, 1, 2]')</li>
13696		 *     <li>string:sName - name of callback</li>
13697		 *   </ul>
13698		 *  @type array
13699		 *  @default []
13700		 */
13701		"aoStateSave": [],
13702	
13703		/**
13704		 * Array of callback functions for state loading. Each array element is an
13705		 * object with the following parameters:
13706		 *   <ul>
13707		 *     <li>function:fn - function to call. Takes two parameters, oSettings
13708		 *       and the object stored. May return false to cancel state loading</li>
13709		 *     <li>string:sName - name of callback</li>
13710		 *   </ul>
13711		 *  @type array
13712		 *  @default []
13713		 */
13714		"aoStateLoad": [],
13715	
13716		/**
13717		 * State that was saved. Useful for back reference
13718		 *  @type object
13719		 *  @default null
13720		 */
13721		"oSavedState": null,
13722	
13723		/**
13724		 * State that was loaded. Useful for back reference
13725		 *  @type object
13726		 *  @default null
13727		 */
13728		"oLoadedState": null,
13729	
13730		/**
13731		 * Source url for AJAX data for the table.
13732		 * Note that this parameter will be set by the initialisation routine. To
13733		 * set a default use {@link DataTable.defaults}.
13734		 *  @type string
13735		 *  @default null
13736		 */
13737		"sAjaxSource": null,
13738	
13739		/**
13740		 * Property from a given object from which to read the table data from. This
13741		 * can be an empty string (when not server-side processing), in which case
13742		 * it is  assumed an an array is given directly.
13743		 * Note that this parameter will be set by the initialisation routine. To
13744		 * set a default use {@link DataTable.defaults}.
13745		 *  @type string
13746		 */
13747		"sAjaxDataProp": null,
13748	
13749		/**
13750		 * The last jQuery XHR object that was used for server-side data gathering.
13751		 * This can be used for working with the XHR information in one of the
13752		 * callbacks
13753		 *  @type object
13754		 *  @default null
13755		 */
13756		"jqXHR": null,
13757	
13758		/**
13759		 * JSON returned from the server in the last Ajax request
13760		 *  @type object
13761		 *  @default undefined
13762		 */
13763		"json": undefined,
13764	
13765		/**
13766		 * Data submitted as part of the last Ajax request
13767		 *  @type object
13768		 *  @default undefined
13769		 */
13770		"oAjaxData": undefined,
13771	
13772		/**
13773		 * Function to get the server-side data.
13774		 * Note that this parameter will be set by the initialisation routine. To
13775		 * set a default use {@link DataTable.defaults}.
13776		 *  @type function
13777		 */
13778		"fnServerData": null,
13779	
13780		/**
13781		 * Functions which are called prior to sending an Ajax request so extra
13782		 * parameters can easily be sent to the server
13783		 *  @type array
13784		 *  @default []
13785		 */
13786		"aoServerParams": [],
13787	
13788		/**
13789		 * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
13790		 * required).
13791		 * Note that this parameter will be set by the initialisation routine. To
13792		 * set a default use {@link DataTable.defaults}.
13793		 *  @type string
13794		 */
13795		"sServerMethod": null,
13796	
13797		/**
13798		 * Format numbers for display.
13799		 * Note that this parameter will be set by the initialisation routine. To
13800		 * set a default use {@link DataTable.defaults}.
13801		 *  @type function
13802		 */
13803		"fnFormatNumber": null,
13804	
13805		/**
13806		 * List of options that can be used for the user selectable length menu.
13807		 * Note that this parameter will be set by the initialisation routine. To
13808		 * set a default use {@link DataTable.defaults}.
13809		 *  @type array
13810		 *  @default []
13811		 */
13812		"aLengthMenu": null,
13813	
13814		/**
13815		 * Counter for the draws that the table does. Also used as a tracker for
13816		 * server-side processing
13817		 *  @type int
13818		 *  @default 0
13819		 */
13820		"iDraw": 0,
13821	
13822		/**
13823		 * Indicate if a redraw is being done - useful for Ajax
13824		 *  @type boolean
13825		 *  @default false
13826		 */
13827		"bDrawing": false,
13828	
13829		/**
13830		 * Draw index (iDraw) of the last error when parsing the returned data
13831		 *  @type int
13832		 *  @default -1
13833		 */
13834		"iDrawError": -1,
13835	
13836		/**
13837		 * Paging display length
13838		 *  @type int
13839		 *  @default 10
13840		 */
13841		"_iDisplayLength": 10,
13842	
13843		/**
13844		 * Paging start point - aiDisplay index
13845		 *  @type int
13846		 *  @default 0
13847		 */
13848		"_iDisplayStart": 0,
13849	
13850		/**
13851		 * Server-side processing - number of records in the result set
13852		 * (i.e. before filtering), Use fnRecordsTotal rather than
13853		 * this property to get the value of the number of records, regardless of
13854		 * the server-side processing setting.
13855		 *  @type int
13856		 *  @default 0
13857		 *  @private
13858		 */
13859		"_iRecordsTotal": 0,
13860	
13861		/**
13862		 * Server-side processing - number of records in the current display set
13863		 * (i.e. after filtering). Use fnRecordsDisplay rather than
13864		 * this property to get the value of the number of records, regardless of
13865		 * the server-side processing setting.
13866		 *  @type boolean
13867		 *  @default 0
13868		 *  @private
13869		 */
13870		"_iRecordsDisplay": 0,
13871	
13872		/**
13873		 * The classes to use for the table
13874		 *  @type object
13875		 *  @default {}
13876		 */
vendor: 4,121 bytes, lines 13877-14048
13877		"oClasses": {},
13878	
13879		/**
13880		 * Flag attached to the settings object so you can check in the draw
13881		 * callback if filtering has been done in the draw. Deprecated in favour of
13882		 * events.
13883		 *  @type boolean
13884		 *  @default false
13885		 *  @deprecated
13886		 */
13887		"bFiltered": false,
13888	
13889		/**
13890		 * Flag attached to the settings object so you can check in the draw
13891		 * callback if sorting has been done in the draw. Deprecated in favour of
13892		 * events.
13893		 *  @type boolean
13894		 *  @default false
13895		 *  @deprecated
13896		 */
13897		"bSorted": false,
13898	
13899		/**
13900		 * Indicate that if multiple rows are in the header and there is more than
13901		 * one unique cell per column, if the top one (true) or bottom one (false)
13902		 * should be used for sorting / title by DataTables.
13903		 * Note that this parameter will be set by the initialisation routine. To
13904		 * set a default use {@link DataTable.defaults}.
13905		 *  @type boolean
13906		 */
13907		"bSortCellsTop": null,
13908	
13909		/**
13910		 * Initialisation object that is used for the table
13911		 *  @type object
13912		 *  @default null
13913		 */
13914		"oInit": null,
13915	
13916		/**
13917		 * Destroy callback functions - for plug-ins to attach themselves to the
13918		 * destroy so they can clean up markup and events.
13919		 *  @type array
13920		 *  @default []
13921		 */
13922		"aoDestroyCallback": [],
13923	
13924	
13925		/**
13926		 * Get the number of records in the current record set, before filtering
13927		 *  @type function
13928		 */
13929		"fnRecordsTotal": function ()
13930		{
13931			return _fnDataSource( this ) == 'ssp' ?
13932				this._iRecordsTotal * 1 :
13933				this.aiDisplayMaster.length;
13934		},
13935	
13936		/**
13937		 * Get the number of records in the current record set, after filtering
13938		 *  @type function
13939		 */
13940		"fnRecordsDisplay": function ()
13941		{
13942			return _fnDataSource( this ) == 'ssp' ?
13943				this._iRecordsDisplay * 1 :
13944				this.aiDisplay.length;
13945		},
13946	
13947		/**
13948		 * Get the display end point - aiDisplay index
13949		 *  @type function
13950		 */
13951		"fnDisplayEnd": function ()
13952		{
13953			var
13954				len      = this._iDisplayLength,
13955				start    = this._iDisplayStart,
13956				calc     = start + len,
13957				records  = this.aiDisplay.length,
13958				features = this.oFeatures,
13959				paginate = features.bPaginate;
13960	
13961			if ( features.bServerSide ) {
13962				return paginate === false || len === -1 ?
13963					start + records :
13964					Math.min( start+len, this._iRecordsDisplay );
13965			}
13966			else {
13967				return ! paginate || calc>records || len===-1 ?
13968					records :
13969					calc;
13970			}
13971		},
13972	
13973		/**
13974		 * The DataTables object for this table
13975		 *  @type object
13976		 *  @default null
13977		 */
13978		"oInstance": null,
13979	
13980		/**
13981		 * Unique identifier for each instance of the DataTables object. If there
13982		 * is an ID on the table node, then it takes that value, otherwise an
13983		 * incrementing internal counter is used.
13984		 *  @type string
13985		 *  @default null
13986		 */
13987		"sInstance": null,
13988	
13989		/**
13990		 * tabindex attribute value that is added to DataTables control elements, allowing
13991		 * keyboard navigation of the table and its controls.
13992		 */
13993		"iTabIndex": 0,
13994	
13995		/**
13996		 * DIV container for the footer scrolling table if scrolling
13997		 */
13998		"nScrollHead": null,
13999	
14000		/**
14001		 * DIV container for the footer scrolling table if scrolling
14002		 */
14003		"nScrollFoot": null,
14004	
14005		/**
14006		 * Last applied sort
14007		 *  @type array
14008		 *  @default []
14009		 */
14010		"aLastSort": [],
14011	
14012		/**
14013		 * Stored plug-in instances
14014		 *  @type object
14015		 *  @default {}
14016		 */
14017		"oPlugins": {},
14018	
14019		/**
14020		 * Function used to get a row's id from the row's data
14021		 *  @type function
14022		 *  @default null
14023		 */
14024		"rowIdFn": null,
14025	
14026		/**
14027		 * Data location where to store a row's id
14028		 *  @type string
14029		 *  @default null
14030		 */
14031		"rowId": null
14032	};
14033	
14034	/**
14035	 * Extension object for DataTables that is used to provide all extension
14036	 * options.
14037	 *
14038	 * Note that the `DataTable.ext` object is available through
14039	 * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is
14040	 * also aliased to `jQuery.fn.dataTableExt` for historic reasons.
14041	 *  @namespace
14042	 *  @extends DataTable.models.ext
14043	 */
14044	
14045	
14046	/**
14047	 * DataTables extensions
14048	 * 
14049	 * This namespace acts as a collection area for plug-ins that can be used to
14050	 * extend DataTables capabilities. Indeed many of the build in methods
14051	 * use this method to provide their own capabilities (sorting methods for
14052	 * example).
14053	 *
14054	 * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy
14055	 * reasons
14056	 *
14057	 *  @namespace
14058	 */
14059	DataTable.ext = _ext = {
14060		/**
14061		 * Buttons. For use with the Buttons extension for DataTables. This is
14062		 * defined here so other extensions can define buttons regardless of load
14063		 * order. It is _not_ used by DataTables core.
14064		 *
14065		 *  @type object
14066		 *  @default {}
14067		 */
14068		buttons: {},
14069	
14070	
14071		/**
14072		 * Element class names
14073		 *
14074		 *  @type object
14075		 *  @default {}
14076		 */
14077		classes: {},
14078	
14079	
14080		/**
14081		 * DataTables build type (expanded by the download builder)
14082		 *
14083		 *  @type string
14084		 */
14085		builder: "-source-",
14086	
14087	
14088		/**
14089		 * Error reporting.
14090		 * 
14091		 * How should DataTables report an error. Can take the value 'alert',
14092		 * 'throw', 'none' or a function.
14093		 *
14094		 *  @type string|function
14095		 *  @default alert
14096		 */
14097		errMode: "alert",
14098	
14099	
14100		/**
14101		 * Feature plug-ins.
14102		 * 
14103		 * This is an array of objects which describe the feature plug-ins that are
14104		 * available to DataTables. These feature plug-ins are then available for
14105		 * use through the `dom` initialisation option.
14106		 * 
14107		 * Each feature plug-in is described by an object which must have the
14108		 * following properties:
14109		 * 
14110		 * * `fnInit` - function that is used to initialise the plug-in,
14111		 * * `cFeature` - a character so the feature can be enabled by the `dom`
14112		 *   instillation option. This is case sensitive.
14113		 *
14114		 * The `fnInit` function has the following input parameters:
14115		 *
14116		 * 1. `{object}` DataTables settings object: see
14117		 *    {@link DataTable.models.oSettings}
14118		 *
14119		 * And the following return is expected:
14120		 * 
14121		 * * {node|null} The element which contains your feature. Note that the
14122		 *   return may also be void if your plug-in does not require to inject any
14123		 *   DOM elements into DataTables control (`dom`) - for example this might
14124		 *   be useful when developing a plug-in which allows table control via
14125		 *   keyboard entry
14126		 *
14127		 *  @type array
14128		 *
14129		 *  @example
14130		 *    $.fn.dataTable.ext.features.push( {
14131		 *      "fnInit": function( oSettings ) {
14132		 *        return new TableTools( { "oDTSettings": oSettings } );
14133		 *      },
14134		 *      "cFeature": "T"
14135		 *    } );
14136		 */
14137		feature: [],
14138	
14139	
14140		/**
14141		 * Row searching.
14142		 * 
14143		 * This method of searching is complimentary to the default type based
14144		 * searching, and a lot more comprehensive as it allows you complete control
14145		 * over the searching logic. Each element in this array is a function
14146		 * (parameters described below) that is called for every row in the table,
14147		 * and your logic decides if it should be included in the searching data set
14148		 * or not.
14149		 *
14150		 * Searching functions have the following input parameters:
14151		 *
14152		 * 1. `{object}` DataTables settings object: see
14153		 *    {@link DataTable.models.oSettings}
14154		 * 2. `{array|object}` Data for the row to be processed (same as the
14155		 *    original format that was passed in as the data source, or an array
14156		 *    from a DOM data source
14157		 * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which
14158		 *    can be useful to retrieve the `TR` element if you need DOM interaction.
14159		 *
14160		 * And the following return is expected:
14161		 *
14162		 * * {boolean} Include the row in the searched result set (true) or not
14163		 *   (false)
14164		 *
14165		 * Note that as with the main search ability in DataTables, technically this
14166		 * is "filtering", since it is subtractive. However, for consistency in
14167		 * naming we call it searching here.
14168		 *
14169		 *  @type array
14170		 *  @default []
14171		 *
14172		 *  @example
14173		 *    // The following example shows custom search being applied to the
14174		 *    // fourth column (i.e. the data[3] index) based on two input values
14175		 *    // from the end-user, matching the data in a certain range.
14176		 *    $.fn.dataTable.ext.search.push(
14177		 *      function( settings, data, dataIndex ) {
14178		 *        var min = document.getElementById('min').value * 1;
14179		 *        var max = document.getElementById('max').value * 1;
14180		 *        var version = data[3] == "-" ? 0 : data[3]*1;
14181		 *
14182		 *        if ( min == "" && max == "" ) {
14183		 *          return true;
14184		 *        }
14185		 *        else if ( min == "" && version < max ) {
14186		 *          return true;
14187		 *        }
14188		 *        else if ( min < version && "" == max ) {
14189		 *          return true;
14190		 *        }
14191		 *        else if ( min < version && version < max ) {
14192		 *          return true;
14193		 *        }
14194		 *        return false;
14195		 *      }
14196		 *    );
14197		 */
14198		search: [],
14199	
14200	
14201		/**
14202		 * Selector extensions
14203		 *
14204		 * The `selector` option can be used to extend the options available for the
14205		 * selector modifier options (`selector-modifier` object data type) that
14206		 * each of the three built in selector types offer (row, column and cell +
14207		 * their plural counterparts). For example the Select extension uses this
14208		 * mechanism to provide an option to select only rows, columns and cells
14209		 * that have been marked as selected by the end user (`{selected: true}`),
14210		 * which can be used in conjunction with the existing built in selector
14211		 * options.
14212		 *
14213		 * Each property is an array to which functions can be pushed. The functions
14214		 * take three attributes:
14215		 *
14216		 * * Settings object for the host table
14217		 * * Options object (`selector-modifier` object type)
14218		 * * Array of selected item indexes
14219		 *
14220		 * The return is an array of the resulting item indexes after the custom
14221		 * selector has been applied.
14222		 *
14223		 *  @type object
14224		 */
14225		selector: {
14226			cell: [],
14227			column: [],
14228			row: []
14229		},
14230	
14231	
14232		/**
14233		 * Internal functions, exposed for used in plug-ins.
14234		 * 
14235		 * Please note that you should not need to use the internal methods for
14236		 * anything other than a plug-in (and even then, try to avoid if possible).
14237		 * The internal function may change between releases.
14238		 *
14239		 *  @type object
14240		 *  @default {}
14241		 */
14242		internal: {},
14243	
14244	
14245		/**
14246		 * Legacy configuration options. Enable and disable legacy options that
14247		 * are available in DataTables.
14248		 *
14249		 *  @type object
14250		 */
14251		legacy: {
14252			/**
14253			 * Enable / disable DataTables 1.9 compatible server-side processing
14254			 * requests
14255			 *
14256			 *  @type boolean
14257			 *  @default null
14258			 */
14259			ajax: null
14260		},
14261	
14262	
14263		/**
14264		 * Pagination plug-in methods.
14265		 * 
14266		 * Each entry in this object is a function and defines which buttons should
14267		 * be shown by the pagination rendering method that is used for the table:
14268		 * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the
14269		 * buttons are displayed in the document, while the functions here tell it
14270		 * what buttons to display. This is done by returning an array of button
14271		 * descriptions (what each button will do).
14272		 *
14273		 * Pagination types (the four built in options and any additional plug-in
14274		 * options defined here) can be used through the `paginationType`
14275		 * initialisation parameter.
14276		 *
14277		 * The functions defined take two parameters:
14278		 *
14279		 * 1. `{int} page` The current page index
14280		 * 2. `{int} pages` The number of pages in the table
14281		 *
14282		 * Each function is expected to return an array where each element of the
14283		 * array can be one of:
14284		 *
14285		 * * `first` - Jump to first page when activated
14286		 * * `last` - Jump to last page when activated
14287		 * * `previous` - Show previous page when activated
14288		 * * `next` - Show next page when activated
14289		 * * `{int}` - Show page of the index given
14290		 * * `{array}` - A nested array containing the above elements to add a
14291		 *   containing 'DIV' element (might be useful for styling).
14292		 *
14293		 * Note that DataTables v1.9- used this object slightly differently whereby
14294		 * an object with two functions would be defined for each plug-in. That
14295		 * ability is still supported by DataTables 1.10+ to provide backwards
14296		 * compatibility, but this option of use is now decremented and no longer
14297		 * documented in DataTables 1.10+.
14298		 *
14299		 *  @type object
14300		 *  @default {}
14301		 *
14302		 *  @example
14303		 *    // Show previous, next and current page buttons only
14304		 *    $.fn.dataTableExt.oPagination.current = function ( page, pages ) {
14305		 *      return [ 'previous', page, 'next' ];
14306		 *    };
14307		 */
14308		pager: {},
14309	
14310	
14311		renderer: {
14312			pageButton: {},
14313			header: {}
14314		},
14315	
14316	
14317		/**
14318		 * Ordering plug-ins - custom data source
14319		 * 
14320		 * The extension options for ordering of data available here is complimentary
14321		 * to the default type based ordering that DataTables typically uses. It
14322		 * allows much greater control over the the data that is being used to
14323		 * order a column, but is necessarily therefore more complex.
14324		 * 
14325		 * This type of ordering is useful if you want to do ordering based on data
14326		 * live from the DOM (for example the contents of an 'input' element) rather
14327		 * than just the static string that DataTables knows of.
14328		 * 
14329		 * The way these plug-ins work is that you create an array of the values you
14330		 * wish to be ordering for the column in question and then return that
14331		 * array. The data in the array much be in the index order of the rows in
14332		 * the table (not the currently ordering order!). Which order data gathering
14333		 * function is run here depends on the `dt-init columns.orderDataType`
14334		 * parameter that is used for the column (if any).
14335		 *
14336		 * The functions defined take two parameters:
14337		 *
14338		 * 1. `{object}` DataTables settings object: see
14339		 *    {@link DataTable.models.oSettings}
14340		 * 2. `{int}` Target column index
14341		 *
14342		 * Each function is expected to return an array:
14343		 *
14344		 * * `{array}` Data for the column to be ordering upon
14345		 *
14346		 *  @type array
14347		 *
14348		 *  @example
14349		 *    // Ordering using `input` node values
14350		 *    $.fn.dataTable.ext.order['dom-text'] = function  ( settings, col )
14351		 *    {
14352		 *      return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
14353		 *        return $('input', td).val();
14354		 *      } );
14355		 *    }
14356		 */
14357		order: {},
14358	
14359	
14360		/**
14361		 * Type based plug-ins.
14362		 *
14363		 * Each column in DataTables has a type assigned to it, either by automatic
14364		 * detection or by direct assignment using the `type` option for the column.
14365		 * The type of a column will effect how it is ordering and search (plug-ins
14366		 * can also make use of the column type if required).
14367		 *
14368		 * @namespace
14369		 */
14370		type: {
14371			/**
14372			 * Type detection functions.
14373			 *
14374			 * The functions defined in this object are used to automatically detect
14375			 * a column's type, making initialisation of DataTables super easy, even
14376			 * when complex data is in the table.
14377			 *
14378			 * The functions defined take two parameters:
14379			 *
14380		     *  1. `{*}` Data from the column cell to be analysed
14381		     *  2. `{settings}` DataTables settings object. This can be used to
14382		     *     perform context specific type detection - for example detection
14383		     *     based on language settings such as using a comma for a decimal
14384		     *     place. Generally speaking the options from the settings will not
14385		     *     be required
14386			 *
14387			 * Each function is expected to return:
14388			 *
14389			 * * `{string|null}` Data type detected, or null if unknown (and thus
14390			 *   pass it on to the other type detection functions.
14391			 *
14392			 *  @type array
14393			 *
14394			 *  @example
14395			 *    // Currency type detection plug-in:
14396			 *    $.fn.dataTable.ext.type.detect.push(
14397			 *      function ( data, settings ) {
14398			 *        // Check the numeric part
14399			 *        if ( ! data.substring(1).match(/[0-9]/) ) {
14400			 *          return null;
14401			 *        }
14402			 *
14403			 *        // Check prefixed by currency
14404			 *        if ( data.charAt(0) == '$' || data.charAt(0) == '&pound;' ) {
14405			 *          return 'currency';
14406			 *        }
14407			 *        return null;
14408			 *      }
14409			 *    );
14410			 */
14411			detect: [],
14412	
14413	
14414			/**
14415			 * Type based search formatting.
14416			 *
14417			 * The type based searching functions can be used to pre-format the
14418			 * data to be search on. For example, it can be used to strip HTML
14419			 * tags or to de-format telephone numbers for numeric only searching.
14420			 *
14421			 * Note that is a search is not defined for a column of a given type,
14422			 * no search formatting will be performed.
14423			 * 
14424			 * Pre-processing of searching data plug-ins - When you assign the sType
14425			 * for a column (or have it automatically detected for you by DataTables
14426			 * or a type detection plug-in), you will typically be using this for
14427			 * custom sorting, but it can also be used to provide custom searching
14428			 * by allowing you to pre-processing the data and returning the data in
14429			 * the format that should be searched upon. This is done by adding
14430			 * functions this object with a parameter name which matches the sType
14431			 * for that target column. This is the corollary of <i>afnSortData</i>
14432			 * for searching data.
14433			 *
14434			 * The functions defined take a single parameter:
14435			 *
14436		     *  1. `{*}` Data from the column cell to be prepared for searching
14437			 *
14438			 * Each function is expected to return:
14439			 *
14440			 * * `{string|null}` Formatted string that will be used for the searching.
14441			 *
14442			 *  @type object
14443			 *  @default {}
14444			 *
14445			 *  @example
14446			 *    $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) {
14447			 *      return d.replace(/\n/g," ").replace( /<.*?>/g, "" );
14448			 *    }
14449			 */
14450			search: {},
14451	
14452	
14453			/**
14454			 * Type based ordering.
14455			 *
14456			 * The column type tells DataTables what ordering to apply to the table
14457			 * when a column is sorted upon. The order for each type that is defined,
14458			 * is defined by the functions available in this object.
14459			 *
14460			 * Each ordering option can be described by three properties added to
14461			 * this object:
14462			 *
14463			 * * `{type}-pre` - Pre-formatting function
14464			 * * `{type}-asc` - Ascending order function
14465			 * * `{type}-desc` - Descending order function
14466			 *
14467			 * All three can be used together, only `{type}-pre` or only
14468			 * `{type}-asc` and `{type}-desc` together. It is generally recommended
14469			 * that only `{type}-pre` is used, as this provides the optimal
14470			 * implementation in terms of speed, although the others are provided
14471			 * for compatibility with existing Javascript sort functions.
14472			 *
14473			 * `{type}-pre`: Functions defined take a single parameter:
14474			 *
14475		     *  1. `{*}` Data from the column cell to be prepared for ordering
14476			 *
14477			 * And return:
14478			 *
14479			 * * `{*}` Data to be sorted upon
14480			 *
14481			 * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort
14482			 * functions, taking two parameters:
14483			 *
14484		     *  1. `{*}` Data to compare to the second parameter
14485		     *  2. `{*}` Data to compare to the first parameter
14486			 *
14487			 * And returning:
14488			 *
14489			 * * `{*}` Ordering match: <0 if first parameter should be sorted lower
14490			 *   than the second parameter, ===0 if the two parameters are equal and
14491			 *   >0 if the first parameter should be sorted height than the second
14492			 *   parameter.
14493			 * 
14494			 *  @type object
14495			 *  @default {}
14496			 *
14497			 *  @example
14498			 *    // Numeric ordering of formatted numbers with a pre-formatter
14499			 *    $.extend( $.fn.dataTable.ext.type.order, {
14500			 *      "string-pre": function(x) {
14501			 *        a = (a === "-" || a === "") ? 0 : a.replace( /[^\d\-\.]/g, "" );
14502			 *        return parseFloat( a );
14503			 *      }
14504			 *    } );
14505			 *
14506			 *  @example
14507			 *    // Case-sensitive string ordering, with no pre-formatting method
14508			 *    $.extend( $.fn.dataTable.ext.order, {
14509			 *      "string-case-asc": function(x,y) {
14510			 *        return ((x < y) ? -1 : ((x > y) ? 1 : 0));
14511			 *      },
14512			 *      "string-case-desc": function(x,y) {
14513			 *        return ((x < y) ? 1 : ((x > y) ? -1 : 0));
14514			 *      }
14515			 *    } );
14516			 */
14517			order: {}
14518		},
14519	
14520		/**
14521		 * Unique DataTables instance counter
14522		 *
14523		 * @type int
14524		 * @private
14525		 */
14526		_unique: 0,
14527	
14528	
14529		//
14530		// Depreciated
14531		// The following properties are retained for backwards compatibility only.
14532		// The should not be used in new projects and will be removed in a future
14533		// version
14534		//
14535	
14536		/**
14537		 * Version check function.
14538		 *  @type function
14539		 *  @depreciated Since 1.10
14540		 */
14541		fnVersionCheck: DataTable.fnVersionCheck,
14542	
14543	
14544		/**
14545		 * Index for what 'this' index API functions should use
14546		 *  @type int
14547		 *  @deprecated Since v1.10
14548		 */
14549		iApiIndex: 0,
14550	
14551	
14552		/**
14553		 * jQuery UI class container
14554		 *  @type object
14555		 *  @deprecated Since v1.10
14556		 */
14557		oJUIClasses: {},
14558	
14559	
14560		/**
14561		 * Software version
14562		 *  @type string
14563		 *  @deprecated Since v1.10
14564		 */
vendor: 28,324 bytes, lines 14565-15580
14565		sVersion: DataTable.version
14566	};
14567	
14568	
14569	//
14570	// Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts
14571	//
14572	$.extend( _ext, {
14573		afnFiltering: _ext.search,
14574		aTypes:       _ext.type.detect,
14575		ofnSearch:    _ext.type.search,
14576		oSort:        _ext.type.order,
14577		afnSortData:  _ext.order,
14578		aoFeatures:   _ext.feature,
14579		oApi:         _ext.internal,
14580		oStdClasses:  _ext.classes,
14581		oPagination:  _ext.pager
14582	} );
14583	
14584	
14585	$.extend( DataTable.ext.classes, {
14586		"sTable": "dataTable",
14587		"sNoFooter": "no-footer",
14588	
14589		/* Paging buttons */
14590		"sPageButton": "paginate_button",
14591		"sPageButtonActive": "current",
14592		"sPageButtonDisabled": "disabled",
14593	
14594		/* Striping classes */
14595		"sStripeOdd": "odd",
14596		"sStripeEven": "even",
14597	
14598		/* Empty row */
14599		"sRowEmpty": "dataTables_empty",
14600	
14601		/* Features */
14602		"sWrapper": "dataTables_wrapper",
14603		"sFilter": "dataTables_filter",
14604		"sInfo": "dataTables_info",
14605		"sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
14606		"sLength": "dataTables_length",
14607		"sProcessing": "dataTables_processing",
14608	
14609		/* Sorting */
14610		"sSortAsc": "sorting_asc",
14611		"sSortDesc": "sorting_desc",
14612		"sSortable": "sorting", /* Sortable in both directions */
14613		"sSortableAsc": "sorting_desc_disabled",
14614		"sSortableDesc": "sorting_asc_disabled",
14615		"sSortableNone": "sorting_disabled",
14616		"sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
14617	
14618		/* Filtering */
14619		"sFilterInput": "",
14620	
14621		/* Page length */
14622		"sLengthSelect": "",
14623	
14624		/* Scrolling */
14625		"sScrollWrapper": "dataTables_scroll",
14626		"sScrollHead": "dataTables_scrollHead",
14627		"sScrollHeadInner": "dataTables_scrollHeadInner",
14628		"sScrollBody": "dataTables_scrollBody",
14629		"sScrollFoot": "dataTables_scrollFoot",
14630		"sScrollFootInner": "dataTables_scrollFootInner",
14631	
14632		/* Misc */
14633		"sHeaderTH": "",
14634		"sFooterTH": "",
14635	
14636		// Deprecated
14637		"sSortJUIAsc": "",
14638		"sSortJUIDesc": "",
14639		"sSortJUI": "",
14640		"sSortJUIAscAllowed": "",
14641		"sSortJUIDescAllowed": "",
14642		"sSortJUIWrapper": "",
14643		"sSortIcon": "",
14644		"sJUIHeader": "",
14645		"sJUIFooter": ""
14646	} );
14647	
14648	
14649	var extPagination = DataTable.ext.pager;
14650	
14651	function _numbers ( page, pages ) {
14652		var
14653			numbers = [],
14654			buttons = extPagination.numbers_length,
14655			half = Math.floor( buttons / 2 ),
14656			i = 1;
14657	
14658		if ( pages <= buttons ) {
14659			numbers = _range( 0, pages );
14660		}
14661		else if ( page <= half ) {
14662			numbers = _range( 0, buttons-2 );
14663			numbers.push( 'ellipsis' );
14664			numbers.push( pages-1 );
14665		}
14666		else if ( page >= pages - 1 - half ) {
14667			numbers = _range( pages-(buttons-2), pages );
14668			numbers.splice( 0, 0, 'ellipsis' ); // no unshift in ie6
14669			numbers.splice( 0, 0, 0 );
14670		}
14671		else {
14672			numbers = _range( page-half+2, page+half-1 );
14673			numbers.push( 'ellipsis' );
14674			numbers.push( pages-1 );
14675			numbers.splice( 0, 0, 'ellipsis' );
14676			numbers.splice( 0, 0, 0 );
14677		}
14678	
14679		numbers.DT_el = 'span';
14680		return numbers;
14681	}
14682	
14683	
14684	$.extend( extPagination, {
14685		simple: function ( page, pages ) {
14686			return [ 'previous', 'next' ];
14687		},
14688	
14689		full: function ( page, pages ) {
14690			return [  'first', 'previous', 'next', 'last' ];
14691		},
14692	
14693		numbers: function ( page, pages ) {
14694			return [ _numbers(page, pages) ];
14695		},
14696	
14697		simple_numbers: function ( page, pages ) {
14698			return [ 'previous', _numbers(page, pages), 'next' ];
14699		},
14700	
14701		full_numbers: function ( page, pages ) {
14702			return [ 'first', 'previous', _numbers(page, pages), 'next', 'last' ];
14703		},
14704		
14705		first_last_numbers: function (page, pages) {
14706	 		return ['first', _numbers(page, pages), 'last'];
14707	 	},
14708	
14709		// For testing and plug-ins to use
14710		_numbers: _numbers,
14711	
14712		// Number of number buttons (including ellipsis) to show. _Must be odd!_
14713		numbers_length: 7
14714	} );
14715	
14716	
14717	$.extend( true, DataTable.ext.renderer, {
14718		pageButton: {
14719			_: function ( settings, host, idx, buttons, page, pages ) {
14720				var classes = settings.oClasses;
14721				var lang = settings.oLanguage.oPaginate;
14722				var aria = settings.oLanguage.oAria.paginate || {};
14723				var btnDisplay, btnClass, counter=0;
14724	
14725				var attach = function( container, buttons ) {
14726					var i, ien, node, button, tabIndex;
14727					var disabledClass = classes.sPageButtonDisabled;
14728					var clickHandler = function ( e ) {
14729						_fnPageChange( settings, e.data.action, true );
14730					};
14731	
14732					for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
14733						button = buttons[i];
14734	
14735						if ( Array.isArray( button ) ) {
14736							var inner = $( '<'+(button.DT_el || 'div')+'/>' )
14737								.appendTo( container );
14738							attach( inner, button );
14739						}
14740						else {
14741							btnDisplay = null;
14742							btnClass = button;
14743							tabIndex = settings.iTabIndex;
14744	
14745							switch ( button ) {
14746								case 'ellipsis':
14747									container.append('<span class="ellipsis">&#x2026;</span>');
14748									break;
14749	
14750								case 'first':
14751									btnDisplay = lang.sFirst;
14752	
14753									if ( page === 0 ) {
14754										tabIndex = -1;
14755										btnClass += ' ' + disabledClass;
14756									}
14757									break;
14758	
14759								case 'previous':
14760									btnDisplay = lang.sPrevious;
14761	
14762									if ( page === 0 ) {
14763										tabIndex = -1;
14764										btnClass += ' ' + disabledClass;
14765									}
14766									break;
14767	
14768								case 'next':
14769									btnDisplay = lang.sNext;
14770	
14771									if ( pages === 0 || page === pages-1 ) {
14772										tabIndex = -1;
14773										btnClass += ' ' + disabledClass;
14774									}
14775									break;
14776	
14777								case 'last':
14778									btnDisplay = lang.sLast;
14779	
14780									if ( pages === 0 || page === pages-1 ) {
14781										tabIndex = -1;
14782										btnClass += ' ' + disabledClass;
14783									}
14784									break;
14785	
14786								default:
14787									btnDisplay = settings.fnFormatNumber( button + 1 );
14788									btnClass = page === button ?
14789										classes.sPageButtonActive : '';
14790									break;
14791							}
14792	
14793							if ( btnDisplay !== null ) {
14794								node = $('<a>', {
14795										'class': classes.sPageButton+' '+btnClass,
14796										'aria-controls': settings.sTableId,
14797										'aria-label': aria[ button ],
14798										'data-dt-idx': counter,
14799										'tabindex': tabIndex,
14800										'id': idx === 0 && typeof button === 'string' ?
14801											settings.sTableId +'_'+ button :
14802											null
14803									} )
14804									.html( btnDisplay )
14805									.appendTo( container );
14806	
14807								_fnBindAction(
14808									node, {action: button}, clickHandler
14809								);
14810	
14811								counter++;
14812							}
14813						}
14814					}
14815				};
14816	
14817				// IE9 throws an 'unknown error' if document.activeElement is used
14818				// inside an iframe or frame. Try / catch the error. Not good for
14819				// accessibility, but neither are frames.
14820				var activeEl;
14821	
14822				try {
14823					// Because this approach is destroying and recreating the paging
14824					// elements, focus is lost on the select button which is bad for
14825					// accessibility. So we want to restore focus once the draw has
14826					// completed
14827					activeEl = $(host).find(document.activeElement).data('dt-idx');
14828				}
14829				catch (e) {}
14830	
14831				attach( $(host).empty(), buttons );
14832	
14833				if ( activeEl !== undefined ) {
14834					$(host).find( '[data-dt-idx='+activeEl+']' ).trigger('focus');
14835				}
14836			}
14837		}
14838	} );
14839	
14840	
14841	
14842	// Built in type detection. See model.ext.aTypes for information about
14843	// what is required from this methods.
14844	$.extend( DataTable.ext.type.detect, [
14845		// Plain numbers - first since V8 detects some plain numbers as dates
14846		// e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...).
14847		function ( d, settings )
14848		{
14849			var decimal = settings.oLanguage.sDecimal;
14850			return _isNumber( d, decimal ) ? 'num'+decimal : null;
14851		},
14852	
14853		// Dates (only those recognised by the browser's Date.parse)
14854		function ( d, settings )
14855		{
14856			// V8 tries _very_ hard to make a string passed into `Date.parse()`
14857			// valid, so we need to use a regex to restrict date formats. Use a
14858			// plug-in for anything other than ISO8601 style strings
14859			if ( d && !(d instanceof Date) && ! _re_date.test(d) ) {
14860				return null;
14861			}
14862			var parsed = Date.parse(d);
14863			return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null;
14864		},
14865	
14866		// Formatted numbers
14867		function ( d, settings )
14868		{
14869			var decimal = settings.oLanguage.sDecimal;
14870			return _isNumber( d, decimal, true ) ? 'num-fmt'+decimal : null;
14871		},
14872	
14873		// HTML numeric
14874		function ( d, settings )
14875		{
14876			var decimal = settings.oLanguage.sDecimal;
14877			return _htmlNumeric( d, decimal ) ? 'html-num'+decimal : null;
14878		},
14879	
14880		// HTML numeric, formatted
14881		function ( d, settings )
14882		{
14883			var decimal = settings.oLanguage.sDecimal;
14884			return _htmlNumeric( d, decimal, true ) ? 'html-num-fmt'+decimal : null;
14885		},
14886	
14887		// HTML (this is strict checking - there must be html)
14888		function ( d, settings )
14889		{
14890			return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ?
14891				'html' : null;
14892		}
14893	] );
14894	
14895	
14896	
14897	// Filter formatting functions. See model.ext.ofnSearch for information about
14898	// what is required from these methods.
14899	// 
14900	// Note that additional search methods are added for the html numbers and
14901	// html formatted numbers by `_addNumericSort()` when we know what the decimal
14902	// place is
14903	
14904	
14905	$.extend( DataTable.ext.type.search, {
14906		html: function ( data ) {
14907			return _empty(data) ?
14908				data :
14909				typeof data === 'string' ?
14910					data
14911						.replace( _re_new_lines, " " )
14912						.replace( _re_html, "" ) :
14913					'';
14914		},
14915	
14916		string: function ( data ) {
14917			return _empty(data) ?
14918				data :
14919				typeof data === 'string' ?
14920					data.replace( _re_new_lines, " " ) :
14921					data;
14922		}
14923	} );
14924	
14925	
14926	
14927	var __numericReplace = function ( d, decimalPlace, re1, re2 ) {
14928		if ( d !== 0 && (!d || d === '-') ) {
14929			return -Infinity;
14930		}
14931	
14932		// If a decimal place other than `.` is used, it needs to be given to the
14933		// function so we can detect it and replace with a `.` which is the only
14934		// decimal place Javascript recognises - it is not locale aware.
14935		if ( decimalPlace ) {
14936			d = _numToDecimal( d, decimalPlace );
14937		}
14938	
14939		if ( d.replace ) {
14940			if ( re1 ) {
14941				d = d.replace( re1, '' );
14942			}
14943	
14944			if ( re2 ) {
14945				d = d.replace( re2, '' );
14946			}
14947		}
14948	
14949		return d * 1;
14950	};
14951	
14952	
14953	// Add the numeric 'deformatting' functions for sorting and search. This is done
14954	// in a function to provide an easy ability for the language options to add
14955	// additional methods if a non-period decimal place is used.
14956	function _addNumericSort ( decimalPlace ) {
14957		$.each(
14958			{
14959				// Plain numbers
14960				"num": function ( d ) {
14961					return __numericReplace( d, decimalPlace );
14962				},
14963	
14964				// Formatted numbers
14965				"num-fmt": function ( d ) {
14966					return __numericReplace( d, decimalPlace, _re_formatted_numeric );
14967				},
14968	
14969				// HTML numeric
14970				"html-num": function ( d ) {
14971					return __numericReplace( d, decimalPlace, _re_html );
14972				},
14973	
14974				// HTML numeric, formatted
14975				"html-num-fmt": function ( d ) {
14976					return __numericReplace( d, decimalPlace, _re_html, _re_formatted_numeric );
14977				}
14978			},
14979			function ( key, fn ) {
14980				// Add the ordering method
14981				_ext.type.order[ key+decimalPlace+'-pre' ] = fn;
14982	
14983				// For HTML types add a search formatter that will strip the HTML
14984				if ( key.match(/^html\-/) ) {
14985					_ext.type.search[ key+decimalPlace ] = _ext.type.search.html;
14986				}
14987			}
14988		);
14989	}
14990	
14991	
14992	// Default sort methods
14993	$.extend( _ext.type.order, {
14994		// Dates
14995		"date-pre": function ( d ) {
14996			var ts = Date.parse( d );
14997			return isNaN(ts) ? -Infinity : ts;
14998		},
14999	
15000		// html
15001		"html-pre": function ( a ) {
15002			return _empty(a) ?
15003				'' :
15004				a.replace ?
15005					a.replace( /<.*?>/g, "" ).toLowerCase() :
15006					a+'';
15007		},
15008	
15009		// string
15010		"string-pre": function ( a ) {
15011			// This is a little complex, but faster than always calling toString,
15012			// http://jsperf.com/tostring-v-check
15013			return _empty(a) ?
15014				'' :
15015				typeof a === 'string' ?
15016					a.toLowerCase() :
15017					! a.toString ?
15018						'' :
15019						a.toString();
15020		},
15021	
15022		// string-asc and -desc are retained only for compatibility with the old
15023		// sort methods
15024		"string-asc": function ( x, y ) {
15025			return ((x < y) ? -1 : ((x > y) ? 1 : 0));
15026		},
15027	
15028		"string-desc": function ( x, y ) {
15029			return ((x < y) ? 1 : ((x > y) ? -1 : 0));
15030		}
15031	} );
15032	
15033	
15034	// Numeric sorting types - order doesn't matter here
15035	_addNumericSort( '' );
15036	
15037	
15038	$.extend( true, DataTable.ext.renderer, {
15039		header: {
15040			_: function ( settings, cell, column, classes ) {
15041				// No additional mark-up required
15042				// Attach a sort listener to update on sort - note that using the
15043				// `DT` namespace will allow the event to be removed automatically
15044				// on destroy, while the `dt` namespaced event is the one we are
15045				// listening for
15046				$(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
15047					if ( settings !== ctx ) { // need to check this this is the host
15048						return;               // table, not a nested one
15049					}
15050	
15051					var colIdx = column.idx;
15052	
15053					cell
15054						.removeClass(
15055							classes.sSortAsc +' '+
15056							classes.sSortDesc
15057						)
15058						.addClass( columns[ colIdx ] == 'asc' ?
15059							classes.sSortAsc : columns[ colIdx ] == 'desc' ?
15060								classes.sSortDesc :
15061								column.sSortingClass
15062						);
15063				} );
15064			},
15065	
15066			jqueryui: function ( settings, cell, column, classes ) {
15067				$('<div/>')
15068					.addClass( classes.sSortJUIWrapper )
15069					.append( cell.contents() )
15070					.append( $('<span/>')
15071						.addClass( classes.sSortIcon+' '+column.sSortingClassJUI )
15072					)
15073					.appendTo( cell );
15074	
15075				// Attach a sort listener to update on sort
15076				$(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
15077					if ( settings !== ctx ) {
15078						return;
15079					}
15080	
15081					var colIdx = column.idx;
15082	
15083					cell
15084						.removeClass( classes.sSortAsc +" "+classes.sSortDesc )
15085						.addClass( columns[ colIdx ] == 'asc' ?
15086							classes.sSortAsc : columns[ colIdx ] == 'desc' ?
15087								classes.sSortDesc :
15088								column.sSortingClass
15089						);
15090	
15091					cell
15092						.find( 'span.'+classes.sSortIcon )
15093						.removeClass(
15094							classes.sSortJUIAsc +" "+
15095							classes.sSortJUIDesc +" "+
15096							classes.sSortJUI +" "+
15097							classes.sSortJUIAscAllowed +" "+
15098							classes.sSortJUIDescAllowed
15099						)
15100						.addClass( columns[ colIdx ] == 'asc' ?
15101							classes.sSortJUIAsc : columns[ colIdx ] == 'desc' ?
15102								classes.sSortJUIDesc :
15103								column.sSortingClassJUI
15104						);
15105				} );
15106			}
15107		}
15108	} );
15109	
15110	/*
15111	 * Public helper functions. These aren't used internally by DataTables, or
15112	 * called by any of the options passed into DataTables, but they can be used
15113	 * externally by developers working with DataTables. They are helper functions
15114	 * to make working with DataTables a little bit easier.
15115	 */
15116	
15117	var __htmlEscapeEntities = function ( d ) {
15118		if (Array.isArray(d)) {
15119			d = d.join(',');
15120		}
15121	
15122		return typeof d === 'string' ?
15123			d
15124				.replace(/&/g, '&amp;')
15125				.replace(/</g, '&lt;')
15126				.replace(/>/g, '&gt;')
15127				.replace(/"/g, '&quot;') :
15128			d;
15129	};
15130	
15131	// Common logic for moment, luxon or a date action
15132	function __mld( dt, momentFn, luxonFn, dateFn, arg1 ) {
15133		if (window.moment) {
15134			return dt[momentFn]( arg1 );
15135		}
15136		else if (window.luxon) {
15137			return dt[luxonFn]( arg1 );
15138		}
15139		
15140		return dateFn ? dt[dateFn]( arg1 ) : dt;
15141	}
15142	
15143	
15144	var __mlWarning = false;
15145	function __mldObj (d, format, locale) {
15146		var dt;
15147	
15148		if (window.moment) {
15149			dt = window.moment.utc( d, format, locale, true );
15150	
15151			if (! dt.isValid()) {
15152				return null;
15153			}
15154		}
15155		else if (window.luxon) {
15156			dt = format
15157				? window.luxon.DateTime.fromFormat( d, format )
15158				: window.luxon.DateTime.fromISO( d );
15159	
15160			if (! dt.isValid) {
15161				return null;
15162			}
15163	
15164			dt.setLocale(locale);
15165		}
15166		else if (! format) {
15167			// No format given, must be ISO
15168			dt = new Date(d);
15169		}
15170		else {
15171			if (! __mlWarning) {
15172				alert('DataTables warning: Formatted date without Moment.js or Luxon - https://datatables.net/tn/17');
15173			}
15174	
15175			__mlWarning = true;
15176		}
15177	
15178		return dt;
15179	}
15180	
15181	// Wrapper for date, datetime and time which all operate the same way with the exception of
15182	// the output string for auto locale support
15183	function __mlHelper (localeString) {
15184		return function ( from, to, locale, def ) {
15185			// Luxon and Moment support
15186			// Argument shifting
15187			if ( arguments.length === 0 ) {
15188				locale = 'en';
15189				to = null; // means toLocaleString
15190				from = null; // means iso8601
15191			}
15192			else if ( arguments.length === 1 ) {
15193				locale = 'en';
15194				to = from;
15195				from = null;
15196			}
15197			else if ( arguments.length === 2 ) {
15198				locale = to;
15199				to = from;
15200				from = null;
15201			}
15202	
15203			var typeName = 'datetime-' + to;
15204	
15205			// Add type detection and sorting specific to this date format - we need to be able to identify
15206			// date type columns as such, rather than as numbers in extensions. Hence the need for this.
15207			if (! DataTable.ext.type.order[typeName]) {
15208				// The renderer will give the value to type detect as the type!
15209				DataTable.ext.type.detect.unshift(function (d) {
15210					return d === typeName ? typeName : false;
15211				});
15212	
15213				// The renderer gives us Moment, Luxon or Date obects for the sorting, all of which have a
15214				// `valueOf` which gives milliseconds epoch
15215				DataTable.ext.type.order[typeName + '-asc'] = function (a, b) {
15216					var x = a.valueOf();
15217					var y = b.valueOf();
15218	
15219					return x === y
15220						? 0
15221						: x < y
15222							? -1
15223							: 1;
15224				}
15225	
15226				DataTable.ext.type.order[typeName + '-desc'] = function (a, b) {
15227					var x = a.valueOf();
15228					var y = b.valueOf();
15229	
15230					return x === y
15231						? 0
15232						: x > y
15233							? -1
15234							: 1;
15235				}
15236			}
15237		
15238			return function ( d, type ) {
15239				// Allow for a default value
15240				if (d === null || d === undefined) {
15241					if (def === '--now') {
15242						// We treat everything as UTC further down, so no changes are
15243						// made, as such need to get the local date / time as if it were
15244						// UTC
15245						var local = new Date();
15246						d = new Date( Date.UTC(
15247							local.getFullYear(), local.getMonth(), local.getDate(),
15248							local.getHours(), local.getMinutes(), local.getSeconds()
15249						) );
15250					}
15251					else {
15252						d = '';
15253					}
15254				}
15255	
15256				if (type === 'type') {
15257					// Typing uses the type name for fast matching
15258					return typeName;
15259				}
15260	
15261				if (d === '') {
15262					return type !== 'sort'
15263						? ''
15264						: __mldObj('0000-01-01 00:00:00', null, locale);
15265				}
15266	
15267				// Shortcut. If `from` and `to` are the same, we are using the renderer to
15268				// format for ordering, not display - its already in the display format.
15269				if ( to !== null && from === to && type !== 'sort' && type !== 'type' && ! (d instanceof Date) ) {
15270					return d;
15271				}
15272	
15273				var dt = __mldObj(d, from, locale);
15274	
15275				if (dt === null) {
15276					return d;
15277				}
15278	
15279				if (type === 'sort') {
15280					return dt;
15281				}
15282				
15283				var formatted = to === null
15284					? __mld(dt, 'toDate', 'toJSDate', '')[localeString]()
15285					: __mld(dt, 'format', 'toFormat', 'toISOString', to);
15286	
15287				// XSS protection
15288				return type === 'display' ?
15289					__htmlEscapeEntities( formatted ) :
15290					formatted;
15291			};
15292		}
15293	}
15294	
15295	// Based on locale, determine standard number formatting
15296	// Fallback for legacy browsers is US English
15297	var __thousands = ',';
15298	var __decimal = '.';
15299	
15300	if (Intl) {
15301		try {
15302			var num = new Intl.NumberFormat().formatToParts(100000.1);
15303		
15304			for (var i=0 ; i<num.length ; i++) {
15305				if (num[i].type === 'group') {
15306					__thousands = num[i].value;
15307				}
15308				else if (num[i].type === 'decimal') {
15309					__decimal = num[i].value;
15310				}
15311			}
15312		}
15313		catch (e) {
15314			// noop
15315		}
15316	}
15317	
15318	// Formatted date time detection - use by declaring the formats you are going to use
15319	DataTable.datetime = function ( format, locale ) {
15320		var typeName = 'datetime-detect-' + format;
15321	
15322		if (! locale) {
15323			locale = 'en';
15324		}
15325	
15326		if (! DataTable.ext.type.order[typeName]) {
15327			DataTable.ext.type.detect.unshift(function (d) {
15328				var dt = __mldObj(d, format, locale);
15329				return d === '' || dt ? typeName : false;
15330			});
15331	
15332			DataTable.ext.type.order[typeName + '-pre'] = function (d) {
15333				return __mldObj(d, format, locale) || 0;
15334			}
15335		}
15336	}
15337	
15338	/**
15339	 * Helpers for `columns.render`.
15340	 *
15341	 * The options defined here can be used with the `columns.render` initialisation
15342	 * option to provide a display renderer. The following functions are defined:
15343	 *
15344	 * * `number` - Will format numeric data (defined by `columns.data`) for
15345	 *   display, retaining the original unformatted data for sorting and filtering.
15346	 *   It takes 5 parameters:
15347	 *   * `string` - Thousands grouping separator
15348	 *   * `string` - Decimal point indicator
15349	 *   * `integer` - Number of decimal points to show
15350	 *   * `string` (optional) - Prefix.
15351	 *   * `string` (optional) - Postfix (/suffix).
15352	 * * `text` - Escape HTML to help prevent XSS attacks. It has no optional
15353	 *   parameters.
15354	 *
15355	 * @example
15356	 *   // Column definition using the number renderer
15357	 *   {
15358	 *     data: "salary",
15359	 *     render: $.fn.dataTable.render.number( '\'', '.', 0, '$' )
15360	 *   }
15361	 *
15362	 * @namespace
15363	 */
15364	DataTable.render = {
15365		date: __mlHelper('toLocaleDateString'),
15366		datetime: __mlHelper('toLocaleString'),
15367		time: __mlHelper('toLocaleTimeString'),
15368		number: function ( thousands, decimal, precision, prefix, postfix ) {
15369			// Auto locale detection
15370			if (thousands === null || thousands === undefined) {
15371				thousands = __thousands;
15372			}
15373	
15374			if (decimal === null || decimal === undefined) {
15375				decimal = __decimal;
15376			}
15377	
15378			return {
15379				display: function ( d ) {
15380					if ( typeof d !== 'number' && typeof d !== 'string' ) {
15381						return d;
15382					}
15383	
15384					if (d === '' || d === null) {
15385						return d;
15386					}
15387	
15388					var negative = d < 0 ? '-' : '';
15389					var flo = parseFloat( d );
15390	
15391					// If NaN then there isn't much formatting that we can do - just
15392					// return immediately, escaping any HTML (this was supposed to
15393					// be a number after all)
15394					if ( isNaN( flo ) ) {
15395						return __htmlEscapeEntities( d );
15396					}
15397	
15398					flo = flo.toFixed( precision );
15399					d = Math.abs( flo );
15400	
15401					var intPart = parseInt( d, 10 );
15402					var floatPart = precision ?
15403						decimal+(d - intPart).toFixed( precision ).substring( 2 ):
15404						'';
15405	
15406					// If zero, then can't have a negative prefix
15407					if (intPart === 0 && parseFloat(floatPart) === 0) {
15408						negative = '';
15409					}
15410	
15411					return negative + (prefix||'') +
15412						intPart.toString().replace(
15413							/\B(?=(\d{3})+(?!\d))/g, thousands
15414						) +
15415						floatPart +
15416						(postfix||'');
15417				}
15418			};
15419		},
15420	
15421		text: function () {
15422			return {
15423				display: __htmlEscapeEntities,
15424				filter: __htmlEscapeEntities
15425			};
15426		}
15427	};
15428	
15429	
15430	/*
15431	 * This is really a good bit rubbish this method of exposing the internal methods
15432	 * publicly... - To be fixed in 2.0 using methods on the prototype
15433	 */
15434	
15435	
15436	/**
15437	 * Create a wrapper function for exporting an internal functions to an external API.
15438	 *  @param {string} fn API function name
15439	 *  @returns {function} wrapped function
15440	 *  @memberof DataTable#internal
15441	 */
15442	function _fnExternApiFunc (fn)
15443	{
15444		return function() {
15445			var args = [_fnSettingsFromNode( this[DataTable.ext.iApiIndex] )].concat(
15446				Array.prototype.slice.call(arguments)
15447			);
15448			return DataTable.ext.internal[fn].apply( this, args );
15449		};
15450	}
15451	
15452	
15453	/**
15454	 * Reference to internal functions for use by plug-in developers. Note that
15455	 * these methods are references to internal functions and are considered to be
15456	 * private. If you use these methods, be aware that they are liable to change
15457	 * between versions.
15458	 *  @namespace
15459	 */
15460	$.extend( DataTable.ext.internal, {
15461		_fnExternApiFunc: _fnExternApiFunc,
15462		_fnBuildAjax: _fnBuildAjax,
15463		_fnAjaxUpdate: _fnAjaxUpdate,
15464		_fnAjaxParameters: _fnAjaxParameters,
15465		_fnAjaxUpdateDraw: _fnAjaxUpdateDraw,
15466		_fnAjaxDataSrc: _fnAjaxDataSrc,
15467		_fnAddColumn: _fnAddColumn,
15468		_fnColumnOptions: _fnColumnOptions,
15469		_fnAdjustColumnSizing: _fnAdjustColumnSizing,
15470		_fnVisibleToColumnIndex: _fnVisibleToColumnIndex,
15471		_fnColumnIndexToVisible: _fnColumnIndexToVisible,
15472		_fnVisbleColumns: _fnVisbleColumns,
15473		_fnGetColumns: _fnGetColumns,
15474		_fnColumnTypes: _fnColumnTypes,
15475		_fnApplyColumnDefs: _fnApplyColumnDefs,
15476		_fnHungarianMap: _fnHungarianMap,
15477		_fnCamelToHungarian: _fnCamelToHungarian,
15478		_fnLanguageCompat: _fnLanguageCompat,
15479		_fnBrowserDetect: _fnBrowserDetect,
15480		_fnAddData: _fnAddData,
15481		_fnAddTr: _fnAddTr,
15482		_fnNodeToDataIndex: _fnNodeToDataIndex,
15483		_fnNodeToColumnIndex: _fnNodeToColumnIndex,
15484		_fnGetCellData: _fnGetCellData,
15485		_fnSetCellData: _fnSetCellData,
15486		_fnSplitObjNotation: _fnSplitObjNotation,
15487		_fnGetObjectDataFn: _fnGetObjectDataFn,
15488		_fnSetObjectDataFn: _fnSetObjectDataFn,
15489		_fnGetDataMaster: _fnGetDataMaster,
15490		_fnClearTable: _fnClearTable,
15491		_fnDeleteIndex: _fnDeleteIndex,
15492		_fnInvalidate: _fnInvalidate,
15493		_fnGetRowElements: _fnGetRowElements,
15494		_fnCreateTr: _fnCreateTr,
15495		_fnBuildHead: _fnBuildHead,
15496		_fnDrawHead: _fnDrawHead,
15497		_fnDraw: _fnDraw,
15498		_fnReDraw: _fnReDraw,
15499		_fnAddOptionsHtml: _fnAddOptionsHtml,
15500		_fnDetectHeader: _fnDetectHeader,
15501		_fnGetUniqueThs: _fnGetUniqueThs,
15502		_fnFeatureHtmlFilter: _fnFeatureHtmlFilter,
15503		_fnFilterComplete: _fnFilterComplete,
15504		_fnFilterCustom: _fnFilterCustom,
15505		_fnFilterColumn: _fnFilterColumn,
15506		_fnFilter: _fnFilter,
15507		_fnFilterCreateSearch: _fnFilterCreateSearch,
15508		_fnEscapeRegex: _fnEscapeRegex,
15509		_fnFilterData: _fnFilterData,
15510		_fnFeatureHtmlInfo: _fnFeatureHtmlInfo,
15511		_fnUpdateInfo: _fnUpdateInfo,
15512		_fnInfoMacros: _fnInfoMacros,
15513		_fnInitialise: _fnInitialise,
15514		_fnInitComplete: _fnInitComplete,
15515		_fnLengthChange: _fnLengthChange,
15516		_fnFeatureHtmlLength: _fnFeatureHtmlLength,
15517		_fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate,
15518		_fnPageChange: _fnPageChange,
15519		_fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing,
15520		_fnProcessingDisplay: _fnProcessingDisplay,
15521		_fnFeatureHtmlTable: _fnFeatureHtmlTable,
15522		_fnScrollDraw: _fnScrollDraw,
15523		_fnApplyToChildren: _fnApplyToChildren,
15524		_fnCalculateColumnWidths: _fnCalculateColumnWidths,
15525		_fnThrottle: _fnThrottle,
15526		_fnConvertToWidth: _fnConvertToWidth,
15527		_fnGetWidestNode: _fnGetWidestNode,
15528		_fnGetMaxLenString: _fnGetMaxLenString,
15529		_fnStringToCss: _fnStringToCss,
15530		_fnSortFlatten: _fnSortFlatten,
15531		_fnSort: _fnSort,
15532		_fnSortAria: _fnSortAria,
15533		_fnSortListener: _fnSortListener,
15534		_fnSortAttachListener: _fnSortAttachListener,
15535		_fnSortingClasses: _fnSortingClasses,
15536		_fnSortData: _fnSortData,
15537		_fnSaveState: _fnSaveState,
15538		_fnLoadState: _fnLoadState,
15539		_fnImplementState: _fnImplementState,
15540		_fnSettingsFromNode: _fnSettingsFromNode,
15541		_fnLog: _fnLog,
15542		_fnMap: _fnMap,
15543		_fnBindAction: _fnBindAction,
15544		_fnCallbackReg: _fnCallbackReg,
15545		_fnCallbackFire: _fnCallbackFire,
15546		_fnLengthOverflow: _fnLengthOverflow,
15547		_fnRenderer: _fnRenderer,
15548		_fnDataSource: _fnDataSource,
15549		_fnRowAttributes: _fnRowAttributes,
15550		_fnExtend: _fnExtend,
15551		_fnCalculateEnd: function () {} // Used by a lot of plug-ins, but redundant
15552		                                // in 1.10, so this dead-end function is
15553		                                // added to prevent errors
15554	} );
15555	
15556	
15557	// jQuery access
15558	$.fn.dataTable = DataTable;
15559	
15560	// Provide access to the host jQuery object (circular reference)
15561	DataTable.$ = $;
15562	
15563	// Legacy aliases
15564	$.fn.dataTableSettings = DataTable.settings;
15565	$.fn.dataTableExt = DataTable.ext;
15566	
15567	// With a capital `D` we return a DataTables API instance rather than a
15568	// jQuery object
15569	$.fn.DataTable = function ( opts ) {
15570		return $(this).dataTable( opts ).api();
15571	};
15572	
15573	// All properties that are available to $.fn.dataTable should also be
15574	// available on $.fn.DataTable
15575	$.each( DataTable, function ( prop, val ) {
15576		$.fn.DataTable[ prop ] = val;
15577	} );
15578	
15579	return DataTable;
15580}));

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.