PageSourceSearch

https://cgu-odisha.ac.in/wp-content/themes/cgu-child/js/cdn.datatables.net_1.13.4_js_jquery.dataTables.js

js cgu-odisha.ac.in collected 2026-10-04 01:45:39 UTC 456,433 bytes, 15,686 lines download raw bytes

1/*! DataTables 1.13.4
vendor: 46,563 bytes, lines 1-1387
1
2 * ©2008-2023 SpryMedia Ltd - datatables.net/license
3 */
4
5/**
6 * @summary     DataTables
7 * @description Paginate, search and order HTML tables
8 * @version     1.13.4
9 * @author      SpryMedia Ltd
10 * @contact     www.datatables.net
11 * @copyright   SpryMedia Ltd.
12 *
13 * This source file is free software, available under the following license:
14 *   MIT license - http://datatables.net/license
15 *
16 * This source file is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
19 *
20 * For details please refer to: http://www.datatables.net
21 */
22
23/*jslint evil: true, undef: true, browser: true */
24/*globals $,require,jQuery,define,_selector_run,_selector_opts,_selector_first,_selector_row_indexes,_ext,_Api,_api_register,_api_registerPlural,_re_new_lines,_re_html,_re_formatted_numeric,_re_escape_regex,_empty,_intVal,_numToDecimal,_isNumber,_isHtml,_htmlNumeric,_pluck,_pluck_order,_range,_stripHtml,_unique,_fnBuildAjax,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnAjaxDataSrc,_fnAddColumn,_fnColumnOptions,_fnAdjustColumnSizing,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnVisbleColumns,_fnGetColumns,_fnColumnTypes,_fnApplyColumnDefs,_fnHungarianMap,_fnCamelToHungarian,_fnLanguageCompat,_fnBrowserDetect,_fnAddData,_fnAddTr,_fnNodeToDataIndex,_fnNodeToColumnIndex,_fnGetCellData,_fnSetCellData,_fnSplitObjNotation,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnGetDataMaster,_fnClearTable,_fnDeleteIndex,_fnInvalidate,_fnGetRowElements,_fnCreateTr,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAddOptionsHtml,_fnDetectHeader,_fnGetUniqueThs,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnFilterCreateSearch,_fnEscapeRegex,_fnFilterData,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnInfoMacros,_fnInitialise,_fnInitComplete,_fnLengthChange,_fnFeatureHtmlLength,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnFeatureHtmlTable,_fnScrollDraw,_fnApplyToChildren,_fnCalculateColumnWidths,_fnThrottle,_fnConvertToWidth,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnSortFlatten,_fnSort,_fnSortAria,_fnSortListener,_fnSortAttachListener,_fnSortingClasses,_fnSortData,_fnSaveState,_fnLoadState,_fnSettingsFromNode,_fnLog,_fnMap,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnLengthOverflow,_fnRenderer,_fnDataSource,_fnRowAttributes*/
25
26(function( factory ) {
27	"use strict";
28
29	if ( typeof define === 'function' && define.amd ) {
30		// AMD
31		define( ['jquery'], function ( $ ) {
32			return factory( $, window, document );
33		} );
34	}
35	else if ( typeof exports === 'object' ) {
36		// CommonJS
37		// jQuery's factory checks for a global window - if it isn't present then it
38		// returns a factory function that expects the window object
39		var jq = require('jquery');
40
41		if (typeof window !== 'undefined') {
42			module.exports = function (root, $) {
43				if ( ! root ) {
44					// CommonJS environments without a window global must pass a
45					// root. This will give an error otherwise
46					root = window;
47				}
48
49				if ( ! $ ) {
50					$ = jq( root );
51				}
52
53				return factory( $, root, root.document );
54			};
55		}
56		else {
57			return factory( jq, window, window.document );
58		}
59	}
60	else {
61		// Browser
62		window.DataTable = factory( jQuery, window, document );
63	}
64}
65(function( $, window, document, undefined ) {
66	"use strict";
67
68	
69	var DataTable = function ( selector, options )
70	{
71		// Check if called with a window or jQuery object for DOM less applications
72		// This is for backwards compatibility
73		if (DataTable.factory(selector, options)) {
74			return DataTable;
75		}
76	
77		// When creating with `new`, create a new DataTable, returning the API instance
78		if (this instanceof DataTable) {
79			return $(selector).DataTable(options);
80		}
81		else {
82			// Argument switching
83			options = selector;
84		}
85	
86		/**
87		 * Perform a jQuery selector action on the table's TR elements (from the tbody) and
88		 * return the resulting jQuery object.
89		 *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
90		 *  @param {object} [oOpts] Optional parameters for modifying the rows to be included
91		 *  @param {string} [oOpts.filter=none] Select TR elements that meet the current filter
92		 *    criterion ("applied") or all TR elements (i.e. no filter).
93		 *  @param {string} [oOpts.order=current] Order of the TR elements in the processed array.
94		 *    Can be either 'current', whereby the current sorting of the table is used, or
95		 *    'original' whereby the original order the data was read into the table is used.
96		 *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
97		 *    ("current") or not ("all"). If 'current' is given, then order is assumed to be
98		 *    'current' and filter is 'applied', regardless of what they might be given as.
99		 *  @returns {object} jQuery object, filtered by the given selector.
100		 *  @dtopt API
101		 *  @deprecated Since v1.10
102		 *
103		 *  @example
104		 *    $(document).ready(function() {
105		 *      var oTable = $('#example').dataTable();
106		 *
107		 *      // Highlight every second row
108		 *      oTable.$('tr:odd').css('backgroundColor', 'blue');
109		 *    } );
110		 *
111		 *  @example
112		 *    $(document).ready(function() {
113		 *      var oTable = $('#example').dataTable();
114		 *
115		 *      // Filter to rows with 'Webkit' in them, add a background colour and then
116		 *      // remove the filter, thus highlighting the 'Webkit' rows only.
117		 *      oTable.fnFilter('Webkit');
118		 *      oTable.$('tr', {"search": "applied"}).css('backgroundColor', 'blue');
119		 *      oTable.fnFilter('');
120		 *    } );
121		 */
122		this.$ = function ( sSelector, oOpts )
123		{
124			return this.api(true).$( sSelector, oOpts );
125		};
126		
127		
128		/**
129		 * Almost identical to $ in operation, but in this case returns the data for the matched
130		 * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes
131		 * rather than any descendants, so the data can be obtained for the row/cell. If matching
132		 * rows are found, the data returned is the original data array/object that was used to
133		 * create the row (or a generated array if from a DOM source).
134		 *
135		 * This method is often useful in-combination with $ where both functions are given the
136		 * same parameters and the array indexes will match identically.
137		 *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
138		 *  @param {object} [oOpts] Optional parameters for modifying the rows to be included
139		 *  @param {string} [oOpts.filter=none] Select elements that meet the current filter
140		 *    criterion ("applied") or all elements (i.e. no filter).
141		 *  @param {string} [oOpts.order=current] Order of the data in the processed array.
142		 *    Can be either 'current', whereby the current sorting of the table is used, or
143		 *    'original' whereby the original order the data was read into the table is used.
144		 *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
145		 *    ("current") or not ("all"). If 'current' is given, then order is assumed to be
146		 *    'current' and filter is 'applied', regardless of what they might be given as.
147		 *  @returns {array} Data for the matched elements. If any elements, as a result of the
148		 *    selector, were not TR, TD or TH elements in the DataTable, they will have a null
149		 *    entry in the array.
150		 *  @dtopt API
151		 *  @deprecated Since v1.10
152		 *
153		 *  @example
154		 *    $(document).ready(function() {
155		 *      var oTable = $('#example').dataTable();
156		 *
157		 *      // Get the data from the first row in the table
158		 *      var data = oTable._('tr:first');
159		 *
160		 *      // Do something useful with the data
161		 *      alert( "First cell is: "+data[0] );
162		 *    } );
163		 *
164		 *  @example
165		 *    $(document).ready(function() {
166		 *      var oTable = $('#example').dataTable();
167		 *
168		 *      // Filter to 'Webkit' and get all data for
169		 *      oTable.fnFilter('Webkit');
170		 *      var data = oTable._('tr', {"search": "applied"});
171		 *
172		 *      // Do something with the data
173		 *      alert( data.length+" rows matched the search" );
174		 *    } );
175		 */
176		this._ = function ( sSelector, oOpts )
177		{
178			return this.api(true).rows( sSelector, oOpts ).data();
179		};
180		
181		
182		/**
183		 * Create a DataTables Api instance, with the currently selected tables for
184		 * the Api's context.
185		 * @param {boolean} [traditional=false] Set the API instance's context to be
186		 *   only the table referred to by the `DataTable.ext.iApiIndex` option, as was
187		 *   used in the API presented by DataTables 1.9- (i.e. the traditional mode),
188		 *   or if all tables captured in the jQuery object should be used.
189		 * @return {DataTables.Api}
190		 */
191		this.api = function ( traditional )
192		{
193			return traditional ?
194				new _Api(
195					_fnSettingsFromNode( this[ _ext.iApiIndex ] )
196				) :
197				new _Api( this );
198		};
199		
200		
201		/**
202		 * Add a single new row or multiple rows of data to the table. Please note
203		 * that this is suitable for client-side processing only - if you are using
204		 * server-side processing (i.e. "bServerSide": true), then to add data, you
205		 * must add it to the data source, i.e. the server-side, through an Ajax call.
206		 *  @param {array|object} data The data to be added to the table. This can be:
207		 *    <ul>
208		 *      <li>1D array of data - add a single row with the data provided</li>
209		 *      <li>2D array of arrays - add multiple rows in a single call</li>
210		 *      <li>object - data object when using <i>mData</i></li>
211		 *      <li>array of objects - multiple data objects when using <i>mData</i></li>
212		 *    </ul>
213		 *  @param {bool} [redraw=true] redraw the table or not
214		 *  @returns {array} An array of integers, representing the list of indexes in
215		 *    <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to
216		 *    the table.
217		 *  @dtopt API
218		 *  @deprecated Since v1.10
219		 *
220		 *  @example
221		 *    // Global var for counter
222		 *    var giCount = 2;
223		 *
224		 *    $(document).ready(function() {
225		 *      $('#example').dataTable();
226		 *    } );
227		 *
228		 *    function fnClickAddRow() {
229		 *      $('#example').dataTable().fnAddData( [
230		 *        giCount+".1",
231		 *        giCount+".2",
232		 *        giCount+".3",
233		 *        giCount+".4" ]
234		 *      );
235		 *
236		 *      giCount++;
237		 *    }
238		 */
239		this.fnAddData = function( data, redraw )
240		{
241			var api = this.api( true );
242		
243			/* Check if we want to add multiple rows or not */
244			var rows = Array.isArray(data) && ( Array.isArray(data[0]) || $.isPlainObject(data[0]) ) ?
245				api.rows.add( data ) :
246				api.row.add( data );
247		
248			if ( redraw === undefined || redraw ) {
249				api.draw();
250			}
251		
252			return rows.flatten().toArray();
253		};
254		
255		
256		/**
257		 * This function will make DataTables recalculate the column sizes, based on the data
258		 * contained in the table and the sizes applied to the columns (in the DOM, CSS or
259		 * through the sWidth parameter). This can be useful when the width of the table's
260		 * parent element changes (for example a window resize).
261		 *  @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to
262		 *  @dtopt API
263		 *  @deprecated Since v1.10
264		 *
265		 *  @example
266		 *    $(document).ready(function() {
267		 *      var oTable = $('#example').dataTable( {
268		 *        "sScrollY": "200px",
269		 *        "bPaginate": false
270		 *      } );
271		 *
272		 *      $(window).on('resize', function () {
273		 *        oTable.fnAdjustColumnSizing();
274		 *      } );
275		 *    } );
276		 */
277		this.fnAdjustColumnSizing = function ( bRedraw )
278		{
279			var api = this.api( true ).columns.adjust();
280			var settings = api.settings()[0];
281			var scroll = settings.oScroll;
282		
283			if ( bRedraw === undefined || bRedraw ) {
284				api.draw( false );
285			}
286			else if ( scroll.sX !== "" || scroll.sY !== "" ) {
287				/* If not redrawing, but scrolling, we want to apply the new column sizes anyway */
288				_fnScrollDraw( settings );
289			}
290		};
291		
292		
293		/**
294		 * Quickly and simply clear a table
295		 *  @param {bool} [bRedraw=true] redraw the table or not
296		 *  @dtopt API
297		 *  @deprecated Since v1.10
298		 *
299		 *  @example
300		 *    $(document).ready(function() {
301		 *      var oTable = $('#example').dataTable();
302		 *
303		 *      // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...)
304		 *      oTable.fnClearTable();
305		 *    } );
306		 */
307		this.fnClearTable = function( bRedraw )
308		{
309			var api = this.api( true ).clear();
310		
311			if ( bRedraw === undefined || bRedraw ) {
312				api.draw();
313			}
314		};
315		
316		
317		/**
318		 * The exact opposite of 'opening' a row, this function will close any rows which
319		 * are currently 'open'.
320		 *  @param {node} nTr the table row to 'close'
321		 *  @returns {int} 0 on success, or 1 if failed (can't find the row)
322		 *  @dtopt API
323		 *  @deprecated Since v1.10
324		 *
325		 *  @example
326		 *    $(document).ready(function() {
327		 *      var oTable;
328		 *
329		 *      // 'open' an information row when a row is clicked on
330		 *      $('#example tbody tr').click( function () {
331		 *        if ( oTable.fnIsOpen(this) ) {
332		 *          oTable.fnClose( this );
333		 *        } else {
334		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
335		 *        }
336		 *      } );
337		 *
338		 *      oTable = $('#example').dataTable();
339		 *    } );
340		 */
341		this.fnClose = function( nTr )
342		{
343			this.api( true ).row( nTr ).child.hide();
344		};
345		
346		
347		/**
348		 * Remove a row for the table
349		 *  @param {mixed} target The index of the row from aoData to be deleted, or
350		 *    the TR element you want to delete
351		 *  @param {function|null} [callBack] Callback function
352		 *  @param {bool} [redraw=true] Redraw the table or not
353		 *  @returns {array} The row that was deleted
354		 *  @dtopt API
355		 *  @deprecated Since v1.10
356		 *
357		 *  @example
358		 *    $(document).ready(function() {
359		 *      var oTable = $('#example').dataTable();
360		 *
361		 *      // Immediately remove the first row
362		 *      oTable.fnDeleteRow( 0 );
363		 *    } );
364		 */
365		this.fnDeleteRow = function( target, callback, redraw )
366		{
367			var api = this.api( true );
368			var rows = api.rows( target );
369			var settings = rows.settings()[0];
370			var data = settings.aoData[ rows[0][0] ];
371		
372			rows.remove();
373		
374			if ( callback ) {
375				callback.call( this, settings, data );
376			}
377		
378			if ( redraw === undefined || redraw ) {
379				api.draw();
380			}
381		
382			return data;
383		};
384		
385		
386		/**
387		 * Restore the table to it's original state in the DOM by removing all of DataTables
388		 * enhancements, alterations to the DOM structure of the table and event listeners.
389		 *  @param {boolean} [remove=false] Completely remove the table from the DOM
390		 *  @dtopt API
391		 *  @deprecated Since v1.10
392		 *
393		 *  @example
394		 *    $(document).ready(function() {
395		 *      // This example is fairly pointless in reality, but shows how fnDestroy can be used
396		 *      var oTable = $('#example').dataTable();
397		 *      oTable.fnDestroy();
398		 *    } );
399		 */
400		this.fnDestroy = function ( remove )
401		{
402			this.api( true ).destroy( remove );
403		};
404		
405		
406		/**
407		 * Redraw the table
408		 *  @param {bool} [complete=true] Re-filter and resort (if enabled) the table before the draw.
409		 *  @dtopt API
410		 *  @deprecated Since v1.10
411		 *
412		 *  @example
413		 *    $(document).ready(function() {
414		 *      var oTable = $('#example').dataTable();
415		 *
416		 *      // Re-draw the table - you wouldn't want to do it here, but it's an example :-)
417		 *      oTable.fnDraw();
418		 *    } );
419		 */
420		this.fnDraw = function( complete )
421		{
422			// Note that this isn't an exact match to the old call to _fnDraw - it takes
423			// into account the new data, but can hold position.
424			this.api( true ).draw( complete );
425		};
426		
427		
428		/**
429		 * Filter the input based on data
430		 *  @param {string} sInput String to filter the table on
431		 *  @param {int|null} [iColumn] Column to limit filtering to
432		 *  @param {bool} [bRegex=false] Treat as regular expression or not
433		 *  @param {bool} [bSmart=true] Perform smart filtering or not
434		 *  @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es)
435		 *  @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false)
436		 *  @dtopt API
437		 *  @deprecated Since v1.10
438		 *
439		 *  @example
440		 *    $(document).ready(function() {
441		 *      var oTable = $('#example').dataTable();
442		 *
443		 *      // Sometime later - filter...
444		 *      oTable.fnFilter( 'test string' );
445		 *    } );
446		 */
447		this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive )
448		{
449			var api = this.api( true );
450		
451			if ( iColumn === null || iColumn === undefined ) {
452				api.search( sInput, bRegex, bSmart, bCaseInsensitive );
453			}
454			else {
455				api.column( iColumn ).search( sInput, bRegex, bSmart, bCaseInsensitive );
456			}
457		
458			api.draw();
459		};
460		
461		
462		/**
463		 * Get the data for the whole table, an individual row or an individual cell based on the
464		 * provided parameters.
465		 *  @param {int|node} [src] A TR row node, TD/TH cell node or an integer. If given as
466		 *    a TR node then the data source for the whole row will be returned. If given as a
467		 *    TD/TH cell node then iCol will be automatically calculated and the data for the
468		 *    cell returned. If given as an integer, then this is treated as the aoData internal
469		 *    data index for the row (see fnGetPosition) and the data for that row used.
470		 *  @param {int} [col] Optional column index that you want the data of.
471		 *  @returns {array|object|string} If mRow is undefined, then the data for all rows is
472		 *    returned. If mRow is defined, just data for that row, and is iCol is
473		 *    defined, only data for the designated cell is returned.
474		 *  @dtopt API
475		 *  @deprecated Since v1.10
476		 *
477		 *  @example
478		 *    // Row data
479		 *    $(document).ready(function() {
480		 *      oTable = $('#example').dataTable();
481		 *
482		 *      oTable.$('tr').click( function () {
483		 *        var data = oTable.fnGetData( this );
484		 *        // ... do something with the array / object of data for the row
485		 *      } );
486		 *    } );
487		 *
488		 *  @example
489		 *    // Individual cell data
490		 *    $(document).ready(function() {
491		 *      oTable = $('#example').dataTable();
492		 *
493		 *      oTable.$('td').click( function () {
494		 *        var sData = oTable.fnGetData( this );
495		 *        alert( 'The cell clicked on had the value of '+sData );
496		 *      } );
497		 *    } );
498		 */
499		this.fnGetData = function( src, col )
500		{
501			var api = this.api( true );
502		
503			if ( src !== undefined ) {
504				var type = src.nodeName ? src.nodeName.toLowerCase() : '';
505		
506				return col !== undefined || type == 'td' || type == 'th' ?
507					api.cell( src, col ).data() :
508					api.row( src ).data() || null;
509			}
510		
511			return api.data().toArray();
512		};
513		
514		
515		/**
516		 * Get an array of the TR nodes that are used in the table's body. Note that you will
517		 * typically want to use the '$' API method in preference to this as it is more
518		 * flexible.
519		 *  @param {int} [iRow] Optional row index for the TR element you want
520		 *  @returns {array|node} If iRow is undefined, returns an array of all TR elements
521		 *    in the table's body, or iRow is defined, just the TR element requested.
522		 *  @dtopt API
523		 *  @deprecated Since v1.10
524		 *
525		 *  @example
526		 *    $(document).ready(function() {
527		 *      var oTable = $('#example').dataTable();
528		 *
529		 *      // Get the nodes from the table
530		 *      var nNodes = oTable.fnGetNodes( );
531		 *    } );
532		 */
533		this.fnGetNodes = function( iRow )
534		{
535			var api = this.api( true );
536		
537			return iRow !== undefined ?
538				api.row( iRow ).node() :
539				api.rows().nodes().flatten().toArray();
540		};
541		
542		
543		/**
544		 * Get the array indexes of a particular cell from it's DOM element
545		 * and column index including hidden columns
546		 *  @param {node} node this can either be a TR, TD or TH in the table's body
547		 *  @returns {int} If nNode is given as a TR, then a single index is returned, or
548		 *    if given as a cell, an array of [row index, column index (visible),
549		 *    column index (all)] is given.
550		 *  @dtopt API
551		 *  @deprecated Since v1.10
552		 *
553		 *  @example
554		 *    $(document).ready(function() {
555		 *      $('#example tbody td').click( function () {
556		 *        // Get the position of the current data from the node
557		 *        var aPos = oTable.fnGetPosition( this );
558		 *
559		 *        // Get the data array for this row
560		 *        var aData = oTable.fnGetData( aPos[0] );
561		 *
562		 *        // Update the data array and return the value
563		 *        aData[ aPos[1] ] = 'clicked';
564		 *        this.innerHTML = 'clicked';
565		 *      } );
566		 *
567		 *      // Init DataTables
568		 *      oTable = $('#example').dataTable();
569		 *    } );
570		 */
571		this.fnGetPosition = function( node )
572		{
573			var api = this.api( true );
574			var nodeName = node.nodeName.toUpperCase();
575		
576			if ( nodeName == 'TR' ) {
577				return api.row( node ).index();
578			}
579			else if ( nodeName == 'TD' || nodeName == 'TH' ) {
580				var cell = api.cell( node ).index();
581		
582				return [
583					cell.row,
584					cell.columnVisible,
585					cell.column
586				];
587			}
588			return null;
589		};
590		
591		
592		/**
593		 * Check to see if a row is 'open' or not.
594		 *  @param {node} nTr the table row to check
595		 *  @returns {boolean} true if the row is currently open, false otherwise
596		 *  @dtopt API
597		 *  @deprecated Since v1.10
598		 *
599		 *  @example
600		 *    $(document).ready(function() {
601		 *      var oTable;
602		 *
603		 *      // 'open' an information row when a row is clicked on
604		 *      $('#example tbody tr').click( function () {
605		 *        if ( oTable.fnIsOpen(this) ) {
606		 *          oTable.fnClose( this );
607		 *        } else {
608		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
609		 *        }
610		 *      } );
611		 *
612		 *      oTable = $('#example').dataTable();
613		 *    } );
614		 */
615		this.fnIsOpen = function( nTr )
616		{
617			return this.api( true ).row( nTr ).child.isShown();
618		};
619		
620		
621		/**
622		 * This function will place a new row directly after a row which is currently
623		 * on display on the page, with the HTML contents that is passed into the
624		 * function. This can be used, for example, to ask for confirmation that a
625		 * particular record should be deleted.
626		 *  @param {node} nTr The table row to 'open'
627		 *  @param {string|node|jQuery} mHtml The HTML to put into the row
628		 *  @param {string} sClass Class to give the new TD cell
629		 *  @returns {node} The row opened. Note that if the table row passed in as the
630		 *    first parameter, is not found in the table, this method will silently
631		 *    return.
632		 *  @dtopt API
633		 *  @deprecated Since v1.10
634		 *
635		 *  @example
636		 *    $(document).ready(function() {
637		 *      var oTable;
638		 *
639		 *      // 'open' an information row when a row is clicked on
640		 *      $('#example tbody tr').click( function () {
641		 *        if ( oTable.fnIsOpen(this) ) {
642		 *          oTable.fnClose( this );
643		 *        } else {
644		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
645		 *        }
646		 *      } );
647		 *
648		 *      oTable = $('#example').dataTable();
649		 *    } );
650		 */
651		this.fnOpen = function( nTr, mHtml, sClass )
652		{
653			return this.api( true )
654				.row( nTr )
655				.child( mHtml, sClass )
656				.show()
657				.child()[0];
658		};
659		
660		
661		/**
662		 * Change the pagination - provides the internal logic for pagination in a simple API
663		 * function. With this function you can have a DataTables table go to the next,
664		 * previous, first or last pages.
665		 *  @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
666		 *    or page number to jump to (integer), note that page 0 is the first page.
667		 *  @param {bool} [bRedraw=true] Redraw the table or not
668		 *  @dtopt API
669		 *  @deprecated Since v1.10
670		 *
671		 *  @example
672		 *    $(document).ready(function() {
673		 *      var oTable = $('#example').dataTable();
674		 *      oTable.fnPageChange( 'next' );
675		 *    } );
676		 */
677		this.fnPageChange = function ( mAction, bRedraw )
678		{
679			var api = this.api( true ).page( mAction );
680		
681			if ( bRedraw === undefined || bRedraw ) {
682				api.draw(false);
683			}
684		};
685		
686		
687		/**
688		 * Show a particular column
689		 *  @param {int} iCol The column whose display should be changed
690		 *  @param {bool} bShow Show (true) or hide (false) the column
691		 *  @param {bool} [bRedraw=true] Redraw the table or not
692		 *  @dtopt API
693		 *  @deprecated Since v1.10
694		 *
695		 *  @example
696		 *    $(document).ready(function() {
697		 *      var oTable = $('#example').dataTable();
698		 *
699		 *      // Hide the second column after initialisation
700		 *      oTable.fnSetColumnVis( 1, false );
701		 *    } );
702		 */
703		this.fnSetColumnVis = function ( iCol, bShow, bRedraw )
704		{
705			var api = this.api( true ).column( iCol ).visible( bShow );
706		
707			if ( bRedraw === undefined || bRedraw ) {
708				api.columns.adjust().draw();
709			}
710		};
711		
712		
713		/**
714		 * Get the settings for a particular table for external manipulation
715		 *  @returns {object} DataTables settings object. See
716		 *    {@link DataTable.models.oSettings}
717		 *  @dtopt API
718		 *  @deprecated Since v1.10
719		 *
720		 *  @example
721		 *    $(document).ready(function() {
722		 *      var oTable = $('#example').dataTable();
723		 *      var oSettings = oTable.fnSettings();
724		 *
725		 *      // Show an example parameter from the settings
726		 *      alert( oSettings._iDisplayStart );
727		 *    } );
728		 */
729		this.fnSettings = function()
730		{
731			return _fnSettingsFromNode( this[_ext.iApiIndex] );
732		};
733		
734		
735		/**
736		 * Sort the table by a particular column
737		 *  @param {int} iCol the data index to sort on. Note that this will not match the
738		 *    'display index' if you have hidden data entries
739		 *  @dtopt API
740		 *  @deprecated Since v1.10
741		 *
742		 *  @example
743		 *    $(document).ready(function() {
744		 *      var oTable = $('#example').dataTable();
745		 *
746		 *      // Sort immediately with columns 0 and 1
747		 *      oTable.fnSort( [ [0,'asc'], [1,'asc'] ] );
748		 *    } );
749		 */
750		this.fnSort = function( aaSort )
751		{
752			this.api( true ).order( aaSort ).draw();
753		};
754		
755		
756		/**
757		 * Attach a sort listener to an element for a given column
758		 *  @param {node} nNode the element to attach the sort listener to
759		 *  @param {int} iColumn the column that a click on this node will sort on
760		 *  @param {function} [fnCallback] callback function when sort is run
761		 *  @dtopt API
762		 *  @deprecated Since v1.10
763		 *
764		 *  @example
765		 *    $(document).ready(function() {
766		 *      var oTable = $('#example').dataTable();
767		 *
768		 *      // Sort on column 1, when 'sorter' is clicked on
769		 *      oTable.fnSortListener( document.getElementById('sorter'), 1 );
770		 *    } );
771		 */
772		this.fnSortListener = function( nNode, iColumn, fnCallback )
773		{
774			this.api( true ).order.listener( nNode, iColumn, fnCallback );
775		};
776		
777		
778		/**
779		 * Update a table cell or row - this method will accept either a single value to
780		 * update the cell with, an array of values with one element for each column or
781		 * an object in the same format as the original data source. The function is
782		 * self-referencing in order to make the multi column updates easier.
783		 *  @param {object|array|string} mData Data to update the cell/row with
784		 *  @param {node|int} mRow TR element you want to update or the aoData index
785		 *  @param {int} [iColumn] The column to update, give as null or undefined to
786		 *    update a whole row.
787		 *  @param {bool} [bRedraw=true] Redraw the table or not
788		 *  @param {bool} [bAction=true] Perform pre-draw actions or not
789		 *  @returns {int} 0 on success, 1 on error
790		 *  @dtopt API
791		 *  @deprecated Since v1.10
792		 *
793		 *  @example
794		 *    $(document).ready(function() {
795		 *      var oTable = $('#example').dataTable();
796		 *      oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell
797		 *      oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], $('tbody tr')[0] ); // Row
798		 *    } );
799		 */
800		this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction )
801		{
802			var api = this.api( true );
803		
804			if ( iColumn === undefined || iColumn === null ) {
805				api.row( mRow ).data( mData );
806			}
807			else {
808				api.cell( mRow, iColumn ).data( mData );
809			}
810		
811			if ( bAction === undefined || bAction ) {
812				api.columns.adjust();
813			}
814		
815			if ( bRedraw === undefined || bRedraw ) {
816				api.draw();
817			}
818			return 0;
819		};
820		
821		
822		/**
823		 * Provide a common method for plug-ins to check the version of DataTables being used, in order
824		 * to ensure compatibility.
825		 *  @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the
826		 *    formats "X" and "X.Y" are also acceptable.
827		 *  @returns {boolean} true if this version of DataTables is greater or equal to the required
828		 *    version, or false if this version of DataTales is not suitable
829		 *  @method
830		 *  @dtopt API
831		 *  @deprecated Since v1.10
832		 *
833		 *  @example
834		 *    $(document).ready(function() {
835		 *      var oTable = $('#example').dataTable();
836		 *      alert( oTable.fnVersionCheck( '1.9.0' ) );
837		 *    } );
838		 */
839		this.fnVersionCheck = _ext.fnVersionCheck;
840		
841	
842		var _that = this;
843		var emptyInit = options === undefined;
844		var len = this.length;
845	
846		if ( emptyInit ) {
847			options = {};
848		}
849	
850		this.oApi = this.internal = _ext.internal;
851	
852		// Extend with old style plug-in API methods
853		for ( var fn in DataTable.ext.internal ) {
854			if ( fn ) {
855				this[fn] = _fnExternApiFunc(fn);
856			}
857		}
858	
859		this.each(function() {
860			// For each initialisation we want to give it a clean initialisation
861			// object that can be bashed around
862			var o = {};
863			var oInit = len > 1 ? // optimisation for single table case
864				_fnExtend( o, options, true ) :
865				options;
866	
867			/*global oInit,_that,emptyInit*/
868			var i=0, iLen, j, jLen, k, kLen;
869			var sId = this.getAttribute( 'id' );
870			var bInitHandedOff = false;
871			var defaults = DataTable.defaults;
872			var $this = $(this);
873			
874			
875			/* Sanity check */
876			if ( this.nodeName.toLowerCase() != 'table' )
877			{
878				_fnLog( null, 0, 'Non-table node initialisation ('+this.nodeName+')', 2 );
879				return;
880			}
881			
882			/* Backwards compatibility for the defaults */
883			_fnCompatOpts( defaults );
884			_fnCompatCols( defaults.column );
885			
886			/* Convert the camel-case defaults to Hungarian */
887			_fnCamelToHungarian( defaults, defaults, true );
888			_fnCamelToHungarian( defaults.column, defaults.column, true );
889			
890			/* Setting up the initialisation object */
891			_fnCamelToHungarian( defaults, $.extend( oInit, $this.data() ), true );
892			
893			
894			
895			/* Check to see if we are re-initialising a table */
896			var allSettings = DataTable.settings;
897			for ( i=0, iLen=allSettings.length ; i<iLen ; i++ )
898			{
899				var s = allSettings[i];
900			
901				/* Base check on table node */
902				if (
903					s.nTable == this ||
904					(s.nTHead && s.nTHead.parentNode == this) ||
905					(s.nTFoot && s.nTFoot.parentNode == this)
906				) {
907					var bRetrieve = oInit.bRetrieve !== undefined ? oInit.bRetrieve : defaults.bRetrieve;
908					var bDestroy = oInit.bDestroy !== undefined ? oInit.bDestroy : defaults.bDestroy;
909			
910					if ( emptyInit || bRetrieve )
911					{
912						return s.oInstance;
913					}
914					else if ( bDestroy )
915					{
916						s.oInstance.fnDestroy();
917						break;
918					}
919					else
920					{
921						_fnLog( s, 0, 'Cannot reinitialise DataTable', 3 );
922						return;
923					}
924				}
925			
926				/* If the element we are initialising has the same ID as a table which was previously
927				 * initialised, but the table nodes don't match (from before) then we destroy the old
928				 * instance by simply deleting it. This is under the assumption that the table has been
929				 * destroyed by other methods. Anyone using non-id selectors will need to do this manually
930				 */
931				if ( s.sTableId == this.id )
932				{
933					allSettings.splice( i, 1 );
934					break;
935				}
936			}
937			
938			/* Ensure the table has an ID - required for accessibility */
939			if ( sId === null || sId === "" )
940			{
941				sId = "DataTables_Table_"+(DataTable.ext._unique++);
942				this.id = sId;
943			}
944			
945			/* Create the settings object for this table and set some of the default parameters */
946			var oSettings = $.extend( true, {}, DataTable.models.oSettings, {
947				"sDestroyWidth": $this[0].style.width,
948				"sInstance":     sId,
949				"sTableId":      sId
950			} );
951			oSettings.nTable = this;
952			oSettings.oApi   = _that.internal;
953			oSettings.oInit  = oInit;
954			
955			allSettings.push( oSettings );
956			
957			// Need to add the instance after the instance after the settings object has been added
958			// to the settings array, so we can self reference the table instance if more than one
959			oSettings.oInstance = (_that.length===1) ? _that : $this.dataTable();
960			
961			// Backwards compatibility, before we apply all the defaults
962			_fnCompatOpts( oInit );
963			_fnLanguageCompat( oInit.oLanguage );
964			
965			// If the length menu is given, but the init display length is not, use the length menu
966			if ( oInit.aLengthMenu && ! oInit.iDisplayLength )
967			{
968				oInit.iDisplayLength = Array.isArray( oInit.aLengthMenu[0] ) ?
969					oInit.aLengthMenu[0][0] : oInit.aLengthMenu[0];
970			}
971			
972			// Apply the defaults and init options to make a single init object will all
973			// options defined from defaults and instance options.
974			oInit = _fnExtend( $.extend( true, {}, defaults ), oInit );
975			
976			
977			// Map the initialisation options onto the settings object
978			_fnMap( oSettings.oFeatures, oInit, [
979				"bPaginate",
980				"bLengthChange",
981				"bFilter",
982				"bSort",
983				"bSortMulti",
984				"bInfo",
985				"bProcessing",
986				"bAutoWidth",
987				"bSortClasses",
988				"bServerSide",
989				"bDeferRender"
990			] );
991			_fnMap( oSettings, oInit, [
992				"asStripeClasses",
993				"ajax",
994				"fnServerData",
995				"fnFormatNumber",
996				"sServerMethod",
997				"aaSorting",
998				"aaSortingFixed",
999				"aLengthMenu",
1000				"sPaginationType",
1001				"sAjaxSource",
1002				"sAjaxDataProp",
1003				"iStateDuration",
1004				"sDom",
1005				"bSortCellsTop",
1006				"iTabIndex",
1007				"fnStateLoadCallback",
1008				"fnStateSaveCallback",
1009				"renderer",
1010				"searchDelay",
1011				"rowId",
1012				[ "iCookieDuration", "iStateDuration" ], // backwards compat
1013				[ "oSearch", "oPreviousSearch" ],
1014				[ "aoSearchCols", "aoPreSearchCols" ],
1015				[ "iDisplayLength", "_iDisplayLength" ]
1016			] );
1017			_fnMap( oSettings.oScroll, oInit, [
1018				[ "sScrollX", "sX" ],
1019				[ "sScrollXInner", "sXInner" ],
1020				[ "sScrollY", "sY" ],
1021				[ "bScrollCollapse", "bCollapse" ]
1022			] );
1023			_fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" );
1024			
1025			/* Callback functions which are array driven */
1026			_fnCallbackReg( oSettings, 'aoDrawCallback',       oInit.fnDrawCallback,      'user' );
1027			_fnCallbackReg( oSettings, 'aoServerParams',       oInit.fnServerParams,      'user' );
1028			_fnCallbackReg( oSettings, 'aoStateSaveParams',    oInit.fnStateSaveParams,   'user' );
1029			_fnCallbackReg( oSettings, 'aoStateLoadParams',    oInit.fnStateLoadParams,   'user' );
1030			_fnCallbackReg( oSettings, 'aoStateLoaded',        oInit.fnStateLoaded,       'user' );
1031			_fnCallbackReg( oSettings, 'aoRowCallback',        oInit.fnRowCallback,       'user' );
1032			_fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow,        'user' );
1033			_fnCallbackReg( oSettings, 'aoHeaderCallback',     oInit.fnHeaderCallback,    'user' );
1034			_fnCallbackReg( oSettings, 'aoFooterCallback',     oInit.fnFooterCallback,    'user' );
1035			_fnCallbackReg( oSettings, 'aoInitComplete',       oInit.fnInitComplete,      'user' );
1036			_fnCallbackReg( oSettings, 'aoPreDrawCallback',    oInit.fnPreDrawCallback,   'user' );
1037			
1038			oSettings.rowIdFn = _fnGetObjectDataFn( oInit.rowId );
1039			
1040			/* Browser support detection */
1041			_fnBrowserDetect( oSettings );
1042			
1043			var oClasses = oSettings.oClasses;
1044			
1045			$.extend( oClasses, DataTable.ext.classes, oInit.oClasses );
1046			$this.addClass( oClasses.sTable );
1047			
1048			
1049			if ( oSettings.iInitDisplayStart === undefined )
1050			{
1051				/* Display start point, taking into account the save saving */
1052				oSettings.iInitDisplayStart = oInit.iDisplayStart;
1053				oSettings._iDisplayStart = oInit.iDisplayStart;
1054			}
1055			
1056			if ( oInit.iDeferLoading !== null )
1057			{
1058				oSettings.bDeferLoading = true;
1059				var tmp = Array.isArray( oInit.iDeferLoading );
1060				oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading;
1061				oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading;
1062			}
1063			
1064			/* Language definitions */
1065			var oLanguage = oSettings.oLanguage;
1066			$.extend( true, oLanguage, oInit.oLanguage );
1067			
1068			if ( oLanguage.sUrl )
1069			{
1070				/* Get the language definitions from a file - because this Ajax call makes the language
1071				 * get async to the remainder of this function we use bInitHandedOff to indicate that
1072				 * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor
1073				 */
1074				$.ajax( {
1075					dataType: 'json',
1076					url: oLanguage.sUrl,
1077					success: function ( json ) {
1078						_fnCamelToHungarian( defaults.oLanguage, json );
1079						_fnLanguageCompat( json );
1080						$.extend( true, oLanguage, json, oSettings.oInit.oLanguage );
1081			
1082						_fnCallbackFire( oSettings, null, 'i18n', [oSettings]);
1083						_fnInitialise( oSettings );
1084					},
1085					error: function () {
1086						// Error occurred loading language file, continue on as best we can
1087						_fnInitialise( oSettings );
1088					}
1089				} );
1090				bInitHandedOff = true;
1091			}
1092			else {
1093				_fnCallbackFire( oSettings, null, 'i18n', [oSettings]);
1094			}
1095			
1096			/*
1097			 * Stripes
1098			 */
1099			if ( oInit.asStripeClasses === null )
1100			{
1101				oSettings.asStripeClasses =[
1102					oClasses.sStripeOdd,
1103					oClasses.sStripeEven
1104				];
1105			}
1106			
1107			/* Remove row stripe classes if they are already on the table row */
1108			var stripeClasses = oSettings.asStripeClasses;
1109			var rowOne = $this.children('tbody').find('tr').eq(0);
1110			if ( $.inArray( true, $.map( stripeClasses, function(el, i) {
1111				return rowOne.hasClass(el);
1112			} ) ) !== -1 ) {
1113				$('tbody tr', this).removeClass( stripeClasses.join(' ') );
1114				oSettings.asDestroyStripes = stripeClasses.slice();
1115			}
1116			
1117			/*
1118			 * Columns
1119			 * See if we should load columns automatically or use defined ones
1120			 */
1121			var anThs = [];
1122			var aoColumnsInit;
1123			var nThead = this.getElementsByTagName('thead');
1124			if ( nThead.length !== 0 )
1125			{
1126				_fnDetectHeader( oSettings.aoHeader, nThead[0] );
1127				anThs = _fnGetUniqueThs( oSettings );
1128			}
1129			
1130			/* If not given a column array, generate one with nulls */
1131			if ( oInit.aoColumns === null )
1132			{
1133				aoColumnsInit = [];
1134				for ( i=0, iLen=anThs.length ; i<iLen ; i++ )
1135				{
1136					aoColumnsInit.push( null );
1137				}
1138			}
1139			else
1140			{
1141				aoColumnsInit = oInit.aoColumns;
1142			}
1143			
1144			/* Add the columns */
1145			for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ )
1146			{
1147				_fnAddColumn( oSettings, anThs ? anThs[i] : null );
1148			}
1149			
1150			/* Apply the column definitions */
1151			_fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) {
1152				_fnColumnOptions( oSettings, iCol, oDef );
1153			} );
1154			
1155			/* HTML5 attribute detection - build an mData object automatically if the
1156			 * attributes are found
1157			 */
1158			if ( rowOne.length ) {
1159				var a = function ( cell, name ) {
1160					return cell.getAttribute( 'data-'+name ) !== null ? name : null;
1161				};
1162			
1163				$( rowOne[0] ).children('th, td').each( function (i, cell) {
1164					var col = oSettings.aoColumns[i];
1165			
1166					if (! col) {
1167						_fnLog( oSettings, 0, 'Incorrect column count', 18 );
1168					}
1169			
1170					if ( col.mData === i ) {
1171						var sort = a( cell, 'sort' ) || a( cell, 'order' );
1172						var filter = a( cell, 'filter' ) || a( cell, 'search' );
1173			
1174						if ( sort !== null || filter !== null ) {
1175							col.mData = {
1176								_:      i+'.display',
1177								sort:   sort !== null   ? i+'.@data-'+sort   : undefined,
1178								type:   sort !== null   ? i+'.@data-'+sort   : undefined,
1179								filter: filter !== null ? i+'.@data-'+filter : undefined
1180							};
1181							col._isArrayHost = true;
1182			
1183							_fnColumnOptions( oSettings, i );
1184						}
1185					}
1186				} );
1187			}
1188			
1189			var features = oSettings.oFeatures;
1190			var loadedInit = function () {
1191				/*
1192				 * Sorting
1193				 * @todo For modularisation (1.11) this needs to do into a sort start up handler
1194				 */
1195			
1196				// If aaSorting is not defined, then we use the first indicator in asSorting
1197				// in case that has been altered, so the default sort reflects that option
1198				if ( oInit.aaSorting === undefined ) {
1199					var sorting = oSettings.aaSorting;
1200					for ( i=0, iLen=sorting.length ; i<iLen ; i++ ) {
1201						sorting[i][1] = oSettings.aoColumns[ i ].asSorting[0];
1202					}
1203				}
1204			
1205				/* Do a first pass on the sorting classes (allows any size changes to be taken into
1206				 * account, and also will apply sorting disabled classes if disabled
1207				 */
1208				_fnSortingClasses( oSettings );
1209			
1210				if ( features.bSort ) {
1211					_fnCallbackReg( oSettings, 'aoDrawCallback', function () {
1212						if ( oSettings.bSorted ) {
1213							var aSort = _fnSortFlatten( oSettings );
1214							var sortedColumns = {};
1215			
1216							$.each( aSort, function (i, val) {
1217								sortedColumns[ val.src ] = val.dir;
1218							} );
1219			
1220							_fnCallbackFire( oSettings, null, 'order', [oSettings, aSort, sortedColumns] );
1221							_fnSortAria( oSettings );
1222						}
1223					} );
1224				}
1225			
1226				_fnCallbackReg( oSettings, 'aoDrawCallback', function () {
1227					if ( oSettings.bSorted || _fnDataSource( oSettings ) === 'ssp' || features.bDeferRender ) {
1228						_fnSortingClasses( oSettings );
1229					}
1230				}, 'sc' );
1231			
1232			
1233				/*
1234				 * Final init
1235				 * Cache the header, body and footer as required, creating them if needed
1236				 */
1237			
1238				// Work around for Webkit bug 83867 - store the caption-side before removing from doc
1239				var captions = $this.children('caption').each( function () {
1240					this._captionSide = $(this).css('caption-side');
1241				} );
1242			
1243				var thead = $this.children('thead');
1244				if ( thead.length === 0 ) {
1245					thead = $('<thead/>').appendTo($this);
1246				}
1247				oSettings.nTHead = thead[0];
1248			
1249				var tbody = $this.children('tbody');
1250				if ( tbody.length === 0 ) {
1251					tbody = $('<tbody/>').insertAfter(thead);
1252				}
1253				oSettings.nTBody = tbody[0];
1254			
1255				var tfoot = $this.children('tfoot');
1256				if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") ) {
1257					// If we are a scrolling table, and no footer has been given, then we need to create
1258					// a tfoot element for the caption element to be appended to
1259					tfoot = $('<tfoot/>').appendTo($this);
1260				}
1261			
1262				if ( tfoot.length === 0 || tfoot.children().length === 0 ) {
1263					$this.addClass( oClasses.sNoFooter );
1264				}
1265				else if ( tfoot.length > 0 ) {
1266					oSettings.nTFoot = tfoot[0];
1267					_fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );
1268				}
1269			
1270				/* Check if there is data passing into the constructor */
1271				if ( oInit.aaData ) {
1272					for ( i=0 ; i<oInit.aaData.length ; i++ ) {
1273						_fnAddData( oSettings, oInit.aaData[ i ] );
1274					}
1275				}
1276				else if ( oSettings.bDeferLoading || _fnDataSource( oSettings ) == 'dom' ) {
1277					/* Grab the data from the page - only do this when deferred loading or no Ajax
1278					 * source since there is no point in reading the DOM data if we are then going
1279					 * to replace it with Ajax data
1280					 */
1281					_fnAddTr( oSettings, $(oSettings.nTBody).children('tr') );
1282				}
1283			
1284				/* Copy the data index array */
1285				oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
1286			
1287				/* Initialisation complete - table can be drawn */
1288				oSettings.bInitialised = true;
1289			
1290				/* Check if we need to initialise the table (it might not have been handed off to the
1291				 * language processor)
1292				 */
1293				if ( bInitHandedOff === false ) {
1294					_fnInitialise( oSettings );
1295				}
1296			};
1297			
1298			/* Must be done after everything which can be overridden by the state saving! */
1299			_fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' );
1300			
1301			if ( oInit.bStateSave )
1302			{
1303				features.bStateSave = true;
1304				_fnLoadState( oSettings, oInit, loadedInit );
1305			}
1306			else {
1307				loadedInit();
1308			}
1309			
1310		} );
1311		_that = null;
1312		return this;
1313	};
1314	
1315	
1316	/*
1317	 * It is useful to have variables which are scoped locally so only the
1318	 * DataTables functions can access them and they don't leak into global space.
1319	 * At the same time these functions are often useful over multiple files in the
1320	 * core and API, so we list, or at least document, all variables which are used
1321	 * by DataTables as private variables here. This also ensures that there is no
1322	 * clashing of variable names and that they can easily referenced for reuse.
1323	 */
1324	
1325	
1326	// Defined else where
1327	//  _selector_run
1328	//  _selector_opts
1329	//  _selector_first
1330	//  _selector_row_indexes
1331	
1332	var _ext; // DataTable.ext
1333	var _Api; // DataTable.Api
1334	var _api_register; // DataTable.Api.register
1335	var _api_registerPlural; // DataTable.Api.registerPlural
1336	
1337	var _re_dic = {};
1338	var _re_new_lines = /[\r\n\u2028]/g;
1339	var _re_html = /<.*?>/g;
1340	
1341	// This is not strict ISO8601 - Date.parse() is quite lax, although
1342	// implementations differ between browsers.
1343	var _re_date = /^\d{2,4}[\.\/\-]\d{1,2}[\.\/\-]\d{1,2}([T ]{1}\d{1,2}[:\.]\d{2}([\.:]\d{2})?)?$/;
1344	
1345	// Escape regular expression special characters
1346	var _re_escape_regex = new RegExp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' );
1347	
1348	// http://en.wikipedia.org/wiki/Foreign_exchange_market
1349	// - \u20BD - Russian ruble.
1350	// - \u20a9 - South Korean Won
1351	// - \u20BA - Turkish Lira
1352	// - \u20B9 - Indian Rupee
1353	// - R - Brazil (R$) and South Africa
1354	// - fr - Swiss Franc
1355	// - kr - Swedish krona, Norwegian krone and Danish krone
1356	// - \u2009 is thin space and \u202F is narrow no-break space, both used in many
1357	// - Ƀ - Bitcoin
1358	// - Ξ - Ethereum
1359	//   standards as thousands separators.
1360	var _re_formatted_numeric = /['\u00A0,$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfkɃΞ]/gi;
1361	
1362	
1363	var _empty = function ( d ) {
1364		return !d || d === true || d === '-' ? true : false;
1365	};
1366	
1367	
1368	var _intVal = function ( s ) {
1369		var integer = parseInt( s, 10 );
1370		return !isNaN(integer) && isFinite(s) ? integer : null;
1371	};
1372	
1373	// Convert from a formatted number with characters other than `.` as the
1374	// decimal place, to a Javascript number
1375	var _numToDecimal = function ( num, decimalPoint ) {
1376		// Cache created regular expressions for speed as this function is called often
1377		if ( ! _re_dic[ decimalPoint ] ) {
1378			_re_dic[ decimalPoint ] = new RegExp( _fnEscapeRegex( decimalPoint ), 'g' );
1379		}
1380		return typeof num === 'string' && decimalPoint !== '.' ?
1381			num.replace( /\./g, '' ).replace( _re_dic[ decimalPoint ], '.' ) :
1382			num;
1383	};
1384	
1385	
1386	var _isNumber = function ( d, decimalPoint, formatted ) {
1387		
vendor: 2,585 bytes, lines 1387-1521
1387let type = typeof d;
1388		var strType = type === 'string';
1389	
1390		if ( type === 'number' || type === 'bigint') {
1391			return true;
1392		}
1393	
1394		// If empty return immediately so there must be a number if it is a
1395		// formatted string (this stops the string "k", or "kr", etc being detected
1396		// as a formatted number for currency
1397		if ( _empty( d ) ) {
1398			return true;
1399		}
1400	
1401		if ( decimalPoint && strType ) {
1402			d = _numToDecimal( d, decimalPoint );
1403		}
1404	
1405		if ( formatted && strType ) {
1406			d = d.replace( _re_formatted_numeric, '' );
1407		}
1408	
1409		return !isNaN( parseFloat(d) ) && isFinite( d );
1410	};
1411	
1412	
1413	// A string without HTML in it can be considered to be HTML still
1414	var _isHtml = function ( d ) {
1415		return _empty( d ) || typeof d === 'string';
1416	};
1417	
1418	
1419	var _htmlNumeric = function ( d, decimalPoint, formatted ) {
1420		if ( _empty( d ) ) {
1421			return true;
1422		}
1423	
1424		var html = _isHtml( d );
1425		return ! html ?
1426			null :
1427			_isNumber( _stripHtml( d ), decimalPoint, formatted ) ?
1428				true :
1429				null;
1430	};
1431	
1432	
1433	var _pluck = function ( a, prop, prop2 ) {
1434		var out = [];
1435		var i=0, ien=a.length;
1436	
1437		// Could have the test in the loop for slightly smaller code, but speed
1438		// is essential here
1439		if ( prop2 !== undefined ) {
1440			for ( ; i<ien ; i++ ) {
1441				if ( a[i] && a[i][ prop ] ) {
1442					out.push( a[i][ prop ][ prop2 ] );
1443				}
1444			}
1445		}
1446		else {
1447			for ( ; i<ien ; i++ ) {
1448				if ( a[i] ) {
1449					out.push( a[i][ prop ] );
1450				}
1451			}
1452		}
1453	
1454		return out;
1455	};
1456	
1457	
1458	// Basically the same as _pluck, but rather than looping over `a` we use `order`
1459	// as the indexes to pick from `a`
1460	var _pluck_order = function ( a, order, prop, prop2 )
1461	{
1462		var out = [];
1463		var i=0, ien=order.length;
1464	
1465		// Could have the test in the loop for slightly smaller code, but speed
1466		// is essential here
1467		if ( prop2 !== undefined ) {
1468			for ( ; i<ien ; i++ ) {
1469				if ( a[ order[i] ][ prop ] ) {
1470					out.push( a[ order[i] ][ prop ][ prop2 ] );
1471				}
1472			}
1473		}
1474		else {
1475			for ( ; i<ien ; i++ ) {
1476				out.push( a[ order[i] ][ prop ] );
1477			}
1478		}
1479	
1480		return out;
1481	};
1482	
1483	
1484	var _range = function ( len, start )
1485	{
1486		var out = [];
1487		var end;
1488	
1489		if ( start === undefined ) {
1490			start = 0;
1491			end = len;
1492		}
1493		else {
1494			end = start;
1495			start = len;
1496		}
1497	
1498		for ( var i=start ; i<end ; i++ ) {
1499			out.push( i );
1500		}
1501	
1502		return out;
1503	};
1504	
1505	
1506	var _removeEmpty = function ( a )
1507	{
1508		var out = [];
1509	
1510		for ( var i=0, ien=a.length ; i<ien ; i++ ) {
1511			if ( a[i] ) { // careful - will remove all falsy values!
1512				out.push( a[i] );
1513			}
1514		}
1515	
1516		return out;
1517	};
1518	
1519	
1520	var _stripHtml = function ( d ) {
1521		return d.replace( _re_html, '' );
vendor: 10,574 bytes, lines 1521-1895
1521
1522	};
1523	
1524	
1525	/**
1526	 * Determine if all values in the array are unique. This means we can short
1527	 * cut the _unique method at the cost of a single loop. A sorted array is used
1528	 * to easily check the values.
1529	 *
1530	 * @param  {array} src Source array
1531	 * @return {boolean} true if all unique, false otherwise
1532	 * @ignore
1533	 */
1534	var _areAllUnique = function ( src ) {
1535		if ( src.length < 2 ) {
1536			return true;
1537		}
1538	
1539		var sorted = src.slice().sort();
1540		var last = sorted[0];
1541	
1542		for ( var i=1, ien=sorted.length ; i<ien ; i++ ) {
1543			if ( sorted[i] === last ) {
1544				return false;
1545			}
1546	
1547			last = sorted[i];
1548		}
1549	
1550		return true;
1551	};
1552	
1553	
1554	/**
1555	 * Find the unique elements in a source array.
1556	 *
1557	 * @param  {array} src Source array
1558	 * @return {array} Array of unique items
1559	 * @ignore
1560	 */
1561	var _unique = function ( src )
1562	{
1563		if ( _areAllUnique( src ) ) {
1564			return src.slice();
1565		}
1566	
1567		// A faster unique method is to use object keys to identify used values,
1568		// but this doesn't work with arrays or objects, which we must also
1569		// consider. See jsperf.com/compare-array-unique-versions/4 for more
1570		// information.
1571		var
1572			out = [],
1573			val,
1574			i, ien=src.length,
1575			j, k=0;
1576	
1577		again: for ( i=0 ; i<ien ; i++ ) {
1578			val = src[i];
1579	
1580			for ( j=0 ; j<k ; j++ ) {
1581				if ( out[j] === val ) {
1582					continue again;
1583				}
1584			}
1585	
1586			out.push( val );
1587			k++;
1588		}
1589	
1590		return out;
1591	};
1592	
1593	// Surprisingly this is faster than [].concat.apply
1594	// https://jsperf.com/flatten-an-array-loop-vs-reduce/2
1595	var _flatten = function (out, val) {
1596		if (Array.isArray(val)) {
1597			for (var i=0 ; i<val.length ; i++) {
1598				_flatten(out, val[i]);
1599			}
1600		}
1601		else {
1602			out.push(val);
1603		}
1604	  
1605		return out;
1606	}
1607	
1608	var _includes = function (search, start) {
1609		if (start === undefined) {
1610			start = 0;
1611		}
1612	
1613		return this.indexOf(search, start) !== -1;	
1614	};
1615	
1616	// Array.isArray polyfill.
1617	// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
1618	if (! Array.isArray) {
1619	    Array.isArray = function(arg) {
1620	        return Object.prototype.toString.call(arg) === '[object Array]';
1621	    };
1622	}
1623	
1624	if (! Array.prototype.includes) {
1625		Array.prototype.includes = _includes;
1626	}
1627	
1628	// .trim() polyfill
1629	// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trim
1630	if (!String.prototype.trim) {
1631	  String.prototype.trim = function () {
1632	    return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
1633	  };
1634	}
1635	
1636	if (! String.prototype.includes) {
1637		String.prototype.includes = _includes;
1638	}
1639	
1640	/**
1641	 * DataTables utility methods
1642	 * 
1643	 * This namespace provides helper methods that DataTables uses internally to
1644	 * create a DataTable, but which are not exclusively used only for DataTables.
1645	 * These methods can be used by extension authors to save the duplication of
1646	 * code.
1647	 *
1648	 *  @namespace
1649	 */
1650	DataTable.util = {
1651		/**
1652		 * Throttle the calls to a function. Arguments and context are maintained
1653		 * for the throttled function.
1654		 *
1655		 * @param {function} fn Function to be called
1656		 * @param {integer} freq Call frequency in mS
1657		 * @return {function} Wrapped function
1658		 */
1659		throttle: function ( fn, freq ) {
1660			var
1661				frequency = freq !== undefined ? freq : 200,
1662				last,
1663				timer;
1664	
1665			return function () {
1666				var
1667					that = this,
1668					now  = +new Date(),
1669					args = arguments;
1670	
1671				if ( last && now < last + frequency ) {
1672					clearTimeout( timer );
1673	
1674					timer = setTimeout( function () {
1675						last = undefined;
1676						fn.apply( that, args );
1677					}, frequency );
1678				}
1679				else {
1680					last = now;
1681					fn.apply( that, args );
1682				}
1683			};
1684		},
1685	
1686	
1687		/**
1688		 * Escape a string such that it can be used in a regular expression
1689		 *
1690		 *  @param {string} val string to escape
1691		 *  @returns {string} escaped string
1692		 */
1693		escapeRegex: function ( val ) {
1694			return val.replace( _re_escape_regex, '\\$1' );
1695		},
1696	
1697		/**
1698		 * Create a function that will write to a nested object or array
1699		 * @param {*} source JSON notation string
1700		 * @returns Write function
1701		 */
1702		set: function ( source ) {
1703			if ( $.isPlainObject( source ) ) {
1704				/* Unlike get, only the underscore (global) option is used for for
1705				 * setting data since we don't know the type here. This is why an object
1706				 * option is not documented for `mData` (which is read/write), but it is
1707				 * for `mRender` which is read only.
1708				 */
1709				return DataTable.util.set( source._ );
1710			}
1711			else if ( source === null ) {
1712				// Nothing to do when the data source is null
1713				return function () {};
1714			}
1715			else if ( typeof source === 'function' ) {
1716				return function (data, val, meta) {
1717					source( data, 'set', val, meta );
1718				};
1719			}
1720			else if ( typeof source === 'string' && (source.indexOf('.') !== -1 ||
1721					  source.indexOf('[') !== -1 || source.indexOf('(') !== -1) )
1722			{
1723				// Like the get, we need to get data from a nested object
1724				var setData = function (data, val, src) {
1725					var a = _fnSplitObjNotation( src ), b;
1726					var aLast = a[a.length-1];
1727					var arrayNotation, funcNotation, o, innerSrc;
1728		
1729					for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ ) {
1730						// Protect against prototype pollution
1731						if (a[i] === '__proto__' || a[i] === 'constructor') {
1732							throw new Error('Cannot set prototype values');
1733						}
1734		
1735						// Check if we are dealing with an array notation request
1736						arrayNotation = a[i].match(__reArray);
1737						funcNotation = a[i].match(__reFn);
1738		
1739						if ( arrayNotation ) {
1740							a[i] = a[i].replace(__reArray, '');
1741							data[ a[i] ] = [];
1742		
1743							// Get the remainder of the nested object to set so we can recurse
1744							b = a.slice();
1745							b.splice( 0, i+1 );
1746							innerSrc = b.join('.');
1747		
1748							// Traverse each entry in the array setting the properties requested
1749							if ( Array.isArray( val ) ) {
1750								for ( var j=0, jLen=val.length ; j<jLen ; j++ ) {
1751									o = {};
1752									setData( o, val[j], innerSrc );
1753									data[ a[i] ].push( o );
1754								}
1755							}
1756							else {
1757								// We've been asked to save data to an array, but it
1758								// isn't array data to be saved. Best that can be done
1759								// is to just save the value.
1760								data[ a[i] ] = val;
1761							}
1762		
1763							// The inner call to setData has already traversed through the remainder
1764							// of the source and has set the data, thus we can exit here
1765							return;
1766						}
1767						else if ( funcNotation ) {
1768							// Function call
1769							a[i] = a[i].replace(__reFn, '');
1770							data = data[ a[i] ]( val );
1771						}
1772		
1773						// If the nested object doesn't currently exist - since we are
1774						// trying to set the value - create it
1775						if ( data[ a[i] ] === null || data[ a[i] ] === undefined ) {
1776							data[ a[i] ] = {};
1777						}
1778						data = data[ a[i] ];
1779					}
1780		
1781					// Last item in the input - i.e, the actual set
1782					if ( aLast.match(__reFn ) ) {
1783						// Function call
1784						data = data[ aLast.replace(__reFn, '') ]( val );
1785					}
1786					else {
1787						// If array notation is used, we just want to strip it and use the property name
1788						// and assign the value. If it isn't used, then we get the result we want anyway
1789						data[ aLast.replace(__reArray, '') ] = val;
1790					}
1791				};
1792		
1793				return function (data, val) { // meta is also passed in, but not used
1794					return setData( data, val, source );
1795				};
1796			}
1797			else {
1798				// Array or flat object mapping
1799				return function (data, val) { // meta is also passed in, but not used
1800					data[source] = val;
1801				};
1802			}
1803		},
1804	
1805		/**
1806		 * Create a function that will read nested objects from arrays, based on JSON notation
1807		 * @param {*} source JSON notation string
1808		 * @returns Value read
1809		 */
1810		get: function ( source ) {
1811			if ( $.isPlainObject( source ) ) {
1812				// Build an object of get functions, and wrap them in a single call
1813				var o = {};
1814				$.each( source, function (key, val) {
1815					if ( val ) {
1816						o[key] = DataTable.util.get( val );
1817					}
1818				} );
1819		
1820				return function (data, type, row, meta) {
1821					var t = o[type] || o._;
1822					return t !== undefined ?
1823						t(data, type, row, meta) :
1824						data;
1825				};
1826			}
1827			else if ( source === null ) {
1828				// Give an empty string for rendering / sorting etc
1829				return function (data) { // type, row and meta also passed, but not used
1830					return data;
1831				};
1832			}
1833			else if ( typeof source === 'function' ) {
1834				return function (data, type, row, meta) {
1835					return source( data, type, row, meta );
1836				};
1837			}
1838			else if ( typeof source === 'string' && (source.indexOf('.') !== -1 ||
1839					  source.indexOf('[') !== -1 || source.indexOf('(') !== -1) )
1840			{
1841				/* If there is a . in the source string then the data source is in a
1842				 * nested object so we loop over the data for each level to get the next
1843				 * level down. On each loop we test for undefined, and if found immediately
1844				 * return. This allows entire objects to be missing and sDefaultContent to
1845				 * be used if defined, rather than throwing an error
1846				 */
1847				var fetchData = function (data, type, src) {
1848					var arrayNotation, funcNotation, out, innerSrc;
1849		
1850					if ( src !== "" ) {
1851						var a = _fnSplitObjNotation( src );
1852		
1853						for ( var i=0, iLen=a.length ; i<iLen ; i++ ) {
1854							// Check if we are dealing with special notation
1855							arrayNotation = a[i].match(__reArray);
1856							funcNotation = a[i].match(__reFn);
1857		
1858							if ( arrayNotation ) {
1859								// Array notation
1860								a[i] = a[i].replace(__reArray, '');
1861		
1862								// Condition allows simply [] to be passed in
1863								if ( a[i] !== "" ) {
1864									data = data[ a[i] ];
1865								}
1866								out = [];
1867		
1868								// Get the remainder of the nested object to get
1869								a.splice( 0, i+1 );
1870								innerSrc = a.join('.');
1871		
1872								// Traverse each entry in the array getting the properties requested
1873								if ( Array.isArray( data ) ) {
1874									for ( var j=0, jLen=data.length ; j<jLen ; j++ ) {
1875										out.push( fetchData( data[j], type, innerSrc ) );
1876									}
1877								}
1878		
1879								// If a string is given in between the array notation indicators, that
1880								// is used to join the strings together, otherwise an array is returned
1881								var join = arrayNotation[0].substring(1, arrayNotation[0].length-1);
1882								data = (join==="") ? out : out.join(join);
1883		
1884								// The inner call to fetchData has already traversed through the remainder
1885								// of the source requested, so we exit from the loop
1886								break;
1887							}
1888							else if ( funcNotation ) {
1889								// Function call
1890								a[i] = a[i].replace(__reFn, '');
1891								data = data[ a[i] ]();
1892								continue;
1893							}
1894		
1895							if (
1895 data === null
vendor: 60,603 bytes, lines 1895-4066
1895 || data[ a[i] ] === undefined ) {
1896								return undefined;
1897							}
1898	
1899							data = data[ a[i] ];
1900						}
1901					}
1902		
1903					return data;
1904				};
1905		
1906				return function (data, type) { // row and meta also passed, but not used
1907					return fetchData( data, type, source );
1908				};
1909			}
1910			else {
1911				// Array or flat object mapping
1912				return function (data, type) { // row and meta also passed, but not used
1913					return data[source];
1914				};
1915			}
1916		}
1917	};
1918	
1919	
1920	
1921	/**
1922	 * Create a mapping object that allows camel case parameters to be looked up
1923	 * for their Hungarian counterparts. The mapping is stored in a private
1924	 * parameter called `_hungarianMap` which can be accessed on the source object.
1925	 *  @param {object} o
1926	 *  @memberof DataTable#oApi
1927	 */
1928	function _fnHungarianMap ( o )
1929	{
1930		var
1931			hungarian = 'a aa ai ao as b fn i m o s ',
1932			match,
1933			newKey,
1934			map = {};
1935	
1936		$.each( o, function (key, val) {
1937			match = key.match(/^([^A-Z]+?)([A-Z])/);
1938	
1939			if ( match && hungarian.indexOf(match[1]+' ') !== -1 )
1940			{
1941				newKey = key.replace( match[0], match[2].toLowerCase() );
1942				map[ newKey ] = key;
1943	
1944				if ( match[1] === 'o' )
1945				{
1946					_fnHungarianMap( o[key] );
1947				}
1948			}
1949		} );
1950	
1951		o._hungarianMap = map;
1952	}
1953	
1954	
1955	/**
1956	 * Convert from camel case parameters to Hungarian, based on a Hungarian map
1957	 * created by _fnHungarianMap.
1958	 *  @param {object} src The model object which holds all parameters that can be
1959	 *    mapped.
1960	 *  @param {object} user The object to convert from camel case to Hungarian.
1961	 *  @param {boolean} force When set to `true`, properties which already have a
1962	 *    Hungarian value in the `user` object will be overwritten. Otherwise they
1963	 *    won't be.
1964	 *  @memberof DataTable#oApi
1965	 */
1966	function _fnCamelToHungarian ( src, user, force )
1967	{
1968		if ( ! src._hungarianMap ) {
1969			_fnHungarianMap( src );
1970		}
1971	
1972		var hungarianKey;
1973	
1974		$.each( user, function (key, val) {
1975			hungarianKey = src._hungarianMap[ key ];
1976	
1977			if ( hungarianKey !== undefined && (force || user[hungarianKey] === undefined) )
1978			{
1979				// For objects, we need to buzz down into the object to copy parameters
1980				if ( hungarianKey.charAt(0) === 'o' )
1981				{
1982					// Copy the camelCase options over to the hungarian
1983					if ( ! user[ hungarianKey ] ) {
1984						user[ hungarianKey ] = {};
1985					}
1986					$.extend( true, user[hungarianKey], user[key] );
1987	
1988					_fnCamelToHungarian( src[hungarianKey], user[hungarianKey], force );
1989				}
1990				else {
1991					user[hungarianKey] = user[ key ];
1992				}
1993			}
1994		} );
1995	}
1996	
1997	
1998	/**
1999	 * Language compatibility - when certain options are given, and others aren't, we
2000	 * need to duplicate the values over, in order to provide backwards compatibility
2001	 * with older language files.
2002	 *  @param {object} oSettings dataTables settings object
2003	 *  @memberof DataTable#oApi
2004	 */
2005	function _fnLanguageCompat( lang )
2006	{
2007		// Note the use of the Hungarian notation for the parameters in this method as
2008		// this is called after the mapping of camelCase to Hungarian
2009		var defaults = DataTable.defaults.oLanguage;
2010	
2011		// Default mapping
2012		var defaultDecimal = defaults.sDecimal;
2013		if ( defaultDecimal ) {
2014			_addNumericSort( defaultDecimal );
2015		}
2016	
2017		if ( lang ) {
2018			var zeroRecords = lang.sZeroRecords;
2019	
2020			// Backwards compatibility - if there is no sEmptyTable given, then use the same as
2021			// sZeroRecords - assuming that is given.
2022			if ( ! lang.sEmptyTable && zeroRecords &&
2023				defaults.sEmptyTable === "No data available in table" )
2024			{
2025				_fnMap( lang, lang, 'sZeroRecords', 'sEmptyTable' );
2026			}
2027	
2028			// Likewise with loading records
2029			if ( ! lang.sLoadingRecords && zeroRecords &&
2030				defaults.sLoadingRecords === "Loading..." )
2031			{
2032				_fnMap( lang, lang, 'sZeroRecords', 'sLoadingRecords' );
2033			}
2034	
2035			// Old parameter name of the thousands separator mapped onto the new
2036			if ( lang.sInfoThousands ) {
2037				lang.sThousands = lang.sInfoThousands;
2038			}
2039	
2040			var decimal = lang.sDecimal;
2041			if ( decimal && defaultDecimal !== decimal ) {
2042				_addNumericSort( decimal );
2043			}
2044		}
2045	}
2046	
2047	
2048	/**
2049	 * Map one parameter onto another
2050	 *  @param {object} o Object to map
2051	 *  @param {*} knew The new parameter name
2052	 *  @param {*} old The old parameter name
2053	 */
2054	var _fnCompatMap = function ( o, knew, old ) {
2055		if ( o[ knew ] !== undefined ) {
2056			o[ old ] = o[ knew ];
2057		}
2058	};
2059	
2060	
2061	/**
2062	 * Provide backwards compatibility for the main DT options. Note that the new
2063	 * options are mapped onto the old parameters, so this is an external interface
2064	 * change only.
2065	 *  @param {object} init Object to map
2066	 */
2067	function _fnCompatOpts ( init )
2068	{
2069		_fnCompatMap( init, 'ordering',      'bSort' );
2070		_fnCompatMap( init, 'orderMulti',    'bSortMulti' );
2071		_fnCompatMap( init, 'orderClasses',  'bSortClasses' );
2072		_fnCompatMap( init, 'orderCellsTop', 'bSortCellsTop' );
2073		_fnCompatMap( init, 'order',         'aaSorting' );
2074		_fnCompatMap( init, 'orderFixed',    'aaSortingFixed' );
2075		_fnCompatMap( init, 'paging',        'bPaginate' );
2076		_fnCompatMap( init, 'pagingType',    'sPaginationType' );
2077		_fnCompatMap( init, 'pageLength',    'iDisplayLength' );
2078		_fnCompatMap( init, 'searching',     'bFilter' );
2079	
2080		// Boolean initialisation of x-scrolling
2081		if ( typeof init.sScrollX === 'boolean' ) {
2082			init.sScrollX = init.sScrollX ? '100%' : '';
2083		}
2084		if ( typeof init.scrollX === 'boolean' ) {
2085			init.scrollX = init.scrollX ? '100%' : '';
2086		}
2087	
2088		// Column search objects are in an array, so it needs to be converted
2089		// element by element
2090		var searchCols = init.aoSearchCols;
2091	
2092		if ( searchCols ) {
2093			for ( var i=0, ien=searchCols.length ; i<ien ; i++ ) {
2094				if ( searchCols[i] ) {
2095					_fnCamelToHungarian( DataTable.models.oSearch, searchCols[i] );
2096				}
2097			}
2098		}
2099	}
2100	
2101	
2102	/**
2103	 * Provide backwards compatibility for column options. Note that the new options
2104	 * are mapped onto the old parameters, so this is an external interface change
2105	 * only.
2106	 *  @param {object} init Object to map
2107	 */
2108	function _fnCompatCols ( init )
2109	{
2110		_fnCompatMap( init, 'orderable',     'bSortable' );
2111		_fnCompatMap( init, 'orderData',     'aDataSort' );
2112		_fnCompatMap( init, 'orderSequence', 'asSorting' );
2113		_fnCompatMap( init, 'orderDataType', 'sortDataType' );
2114	
2115		// orderData can be given as an integer
2116		var dataSort = init.aDataSort;
2117		if ( typeof dataSort === 'number' && ! Array.isArray( dataSort ) ) {
2118			init.aDataSort = [ dataSort ];
2119		}
2120	}
2121	
2122	
2123	/**
2124	 * Browser feature detection for capabilities, quirks
2125	 *  @param {object} settings dataTables settings object
2126	 *  @memberof DataTable#oApi
2127	 */
2128	function _fnBrowserDetect( settings )
2129	{
2130		// We don't need to do this every time DataTables is constructed, the values
2131		// calculated are specific to the browser and OS configuration which we
2132		// don't expect to change between initialisations
2133		if ( ! DataTable.__browser ) {
2134			var browser = {};
2135			DataTable.__browser = browser;
2136	
2137			// Scrolling feature / quirks detection
2138			var n = $('<div/>')
2139				.css( {
2140					position: 'fixed',
2141					top: 0,
2142					left: $(window).scrollLeft()*-1, // allow for scrolling
2143					height: 1,
2144					width: 1,
2145					overflow: 'hidden'
2146				} )
2147				.append(
2148					$('<div/>')
2149						.css( {
2150							position: 'absolute',
2151							top: 1,
2152							left: 1,
2153							width: 100,
2154							overflow: 'scroll'
2155						} )
2156						.append(
2157							$('<div/>')
2158								.css( {
2159									width: '100%',
2160									height: 10
2161								} )
2162						)
2163				)
2164				.appendTo( 'body' );
2165	
2166			var outer = n.children();
2167			var inner = outer.children();
2168	
2169			// Numbers below, in order, are:
2170			// inner.offsetWidth, inner.clientWidth, outer.offsetWidth, outer.clientWidth
2171			//
2172			// IE6 XP:                           100 100 100  83
2173			// IE7 Vista:                        100 100 100  83
2174			// IE 8+ Windows:                     83  83 100  83
2175			// Evergreen Windows:                 83  83 100  83
2176			// Evergreen Mac with scrollbars:     85  85 100  85
2177			// Evergreen Mac without scrollbars: 100 100 100 100
2178	
2179			// Get scrollbar width
2180			browser.barWidth = outer[0].offsetWidth - outer[0].clientWidth;
2181	
2182			// IE6/7 will oversize a width 100% element inside a scrolling element, to
2183			// include the width of the scrollbar, while other browsers ensure the inner
2184			// element is contained without forcing scrolling
2185			browser.bScrollOversize = inner[0].offsetWidth === 100 && outer[0].clientWidth !== 100;
2186	
2187			// In rtl text layout, some browsers (most, but not all) will place the
2188			// scrollbar on the left, rather than the right.
2189			browser.bScrollbarLeft = Math.round( inner.offset().left ) !== 1;
2190	
2191			// IE8- don't provide height and width for getBoundingClientRect
2192			browser.bBounding = n[0].getBoundingClientRect().width ? true : false;
2193	
2194			n.remove();
2195		}
2196	
2197		$.extend( settings.oBrowser, DataTable.__browser );
2198		settings.oScroll.iBarWidth = DataTable.__browser.barWidth;
2199	}
2200	
2201	
2202	/**
2203	 * Array.prototype reduce[Right] method, used for browsers which don't support
2204	 * JS 1.6. Done this way to reduce code size, since we iterate either way
2205	 *  @param {object} settings dataTables settings object
2206	 *  @memberof DataTable#oApi
2207	 */
2208	function _fnReduce ( that, fn, init, start, end, inc )
2209	{
2210		var
2211			i = start,
2212			value,
2213			isSet = false;
2214	
2215		if ( init !== undefined ) {
2216			value = init;
2217			isSet = true;
2218		}
2219	
2220		while ( i !== end ) {
2221			if ( ! that.hasOwnProperty(i) ) {
2222				continue;
2223			}
2224	
2225			value = isSet ?
2226				fn( value, that[i], i, that ) :
2227				that[i];
2228	
2229			isSet = true;
2230			i += inc;
2231		}
2232	
2233		return value;
2234	}
2235	
2236	/**
2237	 * Add a column to the list used for the table with default values
2238	 *  @param {object} oSettings dataTables settings object
2239	 *  @param {node} nTh The th element for this column
2240	 *  @memberof DataTable#oApi
2241	 */
2242	function _fnAddColumn( oSettings, nTh )
2243	{
2244		// Add column to aoColumns array
2245		var oDefaults = DataTable.defaults.column;
2246		var iCol = oSettings.aoColumns.length;
2247		var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {
2248			"nTh": nTh ? nTh : document.createElement('th'),
2249			"sTitle":    oDefaults.sTitle    ? oDefaults.sTitle    : nTh ? nTh.innerHTML : '',
2250			"aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],
2251			"mData": oDefaults.mData ? oDefaults.mData : iCol,
2252			idx: iCol
2253		} );
2254		oSettings.aoColumns.push( oCol );
2255	
2256		// Add search object for column specific search. Note that the `searchCols[ iCol ]`
2257		// passed into extend can be undefined. This allows the user to give a default
2258		// with only some of the parameters defined, and also not give a default
2259		var searchCols = oSettings.aoPreSearchCols;
2260		searchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] );
2261	
2262		// Use the default column options function to initialise classes etc
2263		_fnColumnOptions( oSettings, iCol, $(nTh).data() );
2264	}
2265	
2266	
2267	/**
2268	 * Apply options for a column
2269	 *  @param {object} oSettings dataTables settings object
2270	 *  @param {int} iCol column index to consider
2271	 *  @param {object} oOptions object with sType, bVisible and bSearchable etc
2272	 *  @memberof DataTable#oApi
2273	 */
2274	function _fnColumnOptions( oSettings, iCol, oOptions )
2275	{
2276		var oCol = oSettings.aoColumns[ iCol ];
2277		var oClasses = oSettings.oClasses;
2278		var th = $(oCol.nTh);
2279	
2280		// Try to get width information from the DOM. We can't get it from CSS
2281		// as we'd need to parse the CSS stylesheet. `width` option can override
2282		if ( ! oCol.sWidthOrig ) {
2283			// Width attribute
2284			oCol.sWidthOrig = th.attr('width') || null;
2285	
2286			// Style attribute
2287			var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/);
2288			if ( t ) {
2289				oCol.sWidthOrig = t[1];
2290			}
2291		}
2292	
2293		/* User specified column options */
2294		if ( oOptions !== undefined && oOptions !== null )
2295		{
2296			// Backwards compatibility
2297			_fnCompatCols( oOptions );
2298	
2299			// Map camel case parameters to their Hungarian counterparts
2300			_fnCamelToHungarian( DataTable.defaults.column, oOptions, true );
2301	
2302			/* Backwards compatibility for mDataProp */
2303			if ( oOptions.mDataProp !== undefined && !oOptions.mData )
2304			{
2305				oOptions.mData = oOptions.mDataProp;
2306			}
2307	
2308			if ( oOptions.sType )
2309			{
2310				oCol._sManualType = oOptions.sType;
2311			}
2312	
2313			// `class` is a reserved word in Javascript, so we need to provide
2314			// the ability to use a valid name for the camel case input
2315			if ( oOptions.className && ! oOptions.sClass )
2316			{
2317				oOptions.sClass = oOptions.className;
2318			}
2319			if ( oOptions.sClass ) {
2320				th.addClass( oOptions.sClass );
2321			}
2322	
2323			var origClass = oCol.sClass;
2324	
2325			$.extend( oCol, oOptions );
2326			_fnMap( oCol, oOptions, "sWidth", "sWidthOrig" );
2327	
2328			// Merge class from previously defined classes with this one, rather than just
2329			// overwriting it in the extend above
2330			if (origClass !== oCol.sClass) {
2331				oCol.sClass = origClass + ' ' + oCol.sClass;
2332			}
2333	
2334			/* iDataSort to be applied (backwards compatibility), but aDataSort will take
2335			 * priority if defined
2336			 */
2337			if ( oOptions.iDataSort !== undefined )
2338			{
2339				oCol.aDataSort = [ oOptions.iDataSort ];
2340			}
2341			_fnMap( oCol, oOptions, "aDataSort" );
2342		}
2343	
2344		/* Cache the data get and set functions for speed */
2345		var mDataSrc = oCol.mData;
2346		var mData = _fnGetObjectDataFn( mDataSrc );
2347		var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null;
2348	
2349		var attrTest = function( src ) {
2350			return typeof src === 'string' && src.indexOf('@') !== -1;
2351		};
2352		oCol._bAttrSrc = $.isPlainObject( mDataSrc ) && (
2353			attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter)
2354		);
2355		oCol._setter = null;
2356	
2357		oCol.fnGetData = function (rowData, type, meta) {
2358			var innerData = mData( rowData, type, undefined, meta );
2359	
2360			return mRender && type ?
2361				mRender( innerData, type, rowData, meta ) :
2362				innerData;
2363		};
2364		oCol.fnSetData = function ( rowData, val, meta ) {
2365			return _fnSetObjectDataFn( mDataSrc )( rowData, val, meta );
2366		};
2367	
2368		// Indicate if DataTables should read DOM data as an object or array
2369		// Used in _fnGetRowElements
2370		if ( typeof mDataSrc !== 'number' && ! oCol._isArrayHost ) {
2371			oSettings._rowReadObject = true;
2372		}
2373	
2374		/* Feature sorting overrides column specific when off */
2375		if ( !oSettings.oFeatures.bSort )
2376		{
2377			oCol.bSortable = false;
2378			th.addClass( oClasses.sSortableNone ); // Have to add class here as order event isn't called
2379		}
2380	
2381		/* Check that the class assignment is correct for sorting */
2382		var bAsc = $.inArray('asc', oCol.asSorting) !== -1;
2383		var bDesc = $.inArray('desc', oCol.asSorting) !== -1;
2384		if ( !oCol.bSortable || (!bAsc && !bDesc) )
2385		{
2386			oCol.sSortingClass = oClasses.sSortableNone;
2387			oCol.sSortingClassJUI = "";
2388		}
2389		else if ( bAsc && !bDesc )
2390		{
2391			oCol.sSortingClass = oClasses.sSortableAsc;
2392			oCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed;
2393		}
2394		else if ( !bAsc && bDesc )
2395		{
2396			oCol.sSortingClass = oClasses.sSortableDesc;
2397			oCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed;
2398		}
2399		else
2400		{
2401			oCol.sSortingClass = oClasses.sSortable;
2402			oCol.sSortingClassJUI = oClasses.sSortJUI;
2403		}
2404	}
2405	
2406	
2407	/**
2408	 * Adjust the table column widths for new data. Note: you would probably want to
2409	 * do a redraw after calling this function!
2410	 *  @param {object} settings dataTables settings object
2411	 *  @memberof DataTable#oApi
2412	 */
2413	function _fnAdjustColumnSizing ( settings )
2414	{
2415		/* Not interested in doing column width calculation if auto-width is disabled */
2416		if ( settings.oFeatures.bAutoWidth !== false )
2417		{
2418			var columns = settings.aoColumns;
2419	
2420			_fnCalculateColumnWidths( settings );
2421			for ( var i=0 , iLen=columns.length ; i<iLen ; i++ )
2422			{
2423				columns[i].nTh.style.width = columns[i].sWidth;
2424			}
2425		}
2426	
2427		var scroll = settings.oScroll;
2428		if ( scroll.sY !== '' || scroll.sX !== '')
2429		{
2430			_fnScrollDraw( settings );
2431		}
2432	
2433		_fnCallbackFire( settings, null, 'column-sizing', [settings] );
2434	}
2435	
2436	
2437	/**
2438	 * Convert the index of a visible column to the index in the data array (take account
2439	 * of hidden columns)
2440	 *  @param {object} oSettings dataTables settings object
2441	 *  @param {int} iMatch Visible column index to lookup
2442	 *  @returns {int} i the data index
2443	 *  @memberof DataTable#oApi
2444	 */
2445	function _fnVisibleToColumnIndex( oSettings, iMatch )
2446	{
2447		var aiVis = _fnGetColumns( oSettings, 'bVisible' );
2448	
2449		return typeof aiVis[iMatch] === 'number' ?
2450			aiVis[iMatch] :
2451			null;
2452	}
2453	
2454	
2455	/**
2456	 * Convert the index of an index in the data array and convert it to the visible
2457	 *   column index (take account of hidden columns)
2458	 *  @param {int} iMatch Column index to lookup
2459	 *  @param {object} oSettings dataTables settings object
2460	 *  @returns {int} i the data index
2461	 *  @memberof DataTable#oApi
2462	 */
2463	function _fnColumnIndexToVisible( oSettings, iMatch )
2464	{
2465		var aiVis = _fnGetColumns( oSettings, 'bVisible' );
2466		var iPos = $.inArray( iMatch, aiVis );
2467	
2468		return iPos !== -1 ? iPos : null;
2469	}
2470	
2471	
2472	/**
2473	 * Get the number of visible columns
2474	 *  @param {object} oSettings dataTables settings object
2475	 *  @returns {int} i the number of visible columns
2476	 *  @memberof DataTable#oApi
2477	 */
2478	function _fnVisbleColumns( oSettings )
2479	{
2480		var vis = 0;
2481	
2482		// No reduce in IE8, use a loop for now
2483		$.each( oSettings.aoColumns, function ( i, col ) {
2484			if ( col.bVisible && $(col.nTh).css('display') !== 'none' ) {
2485				vis++;
2486			}
2487		} );
2488	
2489		return vis;
2490	}
2491	
2492	
2493	/**
2494	 * Get an array of column indexes that match a given property
2495	 *  @param {object} oSettings dataTables settings object
2496	 *  @param {string} sParam Parameter in aoColumns to look for - typically
2497	 *    bVisible or bSearchable
2498	 *  @returns {array} Array of indexes with matched properties
2499	 *  @memberof DataTable#oApi
2500	 */
2501	function _fnGetColumns( oSettings, sParam )
2502	{
2503		var a = [];
2504	
2505		$.map( oSettings.aoColumns, function(val, i) {
2506			if ( val[sParam] ) {
2507				a.push( i );
2508			}
2509		} );
2510	
2511		return a;
2512	}
2513	
2514	
2515	/**
2516	 * Calculate the 'type' of a column
2517	 *  @param {object} settings dataTables settings object
2518	 *  @memberof DataTable#oApi
2519	 */
2520	function _fnColumnTypes ( settings )
2521	{
2522		var columns = settings.aoColumns;
2523		var data = settings.aoData;
2524		var types = DataTable.ext.type.detect;
2525		var i, ien, j, jen, k, ken;
2526		var col, cell, detectedType, cache;
2527	
2528		// For each column, spin over the 
2529		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
2530			col = columns[i];
2531			cache = [];
2532	
2533			if ( ! col.sType && col._sManualType ) {
2534				col.sType = col._sManualType;
2535			}
2536			else if ( ! col.sType ) {
2537				for ( j=0, jen=types.length ; j<jen ; j++ ) {
2538					for ( k=0, ken=data.length ; k<ken ; k++ ) {
2539						// Use a cache array so we only need to get the type data
2540						// from the formatter once (when using multiple detectors)
2541						if ( cache[k] === undefined ) {
2542							cache[k] = _fnGetCellData( settings, k, i, 'type' );
2543						}
2544	
2545						detectedType = types[j]( cache[k], settings );
2546	
2547						// If null, then this type can't apply to this column, so
2548						// rather than testing all cells, break out. There is an
2549						// exception for the last type which is `html`. We need to
2550						// scan all rows since it is possible to mix string and HTML
2551						// types
2552						if ( ! detectedType && j !== types.length-1 ) {
2553							break;
2554						}
2555	
2556						// Only a single match is needed for html type since it is
2557						// bottom of the pile and very similar to string - but it
2558						// must not be empty
2559						if ( detectedType === 'html' && ! _empty(cache[k]) ) {
2560							break;
2561						}
2562					}
2563	
2564					// Type is valid for all data points in the column - use this
2565					// type
2566					if ( detectedType ) {
2567						col.sType = detectedType;
2568						break;
2569					}
2570				}
2571	
2572				// Fall back - if no type was detected, always use string
2573				if ( ! col.sType ) {
2574					col.sType = 'string';
2575				}
2576			}
2577		}
2578	}
2579	
2580	
2581	/**
2582	 * Take the column definitions and static columns arrays and calculate how
2583	 * they relate to column indexes. The callback function will then apply the
2584	 * definition found for a column to a suitable configuration object.
2585	 *  @param {object} oSettings dataTables settings object
2586	 *  @param {array} aoColDefs The aoColumnDefs array that is to be applied
2587	 *  @param {array} aoCols The aoColumns array that defines columns individually
2588	 *  @param {function} fn Callback function - takes two parameters, the calculated
2589	 *    column index and the definition for that column.
2590	 *  @memberof DataTable#oApi
2591	 */
2592	function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )
2593	{
2594		var i, iLen, j, jLen, k, kLen, def;
2595		var columns = oSettings.aoColumns;
2596	
2597		// Column definitions with aTargets
2598		if ( aoColDefs )
2599		{
2600			/* Loop over the definitions array - loop in reverse so first instance has priority */
2601			for ( i=aoColDefs.length-1 ; i>=0 ; i-- )
2602			{
2603				def = aoColDefs[i];
2604	
2605				/* Each definition can target multiple columns, as it is an array */
2606				var aTargets = def.target !== undefined
2607					? def.target
2608					: def.targets !== undefined
2609						? def.targets
2610						: def.aTargets;
2611	
2612				if ( ! Array.isArray( aTargets ) )
2613				{
2614					aTargets = [ aTargets ];
2615				}
2616	
2617				for ( j=0, jLen=aTargets.length ; j<jLen ; j++ )
2618				{
2619					if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 )
2620					{
2621						/* Add columns that we don't yet know about */
2622						while( columns.length <= aTargets[j] )
2623						{
2624							_fnAddColumn( oSettings );
2625						}
2626	
2627						/* Integer, basic index */
2628						fn( aTargets[j], def );
2629					}
2630					else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 )
2631					{
2632						/* Negative integer, right to left column counting */
2633						fn( columns.length+aTargets[j], def );
2634					}
2635					else if ( typeof aTargets[j] === 'string' )
2636					{
2637						/* Class name matching on TH element */
2638						for ( k=0, kLen=columns.length ; k<kLen ; k++ )
2639						{
2640							if ( aTargets[j] == "_all" ||
2641							     $(columns[k].nTh).hasClass( aTargets[j] ) )
2642							{
2643								fn( k, def );
2644							}
2645						}
2646					}
2647				}
2648			}
2649		}
2650	
2651		// Statically defined columns array
2652		if ( aoCols )
2653		{
2654			for ( i=0, iLen=aoCols.length ; i<iLen ; i++ )
2655			{
2656				fn( i, aoCols[i] );
2657			}
2658		}
2659	}
2660	
2661	/**
2662	 * Add a data array to the table, creating DOM node etc. This is the parallel to
2663	 * _fnGatherData, but for adding rows from a Javascript source, rather than a
2664	 * DOM source.
2665	 *  @param {object} oSettings dataTables settings object
2666	 *  @param {array} aData data array to be added
2667	 *  @param {node} [nTr] TR element to add to the table - optional. If not given,
2668	 *    DataTables will create a row automatically
2669	 *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
2670	 *    if nTr is.
2671	 *  @returns {int} >=0 if successful (index of new aoData entry), -1 if failed
2672	 *  @memberof DataTable#oApi
2673	 */
2674	function _fnAddData ( oSettings, aDataIn, nTr, anTds )
2675	{
2676		/* Create the object for storing information about this new row */
2677		var iRow = oSettings.aoData.length;
2678		var oData = $.extend( true, {}, DataTable.models.oRow, {
2679			src: nTr ? 'dom' : 'data',
2680			idx: iRow
2681		} );
2682	
2683		oData._aData = aDataIn;
2684		oSettings.aoData.push( oData );
2685	
2686		/* Create the cells */
2687		var nTd, sThisType;
2688		var columns = oSettings.aoColumns;
2689	
2690		// Invalidate the column types as the new data needs to be revalidated
2691		for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
2692		{
2693			columns[i].sType = null;
2694		}
2695	
2696		/* Add to the display array */
2697		oSettings.aiDisplayMaster.push( iRow );
2698	
2699		var id = oSettings.rowIdFn( aDataIn );
2700		if ( id !== undefined ) {
2701			oSettings.aIds[ id ] = oData;
2702		}
2703	
2704		/* Create the DOM information, or register it if already present */
2705		if ( nTr || ! oSettings.oFeatures.bDeferRender )
2706		{
2707			_fnCreateTr( oSettings, iRow, nTr, anTds );
2708		}
2709	
2710		return iRow;
2711	}
2712	
2713	
2714	/**
2715	 * Add one or more TR elements to the table. Generally we'd expect to
2716	 * use this for reading data from a DOM sourced table, but it could be
2717	 * used for an TR element. Note that if a TR is given, it is used (i.e.
2718	 * it is not cloned).
2719	 *  @param {object} settings dataTables settings object
2720	 *  @param {array|node|jQuery} trs The TR element(s) to add to the table
2721	 *  @returns {array} Array of indexes for the added rows
2722	 *  @memberof DataTable#oApi
2723	 */
2724	function _fnAddTr( settings, trs )
2725	{
2726		var row;
2727	
2728		// Allow an individual node to be passed in
2729		if ( ! (trs instanceof $) ) {
2730			trs = $(trs);
2731		}
2732	
2733		return trs.map( function (i, el) {
2734			row = _fnGetRowElements( settings, el );
2735			return _fnAddData( settings, row.data, el, row.cells );
2736		} );
2737	}
2738	
2739	
2740	/**
2741	 * Take a TR element and convert it to an index in aoData
2742	 *  @param {object} oSettings dataTables settings object
2743	 *  @param {node} n the TR element to find
2744	 *  @returns {int} index if the node is found, null if not
2745	 *  @memberof DataTable#oApi
2746	 */
2747	function _fnNodeToDataIndex( oSettings, n )
2748	{
2749		return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null;
2750	}
2751	
2752	
2753	/**
2754	 * Take a TD element and convert it into a column data index (not the visible index)
2755	 *  @param {object} oSettings dataTables settings object
2756	 *  @param {int} iRow The row number the TD/TH can be found in
2757	 *  @param {node} n The TD/TH element to find
2758	 *  @returns {int} index if the node is found, -1 if not
2759	 *  @memberof DataTable#oApi
2760	 */
2761	function _fnNodeToColumnIndex( oSettings, iRow, n )
2762	{
2763		return $.inArray( n, oSettings.aoData[ iRow ].anCells );
2764	}
2765	
2766	
2767	/**
2768	 * Get the data for a given cell from the internal cache, taking into account data mapping
2769	 *  @param {object} settings dataTables settings object
2770	 *  @param {int} rowIdx aoData row id
2771	 *  @param {int} colIdx Column index
2772	 *  @param {string} type data get type ('display', 'type' 'filter|search' 'sort|order')
2773	 *  @returns {*} Cell data
2774	 *  @memberof DataTable#oApi
2775	 */
2776	function _fnGetCellData( settings, rowIdx, colIdx, type )
2777	{
2778		if (type === 'search') {
2779			type = 'filter';
2780		}
2781		else if (type === 'order') {
2782			type = 'sort';
2783		}
2784	
2785		var draw           = settings.iDraw;
2786		var col            = settings.aoColumns[colIdx];
2787		var rowData        = settings.aoData[rowIdx]._aData;
2788		var defaultContent = col.sDefaultContent;
2789		var cellData       = col.fnGetData( rowData, type, {
2790			settings: settings,
2791			row:      rowIdx,
2792			col:      colIdx
2793		} );
2794	
2795		if ( cellData === undefined ) {
2796			if ( settings.iDrawError != draw && defaultContent === null ) {
2797				_fnLog( settings, 0, "Requested unknown parameter "+
2798					(typeof col.mData=='function' ? '{function}' : "'"+col.mData+"'")+
2799					" for row "+rowIdx+", column "+colIdx, 4 );
2800				settings.iDrawError = draw;
2801			}
2802			return defaultContent;
2803		}
2804	
2805		// When the data source is null and a specific data type is requested (i.e.
2806		// not the original data), we can use default column data
2807		if ( (cellData === rowData || cellData === null) && defaultContent !== null && type !== undefined ) {
2808			cellData = defaultContent;
2809		}
2810		else if ( typeof cellData === 'function' ) {
2811			// If the data source is a function, then we run it and use the return,
2812			// executing in the scope of the data object (for instances)
2813			return cellData.call( rowData );
2814		}
2815	
2816		if ( cellData === null && type === 'display' ) {
2817			return '';
2818		}
2819	
2820		if ( type === 'filter' ) {
2821			var fomatters = DataTable.ext.type.search;
2822	
2823			if ( fomatters[ col.sType ] ) {
2824				cellData = fomatters[ col.sType ]( cellData );
2825			}
2826		}
2827	
2828		return cellData;
2829	}
2830	
2831	
2832	/**
2833	 * Set the value for a specific cell, into the internal data cache
2834	 *  @param {object} settings dataTables settings object
2835	 *  @param {int} rowIdx aoData row id
2836	 *  @param {int} colIdx Column index
2837	 *  @param {*} val Value to set
2838	 *  @memberof DataTable#oApi
2839	 */
2840	function _fnSetCellData( settings, rowIdx, colIdx, val )
2841	{
2842		var col     = settings.aoColumns[colIdx];
2843		var rowData = settings.aoData[rowIdx]._aData;
2844	
2845		col.fnSetData( rowData, val, {
2846			settings: settings,
2847			row:      rowIdx,
2848			col:      colIdx
2849		}  );
2850	}
2851	
2852	
2853	// Private variable that is used to match action syntax in the data property object
2854	var __reArray = /\[.*?\]$/;
2855	var __reFn = /\(\)$/;
2856	
2857	/**
2858	 * Split string on periods, taking into account escaped periods
2859	 * @param  {string} str String to split
2860	 * @return {array} Split string
2861	 */
2862	function _fnSplitObjNotation( str )
2863	{
2864		return $.map( str.match(/(\\.|[^\.])+/g) || [''], function ( s ) {
2865			return s.replace(/\\\./g, '.');
2866		} );
2867	}
2868	
2869	
2870	/**
2871	 * Return a function that can be used to get data from a source object, taking
2872	 * into account the ability to use nested objects as a source
2873	 *  @param {string|int|function} mSource The data source for the object
2874	 *  @returns {function} Data get function
2875	 *  @memberof DataTable#oApi
2876	 */
2877	var _fnGetObjectDataFn = DataTable.util.get;
2878	
2879	
2880	/**
2881	 * Return a function that can be used to set data from a source object, taking
2882	 * into account the ability to use nested objects as a source
2883	 *  @param {string|int|function} mSource The data source for the object
2884	 *  @returns {function} Data set function
2885	 *  @memberof DataTable#oApi
2886	 */
2887	var _fnSetObjectDataFn = DataTable.util.set;
2888	
2889	
2890	/**
2891	 * Return an array with the full table data
2892	 *  @param {object} oSettings dataTables settings object
2893	 *  @returns array {array} aData Master data array
2894	 *  @memberof DataTable#oApi
2895	 */
2896	function _fnGetDataMaster ( settings )
2897	{
2898		return _pluck( settings.aoData, '_aData' );
2899	}
2900	
2901	
2902	/**
2903	 * Nuke the table
2904	 *  @param {object} oSettings dataTables settings object
2905	 *  @memberof DataTable#oApi
2906	 */
2907	function _fnClearTable( settings )
2908	{
2909		settings.aoData.length = 0;
2910		settings.aiDisplayMaster.length = 0;
2911		settings.aiDisplay.length = 0;
2912		settings.aIds = {};
2913	}
2914	
2915	
2916	 /**
2917	 * Take an array of integers (index array) and remove a target integer (value - not
2918	 * the key!)
2919	 *  @param {array} a Index array to target
2920	 *  @param {int} iTarget value to find
2921	 *  @memberof DataTable#oApi
2922	 */
2923	function _fnDeleteIndex( a, iTarget, splice )
2924	{
2925		var iTargetIndex = -1;
2926	
2927		for ( var i=0, iLen=a.length ; i<iLen ; i++ )
2928		{
2929			if ( a[i] == iTarget )
2930			{
2931				iTargetIndex = i;
2932			}
2933			else if ( a[i] > iTarget )
2934			{
2935				a[i]--;
2936			}
2937		}
2938	
2939		if ( iTargetIndex != -1 && splice === undefined )
2940		{
2941			a.splice( iTargetIndex, 1 );
2942		}
2943	}
2944	
2945	
2946	/**
2947	 * Mark cached data as invalid such that a re-read of the data will occur when
2948	 * the cached data is next requested. Also update from the data source object.
2949	 *
2950	 * @param {object} settings DataTables settings object
2951	 * @param {int}    rowIdx   Row index to invalidate
2952	 * @param {string} [src]    Source to invalidate from: undefined, 'auto', 'dom'
2953	 *     or 'data'
2954	 * @param {int}    [colIdx] Column index to invalidate. If undefined the whole
2955	 *     row will be invalidated
2956	 * @memberof DataTable#oApi
2957	 *
2958	 * @todo For the modularisation of v1.11 this will need to become a callback, so
2959	 *   the sort and filter methods can subscribe to it. That will required
2960	 *   initialisation options for sorting, which is why it is not already baked in
2961	 */
2962	function _fnInvalidate( settings, rowIdx, src, colIdx )
2963	{
2964		var row = settings.aoData[ rowIdx ];
2965		var i, ien;
2966		var cellWrite = function ( cell, col ) {
2967			// This is very frustrating, but in IE if you just write directly
2968			// to innerHTML, and elements that are overwritten are GC'ed,
2969			// even if there is a reference to them elsewhere
2970			while ( cell.childNodes.length ) {
2971				cell.removeChild( cell.firstChild );
2972			}
2973	
2974			cell.innerHTML = _fnGetCellData( settings, rowIdx, col, 'display' );
2975		};
2976	
2977		// Are we reading last data from DOM or the data object?
2978		if ( src === 'dom' || ((! src || src === 'auto') && row.src === 'dom') ) {
2979			// Read the data from the DOM
2980			row._aData = _fnGetRowElements(
2981					settings, row, colIdx, colIdx === undefined ? undefined : row._aData
2982				)
2983				.data;
2984		}
2985		else {
2986			// Reading from data object, update the DOM
2987			var cells = row.anCells;
2988	
2989			if ( cells ) {
2990				if ( colIdx !== undefined ) {
2991					cellWrite( cells[colIdx], colIdx );
2992				}
2993				else {
2994					for ( i=0, ien=cells.length ; i<ien ; i++ ) {
2995						cellWrite( cells[i], i );
2996					}
2997				}
2998			}
2999		}
3000	
3001		// For both row and cell invalidation, the cached data for sorting and
3002		// filtering is nulled out
3003		row._aSortData = null;
3004		row._aFilterData = null;
3005	
3006		// Invalidate the type for a specific column (if given) or all columns since
3007		// the data might have changed
3008		var cols = settings.aoColumns;
3009		if ( colIdx !== undefined ) {
3010			cols[ colIdx ].sType = null;
3011		}
3012		else {
3013			for ( i=0, ien=cols.length ; i<ien ; i++ ) {
3014				cols[i].sType = null;
3015			}
3016	
3017			// Update DataTables special `DT_*` attributes for the row
3018			_fnRowAttributes( settings, row );
3019		}
3020	}
3021	
3022	
3023	/**
3024	 * Build a data source object from an HTML row, reading the contents of the
3025	 * cells that are in the row.
3026	 *
3027	 * @param {object} settings DataTables settings object
3028	 * @param {node|object} TR element from which to read data or existing row
3029	 *   object from which to re-read the data from the cells
3030	 * @param {int} [colIdx] Optional column index
3031	 * @param {array|object} [d] Data source object. If `colIdx` is given then this
3032	 *   parameter should also be given and will be used to write the data into.
3033	 *   Only the column in question will be written
3034	 * @returns {object} Object with two parameters: `data` the data read, in
3035	 *   document order, and `cells` and array of nodes (they can be useful to the
3036	 *   caller, so rather than needing a second traversal to get them, just return
3037	 *   them from here).
3038	 * @memberof DataTable#oApi
3039	 */
3040	function _fnGetRowElements( settings, row, colIdx, d )
3041	{
3042		var
3043			tds = [],
3044			td = row.firstChild,
3045			name, col, o, i=0, contents,
3046			columns = settings.aoColumns,
3047			objectRead = settings._rowReadObject;
3048	
3049		// Allow the data object to be passed in, or construct
3050		d = d !== undefined ?
3051			d :
3052			objectRead ?
3053				{} :
3054				[];
3055	
3056		var attr = function ( str, td  ) {
3057			if ( typeof str === 'string' ) {
3058				var idx = str.indexOf('@');
3059	
3060				if ( idx !== -1 ) {
3061					var attr = str.substring( idx+1 );
3062					var setter = _fnSetObjectDataFn( str );
3063					setter( d, td.getAttribute( attr ) );
3064				}
3065			}
3066		};
3067	
3068		// Read data from a cell and store into the data object
3069		var cellProcess = function ( cell ) {
3070			if ( colIdx === undefined || colIdx === i ) {
3071				col = columns[i];
3072				contents = (cell.innerHTML).trim();
3073	
3074				if ( col && col._bAttrSrc ) {
3075					var setter = _fnSetObjectDataFn( col.mData._ );
3076					setter( d, contents );
3077	
3078					attr( col.mData.sort, cell );
3079					attr( col.mData.type, cell );
3080					attr( col.mData.filter, cell );
3081				}
3082				else {
3083					// Depending on the `data` option for the columns the data can
3084					// be read to either an object or an array.
3085					if ( objectRead ) {
3086						if ( ! col._setter ) {
3087							// Cache the setter function
3088							col._setter = _fnSetObjectDataFn( col.mData );
3089						}
3090						col._setter( d, contents );
3091					}
3092					else {
3093						d[i] = contents;
3094					}
3095				}
3096			}
3097	
3098			i++;
3099		};
3100	
3101		if ( td ) {
3102			// `tr` element was passed in
3103			while ( td ) {
3104				name = td.nodeName.toUpperCase();
3105	
3106				if ( name == "TD" || name == "TH" ) {
3107					cellProcess( td );
3108					tds.push( td );
3109				}
3110	
3111				td = td.nextSibling;
3112			}
3113		}
3114		else {
3115			// Existing row object passed in
3116			tds = row.anCells;
3117	
3118			for ( var j=0, jen=tds.length ; j<jen ; j++ ) {
3119				cellProcess( tds[j] );
3120			}
3121		}
3122	
3123		// Read the ID from the DOM if present
3124		var rowNode = row.firstChild ? row : row.nTr;
3125	
3126		if ( rowNode ) {
3127			var id = rowNode.getAttribute( 'id' );
3128	
3129			if ( id ) {
3130				_fnSetObjectDataFn( settings.rowId )( d, id );
3131			}
3132		}
3133	
3134		return {
3135			data: d,
3136			cells: tds
3137		};
3138	}
3139	/**
3140	 * Create a new TR element (and it's TD children) for a row
3141	 *  @param {object} oSettings dataTables settings object
3142	 *  @param {int} iRow Row to consider
3143	 *  @param {node} [nTrIn] TR element to add to the table - optional. If not given,
3144	 *    DataTables will create a row automatically
3145	 *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
3146	 *    if nTr is.
3147	 *  @memberof DataTable#oApi
3148	 */
3149	function _fnCreateTr ( oSettings, iRow, nTrIn, anTds )
3150	{
3151		var
3152			row = oSettings.aoData[iRow],
3153			rowData = row._aData,
3154			cells = [],
3155			nTr, nTd, oCol,
3156			i, iLen, create;
3157	
3158		if ( row.nTr === null )
3159		{
3160			nTr = nTrIn || document.createElement('tr');
3161	
3162			row.nTr = nTr;
3163			row.anCells = cells;
3164	
3165			/* Use a private property on the node to allow reserve mapping from the node
3166			 * to the aoData array for fast look up
3167			 */
3168			nTr._DT_RowIndex = iRow;
3169	
3170			/* Special parameters can be given by the data source to be used on the row */
3171			_fnRowAttributes( oSettings, row );
3172	
3173			/* Process each column */
3174			for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
3175			{
3176				oCol = oSettings.aoColumns[i];
3177				create = nTrIn ? false : true;
3178	
3179				nTd = create ? document.createElement( oCol.sCellType ) : anTds[i];
3180	
3181				if (! nTd) {
3182					_fnLog( oSettings, 0, 'Incorrect column count', 18 );
3183				}
3184	
3185				nTd._DT_CellIndex = {
3186					row: iRow,
3187					column: i
3188				};
3189				
3190				cells.push( nTd );
3191	
3192				// Need to create the HTML if new, or if a rendering function is defined
3193				if ( create || ((oCol.mRender || oCol.mData !== i) &&
3194					 (!$.isPlainObject(oCol.mData) || oCol.mData._ !== i+'.display')
3195				)) {
3196					nTd.innerHTML = _fnGetCellData( oSettings, iRow, i, 'display' );
3197				}
3198	
3199				/* Add user defined class */
3200				if ( oCol.sClass )
3201				{
3202					nTd.className += ' '+oCol.sClass;
3203				}
3204	
3205				// Visibility - add or remove as required
3206				if ( oCol.bVisible && ! nTrIn )
3207				{
3208					nTr.appendChild( nTd );
3209				}
3210				else if ( ! oCol.bVisible && nTrIn )
3211				{
3212					nTd.parentNode.removeChild( nTd );
3213				}
3214	
3215				if ( oCol.fnCreatedCell )
3216				{
3217					oCol.fnCreatedCell.call( oSettings.oInstance,
3218						nTd, _fnGetCellData( oSettings, iRow, i ), rowData, iRow, i
3219					);
3220				}
3221			}
3222	
3223			_fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow, cells] );
3224		}
3225	}
3226	
3227	
3228	/**
3229	 * Add attributes to a row based on the special `DT_*` parameters in a data
3230	 * source object.
3231	 *  @param {object} settings DataTables settings object
3232	 *  @param {object} DataTables row object for the row to be modified
3233	 *  @memberof DataTable#oApi
3234	 */
3235	function _fnRowAttributes( settings, row )
3236	{
3237		var tr = row.nTr;
3238		var data = row._aData;
3239	
3240		if ( tr ) {
3241			var id = settings.rowIdFn( data );
3242	
3243			if ( id ) {
3244				tr.id = id;
3245			}
3246	
3247			if ( data.DT_RowClass ) {
3248				// Remove any classes added by DT_RowClass before
3249				var a = data.DT_RowClass.split(' ');
3250				row.__rowc = row.__rowc ?
3251					_unique( row.__rowc.concat( a ) ) :
3252					a;
3253	
3254				$(tr)
3255					.removeClass( row.__rowc.join(' ') )
3256					.addClass( data.DT_RowClass );
3257			}
3258	
3259			if ( data.DT_RowAttr ) {
3260				$(tr).attr( data.DT_RowAttr );
3261			}
3262	
3263			if ( data.DT_RowData ) {
3264				$(tr).data( data.DT_RowData );
3265			}
3266		}
3267	}
3268	
3269	
3270	/**
3271	 * Create the HTML header for the table
3272	 *  @param {object} oSettings dataTables settings object
3273	 *  @memberof DataTable#oApi
3274	 */
3275	function _fnBuildHead( oSettings )
3276	{
3277		var i, ien, cell, row, column;
3278		var thead = oSettings.nTHead;
3279		var tfoot = oSettings.nTFoot;
3280		var createHeader = $('th, td', thead).length === 0;
3281		var classes = oSettings.oClasses;
3282		var columns = oSettings.aoColumns;
3283	
3284		if ( createHeader ) {
3285			row = $('<tr/>').appendTo( thead );
3286		}
3287	
3288		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
3289			column = columns[i];
3290			cell = $( column.nTh ).addClass( column.sClass );
3291	
3292			if ( createHeader ) {
3293				cell.appendTo( row );
3294			}
3295	
3296			// 1.11 move into sorting
3297			if ( oSettings.oFeatures.bSort ) {
3298				cell.addClass( column.sSortingClass );
3299	
3300				if ( column.bSortable !== false ) {
3301					cell
3302						.attr( 'tabindex', oSettings.iTabIndex )
3303						.attr( 'aria-controls', oSettings.sTableId );
3304	
3305					_fnSortAttachListener( oSettings, column.nTh, i );
3306				}
3307			}
3308	
3309			if ( column.sTitle != cell[0].innerHTML ) {
3310				cell.html( column.sTitle );
3311			}
3312	
3313			_fnRenderer( oSettings, 'header' )(
3314				oSettings, cell, column, classes
3315			);
3316		}
3317	
3318		if ( createHeader ) {
3319			_fnDetectHeader( oSettings.aoHeader, thead );
3320		}
3321	
3322		/* Deal with the footer - add classes if required */
3323		$(thead).children('tr').children('th, td').addClass( classes.sHeaderTH );
3324		$(tfoot).children('tr').children('th, td').addClass( classes.sFooterTH );
3325	
3326		// Cache the footer cells. Note that we only take the cells from the first
3327		// row in the footer. If there is more than one row the user wants to
3328		// interact with, they need to use the table().foot() method. Note also this
3329		// allows cells to be used for multiple columns using colspan
3330		if ( tfoot !== null ) {
3331			var cells = oSettings.aoFooter[0];
3332	
3333			for ( i=0, ien=cells.length ; i<ien ; i++ ) {
3334				column = columns[i];
3335	
3336				if (column) {
3337					column.nTf = cells[i].cell;
3338		
3339					if ( column.sClass ) {
3340						$(column.nTf).addClass( column.sClass );
3341					}
3342				}
3343				else {
3344					_fnLog( oSettings, 0, 'Incorrect column count', 18 );
3345				}
3346			}
3347		}
3348	}
3349	
3350	
3351	/**
3352	 * Draw the header (or footer) element based on the column visibility states. The
3353	 * methodology here is to use the layout array from _fnDetectHeader, modified for
3354	 * the instantaneous column visibility, to construct the new layout. The grid is
3355	 * traversed over cell at a time in a rows x columns grid fashion, although each
3356	 * cell insert can cover multiple elements in the grid - which is tracks using the
3357	 * aApplied array. Cell inserts in the grid will only occur where there isn't
3358	 * already a cell in that position.
3359	 *  @param {object} oSettings dataTables settings object
3360	 *  @param array {objects} aoSource Layout array from _fnDetectHeader
3361	 *  @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,
3362	 *  @memberof DataTable#oApi
3363	 */
3364	function _fnDrawHead( oSettings, aoSource, bIncludeHidden )
3365	{
3366		var i, iLen, j, jLen, k, kLen, n, nLocalTr;
3367		var aoLocal = [];
3368		var aApplied = [];
3369		var iColumns = oSettings.aoColumns.length;
3370		var iRowspan, iColspan;
3371	
3372		if ( ! aoSource )
3373		{
3374			return;
3375		}
3376	
3377		if (  bIncludeHidden === undefined )
3378		{
3379			bIncludeHidden = false;
3380		}
3381	
3382		/* Make a copy of the master layout array, but without the visible columns in it */
3383		for ( i=0, iLen=aoSource.length ; i<iLen ; i++ )
3384		{
3385			aoLocal[i] = aoSource[i].slice();
3386			aoLocal[i].nTr = aoSource[i].nTr;
3387	
3388			/* Remove any columns which are currently hidden */
3389			for ( j=iColumns-1 ; j>=0 ; j-- )
3390			{
3391				if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden )
3392				{
3393					aoLocal[i].splice( j, 1 );
3394				}
3395			}
3396	
3397			/* Prep the applied array - it needs an element for each row */
3398			aApplied.push( [] );
3399		}
3400	
3401		for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ )
3402		{
3403			nLocalTr = aoLocal[i].nTr;
3404	
3405			/* All cells are going to be replaced, so empty out the row */
3406			if ( nLocalTr )
3407			{
3408				while( (n = nLocalTr.firstChild) )
3409				{
3410					nLocalTr.removeChild( n );
3411				}
3412			}
3413	
3414			for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ )
3415			{
3416				iRowspan = 1;
3417				iColspan = 1;
3418	
3419				/* Check to see if there is already a cell (row/colspan) covering our target
3420				 * insert point. If there is, then there is nothing to do.
3421				 */
3422				if ( aApplied[i][j] === undefined )
3423				{
3424					nLocalTr.appendChild( aoLocal[i][j].cell );
3425					aApplied[i][j] = 1;
3426	
3427					/* Expand the cell to cover as many rows as needed */
3428					while ( aoLocal[i+iRowspan] !== undefined &&
3429					        aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell )
3430					{
3431						aApplied[i+iRowspan][j] = 1;
3432						iRowspan++;
3433					}
3434	
3435					/* Expand the cell to cover as many columns as needed */
3436					while ( aoLocal[i][j+iColspan] !== undefined &&
3437					        aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell )
3438					{
3439						/* Must update the applied array over the rows for the columns */
3440						for ( k=0 ; k<iRowspan ; k++ )
3441						{
3442							aApplied[i+k][j+iColspan] = 1;
3443						}
3444						iColspan++;
3445					}
3446	
3447					/* Do the actual expansion in the DOM */
3448					$(aoLocal[i][j].cell)
3449						.attr('rowspan', iRowspan)
3450						.attr('colspan', iColspan);
3451				}
3452			}
3453		}
3454	}
3455	
3456	
3457	/**
3458	 * Insert the required TR nodes into the table for display
3459	 *  @param {object} oSettings dataTables settings object
3460	 *  @param ajaxComplete true after ajax call to complete rendering
3461	 *  @memberof DataTable#oApi
3462	 */
3463	function _fnDraw( oSettings, ajaxComplete )
3464	{
3465		// Allow for state saving and a custom start position
3466		_fnStart( oSettings );
3467	
3468		/* Provide a pre-callback function which can be used to cancel the draw is false is returned */
3469		var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] );
3470		if ( $.inArray( false, aPreDraw ) !== -1 )
3471		{
3472			_fnProcessingDisplay( oSettings, false );
3473			return;
3474		}
3475	
3476		var anRows = [];
3477		var iRowCount = 0;
3478		var asStripeClasses = oSettings.asStripeClasses;
3479		var iStripes = asStripeClasses.length;
3480		var oLang = oSettings.oLanguage;
3481		var bServerSide = _fnDataSource( oSettings ) == 'ssp';
3482		var aiDisplay = oSettings.aiDisplay;
3483		var iDisplayStart = oSettings._iDisplayStart;
3484		var iDisplayEnd = oSettings.fnDisplayEnd();
3485	
3486		oSettings.bDrawing = true;
3487	
3488		/* Server-side processing draw intercept */
3489		if ( oSettings.bDeferLoading )
3490		{
3491			oSettings.bDeferLoading = false;
3492			oSettings.iDraw++;
3493			_fnProcessingDisplay( oSettings, false );
3494		}
3495		else if ( !bServerSide )
3496		{
3497			oSettings.iDraw++;
3498		}
3499		else if ( !oSettings.bDestroying && !ajaxComplete)
3500		{
3501			_fnAjaxUpdate( oSettings );
3502			return;
3503		}
3504	
3505		if ( aiDisplay.length !== 0 )
3506		{
3507			var iStart = bServerSide ? 0 : iDisplayStart;
3508			var iEnd = bServerSide ? oSettings.aoData.length : iDisplayEnd;
3509	
3510			for ( var j=iStart ; j<iEnd ; j++ )
3511			{
3512				var iDataIndex = aiDisplay[j];
3513				var aoData = oSettings.aoData[ iDataIndex ];
3514				if ( aoData.nTr === null )
3515				{
3516					_fnCreateTr( oSettings, iDataIndex );
3517				}
3518	
3519				var nRow = aoData.nTr;
3520	
3521				/* Remove the old striping classes and then add the new one */
3522				if ( iStripes !== 0 )
3523				{
3524					var sStripe = asStripeClasses[ iRowCount % iStripes ];
3525					if ( aoData._sRowStripe != sStripe )
3526					{
3527						$(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe );
3528						aoData._sRowStripe = sStripe;
3529					}
3530				}
3531	
3532				// Row callback functions - might want to manipulate the row
3533				// iRowCount and j are not currently documented. Are they at all
3534				// useful?
3535				_fnCallbackFire( oSettings, 'aoRowCallback', null,
3536					[nRow, aoData._aData, iRowCount, j, iDataIndex] );
3537	
3538				anRows.push( nRow );
3539				iRowCount++;
3540			}
3541		}
3542		else
3543		{
3544			/* Table is empty - create a row with an empty message in it */
3545			var sZero = oLang.sZeroRecords;
3546			if ( oSettings.iDraw == 1 &&  _fnDataSource( oSettings ) == 'ajax' )
3547			{
3548				sZero = oLang.sLoadingRecords;
3549			}
3550			else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 )
3551			{
3552				sZero = oLang.sEmptyTable;
3553			}
3554	
3555			anRows[ 0 ] = $( '<tr/>', { 'class': iStripes ? asStripeClasses[0] : '' } )
3556				.append( $('<td />', {
3557					'valign':  'top',
3558					'colSpan': _fnVisbleColumns( oSettings ),
3559					'class':   oSettings.oClasses.sRowEmpty
3560				} ).html( sZero ) )[0];
3561		}
3562	
3563		/* Header and footer callbacks */
3564		_fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0],
3565			_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
3566	
3567		_fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0],
3568			_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
3569	
3570		var body = $(oSettings.nTBody);
3571	
3572		body.children().detach();
3573		body.append( $(anRows) );
3574	
3575		/* Call all required callback functions for the end of a draw */
3576		_fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] );
3577	
3578		/* Draw is complete, sorting and filtering must be as well */
3579		oSettings.bSorted = false;
3580		oSettings.bFiltered = false;
3581		oSettings.bDrawing = false;
3582	}
3583	
3584	
3585	/**
3586	 * Redraw the table - taking account of the various features which are enabled
3587	 *  @param {object} oSettings dataTables settings object
3588	 *  @param {boolean} [holdPosition] Keep the current paging position. By default
3589	 *    the paging is reset to the first page
3590	 *  @memberof DataTable#oApi
3591	 */
3592	function _fnReDraw( settings, holdPosition )
3593	{
3594		var
3595			features = settings.oFeatures,
3596			sort     = features.bSort,
3597			filter   = features.bFilter;
3598	
3599		if ( sort ) {
3600			_fnSort( settings );
3601		}
3602	
3603		if ( filter ) {
3604			_fnFilterComplete( settings, settings.oPreviousSearch );
3605		}
3606		else {
3607			// No filtering, so we want to just use the display master
3608			settings.aiDisplay = settings.aiDisplayMaster.slice();
3609		}
3610	
3611		if ( holdPosition !== true ) {
3612			settings._iDisplayStart = 0;
3613		}
3614	
3615		// Let any modules know about the draw hold position state (used by
3616		// scrolling internally)
3617		settings._drawHold = holdPosition;
3618	
3619		_fnDraw( settings );
3620	
3621		settings._drawHold = false;
3622	}
3623	
3624	
3625	/**
3626	 * Add the options to the page HTML for the table
3627	 *  @param {object} oSettings dataTables settings object
3628	 *  @memberof DataTable#oApi
3629	 */
3630	function _fnAddOptionsHtml ( oSettings )
3631	{
3632		var classes = oSettings.oClasses;
3633		var table = $(oSettings.nTable);
3634		var holding = $('<div/>').insertBefore( table ); // Holding element for speed
3635		var features = oSettings.oFeatures;
3636	
3637		// All DataTables are wrapped in a div
3638		var insert = $('<div/>', {
3639			id:      oSettings.sTableId+'_wrapper',
3640			'class': classes.sWrapper + (oSettings.nTFoot ? '' : ' '+classes.sNoFooter)
3641		} );
3642	
3643		oSettings.nHolding = holding[0];
3644		oSettings.nTableWrapper = insert[0];
3645		oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;
3646	
3647		/* Loop over the user set positioning and place the elements as needed */
3648		var aDom = oSettings.sDom.split('');
3649		var featureNode, cOption, nNewNode, cNext, sAttr, j;
3650		for ( var i=0 ; i<aDom.length ; i++ )
3651		{
3652			featureNode = null;
3653			cOption = aDom[i];
3654	
3655			if ( cOption == '<' )
3656			{
3657				/* New container div */
3658				nNewNode = $('<div/>')[0];
3659	
3660				/* Check to see if we should append an id and/or a class name to the container */
3661				cNext = aDom[i+1];
3662				if ( cNext == "'" || cNext == '"' )
3663				{
3664					sAttr = "";
3665					j = 2;
3666					while ( aDom[i+j] != cNext )
3667					{
3668						sAttr += aDom[i+j];
3669						j++;
3670					}
3671	
3672					/* Replace jQuery UI constants @todo depreciated */
3673					if ( sAttr == "H" )
3674					{
3675						sAttr = classes.sJUIHeader;
3676					}
3677					else if ( sAttr == "F" )
3678					{
3679						sAttr = classes.sJUIFooter;
3680					}
3681	
3682					/* The attribute can be in the format of "#id.class", "#id" or "class" This logic
3683					 * breaks the string into parts and applies them as needed
3684					 */
3685					if ( sAttr.indexOf('.') != -1 )
3686					{
3687						var aSplit = sAttr.split('.');
3688						nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);
3689						nNewNode.className = aSplit[1];
3690					}
3691					else if ( sAttr.charAt(0) == "#" )
3692					{
3693						nNewNode.id = sAttr.substr(1, sAttr.length-1);
3694					}
3695					else
3696					{
3697						nNewNode.className = sAttr;
3698					}
3699	
3700					i += j; /* Move along the position array */
3701				}
3702	
3703				insert.append( nNewNode );
3704				insert = $(nNewNode);
3705			}
3706			else if ( cOption == '>' )
3707			{
3708				/* End container div */
3709				insert = insert.parent();
3710			}
3711			// @todo Move options into their own plugins?
3712			else if ( cOption == 'l' && features.bPaginate && features.bLengthChange )
3713			{
3714				/* Length */
3715				featureNode = _fnFeatureHtmlLength( oSettings );
3716			}
3717			else if ( cOption == 'f' && features.bFilter )
3718			{
3719				/* Filter */
3720				featureNode = _fnFeatureHtmlFilter( oSettings );
3721			}
3722			else if ( cOption == 'r' && features.bProcessing )
3723			{
3724				/* pRocessing */
3725				featureNode = _fnFeatureHtmlProcessing( oSettings );
3726			}
3727			else if ( cOption == 't' )
3728			{
3729				/* Table */
3730				featureNode = _fnFeatureHtmlTable( oSettings );
3731			}
3732			else if ( cOption ==  'i' && features.bInfo )
3733			{
3734				/* Info */
3735				featureNode = _fnFeatureHtmlInfo( oSettings );
3736			}
3737			else if ( cOption == 'p' && features.bPaginate )
3738			{
3739				/* Pagination */
3740				featureNode = _fnFeatureHtmlPaginate( oSettings );
3741			}
3742			else if ( DataTable.ext.feature.length !== 0 )
3743			{
3744				/* Plug-in features */
3745				var aoFeatures = DataTable.ext.feature;
3746				for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )
3747				{
3748					if ( cOption == aoFeatures[k].cFeature )
3749					{
3750						featureNode = aoFeatures[k].fnInit( oSettings );
3751						break;
3752					}
3753				}
3754			}
3755	
3756			/* Add to the 2D features array */
3757			if ( featureNode )
3758			{
3759				var aanFeatures = oSettings.aanFeatures;
3760	
3761				if ( ! aanFeatures[cOption] )
3762				{
3763					aanFeatures[cOption] = [];
3764				}
3765	
3766				aanFeatures[cOption].push( featureNode );
3767				insert.append( featureNode );
3768			}
3769		}
3770	
3771		/* Built our DOM structure - replace the holding div with what we want */
3772		holding.replaceWith( insert );
3773		oSettings.nHolding = null;
3774	}
3775	
3776	
3777	/**
3778	 * Use the DOM source to create up an array of header cells. The idea here is to
3779	 * create a layout grid (array) of rows x columns, which contains a reference
3780	 * to the cell that that point in the grid (regardless of col/rowspan), such that
3781	 * any column / row could be removed and the new grid constructed
3782	 *  @param array {object} aLayout Array to store the calculated layout in
3783	 *  @param {node} nThead The header/footer element for the table
3784	 *  @memberof DataTable#oApi
3785	 */
3786	function _fnDetectHeader ( aLayout, nThead )
3787	{
3788		var nTrs = $(nThead).children('tr');
3789		var nTr, nCell;
3790		var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan;
3791		var bUnique;
3792		var fnShiftCol = function ( a, i, j ) {
3793			var k = a[i];
3794	                while ( k[j] ) {
3795				j++;
3796			}
3797			return j;
3798		};
3799	
3800		aLayout.splice( 0, aLayout.length );
3801	
3802		/* We know how many rows there are in the layout - so prep it */
3803		for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
3804		{
3805			aLayout.push( [] );
3806		}
3807	
3808		/* Calculate a layout array */
3809		for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
3810		{
3811			nTr = nTrs[i];
3812			iColumn = 0;
3813	
3814			/* For every cell in the row... */
3815			nCell = nTr.firstChild;
3816			while ( nCell ) {
3817				if ( nCell.nodeName.toUpperCase() == "TD" ||
3818				     nCell.nodeName.toUpperCase() == "TH" )
3819				{
3820					/* Get the col and rowspan attributes from the DOM and sanitise them */
3821					iColspan = nCell.getAttribute('colspan') * 1;
3822					iRowspan = nCell.getAttribute('rowspan') * 1;
3823					iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan;
3824					iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan;
3825	
3826					/* There might be colspan cells already in this row, so shift our target
3827					 * accordingly
3828					 */
3829					iColShifted = fnShiftCol( aLayout, i, iColumn );
3830	
3831					/* Cache calculation for unique columns */
3832					bUnique = iColspan === 1 ? true : false;
3833	
3834					/* If there is col / rowspan, copy the information into the layout grid */
3835					for ( l=0 ; l<iColspan ; l++ )
3836					{
3837						for ( k=0 ; k<iRowspan ; k++ )
3838						{
3839							aLayout[i+k][iColShifted+l] = {
3840								"cell": nCell,
3841								"unique": bUnique
3842							};
3843							aLayout[i+k].nTr = nTr;
3844						}
3845					}
3846				}
3847				nCell = nCell.nextSibling;
3848			}
3849		}
3850	}
3851	
3852	
3853	/**
3854	 * Get an array of unique th elements, one for each column
3855	 *  @param {object} oSettings dataTables settings object
3856	 *  @param {node} nHeader automatically detect the layout from this node - optional
3857	 *  @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional
3858	 *  @returns array {node} aReturn list of unique th's
3859	 *  @memberof DataTable#oApi
3860	 */
3861	function _fnGetUniqueThs ( oSettings, nHeader, aLayout )
3862	{
3863		var aReturn = [];
3864		if ( !aLayout )
3865		{
3866			aLayout = oSettings.aoHeader;
3867			if ( nHeader )
3868			{
3869				aLayout = [];
3870				_fnDetectHeader( aLayout, nHeader );
3871			}
3872		}
3873	
3874		for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ )
3875		{
3876			for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ )
3877			{
3878				if ( aLayout[i][j].unique &&
3879					 (!aReturn[j] || !oSettings.bSortCellsTop) )
3880				{
3881					aReturn[j] = aLayout[i][j].cell;
3882				}
3883			}
3884		}
3885	
3886		return aReturn;
3887	}
3888	
3889	/**
3890	 * Set the start position for draw
3891	 *  @param {object} oSettings dataTables settings object
3892	 */
3893	function _fnStart( oSettings )
3894	{
3895		var bServerSide = _fnDataSource( oSettings ) == 'ssp';
3896		var iInitDisplayStart = oSettings.iInitDisplayStart;
3897	
3898		// Check and see if we have an initial draw position from state saving
3899		if ( iInitDisplayStart !== undefined && iInitDisplayStart !== -1 )
3900		{
3901			oSettings._iDisplayStart = bServerSide ?
3902				iInitDisplayStart :
3903				iInitDisplayStart >= oSettings.fnRecordsDisplay() ?
3904					0 :
3905					iInitDisplayStart;
3906	
3907			oSettings.iInitDisplayStart = -1;
3908		}
3909	}
3910	
3911	/**
3912	 * Create an Ajax call based on the table's settings, taking into account that
3913	 * parameters can have multiple forms, and backwards compatibility.
3914	 *
3915	 * @param {object} oSettings dataTables settings object
3916	 * @param {array} data Data to send to the server, required by
3917	 *     DataTables - may be augmented by developer callbacks
3918	 * @param {function} fn Callback function to run when data is obtained
3919	 */
3920	function _fnBuildAjax( oSettings, data, fn )
3921	{
3922		// Compatibility with 1.9-, allow fnServerData and event to manipulate
3923		_fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [data] );
3924	
3925		// Convert to object based for 1.10+ if using the old array scheme which can
3926		// come from server-side processing or serverParams
3927		if ( data && Array.isArray(data) ) {
3928			var tmp = {};
3929			var rbracket = /(.*?)\[\]$/;
3930	
3931			$.each( data, function (key, val) {
3932				var match = val.name.match(rbracket);
3933	
3934				if ( match ) {
3935					// Support for arrays
3936					var name = match[0];
3937	
3938					if ( ! tmp[ name ] ) {
3939						tmp[ name ] = [];
3940					}
3941					tmp[ name ].push( val.value );
3942				}
3943				else {
3944					tmp[val.name] = val.value;
3945				}
3946			} );
3947			data = tmp;
3948		}
3949	
3950		var ajaxData;
3951		var ajax = oSettings.ajax;
3952		var instance = oSettings.oInstance;
3953		var callback = function ( json ) {
3954			var status = oSettings.jqXHR
3955				? oSettings.jqXHR.status
3956				: null;
3957	
3958			if ( json === null || (typeof status === 'number' && status == 204 ) ) {
3959				json = {};
3960				_fnAjaxDataSrc( oSettings, json, [] );
3961			}
3962	
3963			var error = json.error || json.sError;
3964			if ( error ) {
3965				_fnLog( oSettings, 0, error );
3966			}
3967	
3968			oSettings.json = json;
3969	
3970			_fnCallbackFire( oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR] );
3971			fn( json );
3972		};
3973	
3974		if ( $.isPlainObject( ajax ) && ajax.data )
3975		{
3976			ajaxData = ajax.data;
3977	
3978			var newData = typeof ajaxData === 'function' ?
3979				ajaxData( data, oSettings ) :  // fn can manipulate data or return
3980				ajaxData;                      // an object object or array to merge
3981	
3982			// If the function returned something, use that alone
3983			data = typeof ajaxData === 'function' && newData ?
3984				newData :
3985				$.extend( true, data, newData );
3986	
3987			// Remove the data property as we've resolved it already and don't want
3988			// jQuery to do it again (it is restored at the end of the function)
3989			delete ajax.data;
3990		}
3991	
3992		var baseAjax = {
3993			"data": data,
3994			"success": callback,
3995			"dataType": "json",
3996			"cache": false,
3997			"type": oSettings.sServerMethod,
3998			"error": function (xhr, error, thrown) {
3999				var ret = _fnCallbackFire( oSettings, null, 'xhr', [oSettings, null, oSettings.jqXHR] );
4000	
4001				if ( $.inArray( true, ret ) === -1 ) {
4002					if ( error == "parsererror" ) {
4003						_fnLog( oSettings, 0, 'Invalid JSON response', 1 );
4004					}
4005					else if ( xhr.readyState === 4 ) {
4006						_fnLog( oSettings, 0, 'Ajax error', 7 );
4007					}
4008				}
4009	
4010				_fnProcessingDisplay( oSettings, false );
4011			}
4012		};
4013	
4014		// Store the data submitted for the API
4015		oSettings.oAjaxData = data;
4016	
4017		// Allow plug-ins and external processes to modify the data
4018		_fnCallbackFire( oSettings, null, 'preXhr', [oSettings, data] );
4019	
4020		if ( oSettings.fnServerData )
4021		{
4022			// DataTables 1.9- compatibility
4023			oSettings.fnServerData.call( instance,
4024				oSettings.sAjaxSource,
4025				$.map( data, function (val, key) { // Need to convert back to 1.9 trad format
4026					return { name: key, value: val };
4027				} ),
4028				callback,
4029				oSettings
4030			);
4031		}
4032		else if ( oSettings.sAjaxSource || typeof ajax === 'string' )
4033		{
4034			// DataTables 1.9- compatibility
4035			oSettings.jqXHR = $.ajax( $.extend( baseAjax, {
4036				url: ajax || oSettings.sAjaxSource
4037			} ) );
4038		}
4039		else if ( typeof ajax === 'function' )
4040		{
4041			// Is a function - let the caller define what needs to be done
4042			oSettings.jqXHR = ajax.call( instance, data, callback, oSettings );
4043		}
4044		else
4045		{
4046			// Object to extend the base settings
4047			oSettings.jqXHR = $.ajax( $.extend( baseAjax, ajax ) );
4048	
4049			// Restore for next time around
4050			ajax.data = ajaxData;
4051		}
4052	}
4053	
4054	
4055	/**
4056	 * Update the table using an Ajax call
4057	 *  @param {object} settings dataTables settings object
4058	 *  @returns {boolean} Block the table drawing or not
4059	 *  @memberof DataTable#oApi
4060	 */
4061	function _fnAjaxUpdate( settings )
4062	{
4063		settings.iDraw++;
4064		_fnProcessingDisplay( settings, true );
4065	
4066		
vendor: 15,565 bytes, lines 4066-4571
4066_fnBuildAjax(
4067			settings,
4068			_fnAjaxParameters( settings ),
4069			function(json) {
4070				_fnAjaxUpdateDraw( settings, json );
4071			}
4072		);
4073	}
4074	
4075	
4076	/**
4077	 * Build up the parameters in an object needed for a server-side processing
4078	 * request. Note that this is basically done twice, is different ways - a modern
4079	 * method which is used by default in DataTables 1.10 which uses objects and
4080	 * arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if
4081	 * the sAjaxSource option is used in the initialisation, or the legacyAjax
4082	 * option is set.
4083	 *  @param {object} oSettings dataTables settings object
4084	 *  @returns {bool} block the table drawing or not
4085	 *  @memberof DataTable#oApi
4086	 */
4087	function _fnAjaxParameters( settings )
4088	{
4089		var
4090			columns = settings.aoColumns,
4091			columnCount = columns.length,
4092			features = settings.oFeatures,
4093			preSearch = settings.oPreviousSearch,
4094			preColSearch = settings.aoPreSearchCols,
4095			i, data = [], dataProp, column, columnSearch,
4096			sort = _fnSortFlatten( settings ),
4097			displayStart = settings._iDisplayStart,
4098			displayLength = features.bPaginate !== false ?
4099				settings._iDisplayLength :
4100				-1;
4101	
4102		var param = function ( name, value ) {
4103			data.push( { 'name': name, 'value': value } );
4104		};
4105	
4106		// DataTables 1.9- compatible method
4107		param( 'sEcho',          settings.iDraw );
4108		param( 'iColumns',       columnCount );
4109		param( 'sColumns',       _pluck( columns, 'sName' ).join(',') );
4110		param( 'iDisplayStart',  displayStart );
4111		param( 'iDisplayLength', displayLength );
4112	
4113		// DataTables 1.10+ method
4114		var d = {
4115			draw:    settings.iDraw,
4116			columns: [],
4117			order:   [],
4118			start:   displayStart,
4119			length:  displayLength,
4120			search:  {
4121				value: preSearch.sSearch,
4122				regex: preSearch.bRegex
4123			}
4124		};
4125	
4126		for ( i=0 ; i<columnCount ; i++ ) {
4127			column = columns[i];
4128			columnSearch = preColSearch[i];
4129			dataProp = typeof column.mData=="function" ? 'function' : column.mData ;
4130	
4131			d.columns.push( {
4132				data:       dataProp,
4133				name:       column.sName,
4134				searchable: column.bSearchable,
4135				orderable:  column.bSortable,
4136				search:     {
4137					value: columnSearch.sSearch,
4138					regex: columnSearch.bRegex
4139				}
4140			} );
4141	
4142			param( "mDataProp_"+i, dataProp );
4143	
4144			if ( features.bFilter ) {
4145				param( 'sSearch_'+i,     columnSearch.sSearch );
4146				param( 'bRegex_'+i,      columnSearch.bRegex );
4147				param( 'bSearchable_'+i, column.bSearchable );
4148			}
4149	
4150			if ( features.bSort ) {
4151				param( 'bSortable_'+i, column.bSortable );
4152			}
4153		}
4154	
4155		if ( features.bFilter ) {
4156			param( 'sSearch', preSearch.sSearch );
4157			param( 'bRegex', preSearch.bRegex );
4158		}
4159	
4160		if ( features.bSort ) {
4161			$.each( sort, function ( i, val ) {
4162				d.order.push( { column: val.col, dir: val.dir } );
4163	
4164				param( 'iSortCol_'+i, val.col );
4165				param( 'sSortDir_'+i, val.dir );
4166			} );
4167	
4168			param( 'iSortingCols', sort.length );
4169		}
4170	
4171		// If the legacy.ajax parameter is null, then we automatically decide which
4172		// form to use, based on sAjaxSource
4173		var legacy = DataTable.ext.legacy.ajax;
4174		if ( legacy === null ) {
4175			return settings.sAjaxSource ? data : d;
4176		}
4177	
4178		// Otherwise, if legacy has been specified then we use that to decide on the
4179		// form
4180		return legacy ? data : d;
4181	}
4182	
4183	
4184	/**
4185	 * Data the data from the server (nuking the old) and redraw the table
4186	 *  @param {object} oSettings dataTables settings object
4187	 *  @param {object} json json data return from the server.
4188	 *  @param {string} json.sEcho Tracking flag for DataTables to match requests
4189	 *  @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering
4190	 *  @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering
4191	 *  @param {array} json.aaData The data to display on this page
4192	 *  @param {string} [json.sColumns] Column ordering (sName, comma separated)
4193	 *  @memberof DataTable#oApi
4194	 */
4195	function _fnAjaxUpdateDraw ( settings, json )
4196	{
4197		// v1.10 uses camelCase variables, while 1.9 uses Hungarian notation.
4198		// Support both
4199		var compat = function ( old, modern ) {
4200			return json[old] !== undefined ? json[old] : json[modern];
4201		};
4202	
4203		var data = _fnAjaxDataSrc( settings, json );
4204		var draw            = compat( 'sEcho',                'draw' );
4205		var recordsTotal    = compat( 'iTotalRecords',        'recordsTotal' );
4206		var recordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' );
4207	
4208		if ( draw !== undefined ) {
4209			// Protect against out of sequence returns
4210			if ( draw*1 < settings.iDraw ) {
4211				return;
4212			}
4213			settings.iDraw = draw * 1;
4214		}
4215	
4216		// No data in returned object, so rather than an array, we show an empty table
4217		if ( ! data ) {
4218			data = [];
4219		}
4220	
4221		_fnClearTable( settings );
4222		settings._iRecordsTotal   = parseInt(recordsTotal, 10);
4223		settings._iRecordsDisplay = parseInt(recordsFiltered, 10);
4224	
4225		for ( var i=0, ien=data.length ; i<ien ; i++ ) {
4226			_fnAddData( settings, data[i] );
4227		}
4228		settings.aiDisplay = settings.aiDisplayMaster.slice();
4229	
4230		_fnDraw( settings, true );
4231	
4232		if ( ! settings._bInitComplete ) {
4233			_fnInitComplete( settings, json );
4234		}
4235	
4236		_fnProcessingDisplay( settings, false );
4237	}
4238	
4239	
4240	/**
4241	 * Get the data from the JSON data source to use for drawing a table. Using
4242	 * `_fnGetObjectDataFn` allows the data to be sourced from a property of the
4243	 * source object, or from a processing function.
4244	 *  @param {object} oSettings dataTables settings object
4245	 *  @param  {object} json Data source object / array from the server
4246	 *  @return {array} Array of data to use
4247	 */
4248	 function _fnAjaxDataSrc ( oSettings, json, write )
4249	 {
4250		var dataSrc = $.isPlainObject( oSettings.ajax ) && oSettings.ajax.dataSrc !== undefined ?
4251			oSettings.ajax.dataSrc :
4252			oSettings.sAjaxDataProp; // Compatibility with 1.9-.
4253	
4254		if ( ! write ) {
4255			if ( dataSrc === 'data' ) {
4256				// If the default, then we still want to support the old style, and safely ignore
4257				// it if possible
4258				return json.aaData || json[dataSrc];
4259			}
4260	
4261			return dataSrc !== "" ?
4262				_fnGetObjectDataFn( dataSrc )( json ) :
4263				json;
4264		}
4265	
4266		// set
4267		_fnSetObjectDataFn( dataSrc )( json, write );
4268	}
4269	
4270	/**
4271	 * Generate the node required for filtering text
4272	 *  @returns {node} Filter control element
4273	 *  @param {object} oSettings dataTables settings object
4274	 *  @memberof DataTable#oApi
4275	 */
4276	function _fnFeatureHtmlFilter ( settings )
4277	{
4278		var classes = settings.oClasses;
4279		var tableId = settings.sTableId;
4280		var language = settings.oLanguage;
4281		var previousSearch = settings.oPreviousSearch;
4282		var features = settings.aanFeatures;
4283		var input = '<input type="search" class="'+classes.sFilterInput+'"/>';
4284	
4285		var str = language.sSearch;
4286		str = str.match(/_INPUT_/) ?
4287			str.replace('_INPUT_', input) :
4288			str+input;
4289	
4290		var filter = $('<div/>', {
4291				'id': ! features.f ? tableId+'_filter' : null,
4292				'class': classes.sFilter
4293			} )
4294			.append( $('<label/>' ).append( str ) );
4295	
4296		var searchFn = function(event) {
4297			/* Update all other filter input elements for the new display */
4298			var n = features.f;
4299			var val = !this.value ? "" : this.value; // mental IE8 fix :-(
4300			if(previousSearch.return && event.key !== "Enter") {
4301				return;
4302			}
4303			/* Now do the filter */
4304			if ( val != previousSearch.sSearch ) {
4305				_fnFilterComplete( settings, {
4306					"sSearch": val,
4307					"bRegex": previousSearch.bRegex,
4308					"bSmart": previousSearch.bSmart ,
4309					"bCaseInsensitive": previousSearch.bCaseInsensitive,
4310					"return": previousSearch.return
4311				} );
4312	
4313				// Need to redraw, without resorting
4314				settings._iDisplayStart = 0;
4315				_fnDraw( settings );
4316			}
4317		};
4318	
4319		var searchDelay = settings.searchDelay !== null ?
4320			settings.searchDelay :
4321			_fnDataSource( settings ) === 'ssp' ?
4322				400 :
4323				0;
4324	
4325		var jqFilter = $('input', filter)
4326			.val( previousSearch.sSearch )
4327			.attr( 'placeholder', language.sSearchPlaceholder )
4328			.on(
4329				'keyup.DT search.DT input.DT paste.DT cut.DT',
4330				searchDelay ?
4331					_fnThrottle( searchFn, searchDelay ) :
4332					searchFn
4333			)
4334			.on( 'mouseup', function(e) {
4335				// Edge fix! Edge 17 does not trigger anything other than mouse events when clicking
4336				// on the clear icon (Edge bug 17584515). This is safe in other browsers as `searchFn`
4337				// checks the value to see if it has changed. In other browsers it won't have.
4338				setTimeout( function () {
4339					searchFn.call(jqFilter[0], e);
4340				}, 10);
4341			} )
4342			.on( 'keypress.DT', function(e) {
4343				/* Prevent form submission */
4344				if ( e.keyCode == 13 ) {
4345					return false;
4346				}
4347			} )
4348			.attr('aria-controls', tableId);
4349	
4350		// Update the input elements whenever the table is filtered
4351		$(settings.nTable).on( 'search.dt.DT', function ( ev, s ) {
4352			if ( settings === s ) {
4353				// IE9 throws an 'unknown error' if document.activeElement is used
4354				// inside an iframe or frame...
4355				try {
4356					if ( jqFilter[0] !== document.activeElement ) {
4357						jqFilter.val( previousSearch.sSearch );
4358					}
4359				}
4360				catch ( e ) {}
4361			}
4362		} );
4363	
4364		return filter[0];
4365	}
4366	
4367	
4368	/**
4369	 * Filter the table using both the global filter and column based filtering
4370	 *  @param {object} oSettings dataTables settings object
4371	 *  @param {object} oSearch search information
4372	 *  @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)
4373	 *  @memberof DataTable#oApi
4374	 */
4375	function _fnFilterComplete ( oSettings, oInput, iForce )
4376	{
4377		var oPrevSearch = oSettings.oPreviousSearch;
4378		var aoPrevSearch = oSettings.aoPreSearchCols;
4379		var fnSaveFilter = function ( oFilter ) {
4380			/* Save the filtering values */
4381			oPrevSearch.sSearch = oFilter.sSearch;
4382			oPrevSearch.bRegex = oFilter.bRegex;
4383			oPrevSearch.bSmart = oFilter.bSmart;
4384			oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive;
4385			oPrevSearch.return = oFilter.return;
4386		};
4387		var fnRegex = function ( o ) {
4388			// Backwards compatibility with the bEscapeRegex option
4389			return o.bEscapeRegex !== undefined ? !o.bEscapeRegex : o.bRegex;
4390		};
4391	
4392		// Resolve any column types that are unknown due to addition or invalidation
4393		// @todo As per sort - can this be moved into an event handler?
4394		_fnColumnTypes( oSettings );
4395	
4396		/* In server-side processing all filtering is done by the server, so no point hanging around here */
4397		if ( _fnDataSource( oSettings ) != 'ssp' )
4398		{
4399			/* Global filter */
4400			_fnFilter( oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive, oInput.return );
4401			fnSaveFilter( oInput );
4402	
4403			/* Now do the individual column filter */
4404			for ( var i=0 ; i<aoPrevSearch.length ; i++ )
4405			{
4406				_fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, fnRegex(aoPrevSearch[i]),
4407					aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive );
4408			}
4409	
4410			/* Custom filtering */
4411			_fnFilterCustom( oSettings );
4412		}
4413		else
4414		{
4415			fnSaveFilter( oInput );
4416		}
4417	
4418		/* Tell the draw function we have been filtering */
4419		oSettings.bFiltered = true;
4420		_fnCallbackFire( oSettings, null, 'search', [oSettings] );
4421	}
4422	
4423	
4424	/**
4425	 * Apply custom filtering functions
4426	 *  @param {object} oSettings dataTables settings object
4427	 *  @memberof DataTable#oApi
4428	 */
4429	function _fnFilterCustom( settings )
4430	{
4431		var filters = DataTable.ext.search;
4432		var displayRows = settings.aiDisplay;
4433		var row, rowIdx;
4434	
4435		for ( var i=0, ien=filters.length ; i<ien ; i++ ) {
4436			var rows = [];
4437	
4438			// Loop over each row and see if it should be included
4439			for ( var j=0, jen=displayRows.length ; j<jen ; j++ ) {
4440				rowIdx = displayRows[ j ];
4441				row = settings.aoData[ rowIdx ];
4442	
4443				if ( filters[i]( settings, row._aFilterData, rowIdx, row._aData, j ) ) {
4444					rows.push( rowIdx );
4445				}
4446			}
4447	
4448			// So the array reference doesn't break set the results into the
4449			// existing array
4450			displayRows.length = 0;
4451			$.merge( displayRows, rows );
4452		}
4453	}
4454	
4455	
4456	/**
4457	 * Filter the table on a per-column basis
4458	 *  @param {object} oSettings dataTables settings object
4459	 *  @param {string} sInput string to filter on
4460	 *  @param {int} iColumn column to filter
4461	 *  @param {bool} bRegex treat search string as a regular expression or not
4462	 *  @param {bool} bSmart use smart filtering or not
4463	 *  @param {bool} bCaseInsensitive Do case insensitive matching or not
4464	 *  @memberof DataTable#oApi
4465	 */
4466	function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, caseInsensitive )
4467	{
4468		if ( searchStr === '' ) {
4469			return;
4470		}
4471	
4472		var data;
4473		var out = [];
4474		var display = settings.aiDisplay;
4475		var rpSearch = _fnFilterCreateSearch( searchStr, regex, smart, caseInsensitive );
4476	
4477		for ( var i=0 ; i<display.length ; i++ ) {
4478			data = settings.aoData[ display[i] ]._aFilterData[ colIdx ];
4479	
4480			if ( rpSearch.test( data ) ) {
4481				out.push( display[i] );
4482			}
4483		}
4484	
4485		settings.aiDisplay = out;
4486	}
4487	
4488	
4489	/**
4490	 * Filter the data table based on user input and draw the table
4491	 *  @param {object} settings dataTables settings object
4492	 *  @param {string} input string to filter on
4493	 *  @param {int} force optional - force a research of the master array (1) or not (undefined or 0)
4494	 *  @param {bool} regex treat as a regular expression or not
4495	 *  @param {bool} smart perform smart filtering or not
4496	 *  @param {bool} caseInsensitive Do case insensitive matching or not
4497	 *  @memberof DataTable#oApi
4498	 */
4499	function _fnFilter( settings, input, force, regex, smart, caseInsensitive )
4500	{
4501		var rpSearch = _fnFilterCreateSearch( input, regex, smart, caseInsensitive );
4502		var prevSearch = settings.oPreviousSearch.sSearch;
4503		var displayMaster = settings.aiDisplayMaster;
4504		var display, invalidated, i;
4505		var filtered = [];
4506	
4507		// Need to take account of custom filtering functions - always filter
4508		if ( DataTable.ext.search.length !== 0 ) {
4509			force = true;
4510		}
4511	
4512		// Check if any of the rows were invalidated
4513		invalidated = _fnFilterData( settings );
4514	
4515		// If the input is blank - we just want the full data set
4516		if ( input.length <= 0 ) {
4517			settings.aiDisplay = displayMaster.slice();
4518		}
4519		else {
4520			// New search - start from the master array
4521			if ( invalidated ||
4522				 force ||
4523				 regex ||
4524				 prevSearch.length > input.length ||
4525				 input.indexOf(prevSearch) !== 0 ||
4526				 settings.bSorted // On resort, the display master needs to be
4527				                  // re-filtered since indexes will have changed
4528			) {
4529				settings.aiDisplay = displayMaster.slice();
4530			}
4531	
4532			// Search the display array
4533			display = settings.aiDisplay;
4534	
4535			for ( i=0 ; i<display.length ; i++ ) {
4536				if ( rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) {
4537					filtered.push( display[i] );
4538				}
4539			}
4540	
4541			settings.aiDisplay = filtered;
4542		}
4543	}
4544	
4545	
4546	/**
4547	 * Build a regular expression object suitable for searching a table
4548	 *  @param {string} sSearch string to search for
4549	 *  @param {bool} bRegex treat as a regular expression or not
4550	 *  @param {bool} bSmart perform smart filtering or not
4551	 *  @param {bool} bCaseInsensitive Do case insensitive matching or not
4552	 *  @returns {RegExp} constructed object
4553	 *  @memberof DataTable#oApi
4554	 */
4555	function _fnFilterCreateSearch( search, regex, smart, caseInsensitive )
4556	{
4557		search = regex ?
4558			search :
4559			_fnEscapeRegex( search );
4560		
4561		if ( smart ) {
4562			/* For smart filtering we want to allow the search to work regardless of
4563			 * word order. We also want double quoted text to be preserved, so word
4564			 * order is important - a la google. So this is what we want to
4565			 * generate:
4566			 * 
4567			 * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$
4568			 */
4569			var a = $.map( search.match( /"[^"]+"|[^ ]+/g ) || [''], function ( word ) {
4570				if ( word.charAt(0) === '"' ) {
4571					var m = word.match( /^"(.*)"
vendor: 130,258 bytes, lines 4571-9377
4571$/ );
4572					word = m ? m[1] : word;
4573				}
4574	
4575				return word.replace('"', '');
4576			} );
4577	
4578			search = '^(?=.*?'+a.join( ')(?=.*?' )+').*$';
4579		}
4580	
4581		return new RegExp( search, caseInsensitive ? 'i' : '' );
4582	}
4583	
4584	
4585	/**
4586	 * Escape a string such that it can be used in a regular expression
4587	 *  @param {string} sVal string to escape
4588	 *  @returns {string} escaped string
4589	 *  @memberof DataTable#oApi
4590	 */
4591	var _fnEscapeRegex = DataTable.util.escapeRegex;
4592	
4593	var __filter_div = $('<div>')[0];
4594	var __filter_div_textContent = __filter_div.textContent !== undefined;
4595	
4596	// Update the filtering data for each row if needed (by invalidation or first run)
4597	function _fnFilterData ( settings )
4598	{
4599		var columns = settings.aoColumns;
4600		var column;
4601		var i, j, ien, jen, filterData, cellData, row;
4602		var wasInvalidated = false;
4603	
4604		for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
4605			row = settings.aoData[i];
4606	
4607			if ( ! row._aFilterData ) {
4608				filterData = [];
4609	
4610				for ( j=0, jen=columns.length ; j<jen ; j++ ) {
4611					column = columns[j];
4612	
4613					if ( column.bSearchable ) {
4614						cellData = _fnGetCellData( settings, i, j, 'filter' );
4615	
4616						// Search in DataTables 1.10 is string based. In 1.11 this
4617						// should be altered to also allow strict type checking.
4618						if ( cellData === null ) {
4619							cellData = '';
4620						}
4621	
4622						if ( typeof cellData !== 'string' && cellData.toString ) {
4623							cellData = cellData.toString();
4624						}
4625					}
4626					else {
4627						cellData = '';
4628					}
4629	
4630					// If it looks like there is an HTML entity in the string,
4631					// attempt to decode it so sorting works as expected. Note that
4632					// we could use a single line of jQuery to do this, but the DOM
4633					// method used here is much faster http://jsperf.com/html-decode
4634					if ( cellData.indexOf && cellData.indexOf('&') !== -1 ) {
4635						__filter_div.innerHTML = cellData;
4636						cellData = __filter_div_textContent ?
4637							__filter_div.textContent :
4638							__filter_div.innerText;
4639					}
4640	
4641					if ( cellData.replace ) {
4642						cellData = cellData.replace(/[\r\n\u2028]/g, '');
4643					}
4644	
4645					filterData.push( cellData );
4646				}
4647	
4648				row._aFilterData = filterData;
4649				row._sFilterRow = filterData.join('  ');
4650				wasInvalidated = true;
4651			}
4652		}
4653	
4654		return wasInvalidated;
4655	}
4656	
4657	
4658	/**
4659	 * Convert from the internal Hungarian notation to camelCase for external
4660	 * interaction
4661	 *  @param {object} obj Object to convert
4662	 *  @returns {object} Inverted object
4663	 *  @memberof DataTable#oApi
4664	 */
4665	function _fnSearchToCamel ( obj )
4666	{
4667		return {
4668			search:          obj.sSearch,
4669			smart:           obj.bSmart,
4670			regex:           obj.bRegex,
4671			caseInsensitive: obj.bCaseInsensitive
4672		};
4673	}
4674	
4675	
4676	
4677	/**
4678	 * Convert from camelCase notation to the internal Hungarian. We could use the
4679	 * Hungarian convert function here, but this is cleaner
4680	 *  @param {object} obj Object to convert
4681	 *  @returns {object} Inverted object
4682	 *  @memberof DataTable#oApi
4683	 */
4684	function _fnSearchToHung ( obj )
4685	{
4686		return {
4687			sSearch:          obj.search,
4688			bSmart:           obj.smart,
4689			bRegex:           obj.regex,
4690			bCaseInsensitive: obj.caseInsensitive
4691		};
4692	}
4693	
4694	/**
4695	 * Generate the node required for the info display
4696	 *  @param {object} oSettings dataTables settings object
4697	 *  @returns {node} Information element
4698	 *  @memberof DataTable#oApi
4699	 */
4700	function _fnFeatureHtmlInfo ( settings )
4701	{
4702		var
4703			tid = settings.sTableId,
4704			nodes = settings.aanFeatures.i,
4705			n = $('<div/>', {
4706				'class': settings.oClasses.sInfo,
4707				'id': ! nodes ? tid+'_info' : null
4708			} );
4709	
4710		if ( ! nodes ) {
4711			// Update display on each draw
4712			settings.aoDrawCallback.push( {
4713				"fn": _fnUpdateInfo,
4714				"sName": "information"
4715			} );
4716	
4717			n
4718				.attr( 'role', 'status' )
4719				.attr( 'aria-live', 'polite' );
4720	
4721			// Table is described by our info div
4722			$(settings.nTable).attr( 'aria-describedby', tid+'_info' );
4723		}
4724	
4725		return n[0];
4726	}
4727	
4728	
4729	/**
4730	 * Update the information elements in the display
4731	 *  @param {object} settings dataTables settings object
4732	 *  @memberof DataTable#oApi
4733	 */
4734	function _fnUpdateInfo ( settings )
4735	{
4736		/* Show information about the table */
4737		var nodes = settings.aanFeatures.i;
4738		if ( nodes.length === 0 ) {
4739			return;
4740		}
4741	
4742		var
4743			lang  = settings.oLanguage,
4744			start = settings._iDisplayStart+1,
4745			end   = settings.fnDisplayEnd(),
4746			max   = settings.fnRecordsTotal(),
4747			total = settings.fnRecordsDisplay(),
4748			out   = total ?
4749				lang.sInfo :
4750				lang.sInfoEmpty;
4751	
4752		if ( total !== max ) {
4753			/* Record set after filtering */
4754			out += ' ' + lang.sInfoFiltered;
4755		}
4756	
4757		// Convert the macros
4758		out += lang.sInfoPostFix;
4759		out = _fnInfoMacros( settings, out );
4760	
4761		var callback = lang.fnInfoCallback;
4762		if ( callback !== null ) {
4763			out = callback.call( settings.oInstance,
4764				settings, start, end, max, total, out
4765			);
4766		}
4767	
4768		$(nodes).html( out );
4769	}
4770	
4771	
4772	function _fnInfoMacros ( settings, str )
4773	{
4774		// When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
4775		// internally
4776		var
4777			formatter  = settings.fnFormatNumber,
4778			start      = settings._iDisplayStart+1,
4779			len        = settings._iDisplayLength,
4780			vis        = settings.fnRecordsDisplay(),
4781			all        = len === -1;
4782	
4783		return str.
4784			replace(/_START_/g, formatter.call( settings, start ) ).
4785			replace(/_END_/g,   formatter.call( settings, settings.fnDisplayEnd() ) ).
4786			replace(/_MAX_/g,   formatter.call( settings, settings.fnRecordsTotal() ) ).
4787			replace(/_TOTAL_/g, formatter.call( settings, vis ) ).
4788			replace(/_PAGE_/g,  formatter.call( settings, all ? 1 : Math.ceil( start / len ) ) ).
4789			replace(/_PAGES_/g, formatter.call( settings, all ? 1 : Math.ceil( vis / len ) ) );
4790	}
4791	
4792	
4793	
4794	/**
4795	 * Draw the table for the first time, adding all required features
4796	 *  @param {object} settings dataTables settings object
4797	 *  @memberof DataTable#oApi
4798	 */
4799	function _fnInitialise ( settings )
4800	{
4801		var i, iLen, iAjaxStart=settings.iInitDisplayStart;
4802		var columns = settings.aoColumns, column;
4803		var features = settings.oFeatures;
4804		var deferLoading = settings.bDeferLoading; // value modified by the draw
4805	
4806		/* Ensure that the table data is fully initialised */
4807		if ( ! settings.bInitialised ) {
4808			setTimeout( function(){ _fnInitialise( settings ); }, 200 );
4809			return;
4810		}
4811	
4812		/* Show the display HTML options */
4813		_fnAddOptionsHtml( settings );
4814	
4815		/* Build and draw the header / footer for the table */
4816		_fnBuildHead( settings );
4817		_fnDrawHead( settings, settings.aoHeader );
4818		_fnDrawHead( settings, settings.aoFooter );
4819	
4820		/* Okay to show that something is going on now */
4821		_fnProcessingDisplay( settings, true );
4822	
4823		/* Calculate sizes for columns */
4824		if ( features.bAutoWidth ) {
4825			_fnCalculateColumnWidths( settings );
4826		}
4827	
4828		for ( i=0, iLen=columns.length ; i<iLen ; i++ ) {
4829			column = columns[i];
4830	
4831			if ( column.sWidth ) {
4832				column.nTh.style.width = _fnStringToCss( column.sWidth );
4833			}
4834		}
4835	
4836		_fnCallbackFire( settings, null, 'preInit', [settings] );
4837	
4838		// If there is default sorting required - let's do it. The sort function
4839		// will do the drawing for us. Otherwise we draw the table regardless of the
4840		// Ajax source - this allows the table to look initialised for Ajax sourcing
4841		// data (show 'loading' message possibly)
4842		_fnReDraw( settings );
4843	
4844		// Server-side processing init complete is done by _fnAjaxUpdateDraw
4845		var dataSrc = _fnDataSource( settings );
4846		if ( dataSrc != 'ssp' || deferLoading ) {
4847			// if there is an ajax source load the data
4848			if ( dataSrc == 'ajax' ) {
4849				_fnBuildAjax( settings, [], function(json) {
4850					var aData = _fnAjaxDataSrc( settings, json );
4851	
4852					// Got the data - add it to the table
4853					for ( i=0 ; i<aData.length ; i++ ) {
4854						_fnAddData( settings, aData[i] );
4855					}
4856	
4857					// Reset the init display for cookie saving. We've already done
4858					// a filter, and therefore cleared it before. So we need to make
4859					// it appear 'fresh'
4860					settings.iInitDisplayStart = iAjaxStart;
4861	
4862					_fnReDraw( settings );
4863	
4864					_fnProcessingDisplay( settings, false );
4865					_fnInitComplete( settings, json );
4866				}, settings );
4867			}
4868			else {
4869				_fnProcessingDisplay( settings, false );
4870				_fnInitComplete( settings );
4871			}
4872		}
4873	}
4874	
4875	
4876	/**
4877	 * Draw the table for the first time, adding all required features
4878	 *  @param {object} oSettings dataTables settings object
4879	 *  @param {object} [json] JSON from the server that completed the table, if using Ajax source
4880	 *    with client-side processing (optional)
4881	 *  @memberof DataTable#oApi
4882	 */
4883	function _fnInitComplete ( settings, json )
4884	{
4885		settings._bInitComplete = true;
4886	
4887		// When data was added after the initialisation (data or Ajax) we need to
4888		// calculate the column sizing
4889		if ( json || settings.oInit.aaData ) {
4890			_fnAdjustColumnSizing( settings );
4891		}
4892	
4893		_fnCallbackFire( settings, null, 'plugin-init', [settings, json] );
4894		_fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] );
4895	}
4896	
4897	
4898	function _fnLengthChange ( settings, val )
4899	{
4900		var len = parseInt( val, 10 );
4901		settings._iDisplayLength = len;
4902	
4903		_fnLengthOverflow( settings );
4904	
4905		// Fire length change event
4906		_fnCallbackFire( settings, null, 'length', [settings, len] );
4907	}
4908	
4909	
4910	/**
4911	 * Generate the node required for user display length changing
4912	 *  @param {object} settings dataTables settings object
4913	 *  @returns {node} Display length feature node
4914	 *  @memberof DataTable#oApi
4915	 */
4916	function _fnFeatureHtmlLength ( settings )
4917	{
4918		var
4919			classes  = settings.oClasses,
4920			tableId  = settings.sTableId,
4921			menu     = settings.aLengthMenu,
4922			d2       = Array.isArray( menu[0] ),
4923			lengths  = d2 ? menu[0] : menu,
4924			language = d2 ? menu[1] : menu;
4925	
4926		var select = $('<select/>', {
4927			'name':          tableId+'_length',
4928			'aria-controls': tableId,
4929			'class':         classes.sLengthSelect
4930		} );
4931	
4932		for ( var i=0, ien=lengths.length ; i<ien ; i++ ) {
4933			select[0][ i ] = new Option(
4934				typeof language[i] === 'number' ?
4935					settings.fnFormatNumber( language[i] ) :
4936					language[i],
4937				lengths[i]
4938			);
4939		}
4940	
4941		var div = $('<div><label/></div>').addClass( classes.sLength );
4942		if ( ! settings.aanFeatures.l ) {
4943			div[0].id = tableId+'_length';
4944		}
4945	
4946		div.children().append(
4947			settings.oLanguage.sLengthMenu.replace( '_MENU_', select[0].outerHTML )
4948		);
4949	
4950		// Can't use `select` variable as user might provide their own and the
4951		// reference is broken by the use of outerHTML
4952		$('select', div)
4953			.val( settings._iDisplayLength )
4954			.on( 'change.DT', function(e) {
4955				_fnLengthChange( settings, $(this).val() );
4956				_fnDraw( settings );
4957			} );
4958	
4959		// Update node value whenever anything changes the table's length
4960		$(settings.nTable).on( 'length.dt.DT', function (e, s, len) {
4961			if ( settings === s ) {
4962				$('select', div).val( len );
4963			}
4964		} );
4965	
4966		return div[0];
4967	}
4968	
4969	
4970	
4971	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
4972	 * Note that most of the paging logic is done in
4973	 * DataTable.ext.pager
4974	 */
4975	
4976	/**
4977	 * Generate the node required for default pagination
4978	 *  @param {object} oSettings dataTables settings object
4979	 *  @returns {node} Pagination feature node
4980	 *  @memberof DataTable#oApi
4981	 */
4982	function _fnFeatureHtmlPaginate ( settings )
4983	{
4984		var
4985			type   = settings.sPaginationType,
4986			plugin = DataTable.ext.pager[ type ],
4987			modern = typeof plugin === 'function',
4988			redraw = function( settings ) {
4989				_fnDraw( settings );
4990			},
4991			node = $('<div/>').addClass( settings.oClasses.sPaging + type )[0],
4992			features = settings.aanFeatures;
4993	
4994		if ( ! modern ) {
4995			plugin.fnInit( settings, node, redraw );
4996		}
4997	
4998		/* Add a draw callback for the pagination on first instance, to update the paging display */
4999		if ( ! features.p )
5000		{
5001			node.id = settings.sTableId+'_paginate';
5002	
5003			settings.aoDrawCallback.push( {
5004				"fn": function( settings ) {
5005					if ( modern ) {
5006						var
5007							start      = settings._iDisplayStart,
5008							len        = settings._iDisplayLength,
5009							visRecords = settings.fnRecordsDisplay(),
5010							all        = len === -1,
5011							page = all ? 0 : Math.ceil( start / len ),
5012							pages = all ? 1 : Math.ceil( visRecords / len ),
5013							buttons = plugin(page, pages),
5014							i, ien;
5015	
5016						for ( i=0, ien=features.p.length ; i<ien ; i++ ) {
5017							_fnRenderer( settings, 'pageButton' )(
5018								settings, features.p[i], i, buttons, page, pages
5019							);
5020						}
5021					}
5022					else {
5023						plugin.fnUpdate( settings, redraw );
5024					}
5025				},
5026				"sName": "pagination"
5027			} );
5028		}
5029	
5030		return node;
5031	}
5032	
5033	
5034	/**
5035	 * Alter the display settings to change the page
5036	 *  @param {object} settings DataTables settings object
5037	 *  @param {string|int} action Paging action to take: "first", "previous",
5038	 *    "next" or "last" or page number to jump to (integer)
5039	 *  @param [bool] redraw Automatically draw the update or not
5040	 *  @returns {bool} true page has changed, false - no change
5041	 *  @memberof DataTable#oApi
5042	 */
5043	function _fnPageChange ( settings, action, redraw )
5044	{
5045		var
5046			start     = settings._iDisplayStart,
5047			len       = settings._iDisplayLength,
5048			records   = settings.fnRecordsDisplay();
5049	
5050		if ( records === 0 || len === -1 )
5051		{
5052			start = 0;
5053		}
5054		else if ( typeof action === "number" )
5055		{
5056			start = action * len;
5057	
5058			if ( start > records )
5059			{
5060				start = 0;
5061			}
5062		}
5063		else if ( action == "first" )
5064		{
5065			start = 0;
5066		}
5067		else if ( action == "previous" )
5068		{
5069			start = len >= 0 ?
5070				start - len :
5071				0;
5072	
5073			if ( start < 0 )
5074			{
5075			  start = 0;
5076			}
5077		}
5078		else if ( action == "next" )
5079		{
5080			if ( start + len < records )
5081			{
5082				start += len;
5083			}
5084		}
5085		else if ( action == "last" )
5086		{
5087			start = Math.floor( (records-1) / len) * len;
5088		}
5089		else
5090		{
5091			_fnLog( settings, 0, "Unknown paging action: "+action, 5 );
5092		}
5093	
5094		var changed = settings._iDisplayStart !== start;
5095		settings._iDisplayStart = start;
5096	
5097		if ( changed ) {
5098			_fnCallbackFire( settings, null, 'page', [settings] );
5099	
5100			if ( redraw ) {
5101				_fnDraw( settings );
5102			}
5103		}
5104		else {
5105			// No change event - paging was called, but no change
5106			_fnCallbackFire( settings, null, 'page-nc', [settings] );
5107		}
5108	
5109		return changed;
5110	}
5111	
5112	
5113	
5114	/**
5115	 * Generate the node required for the processing node
5116	 *  @param {object} settings dataTables settings object
5117	 *  @returns {node} Processing element
5118	 *  @memberof DataTable#oApi
5119	 */
5120	function _fnFeatureHtmlProcessing ( settings )
5121	{
5122		return $('<div/>', {
5123				'id': ! settings.aanFeatures.r ? settings.sTableId+'_processing' : null,
5124				'class': settings.oClasses.sProcessing,
5125				'role': 'status'
5126			} )
5127			.html( settings.oLanguage.sProcessing )
5128			.append('<div><div></div><div></div><div></div><div></div></div>')
5129			.insertBefore( settings.nTable )[0];
5130	}
5131	
5132	
5133	/**
5134	 * Display or hide the processing indicator
5135	 *  @param {object} settings dataTables settings object
5136	 *  @param {bool} show Show the processing indicator (true) or not (false)
5137	 *  @memberof DataTable#oApi
5138	 */
5139	function _fnProcessingDisplay ( settings, show )
5140	{
5141		if ( settings.oFeatures.bProcessing ) {
5142			$(settings.aanFeatures.r).css( 'display', show ? 'block' : 'none' );
5143		}
5144	
5145		_fnCallbackFire( settings, null, 'processing', [settings, show] );
5146	}
5147	
5148	/**
5149	 * Add any control elements for the table - specifically scrolling
5150	 *  @param {object} settings dataTables settings object
5151	 *  @returns {node} Node to add to the DOM
5152	 *  @memberof DataTable#oApi
5153	 */
5154	function _fnFeatureHtmlTable ( settings )
5155	{
5156		var table = $(settings.nTable);
5157	
5158		// Scrolling from here on in
5159		var scroll = settings.oScroll;
5160	
5161		if ( scroll.sX === '' && scroll.sY === '' ) {
5162			return settings.nTable;
5163		}
5164	
5165		var scrollX = scroll.sX;
5166		var scrollY = scroll.sY;
5167		var classes = settings.oClasses;
5168		var caption = table.children('caption');
5169		var captionSide = caption.length ? caption[0]._captionSide : null;
5170		var headerClone = $( table[0].cloneNode(false) );
5171		var footerClone = $( table[0].cloneNode(false) );
5172		var footer = table.children('tfoot');
5173		var _div = '<div/>';
5174		var size = function ( s ) {
5175			return !s ? null : _fnStringToCss( s );
5176		};
5177	
5178		if ( ! footer.length ) {
5179			footer = null;
5180		}
5181	
5182		/*
5183		 * The HTML structure that we want to generate in this function is:
5184		 *  div - scroller
5185		 *    div - scroll head
5186		 *      div - scroll head inner
5187		 *        table - scroll head table
5188		 *          thead - thead
5189		 *    div - scroll body
5190		 *      table - table (master table)
5191		 *        thead - thead clone for sizing
5192		 *        tbody - tbody
5193		 *    div - scroll foot
5194		 *      div - scroll foot inner
5195		 *        table - scroll foot table
5196		 *          tfoot - tfoot
5197		 */
5198		var scroller = $( _div, { 'class': classes.sScrollWrapper } )
5199			.append(
5200				$(_div, { 'class': classes.sScrollHead } )
5201					.css( {
5202						overflow: 'hidden',
5203						position: 'relative',
5204						border: 0,
5205						width: scrollX ? size(scrollX) : '100%'
5206					} )
5207					.append(
5208						$(_div, { 'class': classes.sScrollHeadInner } )
5209							.css( {
5210								'box-sizing': 'content-box',
5211								width: scroll.sXInner || '100%'
5212							} )
5213							.append(
5214								headerClone
5215									.removeAttr('id')
5216									.css( 'margin-left', 0 )
5217									.append( captionSide === 'top' ? caption : null )
5218									.append(
5219										table.children('thead')
5220									)
5221							)
5222					)
5223			)
5224			.append(
5225				$(_div, { 'class': classes.sScrollBody } )
5226					.css( {
5227						position: 'relative',
5228						overflow: 'auto',
5229						width: size( scrollX )
5230					} )
5231					.append( table )
5232			);
5233	
5234		if ( footer ) {
5235			scroller.append(
5236				$(_div, { 'class': classes.sScrollFoot } )
5237					.css( {
5238						overflow: 'hidden',
5239						border: 0,
5240						width: scrollX ? size(scrollX) : '100%'
5241					} )
5242					.append(
5243						$(_div, { 'class': classes.sScrollFootInner } )
5244							.append(
5245								footerClone
5246									.removeAttr('id')
5247									.css( 'margin-left', 0 )
5248									.append( captionSide === 'bottom' ? caption : null )
5249									.append(
5250										table.children('tfoot')
5251									)
5252							)
5253					)
5254			);
5255		}
5256	
5257		var children = scroller.children();
5258		var scrollHead = children[0];
5259		var scrollBody = children[1];
5260		var scrollFoot = footer ? children[2] : null;
5261	
5262		// When the body is scrolled, then we also want to scroll the headers
5263		if ( scrollX ) {
5264			$(scrollBody).on( 'scroll.DT', function (e) {
5265				var scrollLeft = this.scrollLeft;
5266	
5267				scrollHead.scrollLeft = scrollLeft;
5268	
5269				if ( footer ) {
5270					scrollFoot.scrollLeft = scrollLeft;
5271				}
5272			} );
5273		}
5274	
5275		$(scrollBody).css('max-height', scrollY);
5276		if (! scroll.bCollapse) {
5277			$(scrollBody).css('height', scrollY);
5278		}
5279	
5280		settings.nScrollHead = scrollHead;
5281		settings.nScrollBody = scrollBody;
5282		settings.nScrollFoot = scrollFoot;
5283	
5284		// On redraw - align columns
5285		settings.aoDrawCallback.push( {
5286			"fn": _fnScrollDraw,
5287			"sName": "scrolling"
5288		} );
5289	
5290		return scroller[0];
5291	}
5292	
5293	
5294	
5295	/**
5296	 * Update the header, footer and body tables for resizing - i.e. column
5297	 * alignment.
5298	 *
5299	 * Welcome to the most horrible function DataTables. The process that this
5300	 * function follows is basically:
5301	 *   1. Re-create the table inside the scrolling div
5302	 *   2. Take live measurements from the DOM
5303	 *   3. Apply the measurements to align the columns
5304	 *   4. Clean up
5305	 *
5306	 *  @param {object} settings dataTables settings object
5307	 *  @memberof DataTable#oApi
5308	 */
5309	function _fnScrollDraw ( settings )
5310	{
5311		// Given that this is such a monster function, a lot of variables are use
5312		// to try and keep the minimised size as small as possible
5313		var
5314			scroll         = settings.oScroll,
5315			scrollX        = scroll.sX,
5316			scrollXInner   = scroll.sXInner,
5317			scrollY        = scroll.sY,
5318			barWidth       = scroll.iBarWidth,
5319			divHeader      = $(settings.nScrollHead),
5320			divHeaderStyle = divHeader[0].style,
5321			divHeaderInner = divHeader.children('div'),
5322			divHeaderInnerStyle = divHeaderInner[0].style,
5323			divHeaderTable = divHeaderInner.children('table'),
5324			divBodyEl      = settings.nScrollBody,
5325			divBody        = $(divBodyEl),
5326			divBodyStyle   = divBodyEl.style,
5327			divFooter      = $(settings.nScrollFoot),
5328			divFooterInner = divFooter.children('div'),
5329			divFooterTable = divFooterInner.children('table'),
5330			header         = $(settings.nTHead),
5331			table          = $(settings.nTable),
5332			tableEl        = table[0],
5333			tableStyle     = tableEl.style,
5334			footer         = settings.nTFoot ? $(settings.nTFoot) : null,
5335			browser        = settings.oBrowser,
5336			ie67           = browser.bScrollOversize,
5337			dtHeaderCells  = _pluck( settings.aoColumns, 'nTh' ),
5338			headerTrgEls, footerTrgEls,
5339			headerSrcEls, footerSrcEls,
5340			headerCopy, footerCopy,
5341			headerWidths=[], footerWidths=[],
5342			headerContent=[], footerContent=[],
5343			idx, correction, sanityWidth,
5344			zeroOut = function(nSizer) {
5345				var style = nSizer.style;
5346				style.paddingTop = "0";
5347				style.paddingBottom = "0";
5348				style.borderTopWidth = "0";
5349				style.borderBottomWidth = "0";
5350				style.height = 0;
5351			};
5352	
5353		// If the scrollbar visibility has changed from the last draw, we need to
5354		// adjust the column sizes as the table width will have changed to account
5355		// for the scrollbar
5356		var scrollBarVis = divBodyEl.scrollHeight > divBodyEl.clientHeight;
5357		
5358		if ( settings.scrollBarVis !== scrollBarVis && settings.scrollBarVis !== undefined ) {
5359			settings.scrollBarVis = scrollBarVis;
5360			_fnAdjustColumnSizing( settings );
5361			return; // adjust column sizing will call this function again
5362		}
5363		else {
5364			settings.scrollBarVis = scrollBarVis;
5365		}
5366	
5367		/*
5368		 * 1. Re-create the table inside the scrolling div
5369		 */
5370	
5371		// Remove the old minimised thead and tfoot elements in the inner table
5372		table.children('thead, tfoot').remove();
5373	
5374		if ( footer ) {
5375			footerCopy = footer.clone().prependTo( table );
5376			footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized
5377			footerSrcEls = footerCopy.find('tr');
5378			footerCopy.find('[id]').removeAttr('id');
5379		}
5380	
5381		// Clone the current header and footer elements and then place it into the inner table
5382		headerCopy = header.clone().prependTo( table );
5383		headerTrgEls = header.find('tr'); // original header is in its own table
5384		headerSrcEls = headerCopy.find('tr');
5385		headerCopy.find('th, td').removeAttr('tabindex');
5386		headerCopy.find('[id]').removeAttr('id');
5387	
5388	
5389		/*
5390		 * 2. Take live measurements from the DOM - do not alter the DOM itself!
5391		 */
5392	
5393		// Remove old sizing and apply the calculated column widths
5394		// Get the unique column headers in the newly created (cloned) header. We want to apply the
5395		// calculated sizes to this header
5396		if ( ! scrollX )
5397		{
5398			divBodyStyle.width = '100%';
5399			divHeader[0].style.width = '100%';
5400		}
5401	
5402		$.each( _fnGetUniqueThs( settings, headerCopy ), function ( i, el ) {
5403			idx = _fnVisibleToColumnIndex( settings, i );
5404			el.style.width = settings.aoColumns[idx].sWidth;
5405		} );
5406	
5407		if ( footer ) {
5408			_fnApplyToChildren( function(n) {
5409				n.style.width = "";
5410			}, footerSrcEls );
5411		}
5412	
5413		// Size the table as a whole
5414		sanityWidth = table.outerWidth();
5415		if ( scrollX === "" ) {
5416			// No x scrolling
5417			tableStyle.width = "100%";
5418	
5419			// IE7 will make the width of the table when 100% include the scrollbar
5420			// - which is shouldn't. When there is a scrollbar we need to take this
5421			// into account.
5422			if ( ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight ||
5423				divBody.css('overflow-y') == "scroll")
5424			) {
5425				tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth);
5426			}
5427	
5428			// Recalculate the sanity width
5429			sanityWidth = table.outerWidth();
5430		}
5431		else if ( scrollXInner !== "" ) {
5432			// legacy x scroll inner has been given - use it
5433			tableStyle.width = _fnStringToCss(scrollXInner);
5434	
5435			// Recalculate the sanity width
5436			sanityWidth = table.outerWidth();
5437		}
5438	
5439		// Hidden header should have zero height, so remove padding and borders. Then
5440		// set the width based on the real headers
5441	
5442		// Apply all styles in one pass
5443		_fnApplyToChildren( zeroOut, headerSrcEls );
5444	
5445		// Read all widths in next pass
5446		_fnApplyToChildren( function(nSizer) {
5447			var style = window.getComputedStyle ?
5448				window.getComputedStyle(nSizer).width :
5449				_fnStringToCss( $(nSizer).width() );
5450	
5451			headerContent.push( nSizer.innerHTML );
5452			headerWidths.push( style );
5453		}, headerSrcEls );
5454	
5455		// Apply all widths in final pass
5456		_fnApplyToChildren( function(nToSize, i) {
5457			nToSize.style.width = headerWidths[i];
5458		}, headerTrgEls );
5459	
5460		$(headerSrcEls).css('height', 0);
5461	
5462		/* Same again with the footer if we have one */
5463		if ( footer )
5464		{
5465			_fnApplyToChildren( zeroOut, footerSrcEls );
5466	
5467			_fnApplyToChildren( function(nSizer) {
5468				footerContent.push( nSizer.innerHTML );
5469				footerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
5470			}, footerSrcEls );
5471	
5472			_fnApplyToChildren( function(nToSize, i) {
5473				nToSize.style.width = footerWidths[i];
5474			}, footerTrgEls );
5475	
5476			$(footerSrcEls).height(0);
5477		}
5478	
5479	
5480		/*
5481		 * 3. Apply the measurements
5482		 */
5483	
5484		// "Hide" the header and footer that we used for the sizing. We need to keep
5485		// the content of the cell so that the width applied to the header and body
5486		// both match, but we want to hide it completely. We want to also fix their
5487		// width to what they currently are
5488		_fnApplyToChildren( function(nSizer, i) {
5489			nSizer.innerHTML = '<div class="dataTables_sizing">'+headerContent[i]+'</div>';
5490			nSizer.childNodes[0].style.height = "0";
5491			nSizer.childNodes[0].style.overflow = "hidden";
5492			nSizer.style.width = headerWidths[i];
5493		}, headerSrcEls );
5494	
5495		if ( footer )
5496		{
5497			_fnApplyToChildren( function(nSizer, i) {
5498				nSizer.innerHTML = '<div class="dataTables_sizing">'+footerContent[i]+'</div>';
5499				nSizer.childNodes[0].style.height = "0";
5500				nSizer.childNodes[0].style.overflow = "hidden";
5501				nSizer.style.width = footerWidths[i];
5502			}, footerSrcEls );
5503		}
5504	
5505		// Sanity check that the table is of a sensible width. If not then we are going to get
5506		// misalignment - try to prevent this by not allowing the table to shrink below its min width
5507		if ( Math.round(table.outerWidth()) < Math.round(sanityWidth) )
5508		{
5509			// The min width depends upon if we have a vertical scrollbar visible or not */
5510			correction = ((divBodyEl.scrollHeight > divBodyEl.offsetHeight ||
5511				divBody.css('overflow-y') == "scroll")) ?
5512					sanityWidth+barWidth :
5513					sanityWidth;
5514	
5515			// IE6/7 are a law unto themselves...
5516			if ( ie67 && (divBodyEl.scrollHeight >
5517				divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll")
5518			) {
5519				tableStyle.width = _fnStringToCss( correction-barWidth );
5520			}
5521	
5522			// And give the user a warning that we've stopped the table getting too small
5523			if ( scrollX === "" || scrollXInner !== "" ) {
5524				_fnLog( settings, 1, 'Possible column misalignment', 6 );
5525			}
5526		}
5527		else
5528		{
5529			correction = '100%';
5530		}
5531	
5532		// Apply to the container elements
5533		divBodyStyle.width = _fnStringToCss( correction );
5534		divHeaderStyle.width = _fnStringToCss( correction );
5535	
5536		if ( footer ) {
5537			settings.nScrollFoot.style.width = _fnStringToCss( correction );
5538		}
5539	
5540	
5541		/*
5542		 * 4. Clean up
5543		 */
5544		if ( ! scrollY ) {
5545			/* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
5546			 * the scrollbar height from the visible display, rather than adding it on. We need to
5547			 * set the height in order to sort this. Don't want to do it in any other browsers.
5548			 */
5549			if ( ie67 ) {
5550				divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+barWidth );
5551			}
5552		}
5553	
5554		/* Finally set the width's of the header and footer tables */
5555		var iOuterWidth = table.outerWidth();
5556		divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth );
5557		divHeaderInnerStyle.width = _fnStringToCss( iOuterWidth );
5558	
5559		// Figure out if there are scrollbar present - if so then we need a the header and footer to
5560		// provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
5561		var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll";
5562		var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' );
5563		divHeaderInnerStyle[ padding ] = bScrolling ? barWidth+"px" : "0px";
5564	
5565		if ( footer ) {
5566			divFooterTable[0].style.width = _fnStringToCss( iOuterWidth );
5567			divFooterInner[0].style.width = _fnStringToCss( iOuterWidth );
5568			divFooterInner[0].style[padding] = bScrolling ? barWidth+"px" : "0px";
5569		}
5570	
5571		// Correct DOM ordering for colgroup - comes before the thead
5572		table.children('colgroup').insertBefore( table.children('thead') );
5573	
5574		/* Adjust the position of the header in case we loose the y-scrollbar */
5575		divBody.trigger('scroll');
5576	
5577		// If sorting or filtering has occurred, jump the scrolling back to the top
5578		// only if we aren't holding the position
5579		if ( (settings.bSorted || settings.bFiltered) && ! settings._drawHold ) {
5580			divBodyEl.scrollTop = 0;
5581		}
5582	}
5583	
5584	
5585	
5586	/**
5587	 * Apply a given function to the display child nodes of an element array (typically
5588	 * TD children of TR rows
5589	 *  @param {function} fn Method to apply to the objects
5590	 *  @param array {nodes} an1 List of elements to look through for display children
5591	 *  @param array {nodes} an2 Another list (identical structure to the first) - optional
5592	 *  @memberof DataTable#oApi
5593	 */
5594	function _fnApplyToChildren( fn, an1, an2 )
5595	{
5596		var index=0, i=0, iLen=an1.length;
5597		var nNode1, nNode2;
5598	
5599		while ( i < iLen ) {
5600			nNode1 = an1[i].firstChild;
5601			nNode2 = an2 ? an2[i].firstChild : null;
5602	
5603			while ( nNode1 ) {
5604				if ( nNode1.nodeType === 1 ) {
5605					if ( an2 ) {
5606						fn( nNode1, nNode2, index );
5607					}
5608					else {
5609						fn( nNode1, index );
5610					}
5611	
5612					index++;
5613				}
5614	
5615				nNode1 = nNode1.nextSibling;
5616				nNode2 = an2 ? nNode2.nextSibling : null;
5617			}
5618	
5619			i++;
5620		}
5621	}
5622	
5623	
5624	
5625	var __re_html_remove = /<.*?>/g;
5626	
5627	
5628	/**
5629	 * Calculate the width of columns for the table
5630	 *  @param {object} oSettings dataTables settings object
5631	 *  @memberof DataTable#oApi
5632	 */
5633	function _fnCalculateColumnWidths ( oSettings )
5634	{
5635		var
5636			table = oSettings.nTable,
5637			columns = oSettings.aoColumns,
5638			scroll = oSettings.oScroll,
5639			scrollY = scroll.sY,
5640			scrollX = scroll.sX,
5641			scrollXInner = scroll.sXInner,
5642			columnCount = columns.length,
5643			visibleColumns = _fnGetColumns( oSettings, 'bVisible' ),
5644			headerCells = $('th', oSettings.nTHead),
5645			tableWidthAttr = table.getAttribute('width'), // from DOM element
5646			tableContainer = table.parentNode,
5647			userInputs = false,
5648			i, column, columnIdx, width, outerWidth,
5649			browser = oSettings.oBrowser,
5650			ie67 = browser.bScrollOversize;
5651	
5652		var styleWidth = table.style.width;
5653		if ( styleWidth && styleWidth.indexOf('%') !== -1 ) {
5654			tableWidthAttr = styleWidth;
5655		}
5656	
5657		/* Convert any user input sizes into pixel sizes */
5658		for ( i=0 ; i<visibleColumns.length ; i++ ) {
5659			column = columns[ visibleColumns[i] ];
5660	
5661			if ( column.sWidth !== null ) {
5662				column.sWidth = _fnConvertToWidth( column.sWidthOrig, tableContainer );
5663	
5664				userInputs = true;
5665			}
5666		}
5667	
5668		/* If the number of columns in the DOM equals the number that we have to
5669		 * process in DataTables, then we can use the offsets that are created by
5670		 * the web- browser. No custom sizes can be set in order for this to happen,
5671		 * nor scrolling used
5672		 */
5673		if ( ie67 || ! userInputs && ! scrollX && ! scrollY &&
5674		     columnCount == _fnVisbleColumns( oSettings ) &&
5675		     columnCount == headerCells.length
5676		) {
5677			for ( i=0 ; i<columnCount ; i++ ) {
5678				var colIdx = _fnVisibleToColumnIndex( oSettings, i );
5679	
5680				if ( colIdx !== null ) {
5681					columns[ colIdx ].sWidth = _fnStringToCss( headerCells.eq(i).width() );
5682				}
5683			}
5684		}
5685		else
5686		{
5687			// Otherwise construct a single row, worst case, table with the widest
5688			// node in the data, assign any user defined widths, then insert it into
5689			// the DOM and allow the browser to do all the hard work of calculating
5690			// table widths
5691			var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table
5692				.css( 'visibility', 'hidden' )
5693				.removeAttr( 'id' );
5694	
5695			// Clean up the table body
5696			tmpTable.find('tbody tr').remove();
5697			var tr = $('<tr/>').appendTo( tmpTable.find('tbody') );
5698	
5699			// Clone the table header and footer - we can't use the header / footer
5700			// from the cloned table, since if scrolling is active, the table's
5701			// real header and footer are contained in different table tags
5702			tmpTable.find('thead, tfoot').remove();
5703			tmpTable
5704				.append( $(oSettings.nTHead).clone() )
5705				.append( $(oSettings.nTFoot).clone() );
5706	
5707			// Remove any assigned widths from the footer (from scrolling)
5708			tmpTable.find('tfoot th, tfoot td').css('width', '');
5709	
5710			// Apply custom sizing to the cloned header
5711			headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] );
5712	
5713			for ( i=0 ; i<visibleColumns.length ; i++ ) {
5714				column = columns[ visibleColumns[i] ];
5715	
5716				headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ?
5717					_fnStringToCss( column.sWidthOrig ) :
5718					'';
5719	
5720				// For scrollX we need to force the column width otherwise the
5721				// browser will collapse it. If this width is smaller than the
5722				// width the column requires, then it will have no effect
5723				if ( column.sWidthOrig && scrollX ) {
5724					$( headerCells[i] ).append( $('<div/>').css( {
5725						width: column.sWidthOrig,
5726						margin: 0,
5727						padding: 0,
5728						border: 0,
5729						height: 1
5730					} ) );
5731				}
5732			}
5733	
5734			// Find the widest cell for each column and put it into the table
5735			if ( oSettings.aoData.length ) {
5736				for ( i=0 ; i<visibleColumns.length ; i++ ) {
5737					columnIdx = visibleColumns[i];
5738					column = columns[ columnIdx ];
5739	
5740					$( _fnGetWidestNode( oSettings, columnIdx ) )
5741						.clone( false )
5742						.append( column.sContentPadding )
5743						.appendTo( tr );
5744				}
5745			}
5746	
5747			// Tidy the temporary table - remove name attributes so there aren't
5748			// duplicated in the dom (radio elements for example)
5749			$('[name]', tmpTable).removeAttr('name');
5750	
5751			// Table has been built, attach to the document so we can work with it.
5752			// A holding element is used, positioned at the top of the container
5753			// with minimal height, so it has no effect on if the container scrolls
5754			// or not. Otherwise it might trigger scrolling when it actually isn't
5755			// needed
5756			var holder = $('<div/>').css( scrollX || scrollY ?
5757					{
5758						position: 'absolute',
5759						top: 0,
5760						left: 0,
5761						height: 1,
5762						right: 0,
5763						overflow: 'hidden'
5764					} :
5765					{}
5766				)
5767				.append( tmpTable )
5768				.appendTo( tableContainer );
5769	
5770			// When scrolling (X or Y) we want to set the width of the table as 
5771			// appropriate. However, when not scrolling leave the table width as it
5772			// is. This results in slightly different, but I think correct behaviour
5773			if ( scrollX && scrollXInner ) {
5774				tmpTable.width( scrollXInner );
5775			}
5776			else if ( scrollX ) {
5777				tmpTable.css( 'width', 'auto' );
5778				tmpTable.removeAttr('width');
5779	
5780				// If there is no width attribute or style, then allow the table to
5781				// collapse
5782				if ( tmpTable.width() < tableContainer.clientWidth && tableWidthAttr ) {
5783					tmpTable.width( tableContainer.clientWidth );
5784				}
5785			}
5786			else if ( scrollY ) {
5787				tmpTable.width( tableContainer.clientWidth );
5788			}
5789			else if ( tableWidthAttr ) {
5790				tmpTable.width( tableWidthAttr );
5791			}
5792	
5793			// Get the width of each column in the constructed table - we need to
5794			// know the inner width (so it can be assigned to the other table's
5795			// cells) and the outer width so we can calculate the full width of the
5796			// table. This is safe since DataTables requires a unique cell for each
5797			// column, but if ever a header can span multiple columns, this will
5798			// need to be modified.
5799			var total = 0;
5800			for ( i=0 ; i<visibleColumns.length ; i++ ) {
5801				var cell = $(headerCells[i]);
5802				var border = cell.outerWidth() - cell.width();
5803	
5804				// Use getBounding... where possible (not IE8-) because it can give
5805				// sub-pixel accuracy, which we then want to round up!
5806				var bounding = browser.bBounding ?
5807					Math.ceil( headerCells[i].getBoundingClientRect().width ) :
5808					cell.outerWidth();
5809	
5810				// Total is tracked to remove any sub-pixel errors as the outerWidth
5811				// of the table might not equal the total given here (IE!).
5812				total += bounding;
5813	
5814				// Width for each column to use
5815				columns[ visibleColumns[i] ].sWidth = _fnStringToCss( bounding - border );
5816			}
5817	
5818			table.style.width = _fnStringToCss( total );
5819	
5820			// Finished with the table - ditch it
5821			holder.remove();
5822		}
5823	
5824		// If there is a width attr, we want to attach an event listener which
5825		// allows the table sizing to automatically adjust when the window is
5826		// resized. Use the width attr rather than CSS, since we can't know if the
5827		// CSS is a relative value or absolute - DOM read is always px.
5828		if ( tableWidthAttr ) {
5829			table.style.width = _fnStringToCss( tableWidthAttr );
5830		}
5831	
5832		if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) {
5833			var bindResize = function () {
5834				$(window).on('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {
5835					_fnAdjustColumnSizing( oSettings );
5836				} ) );
5837			};
5838	
5839			// IE6/7 will crash if we bind a resize event handler on page load.
5840			// To be removed in 1.11 which drops IE6/7 support
5841			if ( ie67 ) {
5842				setTimeout( bindResize, 1000 );
5843			}
5844			else {
5845				bindResize();
5846			}
5847	
5848			oSettings._reszEvt = true;
5849		}
5850	}
5851	
5852	
5853	/**
5854	 * Throttle the calls to a function. Arguments and context are maintained for
5855	 * the throttled function
5856	 *  @param {function} fn Function to be called
5857	 *  @param {int} [freq=200] call frequency in mS
5858	 *  @returns {function} wrapped function
5859	 *  @memberof DataTable#oApi
5860	 */
5861	var _fnThrottle = DataTable.util.throttle;
5862	
5863	
5864	/**
5865	 * Convert a CSS unit width to pixels (e.g. 2em)
5866	 *  @param {string} width width to be converted
5867	 *  @param {node} parent parent to get the with for (required for relative widths) - optional
5868	 *  @returns {int} width in pixels
5869	 *  @memberof DataTable#oApi
5870	 */
5871	function _fnConvertToWidth ( width, parent )
5872	{
5873		if ( ! width ) {
5874			return 0;
5875		}
5876	
5877		var n = $('<div/>')
5878			.css( 'width', _fnStringToCss( width ) )
5879			.appendTo( parent || document.body );
5880	
5881		var val = n[0].offsetWidth;
5882		n.remove();
5883	
5884		return val;
5885	}
5886	
5887	
5888	/**
5889	 * Get the widest node
5890	 *  @param {object} settings dataTables settings object
5891	 *  @param {int} colIdx column of interest
5892	 *  @returns {node} widest table node
5893	 *  @memberof DataTable#oApi
5894	 */
5895	function _fnGetWidestNode( settings, colIdx )
5896	{
5897		var idx = _fnGetMaxLenString( settings, colIdx );
5898		if ( idx < 0 ) {
5899			return null;
5900		}
5901	
5902		var data = settings.aoData[ idx ];
5903		return ! data.nTr ? // Might not have been created when deferred rendering
5904			$('<td/>').html( _fnGetCellData( settings, idx, colIdx, 'display' ) )[0] :
5905			data.anCells[ colIdx ];
5906	}
5907	
5908	
5909	/**
5910	 * Get the maximum strlen for each data column
5911	 *  @param {object} settings dataTables settings object
5912	 *  @param {int} colIdx column of interest
5913	 *  @returns {string} max string length for each column
5914	 *  @memberof DataTable#oApi
5915	 */
5916	function _fnGetMaxLenString( settings, colIdx )
5917	{
5918		var s, max=-1, maxIdx = -1;
5919	
5920		for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
5921			s = _fnGetCellData( settings, i, colIdx, 'display' )+'';
5922			s = s.replace( __re_html_remove, '' );
5923			s = s.replace( /&nbsp;/g, ' ' );
5924	
5925			if ( s.length > max ) {
5926				max = s.length;
5927				maxIdx = i;
5928			}
5929		}
5930	
5931		return maxIdx;
5932	}
5933	
5934	
5935	/**
5936	 * Append a CSS unit (only if required) to a string
5937	 *  @param {string} value to css-ify
5938	 *  @returns {string} value with css unit
5939	 *  @memberof DataTable#oApi
5940	 */
5941	function _fnStringToCss( s )
5942	{
5943		if ( s === null ) {
5944			return '0px';
5945		}
5946	
5947		if ( typeof s == 'number' ) {
5948			return s < 0 ?
5949				'0px' :
5950				s+'px';
5951		}
5952	
5953		// Check it has a unit character already
5954		return s.match(/\d$/) ?
5955			s+'px' :
5956			s;
5957	}
5958	
5959	
5960	
5961	function _fnSortFlatten ( settings )
5962	{
5963		var
5964			i, iLen, k, kLen,
5965			aSort = [],
5966			aiOrig = [],
5967			aoColumns = settings.aoColumns,
5968			aDataSort, iCol, sType, srcCol,
5969			fixed = settings.aaSortingFixed,
5970			fixedObj = $.isPlainObject( fixed ),
5971			nestedSort = [],
5972			add = function ( a ) {
5973				if ( a.length && ! Array.isArray( a[0] ) ) {
5974					// 1D array
5975					nestedSort.push( a );
5976				}
5977				else {
5978					// 2D array
5979					$.merge( nestedSort, a );
5980				}
5981			};
5982	
5983		// Build the sort array, with pre-fix and post-fix options if they have been
5984		// specified
5985		if ( Array.isArray( fixed ) ) {
5986			add( fixed );
5987		}
5988	
5989		if ( fixedObj && fixed.pre ) {
5990			add( fixed.pre );
5991		}
5992	
5993		add( settings.aaSorting );
5994	
5995		if (fixedObj && fixed.post ) {
5996			add( fixed.post );
5997		}
5998	
5999		for ( i=0 ; i<nestedSort.length ; i++ )
6000		{
6001			srcCol = nestedSort[i][0];
6002			aDataSort = aoColumns[ srcCol ].aDataSort;
6003	
6004			for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ )
6005			{
6006				iCol = aDataSort[k];
6007				sType = aoColumns[ iCol ].sType || 'string';
6008	
6009				if ( nestedSort[i]._idx === undefined ) {
6010					nestedSort[i]._idx = $.inArray( nestedSort[i][1], aoColumns[iCol].asSorting );
6011				}
6012	
6013				aSort.push( {
6014					src:       srcCol,
6015					col:       iCol,
6016					dir:       nestedSort[i][1],
6017					index:     nestedSort[i]._idx,
6018					type:      sType,
6019					formatter: DataTable.ext.type.order[ sType+"-pre" ]
6020				} );
6021			}
6022		}
6023	
6024		return aSort;
6025	}
6026	
6027	/**
6028	 * Change the order of the table
6029	 *  @param {object} oSettings dataTables settings object
6030	 *  @memberof DataTable#oApi
6031	 *  @todo This really needs split up!
6032	 */
6033	function _fnSort ( oSettings )
6034	{
6035		var
6036			i, ien, iLen, j, jLen, k, kLen,
6037			sDataType, nTh,
6038			aiOrig = [],
6039			oExtSort = DataTable.ext.type.order,
6040			aoData = oSettings.aoData,
6041			aoColumns = oSettings.aoColumns,
6042			aDataSort, data, iCol, sType, oSort,
6043			formatters = 0,
6044			sortCol,
6045			displayMaster = oSettings.aiDisplayMaster,
6046			aSort;
6047	
6048		// Resolve any column types that are unknown due to addition or invalidation
6049		// @todo Can this be moved into a 'data-ready' handler which is called when
6050		//   data is going to be used in the table?
6051		_fnColumnTypes( oSettings );
6052	
6053		aSort = _fnSortFlatten( oSettings );
6054	
6055		for ( i=0, ien=aSort.length ; i<ien ; i++ ) {
6056			sortCol = aSort[i];
6057	
6058			// Track if we can use the fast sort algorithm
6059			if ( sortCol.formatter ) {
6060				formatters++;
6061			}
6062	
6063			// Load the data needed for the sort, for each cell
6064			_fnSortData( oSettings, sortCol.col );
6065		}
6066	
6067		/* No sorting required if server-side or no sorting array */
6068		if ( _fnDataSource( oSettings ) != 'ssp' && aSort.length !== 0 )
6069		{
6070			// Create a value - key array of the current row positions such that we can use their
6071			// current position during the sort, if values match, in order to perform stable sorting
6072			for ( i=0, iLen=displayMaster.length ; i<iLen ; i++ ) {
6073				aiOrig[ displayMaster[i] ] = i;
6074			}
6075	
6076			/* Do the sort - here we want multi-column sorting based on a given data source (column)
6077			 * and sorting function (from oSort) in a certain direction. It's reasonably complex to
6078			 * follow on it's own, but this is what we want (example two column sorting):
6079			 *  fnLocalSorting = function(a,b){
6080			 *    var iTest;
6081			 *    iTest = oSort['string-asc']('data11', 'data12');
6082			 *      if (iTest !== 0)
6083			 *        return iTest;
6084			 *    iTest = oSort['numeric-desc']('data21', 'data22');
6085			 *    if (iTest !== 0)
6086			 *      return iTest;
6087			 *    return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
6088			 *  }
6089			 * Basically we have a test for each sorting column, if the data in that column is equal,
6090			 * test the next column. If all columns match, then we use a numeric sort on the row
6091			 * positions in the original data array to provide a stable sort.
6092			 *
6093			 * Note - I know it seems excessive to have two sorting methods, but the first is around
6094			 * 15% faster, so the second is only maintained for backwards compatibility with sorting
6095			 * methods which do not have a pre-sort formatting function.
6096			 */
6097			if ( formatters === aSort.length ) {
6098				// All sort types have formatting functions
6099				displayMaster.sort( function ( a, b ) {
6100					var
6101						x, y, k, test, sort,
6102						len=aSort.length,
6103						dataA = aoData[a]._aSortData,
6104						dataB = aoData[b]._aSortData;
6105	
6106					for ( k=0 ; k<len ; k++ ) {
6107						sort = aSort[k];
6108	
6109						x = dataA[ sort.col ];
6110						y = dataB[ sort.col ];
6111	
6112						test = x<y ? -1 : x>y ? 1 : 0;
6113						if ( test !== 0 ) {
6114							return sort.dir === 'asc' ? test : -test;
6115						}
6116					}
6117	
6118					x = aiOrig[a];
6119					y = aiOrig[b];
6120					return x<y ? -1 : x>y ? 1 : 0;
6121				} );
6122			}
6123			else {
6124				// Depreciated - remove in 1.11 (providing a plug-in option)
6125				// Not all sort types have formatting methods, so we have to call their sorting
6126				// methods.
6127				displayMaster.sort( function ( a, b ) {
6128					var
6129						x, y, k, l, test, sort, fn,
6130						len=aSort.length,
6131						dataA = aoData[a]._aSortData,
6132						dataB = aoData[b]._aSortData;
6133	
6134					for ( k=0 ; k<len ; k++ ) {
6135						sort = aSort[k];
6136	
6137						x = dataA[ sort.col ];
6138						y = dataB[ sort.col ];
6139	
6140						fn = oExtSort[ sort.type+"-"+sort.dir ] || oExtSort[ "string-"+sort.dir ];
6141						test = fn( x, y );
6142						if ( test !== 0 ) {
6143							return test;
6144						}
6145					}
6146	
6147					x = aiOrig[a];
6148					y = aiOrig[b];
6149					return x<y ? -1 : x>y ? 1 : 0;
6150				} );
6151			}
6152		}
6153	
6154		/* Tell the draw function that we have sorted the data */
6155		oSettings.bSorted = true;
6156	}
6157	
6158	
6159	function _fnSortAria ( settings )
6160	{
6161		var label;
6162		var nextSort;
6163		var columns = settings.aoColumns;
6164		var aSort = _fnSortFlatten( settings );
6165		var oAria = settings.oLanguage.oAria;
6166	
6167		// ARIA attributes - need to loop all columns, to update all (removing old
6168		// attributes as needed)
6169		for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
6170		{
6171			var col = columns[i];
6172			var asSorting = col.asSorting;
6173			var sTitle = col.ariaTitle || col.sTitle.replace( /<.*?>/g, "" );
6174			var th = col.nTh;
6175	
6176			// IE7 is throwing an error when setting these properties with jQuery's
6177			// attr() and removeAttr() methods...
6178			th.removeAttribute('aria-sort');
6179	
6180			/* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
6181			if ( col.bSortable ) {
6182				if ( aSort.length > 0 && aSort[0].col == i ) {
6183					th.setAttribute('aria-sort', aSort[0].dir=="asc" ? "ascending" : "descending" );
6184					nextSort = asSorting[ aSort[0].index+1 ] || asSorting[0];
6185				}
6186				else {
6187					nextSort = asSorting[0];
6188				}
6189	
6190				label = sTitle + ( nextSort === "asc" ?
6191					oAria.sSortAscending :
6192					oAria.sSortDescending
6193				);
6194			}
6195			else {
6196				label = sTitle;
6197			}
6198	
6199			th.setAttribute('aria-label', label);
6200		}
6201	}
6202	
6203	
6204	/**
6205	 * Function to run on user sort request
6206	 *  @param {object} settings dataTables settings object
6207	 *  @param {node} attachTo node to attach the handler to
6208	 *  @param {int} colIdx column sorting index
6209	 *  @param {boolean} [append=false] Append the requested sort to the existing
6210	 *    sort if true (i.e. multi-column sort)
6211	 *  @param {function} [callback] callback function
6212	 *  @memberof DataTable#oApi
6213	 */
6214	function _fnSortListener ( settings, colIdx, append, callback )
6215	{
6216		var col = settings.aoColumns[ colIdx ];
6217		var sorting = settings.aaSorting;
6218		var asSorting = col.asSorting;
6219		var nextSortIdx;
6220		var next = function ( a, overflow ) {
6221			var idx = a._idx;
6222			if ( idx === undefined ) {
6223				idx = $.inArray( a[1], asSorting );
6224			}
6225	
6226			return idx+1 < asSorting.length ?
6227				idx+1 :
6228				overflow ?
6229					null :
6230					0;
6231		};
6232	
6233		// Convert to 2D array if needed
6234		if ( typeof sorting[0] === 'number' ) {
6235			sorting = settings.aaSorting = [ sorting ];
6236		}
6237	
6238		// If appending the sort then we are multi-column sorting
6239		if ( append && settings.oFeatures.bSortMulti ) {
6240			// Are we already doing some kind of sort on this column?
6241			var sortIdx = $.inArray( colIdx, _pluck(sorting, '0') );
6242	
6243			if ( sortIdx !== -1 ) {
6244				// Yes, modify the sort
6245				nextSortIdx = next( sorting[sortIdx], true );
6246	
6247				if ( nextSortIdx === null && sorting.length === 1 ) {
6248					nextSortIdx = 0; // can't remove sorting completely
6249				}
6250	
6251				if ( nextSortIdx === null ) {
6252					sorting.splice( sortIdx, 1 );
6253				}
6254				else {
6255					sorting[sortIdx][1] = asSorting[ nextSortIdx ];
6256					sorting[sortIdx]._idx = nextSortIdx;
6257				}
6258			}
6259			else {
6260				// No sort on this column yet
6261				sorting.push( [ colIdx, asSorting[0], 0 ] );
6262				sorting[sorting.length-1]._idx = 0;
6263			}
6264		}
6265		else if ( sorting.length && sorting[0][0] == colIdx ) {
6266			// Single column - already sorting on this column, modify the sort
6267			nextSortIdx = next( sorting[0] );
6268	
6269			sorting.length = 1;
6270			sorting[0][1] = asSorting[ nextSortIdx ];
6271			sorting[0]._idx = nextSortIdx;
6272		}
6273		else {
6274			// Single column - sort only on this column
6275			sorting.length = 0;
6276			sorting.push( [ colIdx, asSorting[0] ] );
6277			sorting[0]._idx = 0;
6278		}
6279	
6280		// Run the sort by calling a full redraw
6281		_fnReDraw( settings );
6282	
6283		// callback used for async user interaction
6284		if ( typeof callback == 'function' ) {
6285			callback( settings );
6286		}
6287	}
6288	
6289	
6290	/**
6291	 * Attach a sort handler (click) to a node
6292	 *  @param {object} settings dataTables settings object
6293	 *  @param {node} attachTo node to attach the handler to
6294	 *  @param {int} colIdx column sorting index
6295	 *  @param {function} [callback] callback function
6296	 *  @memberof DataTable#oApi
6297	 */
6298	function _fnSortAttachListener ( settings, attachTo, colIdx, callback )
6299	{
6300		var col = settings.aoColumns[ colIdx ];
6301	
6302		_fnBindAction( attachTo, {}, function (e) {
6303			/* If the column is not sortable - don't to anything */
6304			if ( col.bSortable === false ) {
6305				return;
6306			}
6307	
6308			// If processing is enabled use a timeout to allow the processing
6309			// display to be shown - otherwise to it synchronously
6310			if ( settings.oFeatures.bProcessing ) {
6311				_fnProcessingDisplay( settings, true );
6312	
6313				setTimeout( function() {
6314					_fnSortListener( settings, colIdx, e.shiftKey, callback );
6315	
6316					// In server-side processing, the draw callback will remove the
6317					// processing display
6318					if ( _fnDataSource( settings ) !== 'ssp' ) {
6319						_fnProcessingDisplay( settings, false );
6320					}
6321				}, 0 );
6322			}
6323			else {
6324				_fnSortListener( settings, colIdx, e.shiftKey, callback );
6325			}
6326		} );
6327	}
6328	
6329	
6330	/**
6331	 * Set the sorting classes on table's body, Note: it is safe to call this function
6332	 * when bSort and bSortClasses are false
6333	 *  @param {object} oSettings dataTables settings object
6334	 *  @memberof DataTable#oApi
6335	 */
6336	function _fnSortingClasses( settings )
6337	{
6338		var oldSort = settings.aLastSort;
6339		var sortClass = settings.oClasses.sSortColumn;
6340		var sort = _fnSortFlatten( settings );
6341		var features = settings.oFeatures;
6342		var i, ien, colIdx;
6343	
6344		if ( features.bSort && features.bSortClasses ) {
6345			// Remove old sorting classes
6346			for ( i=0, ien=oldSort.length ; i<ien ; i++ ) {
6347				colIdx = oldSort[i].src;
6348	
6349				// Remove column sorting
6350				$( _pluck( settings.aoData, 'anCells', colIdx ) )
6351					.removeClass( sortClass + (i<2 ? i+1 : 3) );
6352			}
6353	
6354			// Add new column sorting
6355			for ( i=0, ien=sort.length ; i<ien ; i++ ) {
6356				colIdx = sort[i].src;
6357	
6358				$( _pluck( settings.aoData, 'anCells', colIdx ) )
6359					.addClass( sortClass + (i<2 ? i+1 : 3) );
6360			}
6361		}
6362	
6363		settings.aLastSort = sort;
6364	}
6365	
6366	
6367	// Get the data to sort a column, be it from cache, fresh (populating the
6368	// cache), or from a sort formatter
6369	function _fnSortData( settings, idx )
6370	{
6371		// Custom sorting function - provided by the sort data type
6372		var column = settings.aoColumns[ idx ];
6373		var customSort = DataTable.ext.order[ column.sSortDataType ];
6374		var customData;
6375	
6376		if ( customSort ) {
6377			customData = customSort.call( settings.oInstance, settings, idx,
6378				_fnColumnIndexToVisible( settings, idx )
6379			);
6380		}
6381	
6382		// Use / populate cache
6383		var row, cellData;
6384		var formatter = DataTable.ext.type.order[ column.sType+"-pre" ];
6385	
6386		for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
6387			row = settings.aoData[i];
6388	
6389			if ( ! row._aSortData ) {
6390				row._aSortData = [];
6391			}
6392	
6393			if ( ! row._aSortData[idx] || customSort ) {
6394				cellData = customSort ?
6395					customData[i] : // If there was a custom sort function, use data from there
6396					_fnGetCellData( settings, i, idx, 'sort' );
6397	
6398				row._aSortData[ idx ] = formatter ?
6399					formatter( cellData ) :
6400					cellData;
6401			}
6402		}
6403	}
6404	
6405	
6406	
6407	/**
6408	 * Save the state of a table
6409	 *  @param {object} oSettings dataTables settings object
6410	 *  @memberof DataTable#oApi
6411	 */
6412	function _fnSaveState ( settings )
6413	{
6414		if (settings._bLoadingState) {
6415			return;
6416		}
6417	
6418		/* Store the interesting variables */
6419		var state = {
6420			time:    +new Date(),
6421			start:   settings._iDisplayStart,
6422			length:  settings._iDisplayLength,
6423			order:   $.extend( true, [], settings.aaSorting ),
6424			search:  _fnSearchToCamel( settings.oPreviousSearch ),
6425			columns: $.map( settings.aoColumns, function ( col, i ) {
6426				return {
6427					visible: col.bVisible,
6428					search: _fnSearchToCamel( settings.aoPreSearchCols[i] )
6429				};
6430			} )
6431		};
6432	
6433		settings.oSavedState = state;
6434		_fnCallbackFire( settings, "aoStateSaveParams", 'stateSaveParams', [settings, state] );
6435		
6436		if ( settings.oFeatures.bStateSave && !settings.bDestroying )
6437		{
6438			settings.fnStateSaveCallback.call( settings.oInstance, settings, state );
6439		}	
6440	}
6441	
6442	
6443	/**
6444	 * Attempt to load a saved table state
6445	 *  @param {object} oSettings dataTables settings object
6446	 *  @param {object} oInit DataTables init object so we can override settings
6447	 *  @param {function} callback Callback to execute when the state has been loaded
6448	 *  @memberof DataTable#oApi
6449	 */
6450	function _fnLoadState ( settings, oInit, callback )
6451	{
6452		if ( ! settings.oFeatures.bStateSave ) {
6453			callback();
6454			return;
6455		}
6456	
6457		var loaded = function(state) {
6458			_fnImplementState(settings, state, callback);
6459		}
6460	
6461		var state = settings.fnStateLoadCallback.call( settings.oInstance, settings, loaded );
6462	
6463		if ( state !== undefined ) {
6464			_fnImplementState( settings, state, callback );
6465		}
6466		// otherwise, wait for the loaded callback to be executed
6467	
6468		return true;
6469	}
6470	
6471	function _fnImplementState ( settings, s, callback) {
6472		var i, ien;
6473		var columns = settings.aoColumns;
6474		settings._bLoadingState = true;
6475	
6476		// When StateRestore was introduced the state could now be implemented at any time
6477		// Not just initialisation. To do this an api instance is required in some places
6478		var api = settings._bInitComplete ? new DataTable.Api(settings) : null;
6479	
6480		if ( ! s || ! s.time ) {
6481			settings._bLoadingState = false;
6482			callback();
6483			return;
6484		}
6485	
6486		// Allow custom and plug-in manipulation functions to alter the saved data set and
6487		// cancelling of loading by returning false
6488		var abStateLoad = _fnCallbackFire( settings, 'aoStateLoadParams', 'stateLoadParams', [settings, s] );
6489		if ( $.inArray( false, abStateLoad ) !== -1 ) {
6490			settings._bLoadingState = false;
6491			callback();
6492			return;
6493		}
6494	
6495		// Reject old data
6496		var duration = settings.iStateDuration;
6497		if ( duration > 0 && s.time < +new Date() - (duration*1000) ) {
6498			settings._bLoadingState = false;
6499			callback();
6500			return;
6501		}
6502	
6503		// Number of columns have changed - all bets are off, no restore of settings
6504		if ( s.columns && columns.length !== s.columns.length ) {
6505			settings._bLoadingState = false;
6506			callback();
6507			return;
6508		}
6509	
6510		// Store the saved state so it might be accessed at any time
6511		settings.oLoadedState = $.extend( true, {}, s );
6512	
6513		// Page Length
6514		if ( s.length !== undefined ) {
6515			// If already initialised just set the value directly so that the select element is also updated
6516			if (api) {
6517				api.page.len(s.length)
6518			}
6519			else {
6520				settings._iDisplayLength   = s.length;
6521			}
6522		}
6523	
6524		// Restore key features - todo - for 1.11 this needs to be done by
6525		// subscribed events
6526		if ( s.start !== undefined ) {
6527			if(api === null) {
6528				settings._iDisplayStart    = s.start;
6529				settings.iInitDisplayStart = s.start;
6530			}
6531			else {
6532				_fnPageChange(settings, s.start/settings._iDisplayLength);
6533			}
6534		}
6535	
6536		// Order
6537		if ( s.order !== undefined ) {
6538			settings.aaSorting = [];
6539			$.each( s.order, function ( i, col ) {
6540				settings.aaSorting.push( col[0] >= columns.length ?
6541					[ 0, col[1] ] :
6542					col
6543				);
6544			} );
6545		}
6546	
6547		// Search
6548		if ( s.search !== undefined ) {
6549			$.extend( settings.oPreviousSearch, _fnSearchToHung( s.search ) );
6550		}
6551	
6552		// Columns
6553		if ( s.columns ) {
6554			for ( i=0, ien=s.columns.length ; i<ien ; i++ ) {
6555				var col = s.columns[i];
6556	
6557				// Visibility
6558				if ( col.visible !== undefined ) {
6559					// If the api is defined, the table has been initialised so we need to use it rather than internal settings
6560					if (api) {
6561						// Don't redraw the columns on every iteration of this loop, we will do this at the end instead
6562						api.column(i).visible(col.visible, false);
6563					}
6564					else {
6565						columns[i].bVisible = col.visible;
6566					}
6567				}
6568	
6569				// Search
6570				if ( col.search !== undefined ) {
6571					$.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) );
6572				}
6573			}
6574			
6575			// If the api is defined then we need to adjust the columns once the visibility has been changed
6576			if (api) {
6577				api.columns.adjust();
6578			}
6579		}
6580	
6581		settings._bLoadingState = false;
6582		_fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, s] );
6583		callback();
6584	};
6585	
6586	
6587	/**
6588	 * Return the settings object for a particular table
6589	 *  @param {node} table table we are using as a dataTable
6590	 *  @returns {object} Settings object - or null if not found
6591	 *  @memberof DataTable#oApi
6592	 */
6593	function _fnSettingsFromNode ( table )
6594	{
6595		var settings = DataTable.settings;
6596		var idx = $.inArray( table, _pluck( settings, 'nTable' ) );
6597	
6598		return idx !== -1 ?
6599			settings[ idx ] :
6600			null;
6601	}
6602	
6603	
6604	/**
6605	 * Log an error message
6606	 *  @param {object} settings dataTables settings object
6607	 *  @param {int} level log error messages, or display them to the user
6608	 *  @param {string} msg error message
6609	 *  @param {int} tn Technical note id to get more information about the error.
6610	 *  @memberof DataTable#oApi
6611	 */
6612	function _fnLog( settings, level, msg, tn )
6613	{
6614		msg = 'DataTables warning: '+
6615			(settings ? 'table id='+settings.sTableId+' - ' : '')+msg;
6616	
6617		if ( tn ) {
6618			msg += '. For more information about this error, please see '+
6619			'http://datatables.net/tn/'+tn;
6620		}
6621	
6622		if ( ! level  ) {
6623			// Backwards compatibility pre 1.10
6624			var ext = DataTable.ext;
6625			var type = ext.sErrMode || ext.errMode;
6626	
6627			if ( settings ) {
6628				_fnCallbackFire( settings, null, 'error', [ settings, tn, msg ] );
6629			}
6630	
6631			if ( type == 'alert' ) {
6632				alert( msg );
6633			}
6634			else if ( type == 'throw' ) {
6635				throw new Error(msg);
6636			}
6637			else if ( typeof type == 'function' ) {
6638				type( settings, tn, msg );
6639			}
6640		}
6641		else if ( window.console && console.log ) {
6642			console.log( msg );
6643		}
6644	}
6645	
6646	
6647	/**
6648	 * See if a property is defined on one object, if so assign it to the other object
6649	 *  @param {object} ret target object
6650	 *  @param {object} src source object
6651	 *  @param {string} name property
6652	 *  @param {string} [mappedName] name to map too - optional, name used if not given
6653	 *  @memberof DataTable#oApi
6654	 */
6655	function _fnMap( ret, src, name, mappedName )
6656	{
6657		if ( Array.isArray( name ) ) {
6658			$.each( name, function (i, val) {
6659				if ( Array.isArray( val ) ) {
6660					_fnMap( ret, src, val[0], val[1] );
6661				}
6662				else {
6663					_fnMap( ret, src, val );
6664				}
6665			} );
6666	
6667			return;
6668		}
6669	
6670		if ( mappedName === undefined ) {
6671			mappedName = name;
6672		}
6673	
6674		if ( src[name] !== undefined ) {
6675			ret[mappedName] = src[name];
6676		}
6677	}
6678	
6679	
6680	/**
6681	 * Extend objects - very similar to jQuery.extend, but deep copy objects, and
6682	 * shallow copy arrays. The reason we need to do this, is that we don't want to
6683	 * deep copy array init values (such as aaSorting) since the dev wouldn't be
6684	 * able to override them, but we do want to deep copy arrays.
6685	 *  @param {object} out Object to extend
6686	 *  @param {object} extender Object from which the properties will be applied to
6687	 *      out
6688	 *  @param {boolean} breakRefs If true, then arrays will be sliced to take an
6689	 *      independent copy with the exception of the `data` or `aaData` parameters
6690	 *      if they are present. This is so you can pass in a collection to
6691	 *      DataTables and have that used as your data source without breaking the
6692	 *      references
6693	 *  @returns {object} out Reference, just for convenience - out === the return.
6694	 *  @memberof DataTable#oApi
6695	 *  @todo This doesn't take account of arrays inside the deep copied objects.
6696	 */
6697	function _fnExtend( out, extender, breakRefs )
6698	{
6699		var val;
6700	
6701		for ( var prop in extender ) {
6702			if ( extender.hasOwnProperty(prop) ) {
6703				val = extender[prop];
6704	
6705				if ( $.isPlainObject( val ) ) {
6706					if ( ! $.isPlainObject( out[prop] ) ) {
6707						out[prop] = {};
6708					}
6709					$.extend( true, out[prop], val );
6710				}
6711				else if ( breakRefs && prop !== 'data' && prop !== 'aaData' && Array.isArray(val) ) {
6712					out[prop] = val.slice();
6713				}
6714				else {
6715					out[prop] = val;
6716				}
6717			}
6718		}
6719	
6720		return out;
6721	}
6722	
6723	
6724	/**
6725	 * Bind an event handers to allow a click or return key to activate the callback.
6726	 * This is good for accessibility since a return on the keyboard will have the
6727	 * same effect as a click, if the element has focus.
6728	 *  @param {element} n Element to bind the action to
6729	 *  @param {object} oData Data object to pass to the triggered function
6730	 *  @param {function} fn Callback function for when the event is triggered
6731	 *  @memberof DataTable#oApi
6732	 */
6733	function _fnBindAction( n, oData, fn )
6734	{
6735		$(n)
6736			.on( 'click.DT', oData, function (e) {
6737					$(n).trigger('blur'); // Remove focus outline for mouse users
6738					fn(e);
6739				} )
6740			.on( 'keypress.DT', oData, function (e){
6741					if ( e.which === 13 ) {
6742						e.preventDefault();
6743						fn(e);
6744					}
6745				} )
6746			.on( 'selectstart.DT', function () {
6747					/* Take the brutal approach to cancelling text selection */
6748					return false;
6749				} );
6750	}
6751	
6752	
6753	/**
6754	 * Register a callback function. Easily allows a callback function to be added to
6755	 * an array store of callback functions that can then all be called together.
6756	 *  @param {object} oSettings dataTables settings object
6757	 *  @param {string} sStore Name of the array storage for the callbacks in oSettings
6758	 *  @param {function} fn Function to be called back
6759	 *  @param {string} sName Identifying name for the callback (i.e. a label)
6760	 *  @memberof DataTable#oApi
6761	 */
6762	function _fnCallbackReg( oSettings, sStore, fn, sName )
6763	{
6764		if ( fn )
6765		{
6766			oSettings[sStore].push( {
6767				"fn": fn,
6768				"sName": sName
6769			} );
6770		}
6771	}
6772	
6773	
6774	/**
6775	 * Fire callback functions and trigger events. Note that the loop over the
6776	 * callback array store is done backwards! Further note that you do not want to
6777	 * fire off triggers in time sensitive applications (for example cell creation)
6778	 * as its slow.
6779	 *  @param {object} settings dataTables settings object
6780	 *  @param {string} callbackArr Name of the array storage for the callbacks in
6781	 *      oSettings
6782	 *  @param {string} eventName Name of the jQuery custom event to trigger. If
6783	 *      null no trigger is fired
6784	 *  @param {array} args Array of arguments to pass to the callback function /
6785	 *      trigger
6786	 *  @memberof DataTable#oApi
6787	 */
6788	function _fnCallbackFire( settings, callbackArr, eventName, args )
6789	{
6790		var ret = [];
6791	
6792		if ( callbackArr ) {
6793			ret = $.map( settings[callbackArr].slice().reverse(), function (val, i) {
6794				return val.fn.apply( settings.oInstance, args );
6795			} );
6796		}
6797	
6798		if ( eventName !== null ) {
6799			var e = $.Event( eventName+'.dt' );
6800			var table = $(settings.nTable);
6801	
6802			table.trigger( e, args );
6803	
6804			// If not yet attached to the document, trigger the event
6805			// on the body directly to sort of simulate the bubble
6806			if (table.parents('body').length === 0) {
6807				$('body').trigger( e, args );
6808			}
6809	
6810			ret.push( e.result );
6811		}
6812	
6813		return ret;
6814	}
6815	
6816	
6817	function _fnLengthOverflow ( settings )
6818	{
6819		var
6820			start = settings._iDisplayStart,
6821			end = settings.fnDisplayEnd(),
6822			len = settings._iDisplayLength;
6823	
6824		/* If we have space to show extra rows (backing up from the end point - then do so */
6825		if ( start >= end )
6826		{
6827			start = end - len;
6828		}
6829	
6830		// Keep the start record on the current page
6831		start -= (start % len);
6832	
6833		if ( len === -1 || start < 0 )
6834		{
6835			start = 0;
6836		}
6837	
6838		settings._iDisplayStart = start;
6839	}
6840	
6841	
6842	function _fnRenderer( settings, type )
6843	{
6844		var renderer = settings.renderer;
6845		var host = DataTable.ext.renderer[type];
6846	
6847		if ( $.isPlainObject( renderer ) && renderer[type] ) {
6848			// Specific renderer for this type. If available use it, otherwise use
6849			// the default.
6850			return host[renderer[type]] || host._;
6851		}
6852		else if ( typeof renderer === 'string' ) {
6853			// Common renderer - if there is one available for this type use it,
6854			// otherwise use the default
6855			return host[renderer] || host._;
6856		}
6857	
6858		// Use the default
6859		return host._;
6860	}
6861	
6862	
6863	/**
6864	 * Detect the data source being used for the table. Used to simplify the code
6865	 * a little (ajax) and to make it compress a little smaller.
6866	 *
6867	 *  @param {object} settings dataTables settings object
6868	 *  @returns {string} Data source
6869	 *  @memberof DataTable#oApi
6870	 */
6871	function _fnDataSource ( settings )
6872	{
6873		if ( settings.oFeatures.bServerSide ) {
6874			return 'ssp';
6875		}
6876		else if ( settings.ajax || settings.sAjaxSource ) {
6877			return 'ajax';
6878		}
6879		return 'dom';
6880	}
6881	
6882	
6883	
6884	
6885	/**
6886	 * Computed structure of the DataTables API, defined by the options passed to
6887	 * `DataTable.Api.register()` when building the API.
6888	 *
6889	 * The structure is built in order to speed creation and extension of the Api
6890	 * objects since the extensions are effectively pre-parsed.
6891	 *
6892	 * The array is an array of objects with the following structure, where this
6893	 * base array represents the Api prototype base:
6894	 *
6895	 *     [
6896	 *       {
6897	 *         name:      'data'                -- string   - Property name
6898	 *         val:       function () {},       -- function - Api method (or undefined if just an object
6899	 *         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
6900	 *         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
6901	 *       },
6902	 *       {
6903	 *         name:     'row'
6904	 *         val:       {},
6905	 *         methodExt: [ ... ],
6906	 *         propExt:   [
6907	 *           {
6908	 *             name:      'data'
6909	 *             val:       function () {},
6910	 *             methodExt: [ ... ],
6911	 *             propExt:   [ ... ]
6912	 *           },
6913	 *           ...
6914	 *         ]
6915	 *       }
6916	 *     ]
6917	 *
6918	 * @type {Array}
6919	 * @ignore
6920	 */
6921	var __apiStruct = [];
6922	
6923	
6924	/**
6925	 * `Array.prototype` reference.
6926	 *
6927	 * @type object
6928	 * @ignore
6929	 */
6930	var __arrayProto = Array.prototype;
6931	
6932	
6933	/**
6934	 * Abstraction for `context` parameter of the `Api` constructor to allow it to
6935	 * take several different forms for ease of use.
6936	 *
6937	 * Each of the input parameter types will be converted to a DataTables settings
6938	 * object where possible.
6939	 *
6940	 * @param  {string|node|jQuery|object} mixed DataTable identifier. Can be one
6941	 *   of:
6942	 *
6943	 *   * `string` - jQuery selector. Any DataTables' matching the given selector
6944	 *     with be found and used.
6945	 *   * `node` - `TABLE` node which has already been formed into a DataTable.
6946	 *   * `jQuery` - A jQuery object of `TABLE` nodes.
6947	 *   * `object` - DataTables settings object
6948	 *   * `DataTables.Api` - API instance
6949	 * @return {array|null} Matching DataTables settings objects. `null` or
6950	 *   `undefined` is returned if no matching DataTable is found.
6951	 * @ignore
6952	 */
6953	var _toSettings = function ( mixed )
6954	{
6955		var idx, jq;
6956		var settings = DataTable.settings;
6957		var tables = $.map( settings, function (el, i) {
6958			return el.nTable;
6959		} );
6960	
6961		if ( ! mixed ) {
6962			return [];
6963		}
6964		else if ( mixed.nTable && mixed.oApi ) {
6965			// DataTables settings object
6966			return [ mixed ];
6967		}
6968		else if ( mixed.nodeName && mixed.nodeName.toLowerCase() === 'table' ) {
6969			// Table node
6970			idx = $.inArray( mixed, tables );
6971			return idx !== -1 ? [ settings[idx] ] : null;
6972		}
6973		else if ( mixed && typeof mixed.settings === 'function' ) {
6974			return mixed.settings().toArray();
6975		}
6976		else if ( typeof mixed === 'string' ) {
6977			// jQuery selector
6978			jq = $(mixed);
6979		}
6980		else if ( mixed instanceof $ ) {
6981			// jQuery object (also DataTables instance)
6982			jq = mixed;
6983		}
6984	
6985		if ( jq ) {
6986			return jq.map( function(i) {
6987				idx = $.inArray( this, tables );
6988				return idx !== -1 ? settings[idx] : null;
6989			} ).toArray();
6990		}
6991	};
6992	
6993	
6994	/**
6995	 * DataTables API class - used to control and interface with  one or more
6996	 * DataTables enhanced tables.
6997	 *
6998	 * The API class is heavily based on jQuery, presenting a chainable interface
6999	 * that you can use to interact with tables. Each instance of the API class has
7000	 * a "context" - i.e. the tables that it will operate on. This could be a single
7001	 * table, all tables on a page or a sub-set thereof.
7002	 *
7003	 * Additionally the API is designed to allow you to easily work with the data in
7004	 * the tables, retrieving and manipulating it as required. This is done by
7005	 * presenting the API class as an array like interface. The contents of the
7006	 * array depend upon the actions requested by each method (for example
7007	 * `rows().nodes()` will return an array of nodes, while `rows().data()` will
7008	 * return an array of objects or arrays depending upon your table's
7009	 * configuration). The API object has a number of array like methods (`push`,
7010	 * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`,
7011	 * `unique` etc) to assist your working with the data held in a table.
7012	 *
7013	 * Most methods (those which return an Api instance) are chainable, which means
7014	 * the return from a method call also has all of the methods available that the
7015	 * top level object had. For example, these two calls are equivalent:
7016	 *
7017	 *     // Not chained
7018	 *     api.row.add( {...} );
7019	 *     api.draw();
7020	 *
7021	 *     // Chained
7022	 *     api.row.add( {...} ).draw();
7023	 *
7024	 * @class DataTable.Api
7025	 * @param {array|object|string|jQuery} context DataTable identifier. This is
7026	 *   used to define which DataTables enhanced tables this API will operate on.
7027	 *   Can be one of:
7028	 *
7029	 *   * `string` - jQuery selector. Any DataTables' matching the given selector
7030	 *     with be found and used.
7031	 *   * `node` - `TABLE` node which has already been formed into a DataTable.
7032	 *   * `jQuery` - A jQuery object of `TABLE` nodes.
7033	 *   * `object` - DataTables settings object
7034	 * @param {array} [data] Data to initialise the Api instance with.
7035	 *
7036	 * @example
7037	 *   // Direct initialisation during DataTables construction
7038	 *   var api = $('#example').DataTable();
7039	 *
7040	 * @example
7041	 *   // Initialisation using a DataTables jQuery object
7042	 *   var api = $('#example').dataTable().api();
7043	 *
7044	 * @example
7045	 *   // Initialisation as a constructor
7046	 *   var api = new $.fn.DataTable.Api( 'table.dataTable' );
7047	 */
7048	_Api = function ( context, data )
7049	{
7050		if ( ! (this instanceof _Api) ) {
7051			return new _Api( context, data );
7052		}
7053	
7054		var settings = [];
7055		var ctxSettings = function ( o ) {
7056			var a = _toSettings( o );
7057			if ( a ) {
7058				settings.push.apply( settings, a );
7059			}
7060		};
7061	
7062		if ( Array.isArray( context ) ) {
7063			for ( var i=0, ien=context.length ; i<ien ; i++ ) {
7064				ctxSettings( context[i] );
7065			}
7066		}
7067		else {
7068			ctxSettings( context );
7069		}
7070	
7071		// Remove duplicates
7072		this.context = _unique( settings );
7073	
7074		// Initial data
7075		if ( data ) {
7076			$.merge( this, data );
7077		}
7078	
7079		// selector
7080		this.selector = {
7081			rows: null,
7082			cols: null,
7083			opts: null
7084		};
7085	
7086		_Api.extend( this, this, __apiStruct );
7087	};
7088	
7089	DataTable.Api = _Api;
7090	
7091	// Don't destroy the existing prototype, just extend it. Required for jQuery 2's
7092	// isPlainObject.
7093	$.extend( _Api.prototype, {
7094		any: function ()
7095		{
7096			return this.count() !== 0;
7097		},
7098	
7099	
7100		concat:  __arrayProto.concat,
7101	
7102	
7103		context: [], // array of table settings objects
7104	
7105	
7106		count: function ()
7107		{
7108			return this.flatten().length;
7109		},
7110	
7111	
7112		each: function ( fn )
7113		{
7114			for ( var i=0, ien=this.length ; i<ien; i++ ) {
7115				fn.call( this, this[i], i, this );
7116			}
7117	
7118			return this;
7119		},
7120	
7121	
7122		eq: function ( idx )
7123		{
7124			var ctx = this.context;
7125	
7126			return ctx.length > idx ?
7127				new _Api( ctx[idx], this[idx] ) :
7128				null;
7129		},
7130	
7131	
7132		filter: function ( fn )
7133		{
7134			var a = [];
7135	
7136			if ( __arrayProto.filter ) {
7137				a = __arrayProto.filter.call( this, fn, this );
7138			}
7139			else {
7140				// Compatibility for browsers without EMCA-252-5 (JS 1.6)
7141				for ( var i=0, ien=this.length ; i<ien ; i++ ) {
7142					if ( fn.call( this, this[i], i, this ) ) {
7143						a.push( this[i] );
7144					}
7145				}
7146			}
7147	
7148			return new _Api( this.context, a );
7149		},
7150	
7151	
7152		flatten: function ()
7153		{
7154			var a = [];
7155			return new _Api( this.context, a.concat.apply( a, this.toArray() ) );
7156		},
7157	
7158	
7159		join:    __arrayProto.join,
7160	
7161	
7162		indexOf: __arrayProto.indexOf || function (obj, start)
7163		{
7164			for ( var i=(start || 0), ien=this.length ; i<ien ; i++ ) {
7165				if ( this[i] === obj ) {
7166					return i;
7167				}
7168			}
7169			return -1;
7170		},
7171	
7172		iterator: function ( flatten, type, fn, alwaysNew ) {
7173			var
7174				a = [], ret,
7175				i, ien, j, jen,
7176				context = this.context,
7177				rows, items, item,
7178				selector = this.selector;
7179	
7180			// Argument shifting
7181			if ( typeof flatten === 'string' ) {
7182				alwaysNew = fn;
7183				fn = type;
7184				type = flatten;
7185				flatten = false;
7186			}
7187	
7188			for ( i=0, ien=context.length ; i<ien ; i++ ) {
7189				var apiInst = new _Api( context[i] );
7190	
7191				if ( type === 'table' ) {
7192					ret = fn.call( apiInst, context[i], i );
7193	
7194					if ( ret !== undefined ) {
7195						a.push( ret );
7196					}
7197				}
7198				else if ( type === 'columns' || type === 'rows' ) {
7199					// this has same length as context - one entry for each table
7200					ret = fn.call( apiInst, context[i], this[i], i );
7201	
7202					if ( ret !== undefined ) {
7203						a.push( ret );
7204					}
7205				}
7206				else if ( type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell' ) {
7207					// columns and rows share the same structure.
7208					// 'this' is an array of column indexes for each context
7209					items = this[i];
7210	
7211					if ( type === 'column-rows' ) {
7212						rows = _selector_row_indexes( context[i], selector.opts );
7213					}
7214	
7215					for ( j=0, jen=items.length ; j<jen ; j++ ) {
7216						item = items[j];
7217	
7218						if ( type === 'cell' ) {
7219							ret = fn.call( apiInst, context[i], item.row, item.column, i, j );
7220						}
7221						else {
7222							ret = fn.call( apiInst, context[i], item, i, j, rows );
7223						}
7224	
7225						if ( ret !== undefined ) {
7226							a.push( ret );
7227						}
7228					}
7229				}
7230			}
7231	
7232			if ( a.length || alwaysNew ) {
7233				var api = new _Api( context, flatten ? a.concat.apply( [], a ) : a );
7234				var apiSelector = api.selector;
7235				apiSelector.rows = selector.rows;
7236				apiSelector.cols = selector.cols;
7237				apiSelector.opts = selector.opts;
7238				return api;
7239			}
7240			return this;
7241		},
7242	
7243	
7244		lastIndexOf: __arrayProto.lastIndexOf || function (obj, start)
7245		{
7246			// Bit cheeky...
7247			return this.indexOf.apply( this.toArray.reverse(), arguments );
7248		},
7249	
7250	
7251		length:  0,
7252	
7253	
7254		map: function ( fn )
7255		{
7256			var a = [];
7257	
7258			if ( __arrayProto.map ) {
7259				a = __arrayProto.map.call( this, fn, this );
7260			}
7261			else {
7262				// Compatibility for browsers without EMCA-252-5 (JS 1.6)
7263				for ( var i=0, ien=this.length ; i<ien ; i++ ) {
7264					a.push( fn.call( this, this[i], i ) );
7265				}
7266			}
7267	
7268			return new _Api( this.context, a );
7269		},
7270	
7271	
7272		pluck: function ( prop )
7273		{
7274			var fn = DataTable.util.get(prop);
7275	
7276			return this.map( function ( el ) {
7277				return fn(el);
7278			} );
7279		},
7280	
7281		pop:     __arrayProto.pop,
7282	
7283	
7284		push:    __arrayProto.push,
7285	
7286	
7287		// Does not return an API instance
7288		reduce: __arrayProto.reduce || function ( fn, init )
7289		{
7290			return _fnReduce( this, fn, init, 0, this.length, 1 );
7291		},
7292	
7293	
7294		reduceRight: __arrayProto.reduceRight || function ( fn, init )
7295		{
7296			return _fnReduce( this, fn, init, this.length-1, -1, -1 );
7297		},
7298	
7299	
7300		reverse: __arrayProto.reverse,
7301	
7302	
7303		// Object with rows, columns and opts
7304		selector: null,
7305	
7306	
7307		shift:   __arrayProto.shift,
7308	
7309	
7310		slice: function () {
7311			return new _Api( this.context, this );
7312		},
7313	
7314	
7315		sort:    __arrayProto.sort, // ? name - order?
7316	
7317	
7318		splice:  __arrayProto.splice,
7319	
7320	
7321		toArray: function ()
7322		{
7323			return __arrayProto.slice.call( this );
7324		},
7325	
7326	
7327		to$: function ()
7328		{
7329			return $( this );
7330		},
7331	
7332	
7333		toJQuery: function ()
7334		{
7335			return $( this );
7336		},
7337	
7338	
7339		unique: function ()
7340		{
7341			return new _Api( this.context, _unique(this) );
7342		},
7343	
7344	
7345		unshift: __arrayProto.unshift
7346	} );
7347	
7348	
7349	_Api.extend = function ( scope, obj, ext )
7350	{
7351		// Only extend API instances and static properties of the API
7352		if ( ! ext.length || ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) {
7353			return;
7354		}
7355	
7356		var
7357			i, ien,
7358			struct,
7359			methodScoping = function ( scope, fn, struc ) {
7360				return function () {
7361					var ret = fn.apply( scope, arguments );
7362	
7363					// Method extension
7364					_Api.extend( ret, ret, struc.methodExt );
7365					return ret;
7366				};
7367			};
7368	
7369		for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7370			struct = ext[i];
7371	
7372			// Value
7373			obj[ struct.name ] = struct.type === 'function' ?
7374				methodScoping( scope, struct.val, struct ) :
7375				struct.type === 'object' ?
7376					{} :
7377					struct.val;
7378	
7379			obj[ struct.name ].__dt_wrapper = true;
7380	
7381			// Property extension
7382			_Api.extend( scope, obj[ struct.name ], struct.propExt );
7383		}
7384	};
7385	
7386	
7387	// @todo - Is there need for an augment function?
7388	// _Api.augment = function ( inst, name )
7389	// {
7390	// 	// Find src object in the structure from the name
7391	// 	var parts = name.split('.');
7392	
7393	// 	_Api.extend( inst, obj );
7394	// };
7395	
7396	
7397	//     [
7398	//       {
7399	//         name:      'data'                -- string   - Property name
7400	//         val:       function () {},       -- function - Api method (or undefined if just an object
7401	//         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
7402	//         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
7403	//       },
7404	//       {
7405	//         name:     'row'
7406	//         val:       {},
7407	//         methodExt: [ ... ],
7408	//         propExt:   [
7409	//           {
7410	//             name:      'data'
7411	//             val:       function () {},
7412	//             methodExt: [ ... ],
7413	//             propExt:   [ ... ]
7414	//           },
7415	//           ...
7416	//         ]
7417	//       }
7418	//     ]
7419	
7420	_Api.register = _api_register = function ( name, val )
7421	{
7422		if ( Array.isArray( name ) ) {
7423			for ( var j=0, jen=name.length ; j<jen ; j++ ) {
7424				_Api.register( name[j], val );
7425			}
7426			return;
7427		}
7428	
7429		var
7430			i, ien,
7431			heir = name.split('.'),
7432			struct = __apiStruct,
7433			key, method;
7434	
7435		var find = function ( src, name ) {
7436			for ( var i=0, ien=src.length ; i<ien ; i++ ) {
7437				if ( src[i].name === name ) {
7438					return src[i];
7439				}
7440			}
7441			return null;
7442		};
7443	
7444		for ( i=0, ien=heir.length ; i<ien ; i++ ) {
7445			method = heir[i].indexOf('()') !== -1;
7446			key = method ?
7447				heir[i].replace('()', '') :
7448				heir[i];
7449	
7450			var src = find( struct, key );
7451			if ( ! src ) {
7452				src = {
7453					name:      key,
7454					val:       {},
7455					methodExt: [],
7456					propExt:   [],
7457					type:      'object'
7458				};
7459				struct.push( src );
7460			}
7461	
7462			if ( i === ien-1 ) {
7463				src.val = val;
7464				src.type = typeof val === 'function' ?
7465					'function' :
7466					$.isPlainObject( val ) ?
7467						'object' :
7468						'other';
7469			}
7470			else {
7471				struct = method ?
7472					src.methodExt :
7473					src.propExt;
7474			}
7475		}
7476	};
7477	
7478	_Api.registerPlural = _api_registerPlural = function ( pluralName, singularName, val ) {
7479		_Api.register( pluralName, val );
7480	
7481		_Api.register( singularName, function () {
7482			var ret = val.apply( this, arguments );
7483	
7484			if ( ret === this ) {
7485				// Returned item is the API instance that was passed in, return it
7486				return this;
7487			}
7488			else if ( ret instanceof _Api ) {
7489				// New API instance returned, want the value from the first item
7490				// in the returned array for the singular result.
7491				return ret.length ?
7492					Array.isArray( ret[0] ) ?
7493						new _Api( ret.context, ret[0] ) : // Array results are 'enhanced'
7494						ret[0] :
7495					undefined;
7496			}
7497	
7498			// Non-API return - just fire it back
7499			return ret;
7500		} );
7501	};
7502	
7503	
7504	/**
7505	 * Selector for HTML tables. Apply the given selector to the give array of
7506	 * DataTables settings objects.
7507	 *
7508	 * @param {string|integer} [selector] jQuery selector string or integer
7509	 * @param  {array} Array of DataTables settings objects to be filtered
7510	 * @return {array}
7511	 * @ignore
7512	 */
7513	var __table_selector = function ( selector, a )
7514	{
7515		if ( Array.isArray(selector) ) {
7516			return $.map( selector, function (item) {
7517				return __table_selector(item, a);
7518			} );
7519		}
7520	
7521		// Integer is used to pick out a table by index
7522		if ( typeof selector === 'number' ) {
7523			return [ a[ selector ] ];
7524		}
7525	
7526		// Perform a jQuery selector on the table nodes
7527		var nodes = $.map( a, function (el, i) {
7528			return el.nTable;
7529		} );
7530	
7531		return $(nodes)
7532			.filter( selector )
7533			.map( function (i) {
7534				// Need to translate back from the table node to the settings
7535				var idx = $.inArray( this, nodes );
7536				return a[ idx ];
7537			} )
7538			.toArray();
7539	};
7540	
7541	
7542	
7543	/**
7544	 * Context selector for the API's context (i.e. the tables the API instance
7545	 * refers to.
7546	 *
7547	 * @name    DataTable.Api#tables
7548	 * @param {string|integer} [selector] Selector to pick which tables the iterator
7549	 *   should operate on. If not given, all tables in the current context are
7550	 *   used. This can be given as a jQuery selector (for example `':gt(0)'`) to
7551	 *   select multiple tables or as an integer to select a single table.
7552	 * @returns {DataTable.Api} Returns a new API instance if a selector is given.
7553	 */
7554	_api_register( 'tables()', function ( selector ) {
7555		// A new instance is created if there was a selector specified
7556		return selector !== undefined && selector !== null ?
7557			new _Api( __table_selector( selector, this.context ) ) :
7558			this;
7559	} );
7560	
7561	
7562	_api_register( 'table()', function ( selector ) {
7563		var tables = this.tables( selector );
7564		var ctx = tables.context;
7565	
7566		// Truncate to the first matched table
7567		return ctx.length ?
7568			new _Api( ctx[0] ) :
7569			tables;
7570	} );
7571	
7572	
7573	_api_registerPlural( 'tables().nodes()', 'table().node()' , function () {
7574		return this.iterator( 'table', function ( ctx ) {
7575			return ctx.nTable;
7576		}, 1 );
7577	} );
7578	
7579	
7580	_api_registerPlural( 'tables().body()', 'table().body()' , function () {
7581		return this.iterator( 'table', function ( ctx ) {
7582			return ctx.nTBody;
7583		}, 1 );
7584	} );
7585	
7586	
7587	_api_registerPlural( 'tables().header()', 'table().header()' , function () {
7588		return this.iterator( 'table', function ( ctx ) {
7589			return ctx.nTHead;
7590		}, 1 );
7591	} );
7592	
7593	
7594	_api_registerPlural( 'tables().footer()', 'table().footer()' , function () {
7595		return this.iterator( 'table', function ( ctx ) {
7596			return ctx.nTFoot;
7597		}, 1 );
7598	} );
7599	
7600	
7601	_api_registerPlural( 'tables().containers()', 'table().container()' , function () {
7602		return this.iterator( 'table', function ( ctx ) {
7603			return ctx.nTableWrapper;
7604		}, 1 );
7605	} );
7606	
7607	
7608	
7609	/**
7610	 * Redraw the tables in the current context.
7611	 */
7612	_api_register( 'draw()', function ( paging ) {
7613		return this.iterator( 'table', function ( settings ) {
7614			if ( paging === 'page' ) {
7615				_fnDraw( settings );
7616			}
7617			else {
7618				if ( typeof paging === 'string' ) {
7619					paging = paging === 'full-hold' ?
7620						false :
7621						true;
7622				}
7623	
7624				_fnReDraw( settings, paging===false );
7625			}
7626		} );
7627	} );
7628	
7629	
7630	
7631	/**
7632	 * Get the current page index.
7633	 *
7634	 * @return {integer} Current page index (zero based)
7635	 *//**
7636	 * Set the current page.
7637	 *
7638	 * Note that if you attempt to show a page which does not exist, DataTables will
7639	 * not throw an error, but rather reset the paging.
7640	 *
7641	 * @param {integer|string} action The paging action to take. This can be one of:
7642	 *  * `integer` - The page index to jump to
7643	 *  * `string` - An action to take:
7644	 *    * `first` - Jump to first page.
7645	 *    * `next` - Jump to the next page
7646	 *    * `previous` - Jump to previous page
7647	 *    * `last` - Jump to the last page.
7648	 * @returns {DataTables.Api} this
7649	 */
7650	_api_register( 'page()', function ( action ) {
7651		if ( action === undefined ) {
7652			return this.page.info().page; // not an expensive call
7653		}
7654	
7655		// else, have an action to take on all tables
7656		return this.iterator( 'table', function ( settings ) {
7657			_fnPageChange( settings, action );
7658		} );
7659	} );
7660	
7661	
7662	/**
7663	 * Paging information for the first table in the current context.
7664	 *
7665	 * If you require paging information for another table, use the `table()` method
7666	 * with a suitable selector.
7667	 *
7668	 * @return {object} Object with the following properties set:
7669	 *  * `page` - Current page index (zero based - i.e. the first page is `0`)
7670	 *  * `pages` - Total number of pages
7671	 *  * `start` - Display index for the first record shown on the current page
7672	 *  * `end` - Display index for the last record shown on the current page
7673	 *  * `length` - Display length (number of records). Note that generally `start
7674	 *    + length = end`, but this is not always true, for example if there are
7675	 *    only 2 records to show on the final page, with a length of 10.
7676	 *  * `recordsTotal` - Full data set length
7677	 *  * `recordsDisplay` - Data set length once the current filtering criterion
7678	 *    are applied.
7679	 */
7680	_api_register( 'page.info()', function ( action ) {
7681		if ( this.context.length === 0 ) {
7682			return undefined;
7683		}
7684	
7685		var
7686			settings   = this.context[0],
7687			start      = settings._iDisplayStart,
7688			len        = settings.oFeatures.bPaginate ? settings._iDisplayLength : -1,
7689			visRecords = settings.fnRecordsDisplay(),
7690			all        = len === -1;
7691	
7692		return {
7693			"page":           all ? 0 : Math.floor( start / len ),
7694			"pages":          all ? 1 : Math.ceil( visRecords / len ),
7695			"start":          start,
7696			"end":            settings.fnDisplayEnd(),
7697			"length":         len,
7698			"recordsTotal":   settings.fnRecordsTotal(),
7699			"recordsDisplay": visRecords,
7700			"serverSide":     _fnDataSource( settings ) === 'ssp'
7701		};
7702	} );
7703	
7704	
7705	/**
7706	 * Get the current page length.
7707	 *
7708	 * @return {integer} Current page length. Note `-1` indicates that all records
7709	 *   are to be shown.
7710	 *//**
7711	 * Set the current page length.
7712	 *
7713	 * @param {integer} Page length to set. Use `-1` to show all records.
7714	 * @returns {DataTables.Api} this
7715	 */
7716	_api_register( 'page.len()', function ( len ) {
7717		// Note that we can't call this function 'length()' because `length`
7718		// is a Javascript property of functions which defines how many arguments
7719		// the function expects.
7720		if ( len === undefined ) {
7721			return this.context.length !== 0 ?
7722				this.context[0]._iDisplayLength :
7723				undefined;
7724		}
7725	
7726		// else, set the page length
7727		return this.iterator( 'table', function ( settings ) {
7728			_fnLengthChange( settings, len );
7729		} );
7730	} );
7731	
7732	
7733	
7734	var __reload = function ( settings, holdPosition, callback ) {
7735		// Use the draw event to trigger a callback
7736		if ( callback ) {
7737			var api = new _Api( settings );
7738	
7739			api.one( 'draw', function () {
7740				callback( api.ajax.json() );
7741			} );
7742		}
7743	
7744		if ( _fnDataSource( settings ) == 'ssp' ) {
7745			_fnReDraw( settings, holdPosition );
7746		}
7747		else {
7748			_fnProcessingDisplay( settings, true );
7749	
7750			// Cancel an existing request
7751			var xhr = settings.jqXHR;
7752			if ( xhr && xhr.readyState !== 4 ) {
7753				xhr.abort();
7754			}
7755	
7756			// Trigger xhr
7757			_fnBuildAjax( settings, [], function( json ) {
7758				_fnClearTable( settings );
7759	
7760				var data = _fnAjaxDataSrc( settings, json );
7761				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7762					_fnAddData( settings, data[i] );
7763				}
7764	
7765				_fnReDraw( settings, holdPosition );
7766				_fnProcessingDisplay( settings, false );
7767			} );
7768		}
7769	};
7770	
7771	
7772	/**
7773	 * Get the JSON response from the last Ajax request that DataTables made to the
7774	 * server. Note that this returns the JSON from the first table in the current
7775	 * context.
7776	 *
7777	 * @return {object} JSON received from the server.
7778	 */
7779	_api_register( 'ajax.json()', function () {
7780		var ctx = this.context;
7781	
7782		if ( ctx.length > 0 ) {
7783			return ctx[0].json;
7784		}
7785	
7786		// else return undefined;
7787	} );
7788	
7789	
7790	/**
7791	 * Get the data submitted in the last Ajax request
7792	 */
7793	_api_register( 'ajax.params()', function () {
7794		var ctx = this.context;
7795	
7796		if ( ctx.length > 0 ) {
7797			return ctx[0].oAjaxData;
7798		}
7799	
7800		// else return undefined;
7801	} );
7802	
7803	
7804	/**
7805	 * Reload tables from the Ajax data source. Note that this function will
7806	 * automatically re-draw the table when the remote data has been loaded.
7807	 *
7808	 * @param {boolean} [reset=true] Reset (default) or hold the current paging
7809	 *   position. A full re-sort and re-filter is performed when this method is
7810	 *   called, which is why the pagination reset is the default action.
7811	 * @returns {DataTables.Api} this
7812	 */
7813	_api_register( 'ajax.reload()', function ( callback, resetPaging ) {
7814		return this.iterator( 'table', function (settings) {
7815			__reload( settings, resetPaging===false, callback );
7816		} );
7817	} );
7818	
7819	
7820	/**
7821	 * Get the current Ajax URL. Note that this returns the URL from the first
7822	 * table in the current context.
7823	 *
7824	 * @return {string} Current Ajax source URL
7825	 *//**
7826	 * Set the Ajax URL. Note that this will set the URL for all tables in the
7827	 * current context.
7828	 *
7829	 * @param {string} url URL to set.
7830	 * @returns {DataTables.Api} this
7831	 */
7832	_api_register( 'ajax.url()', function ( url ) {
7833		var ctx = this.context;
7834	
7835		if ( url === undefined ) {
7836			// get
7837			if ( ctx.length === 0 ) {
7838				return undefined;
7839			}
7840			ctx = ctx[0];
7841	
7842			return ctx.ajax ?
7843				$.isPlainObject( ctx.ajax ) ?
7844					ctx.ajax.url :
7845					ctx.ajax :
7846				ctx.sAjaxSource;
7847		}
7848	
7849		// set
7850		return this.iterator( 'table', function ( settings ) {
7851			if ( $.isPlainObject( settings.ajax ) ) {
7852				settings.ajax.url = url;
7853			}
7854			else {
7855				settings.ajax = url;
7856			}
7857			// No need to consider sAjaxSource here since DataTables gives priority
7858			// to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any
7859			// value of `sAjaxSource` redundant.
7860		} );
7861	} );
7862	
7863	
7864	/**
7865	 * Load data from the newly set Ajax URL. Note that this method is only
7866	 * available when `ajax.url()` is used to set a URL. Additionally, this method
7867	 * has the same effect as calling `ajax.reload()` but is provided for
7868	 * convenience when setting a new URL. Like `ajax.reload()` it will
7869	 * automatically redraw the table once the remote data has been loaded.
7870	 *
7871	 * @returns {DataTables.Api} this
7872	 */
7873	_api_register( 'ajax.url().load()', function ( callback, resetPaging ) {
7874		// Same as a reload, but makes sense to present it for easy access after a
7875		// url change
7876		return this.iterator( 'table', function ( ctx ) {
7877			__reload( ctx, resetPaging===false, callback );
7878		} );
7879	} );
7880	
7881	
7882	
7883	
7884	var _selector_run = function ( type, selector, selectFn, settings, opts )
7885	{
7886		var
7887			out = [], res,
7888			a, i, ien, j, jen,
7889			selectorType = typeof selector;
7890	
7891		// Can't just check for isArray here, as an API or jQuery instance might be
7892		// given with their array like look
7893		if ( ! selector || selectorType === 'string' || selectorType === 'function' || selector.length === undefined ) {
7894			selector = [ selector ];
7895		}
7896	
7897		for ( i=0, ien=selector.length ; i<ien ; i++ ) {
7898			// Only split on simple strings - complex expressions will be jQuery selectors
7899			a = selector[i] && selector[i].split && ! selector[i].match(/[\[\(:]/) ?
7900				selector[i].split(',') :
7901				[ selector[i] ];
7902	
7903			for ( j=0, jen=a.length ; j<jen ; j++ ) {
7904				res = selectFn( typeof a[j] === 'string' ? (a[j]).trim() : a[j] );
7905	
7906				if ( res && res.length ) {
7907					out = out.concat( res );
7908				}
7909			}
7910		}
7911	
7912		// selector extensions
7913		var ext = _ext.selector[ type ];
7914		if ( ext.length ) {
7915			for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7916				out = ext[i]( settings, opts, out );
7917			}
7918		}
7919	
7920		return _unique( out );
7921	};
7922	
7923	
7924	var _selector_opts = function ( opts )
7925	{
7926		if ( ! opts ) {
7927			opts = {};
7928		}
7929	
7930		// Backwards compatibility for 1.9- which used the terminology filter rather
7931		// than search
7932		if ( opts.filter && opts.search === undefined ) {
7933			opts.search = opts.filter;
7934		}
7935	
7936		return $.extend( {
7937			search: 'none',
7938			order: 'current',
7939			page: 'all'
7940		}, opts );
7941	};
7942	
7943	
7944	var _selector_first = function ( inst )
7945	{
7946		// Reduce the API instance to the first item found
7947		for ( var i=0, ien=inst.length ; i<ien ; i++ ) {
7948			if ( inst[i].length > 0 ) {
7949				// Assign the first element to the first item in the instance
7950				// and truncate the instance and context
7951				inst[0] = inst[i];
7952				inst[0].length = 1;
7953				inst.length = 1;
7954				inst.context = [ inst.context[i] ];
7955	
7956				return inst;
7957			}
7958		}
7959	
7960		// Not found - return an empty instance
7961		inst.length = 0;
7962		return inst;
7963	};
7964	
7965	
7966	var _selector_row_indexes = function ( settings, opts )
7967	{
7968		var
7969			i, ien, tmp, a=[],
7970			displayFiltered = settings.aiDisplay,
7971			displayMaster = settings.aiDisplayMaster;
7972	
7973		var
7974			search = opts.search,  // none, applied, removed
7975			order  = opts.order,   // applied, current, index (original - compatibility with 1.9)
7976			page   = opts.page;    // all, current
7977	
7978		if ( _fnDataSource( settings ) == 'ssp' ) {
7979			// In server-side processing mode, most options are irrelevant since
7980			// rows not shown don't exist and the index order is the applied order
7981			// Removed is a special case - for consistency just return an empty
7982			// array
7983			return search === 'removed' ?
7984				[] :
7985				_range( 0, displayMaster.length );
7986		}
7987		else if ( page == 'current' ) {
7988			// Current page implies that order=current and filter=applied, since it is
7989			// fairly senseless otherwise, regardless of what order and search actually
7990			// are
7991			for ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i<ien ; i++ ) {
7992				a.push( displayFiltered[i] );
7993			}
7994		}
7995		else if ( order == 'current' || order == 'applied' ) {
7996			if ( search == 'none') {
7997				a = displayMaster.slice();
7998			}
7999			else if ( search == 'applied' ) {
8000				a = displayFiltered.slice();
8001			}
8002			else if ( search == 'removed' ) {
8003				// O(n+m) solution by creating a hash map
8004				var displayFilteredMap = {};
8005	
8006				for ( var i=0, ien=displayFiltered.length ; i<ien ; i++ ) {
8007					displayFilteredMap[displayFiltered[i]] = null;
8008				}
8009	
8010				a = $.map( displayMaster, function (el) {
8011					return ! displayFilteredMap.hasOwnProperty(el) ?
8012						el :
8013						null;
8014				} );
8015			}
8016		}
8017		else if ( order == 'index' || order == 'original' ) {
8018			for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
8019				if ( search == 'none' ) {
8020					a.push( i );
8021				}
8022				else { // applied | removed
8023					tmp = $.inArray( i, displayFiltered );
8024	
8025					if ((tmp === -1 && search == 'removed') ||
8026						(tmp >= 0   && search == 'applied') )
8027					{
8028						a.push( i );
8029					}
8030				}
8031			}
8032		}
8033	
8034		return a;
8035	};
8036	
8037	
8038	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
8039	 * Rows
8040	 *
8041	 * {}          - no selector - use all available rows
8042	 * {integer}   - row aoData index
8043	 * {node}      - TR node
8044	 * {string}    - jQuery selector to apply to the TR elements
8045	 * {array}     - jQuery array of nodes, or simply an array of TR nodes
8046	 *
8047	 */
8048	var __row_selector = function ( settings, selector, opts )
8049	{
8050		var rows;
8051		var run = function ( sel ) {
8052			var selInt = _intVal( sel );
8053			var i, ien;
8054			var aoData = settings.aoData;
8055	
8056			// Short cut - selector is a number and no options provided (default is
8057			// all records, so no need to check if the index is in there, since it
8058			// must be - dev error if the index doesn't exist).
8059			if ( selInt !== null && ! opts ) {
8060				return [ selInt ];
8061			}
8062	
8063			if ( ! rows ) {
8064				rows = _selector_row_indexes( settings, opts );
8065			}
8066	
8067			if ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) {
8068				// Selector - integer
8069				return [ selInt ];
8070			}
8071			else if ( sel === null || sel === undefined || sel === '' ) {
8072				// Selector - none
8073				return rows;
8074			}
8075	
8076			// Selector - function
8077			if ( typeof sel === 'function' ) {
8078				return $.map( rows, function (idx) {
8079					var row = aoData[ idx ];
8080					return sel( idx, row._aData, row.nTr ) ? idx : null;
8081				} );
8082			}
8083	
8084			// Selector - node
8085			if ( sel.nodeName ) {
8086				var rowIdx = sel._DT_RowIndex;  // Property added by DT for fast lookup
8087				var cellIdx = sel._DT_CellIndex;
8088	
8089				if ( rowIdx !== undefined ) {
8090					// Make sure that the row is actually still present in the table
8091					return aoData[ rowIdx ] && aoData[ rowIdx ].nTr === sel ?
8092						[ rowIdx ] :
8093						[];
8094				}
8095				else if ( cellIdx ) {
8096					return aoData[ cellIdx.row ] && aoData[ cellIdx.row ].nTr === sel.parentNode ?
8097						[ cellIdx.row ] :
8098						[];
8099				}
8100				else {
8101					var host = $(sel).closest('*[data-dt-row]');
8102					return host.length ?
8103						[ host.data('dt-row') ] :
8104						[];
8105				}
8106			}
8107	
8108			// ID selector. Want to always be able to select rows by id, regardless
8109			// of if the tr element has been created or not, so can't rely upon
8110			// jQuery here - hence a custom implementation. This does not match
8111			// Sizzle's fast selector or HTML4 - in HTML5 the ID can be anything,
8112			// but to select it using a CSS selector engine (like Sizzle or
8113			// querySelect) it would need to need to be escaped for some characters.
8114			// DataTables simplifies this for row selectors since you can select
8115			// only a row. A # indicates an id any anything that follows is the id -
8116			// unescaped.
8117			if ( typeof sel === 'string' && sel.charAt(0) === '#' ) {
8118				// get row index from id
8119				var rowObj = settings.aIds[ sel.replace( /^#/, '' ) ];
8120				if ( rowObj !== undefined ) {
8121					return [ rowObj.idx ];
8122				}
8123	
8124				// need to fall through to jQuery in case there is DOM id that
8125				// matches
8126			}
8127			
8128			// Get nodes in the order from the `rows` array with null values removed
8129			var nodes = _removeEmpty(
8130				_pluck_order( settings.aoData, rows, 'nTr' )
8131			);
8132	
8133			// Selector - jQuery selector string, array of nodes or jQuery object/
8134			// As jQuery's .filter() allows jQuery objects to be passed in filter,
8135			// it also allows arrays, so this will cope with all three options
8136			return $(nodes)
8137				.filter( sel )
8138				.map( function () {
8139					return this._DT_RowIndex;
8140				} )
8141				.toArray();
8142		};
8143	
8144		return _selector_run( 'row', selector, run, settings, opts );
8145	};
8146	
8147	
8148	_api_register( 'rows()', function ( selector, opts ) {
8149		// argument shifting
8150		if ( selector === undefined ) {
8151			selector = '';
8152		}
8153		else if ( $.isPlainObject( selector ) ) {
8154			opts = selector;
8155			selector = '';
8156		}
8157	
8158		opts = _selector_opts( opts );
8159	
8160		var inst = this.iterator( 'table', function ( settings ) {
8161			return __row_selector( settings, selector, opts );
8162		}, 1 );
8163	
8164		// Want argument shifting here and in __row_selector?
8165		inst.selector.rows = selector;
8166		inst.selector.opts = opts;
8167	
8168		return inst;
8169	} );
8170	
8171	_api_register( 'rows().nodes()', function () {
8172		return this.iterator( 'row', function ( settings, row ) {
8173			return settings.aoData[ row ].nTr || undefined;
8174		}, 1 );
8175	} );
8176	
8177	_api_register( 'rows().data()', function () {
8178		return this.iterator( true, 'rows', function ( settings, rows ) {
8179			return _pluck_order( settings.aoData, rows, '_aData' );
8180		}, 1 );
8181	} );
8182	
8183	_api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) {
8184		return this.iterator( 'row', function ( settings, row ) {
8185			var r = settings.aoData[ row ];
8186			return type === 'search' ? r._aFilterData : r._aSortData;
8187		}, 1 );
8188	} );
8189	
8190	_api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) {
8191		return this.iterator( 'row', function ( settings, row ) {
8192			_fnInvalidate( settings, row, src );
8193		} );
8194	} );
8195	
8196	_api_registerPlural( 'rows().indexes()', 'row().index()', function () {
8197		return this.iterator( 'row', function ( settings, row ) {
8198			return row;
8199		}, 1 );
8200	} );
8201	
8202	_api_registerPlural( 'rows().ids()', 'row().id()', function ( hash ) {
8203		var a = [];
8204		var context = this.context;
8205	
8206		// `iterator` will drop undefined values, but in this case we want them
8207		for ( var i=0, ien=context.length ; i<ien ; i++ ) {
8208			for ( var j=0, jen=this[i].length ; j<jen ; j++ ) {
8209				var id = context[i].rowIdFn( context[i].aoData[ this[i][j] ]._aData );
8210				a.push( (hash === true ? '#' : '' )+ id );
8211			}
8212		}
8213	
8214		return new _Api( context, a );
8215	} );
8216	
8217	_api_registerPlural( 'rows().remove()', 'row().remove()', function () {
8218		var that = this;
8219	
8220		this.iterator( 'row', function ( settings, row, thatIdx ) {
8221			var data = settings.aoData;
8222			var rowData = data[ row ];
8223			var i, ien, j, jen;
8224			var loopRow, loopCells;
8225	
8226			data.splice( row, 1 );
8227	
8228			// Update the cached indexes
8229			for ( i=0, ien=data.length ; i<ien ; i++ ) {
8230				loopRow = data[i];
8231				loopCells = loopRow.anCells;
8232	
8233				// Rows
8234				if ( loopRow.nTr !== null ) {
8235					loopRow.nTr._DT_RowIndex = i;
8236				}
8237	
8238				// Cells
8239				if ( loopCells !== null ) {
8240					for ( j=0, jen=loopCells.length ; j<jen ; j++ ) {
8241						loopCells[j]._DT_CellIndex.row = i;
8242					}
8243				}
8244			}
8245	
8246			// Delete from the display arrays
8247			_fnDeleteIndex( settings.aiDisplayMaster, row );
8248			_fnDeleteIndex( settings.aiDisplay, row );
8249			_fnDeleteIndex( that[ thatIdx ], row, false ); // maintain local indexes
8250	
8251			// For server-side processing tables - subtract the deleted row from the count
8252			if ( settings._iRecordsDisplay > 0 ) {
8253				settings._iRecordsDisplay--;
8254			}
8255	
8256			// Check for an 'overflow' they case for displaying the table
8257			_fnLengthOverflow( settings );
8258	
8259			// Remove the row's ID reference if there is one
8260			var id = settings.rowIdFn( rowData._aData );
8261			if ( id !== undefined ) {
8262				delete settings.aIds[ id ];
8263			}
8264		} );
8265	
8266		this.iterator( 'table', function ( settings ) {
8267			for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
8268				settings.aoData[i].idx = i;
8269			}
8270		} );
8271	
8272		return this;
8273	} );
8274	
8275	
8276	_api_register( 'rows.add()', function ( rows ) {
8277		var newRows = this.iterator( 'table', function ( settings ) {
8278				var row, i, ien;
8279				var out = [];
8280	
8281				for ( i=0, ien=rows.length ; i<ien ; i++ ) {
8282					row = rows[i];
8283	
8284					if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
8285						out.push( _fnAddTr( settings, row )[0] );
8286					}
8287					else {
8288						out.push( _fnAddData( settings, row ) );
8289					}
8290				}
8291	
8292				return out;
8293			}, 1 );
8294	
8295		// Return an Api.rows() extended instance, so rows().nodes() etc can be used
8296		var modRows = this.rows( -1 );
8297		modRows.pop();
8298		$.merge( modRows, newRows );
8299	
8300		return modRows;
8301	} );
8302	
8303	
8304	
8305	
8306	
8307	/**
8308	 *
8309	 */
8310	_api_register( 'row()', function ( selector, opts ) {
8311		return _selector_first( this.rows( selector, opts ) );
8312	} );
8313	
8314	
8315	_api_register( 'row().data()', function ( data ) {
8316		var ctx = this.context;
8317	
8318		if ( data === undefined ) {
8319			// Get
8320			return ctx.length && this.length ?
8321				ctx[0].aoData[ this[0] ]._aData :
8322				undefined;
8323		}
8324	
8325		// Set
8326		var row = ctx[0].aoData[ this[0] ];
8327		row._aData = data;
8328	
8329		// If the DOM has an id, and the data source is an array
8330		if ( Array.isArray( data ) && row.nTr && row.nTr.id ) {
8331			_fnSetObjectDataFn( ctx[0].rowId )( data, row.nTr.id );
8332		}
8333	
8334		// Automatically invalidate
8335		_fnInvalidate( ctx[0], this[0], 'data' );
8336	
8337		return this;
8338	} );
8339	
8340	
8341	_api_register( 'row().node()', function () {
8342		var ctx = this.context;
8343	
8344		return ctx.length && this.length ?
8345			ctx[0].aoData[ this[0] ].nTr || null :
8346			null;
8347	} );
8348	
8349	
8350	_api_register( 'row.add()', function ( row ) {
8351		// Allow a jQuery object to be passed in - only a single row is added from
8352		// it though - the first element in the set
8353		if ( row instanceof $ && row.length ) {
8354			row = row[0];
8355		}
8356	
8357		var rows = this.iterator( 'table', function ( settings ) {
8358			if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
8359				return _fnAddTr( settings, row )[0];
8360			}
8361			return _fnAddData( settings, row );
8362		} );
8363	
8364		// Return an Api.rows() extended instance, with the newly added row selected
8365		return this.row( rows[0] );
8366	} );
8367	
8368	
8369	$(document).on('plugin-init.dt', function (e, context) {
8370		var api = new _Api( context );
8371		var namespace = 'on-plugin-init';
8372		var stateSaveParamsEvent = 'stateSaveParams.' + namespace;
8373		var destroyEvent = 'destroy. ' + namespace;
8374	
8375		api.on( stateSaveParamsEvent, function ( e, settings, d ) {
8376			// This could be more compact with the API, but it is a lot faster as a simple
8377			// internal loop
8378			var idFn = settings.rowIdFn;
8379			var data = settings.aoData;
8380			var ids = [];
8381	
8382			for (var i=0 ; i<data.length ; i++) {
8383				if (data[i]._detailsShow) {
8384					ids.push( '#' + idFn(data[i]._aData) );
8385				}
8386			}
8387	
8388			d.childRows = ids;
8389		});
8390	
8391		api.on( destroyEvent, function () {
8392			api.off(stateSaveParamsEvent + ' ' + destroyEvent);
8393		});
8394	
8395		var loaded = api.state.loaded();
8396	
8397		if ( loaded && loaded.childRows ) {
8398			api
8399				.rows( $.map(loaded.childRows, function (id){
8400					return id.replace(/:/g, '\\:')
8401				}) )
8402				.every( function () {
8403					_fnCallbackFire( context, null, 'requestChild', [ this ] )
8404				});
8405		}
8406	});
8407	
8408	var __details_add = function ( ctx, row, data, klass )
8409	{
8410		// Convert to array of TR elements
8411		var rows = [];
8412		var addRow = function ( r, k ) {
8413			// Recursion to allow for arrays of jQuery objects
8414			if ( Array.isArray( r ) || r instanceof $ ) {
8415				for ( var i=0, ien=r.length ; i<ien ; i++ ) {
8416					addRow( r[i], k );
8417				}
8418				return;
8419			}
8420	
8421			// If we get a TR element, then just add it directly - up to the dev
8422			// to add the correct number of columns etc
8423			if ( r.nodeName && r.nodeName.toLowerCase() === 'tr' ) {
8424				rows.push( r );
8425			}
8426			else {
8427				// Otherwise create a row with a wrapper
8428				var created = $('<tr><td></td></tr>').addClass( k );
8429				$('td', created)
8430					.addClass( k )
8431					.html( r )
8432					[0].colSpan = _fnVisbleColumns( ctx );
8433	
8434				rows.push( created[0] );
8435			}
8436		};
8437	
8438		addRow( data, klass );
8439	
8440		if ( row._details ) {
8441			row._details.detach();
8442		}
8443	
8444		row._details = $(rows);
8445	
8446		// If the children were already shown, that state should be retained
8447		if ( row._detailsShow ) {
8448			row._details.insertAfter( row.nTr );
8449		}
8450	};
8451	
8452	
8453	// Make state saving of child row details async to allow them to be batch processed
8454	var __details_state = DataTable.util.throttle(
8455		function (ctx) {
8456			_fnSaveState( ctx[0] )
8457		},
8458		500
8459	);
8460	
8461	
8462	var __details_remove = function ( api, idx )
8463	{
8464		var ctx = api.context;
8465	
8466		if ( ctx.length ) {
8467			var row = ctx[0].aoData[ idx !== undefined ? idx : api[0] ];
8468	
8469			if ( row && row._details ) {
8470				row._details.remove();
8471	
8472				row._detailsShow = undefined;
8473				row._details = undefined;
8474				$( row.nTr ).removeClass( 'dt-hasChild' );
8475				__details_state( ctx );
8476			}
8477		}
8478	};
8479	
8480	
8481	var __details_display = function ( api, show ) {
8482		var ctx = api.context;
8483	
8484		if ( ctx.length && api.length ) {
8485			var row = ctx[0].aoData[ api[0] ];
8486	
8487			if ( row._details ) {
8488				row._detailsShow = show;
8489	
8490				if ( show ) {
8491					row._details.insertAfter( row.nTr );
8492					$( row.nTr ).addClass( 'dt-hasChild' );
8493				}
8494				else {
8495					row._details.detach();
8496					$( row.nTr ).removeClass( 'dt-hasChild' );
8497				}
8498	
8499				_fnCallbackFire( ctx[0], null, 'childRow', [ show, api.row( api[0] ) ] )
8500	
8501				__details_events( ctx[0] );
8502				__details_state( ctx );
8503			}
8504		}
8505	};
8506	
8507	
8508	var __details_events = function ( settings )
8509	{
8510		var api = new _Api( settings );
8511		var namespace = '.dt.DT_details';
8512		var drawEvent = 'draw'+namespace;
8513		var colvisEvent = 'column-sizing'+namespace;
8514		var destroyEvent = 'destroy'+namespace;
8515		var data = settings.aoData;
8516	
8517		api.off( drawEvent +' '+ colvisEvent +' '+ destroyEvent );
8518	
8519		if ( _pluck( data, '_details' ).length > 0 ) {
8520			// On each draw, insert the required elements into the document
8521			api.on( drawEvent, function ( e, ctx ) {
8522				if ( settings !== ctx ) {
8523					return;
8524				}
8525	
8526				api.rows( {page:'current'} ).eq(0).each( function (idx) {
8527					// Internal data grab
8528					var row = data[ idx ];
8529	
8530					if ( row._detailsShow ) {
8531						row._details.insertAfter( row.nTr );
8532					}
8533				} );
8534			} );
8535	
8536			// Column visibility change - update the colspan
8537			api.on( colvisEvent, function ( e, ctx, idx, vis ) {
8538				if ( settings !== ctx ) {
8539					return;
8540				}
8541	
8542				// Update the colspan for the details rows (note, only if it already has
8543				// a colspan)
8544				var row, visible = _fnVisbleColumns( ctx );
8545	
8546				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
8547					row = data[i];
8548	
8549					if ( row._details ) {
8550						row._details.children('td[colspan]').attr('colspan', visible );
8551					}
8552				}
8553			} );
8554	
8555			// Table destroyed - nuke any child rows
8556			api.on( destroyEvent, function ( e, ctx ) {
8557				if ( settings !== ctx ) {
8558					return;
8559				}
8560	
8561				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
8562					if ( data[i]._details ) {
8563						__details_remove( api, i );
8564					}
8565				}
8566			} );
8567		}
8568	};
8569	
8570	// Strings for the method names to help minification
8571	var _emp = '';
8572	var _child_obj = _emp+'row().child';
8573	var _child_mth = _child_obj+'()';
8574	
8575	// data can be:
8576	//  tr
8577	//  string
8578	//  jQuery or array of any of the above
8579	_api_register( _child_mth, function ( data, klass ) {
8580		var ctx = this.context;
8581	
8582		if ( data === undefined ) {
8583			// get
8584			return ctx.length && this.length ?
8585				ctx[0].aoData[ this[0] ]._details :
8586				undefined;
8587		}
8588		else if ( data === true ) {
8589			// show
8590			this.child.show();
8591		}
8592		else if ( data === false ) {
8593			// remove
8594			__details_remove( this );
8595		}
8596		else if ( ctx.length && this.length ) {
8597			// set
8598			__details_add( ctx[0], ctx[0].aoData[ this[0] ], data, klass );
8599		}
8600	
8601		return this;
8602	} );
8603	
8604	
8605	_api_register( [
8606		_child_obj+'.show()',
8607		_child_mth+'.show()' // only when `child()` was called with parameters (without
8608	], function ( show ) {   // it returns an object and this method is not executed)
8609		__details_display( this, true );
8610		return this;
8611	} );
8612	
8613	
8614	_api_register( [
8615		_child_obj+'.hide()',
8616		_child_mth+'.hide()' // only when `child()` was called with parameters (without
8617	], function () {         // it returns an object and this method is not executed)
8618		__details_display( this, false );
8619		return this;
8620	} );
8621	
8622	
8623	_api_register( [
8624		_child_obj+'.remove()',
8625		_child_mth+'.remove()' // only when `child()` was called with parameters (without
8626	], function () {           // it returns an object and this method is not executed)
8627		__details_remove( this );
8628		return this;
8629	} );
8630	
8631	
8632	_api_register( _child_obj+'.isShown()', function () {
8633		var ctx = this.context;
8634	
8635		if ( ctx.length && this.length ) {
8636			// _detailsShown as false or undefined will fall through to return false
8637			return ctx[0].aoData[ this[0] ]._detailsShow || false;
8638		}
8639		return false;
8640	} );
8641	
8642	
8643	
8644	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
8645	 * Columns
8646	 *
8647	 * {integer}           - column index (>=0 count from left, <0 count from right)
8648	 * "{integer}:visIdx"  - visible column index (i.e. translate to column index)  (>=0 count from left, <0 count from right)
8649	 * "{integer}:visible" - alias for {integer}:visIdx  (>=0 count from left, <0 count from right)
8650	 * "{string}:name"     - column name
8651	 * "{string}"          - jQuery selector on column header nodes
8652	 *
8653	 */
8654	
8655	// can be an array of these items, comma separated list, or an array of comma
8656	// separated lists
8657	
8658	var __re_column_selector = /^([^:]+):(name|visIdx|visible)$/;
8659	
8660	
8661	// r1 and r2 are redundant - but it means that the parameters match for the
8662	// iterator callback in columns().data()
8663	var __columnData = function ( settings, column, r1, r2, rows ) {
8664		var a = [];
8665		for ( var row=0, ien=rows.length ; row<ien ; row++ ) {
8666			a.push( _fnGetCellData( settings, rows[row], column ) );
8667		}
8668		return a;
8669	};
8670	
8671	
8672	var __column_selector = function ( settings, selector, opts )
8673	{
8674		var
8675			columns = settings.aoColumns,
8676			names = _pluck( columns, 'sName' ),
8677			nodes = _pluck( columns, 'nTh' );
8678	
8679		var run = function ( s ) {
8680			var selInt = _intVal( s );
8681	
8682			// Selector - all
8683			if ( s === '' ) {
8684				return _range( columns.length );
8685			}
8686	
8687			// Selector - index
8688			if ( selInt !== null ) {
8689				return [ selInt >= 0 ?
8690					selInt : // Count from left
8691					columns.length + selInt // Count from right (+ because its a negative value)
8692				];
8693			}
8694	
8695			// Selector = function
8696			if ( typeof s === 'function' ) {
8697				var rows = _selector_row_indexes( settings, opts );
8698	
8699				return $.map( columns, function (col, idx) {
8700					return s(
8701							idx,
8702							__columnData( settings, idx, 0, 0, rows ),
8703							nodes[ idx ]
8704						) ? idx : null;
8705				} );
8706			}
8707	
8708			// jQuery or string selector
8709			var match = typeof s === 'string' ?
8710				s.match( __re_column_selector ) :
8711				'';
8712	
8713			if ( match ) {
8714				switch( match[2] ) {
8715					case 'visIdx':
8716					case 'visible':
8717						var idx = parseInt( match[1], 10 );
8718						// Visible index given, convert to column index
8719						if ( idx < 0 ) {
8720							// Counting from the right
8721							var visColumns = $.map( columns, function (col,i) {
8722								return col.bVisible ? i : null;
8723							} );
8724							return [ visColumns[ visColumns.length + idx ] ];
8725						}
8726						// Counting from the left
8727						return [ _fnVisibleToColumnIndex( settings, idx ) ];
8728	
8729					case 'name':
8730						// match by name. `names` is column index complete and in order
8731						return $.map( names, function (name, i) {
8732							return name === match[1] ? i : null;
8733						} );
8734	
8735					default:
8736						return [];
8737				}
8738			}
8739	
8740			// Cell in the table body
8741			if ( s.nodeName && s._DT_CellIndex ) {
8742				return [ s._DT_CellIndex.column ];
8743			}
8744	
8745			// jQuery selector on the TH elements for the columns
8746			var jqResult = $( nodes )
8747				.filter( s )
8748				.map( function () {
8749					return $.inArray( this, nodes ); // `nodes` is column index complete and in order
8750				} )
8751				.toArray();
8752	
8753			if ( jqResult.length || ! s.nodeName ) {
8754				return jqResult;
8755			}
8756	
8757			// Otherwise a node which might have a `dt-column` data attribute, or be
8758			// a child or such an element
8759			var host = $(s).closest('*[data-dt-column]');
8760			return host.length ?
8761				[ host.data('dt-column') ] :
8762				[];
8763		};
8764	
8765		return _selector_run( 'column', selector, run, settings, opts );
8766	};
8767	
8768	
8769	var __setColumnVis = function ( settings, column, vis ) {
8770		var
8771			cols = settings.aoColumns,
8772			col  = cols[ column ],
8773			data = settings.aoData,
8774			row, cells, i, ien, tr;
8775	
8776		// Get
8777		if ( vis === undefined ) {
8778			return col.bVisible;
8779		}
8780	
8781		// Set
8782		// No change
8783		if ( col.bVisible === vis ) {
8784			return;
8785		}
8786	
8787		if ( vis ) {
8788			// Insert column
8789			// Need to decide if we should use appendChild or insertBefore
8790			var insertBefore = $.inArray( true, _pluck(cols, 'bVisible'), column+1 );
8791	
8792			for ( i=0, ien=data.length ; i<ien ; i++ ) {
8793				tr = data[i].nTr;
8794				cells = data[i].anCells;
8795	
8796				if ( tr ) {
8797					// insertBefore can act like appendChild if 2nd arg is null
8798					tr.insertBefore( cells[ column ], cells[ insertBefore ] || null );
8799				}
8800			}
8801		}
8802		else {
8803			// Remove column
8804			$( _pluck( settings.aoData, 'anCells', column ) ).detach();
8805		}
8806	
8807		// Common actions
8808		col.bVisible = vis;
8809	};
8810	
8811	
8812	_api_register( 'columns()', function ( selector, opts ) {
8813		// argument shifting
8814		if ( selector === undefined ) {
8815			selector = '';
8816		}
8817		else if ( $.isPlainObject( selector ) ) {
8818			opts = selector;
8819			selector = '';
8820		}
8821	
8822		opts = _selector_opts( opts );
8823	
8824		var inst = this.iterator( 'table', function ( settings ) {
8825			return __column_selector( settings, selector, opts );
8826		}, 1 );
8827	
8828		// Want argument shifting here and in _row_selector?
8829		inst.selector.cols = selector;
8830		inst.selector.opts = opts;
8831	
8832		return inst;
8833	} );
8834	
8835	_api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) {
8836		return this.iterator( 'column', function ( settings, column ) {
8837			return settings.aoColumns[column].nTh;
8838		}, 1 );
8839	} );
8840	
8841	_api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) {
8842		return this.iterator( 'column', function ( settings, column ) {
8843			return settings.aoColumns[column].nTf;
8844		}, 1 );
8845	} );
8846	
8847	_api_registerPlural( 'columns().data()', 'column().data()', function () {
8848		return this.iterator( 'column-rows', __columnData, 1 );
8849	} );
8850	
8851	_api_registerPlural( 'columns().dataSrc()', 'column().dataSrc()', function () {
8852		return this.iterator( 'column', function ( settings, column ) {
8853			return settings.aoColumns[column].mData;
8854		}, 1 );
8855	} );
8856	
8857	_api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) {
8858		return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8859			return _pluck_order( settings.aoData, rows,
8860				type === 'search' ? '_aFilterData' : '_aSortData', column
8861			);
8862		}, 1 );
8863	} );
8864	
8865	_api_registerPlural( 'columns().nodes()', 'column().nodes()', function () {
8866		return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8867			return _pluck_order( settings.aoData, rows, 'anCells', column ) ;
8868		}, 1 );
8869	} );
8870	
8871	_api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis, calc ) {
8872		var that = this;
8873		var ret = this.iterator( 'column', function ( settings, column ) {
8874			if ( vis === undefined ) {
8875				return settings.aoColumns[ column ].bVisible;
8876			} // else
8877			__setColumnVis( settings, column, vis );
8878		} );
8879	
8880		// Group the column visibility changes
8881		if ( vis !== undefined ) {
8882			this.iterator( 'table', function ( settings ) {
8883				// Redraw the header after changes
8884				_fnDrawHead( settings, settings.aoHeader );
8885				_fnDrawHead( settings, settings.aoFooter );
8886		
8887				// Update colspan for no records display. Child rows and extensions will use their own
8888				// listeners to do this - only need to update the empty table item here
8889				if ( ! settings.aiDisplay.length ) {
8890					$(settings.nTBody).find('td[colspan]').attr('colspan', _fnVisbleColumns(settings));
8891				}
8892		
8893				_fnSaveState( settings );
8894	
8895				// Second loop once the first is done for events
8896				that.iterator( 'column', function ( settings, column ) {
8897					_fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis, calc] );
8898				} );
8899	
8900				if ( calc === undefined || calc ) {
8901					that.columns.adjust();
8902				}
8903			});
8904		}
8905	
8906		return ret;
8907	} );
8908	
8909	_api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) {
8910		return this.iterator( 'column', function ( settings, column ) {
8911			return type === 'visible' ?
8912				_fnColumnIndexToVisible( settings, column ) :
8913				column;
8914		}, 1 );
8915	} );
8916	
8917	_api_register( 'columns.adjust()', function () {
8918		return this.iterator( 'table', function ( settings ) {
8919			_fnAdjustColumnSizing( settings );
8920		}, 1 );
8921	} );
8922	
8923	_api_register( 'column.index()', function ( type, idx ) {
8924		if ( this.context.length !== 0 ) {
8925			var ctx = this.context[0];
8926	
8927			if ( type === 'fromVisible' || type === 'toData' ) {
8928				return _fnVisibleToColumnIndex( ctx, idx );
8929			}
8930			else if ( type === 'fromData' || type === 'toVisible' ) {
8931				return _fnColumnIndexToVisible( ctx, idx );
8932			}
8933		}
8934	} );
8935	
8936	_api_register( 'column()', function ( selector, opts ) {
8937		return _selector_first( this.columns( selector, opts ) );
8938	} );
8939	
8940	var __cell_selector = function ( settings, selector, opts )
8941	{
8942		var data = settings.aoData;
8943		var rows = _selector_row_indexes( settings, opts );
8944		var cells = _removeEmpty( _pluck_order( data, rows, 'anCells' ) );
8945		var allCells = $(_flatten( [], cells ));
8946		var row;
8947		var columns = settings.aoColumns.length;
8948		var a, i, ien, j, o, host;
8949	
8950		var run = function ( s ) {
8951			var fnSelector = typeof s === 'function';
8952	
8953			if ( s === null || s === undefined || fnSelector ) {
8954				// All cells and function selectors
8955				a = [];
8956	
8957				for ( i=0, ien=rows.length ; i<ien ; i++ ) {
8958					row = rows[i];
8959	
8960					for ( j=0 ; j<columns ; j++ ) {
8961						o = {
8962							row: row,
8963							column: j
8964						};
8965	
8966						if ( fnSelector ) {
8967							// Selector - function
8968							host = data[ row ];
8969	
8970							if ( s( o, _fnGetCellData(settings, row, j), host.anCells ? host.anCells[j] : null ) ) {
8971								a.push( o );
8972							}
8973						}
8974						else {
8975							// Selector - all
8976							a.push( o );
8977						}
8978					}
8979				}
8980	
8981				return a;
8982			}
8983			
8984			// Selector - index
8985			if ( $.isPlainObject( s ) ) {
8986				// Valid cell index and its in the array of selectable rows
8987				return s.column !== undefined && s.row !== undefined && $.inArray( s.row, rows ) !== -1 ?
8988					[s] :
8989					[];
8990			}
8991	
8992			// Selector - jQuery filtered cells
8993			var jqResult = allCells
8994				.filter( s )
8995				.map( function (i, el) {
8996					return { // use a new object, in case someone changes the values
8997						row:    el._DT_CellIndex.row,
8998						column: el._DT_CellIndex.column
8999	 				};
9000				} )
9001				.toArray();
9002	
9003			if ( jqResult.length || ! s.nodeName ) {
9004				return jqResult;
9005			}
9006	
9007			// Otherwise the selector is a node, and there is one last option - the
9008			// element might be a child of an element which has dt-row and dt-column
9009			// data attributes
9010			host = $(s).closest('*[data-dt-row]');
9011			return host.length ?
9012				[ {
9013					row: host.data('dt-row'),
9014					column: host.data('dt-column')
9015				} ] :
9016				[];
9017		};
9018	
9019		return _selector_run( 'cell', selector, run, settings, opts );
9020	};
9021	
9022	
9023	
9024	
9025	_api_register( 'cells()', function ( rowSelector, columnSelector, opts ) {
9026		// Argument shifting
9027		if ( $.isPlainObject( rowSelector ) ) {
9028			// Indexes
9029			if ( rowSelector.row === undefined ) {
9030				// Selector options in first parameter
9031				opts = rowSelector;
9032				rowSelector = null;
9033			}
9034			else {
9035				// Cell index objects in first parameter
9036				opts = columnSelector;
9037				columnSelector = null;
9038			}
9039		}
9040		if ( $.isPlainObject( columnSelector ) ) {
9041			opts = columnSelector;
9042			columnSelector = null;
9043		}
9044	
9045		// Cell selector
9046		if ( columnSelector === null || columnSelector === undefined ) {
9047			return this.iterator( 'table', function ( settings ) {
9048				return __cell_selector( settings, rowSelector, _selector_opts( opts ) );
9049			} );
9050		}
9051	
9052		// The default built in options need to apply to row and columns
9053		var internalOpts = opts ? {
9054			page: opts.page,
9055			order: opts.order,
9056			search: opts.search
9057		} : {};
9058	
9059		// Row + column selector
9060		var columns = this.columns( columnSelector, internalOpts );
9061		var rows = this.rows( rowSelector, internalOpts );
9062		var i, ien, j, jen;
9063	
9064		var cellsNoOpts = this.iterator( 'table', function ( settings, idx ) {
9065			var a = [];
9066	
9067			for ( i=0, ien=rows[idx].length ; i<ien ; i++ ) {
9068				for ( j=0, jen=columns[idx].length ; j<jen ; j++ ) {
9069					a.push( {
9070						row:    rows[idx][i],
9071						column: columns[idx][j]
9072					} );
9073				}
9074			}
9075	
9076			return a;
9077		}, 1 );
9078	
9079		// There is currently only one extension which uses a cell selector extension
9080		// It is a _major_ performance drag to run this if it isn't needed, so this is
9081		// an extension specific check at the moment
9082		var cells = opts && opts.selected ?
9083			this.cells( cellsNoOpts, opts ) :
9084			cellsNoOpts;
9085	
9086		$.extend( cells.selector, {
9087			cols: columnSelector,
9088			rows: rowSelector,
9089			opts: opts
9090		} );
9091	
9092		return cells;
9093	} );
9094	
9095	
9096	_api_registerPlural( 'cells().nodes()', 'cell().node()', function () {
9097		return this.iterator( 'cell', function ( settings, row, column ) {
9098			var data = settings.aoData[ row ];
9099	
9100			return data && data.anCells ?
9101				data.anCells[ column ] :
9102				undefined;
9103		}, 1 );
9104	} );
9105	
9106	
9107	_api_register( 'cells().data()', function () {
9108		return this.iterator( 'cell', function ( settings, row, column ) {
9109			return _fnGetCellData( settings, row, column );
9110		}, 1 );
9111	} );
9112	
9113	
9114	_api_registerPlural( 'cells().cache()', 'cell().cache()', function ( type ) {
9115		type = type === 'search' ? '_aFilterData' : '_aSortData';
9116	
9117		return this.iterator( 'cell', function ( settings, row, column ) {
9118			return settings.aoData[ row ][ type ][ column ];
9119		}, 1 );
9120	} );
9121	
9122	
9123	_api_registerPlural( 'cells().render()', 'cell().render()', function ( type ) {
9124		return this.iterator( 'cell', function ( settings, row, column ) {
9125			return _fnGetCellData( settings, row, column, type );
9126		}, 1 );
9127	} );
9128	
9129	
9130	_api_registerPlural( 'cells().indexes()', 'cell().index()', function () {
9131		return this.iterator( 'cell', function ( settings, row, column ) {
9132			return {
9133				row: row,
9134				column: column,
9135				columnVisible: _fnColumnIndexToVisible( settings, column )
9136			};
9137		}, 1 );
9138	} );
9139	
9140	
9141	_api_registerPlural( 'cells().invalidate()', 'cell().invalidate()', function ( src ) {
9142		return this.iterator( 'cell', function ( settings, row, column ) {
9143			_fnInvalidate( settings, row, src, column );
9144		} );
9145	} );
9146	
9147	
9148	
9149	_api_register( 'cell()', function ( rowSelector, columnSelector, opts ) {
9150		return _selector_first( this.cells( rowSelector, columnSelector, opts ) );
9151	} );
9152	
9153	
9154	_api_register( 'cell().data()', function ( data ) {
9155		var ctx = this.context;
9156		var cell = this[0];
9157	
9158		if ( data === undefined ) {
9159			// Get
9160			return ctx.length && cell.length ?
9161				_fnGetCellData( ctx[0], cell[0].row, cell[0].column ) :
9162				undefined;
9163		}
9164	
9165		// Set
9166		_fnSetCellData( ctx[0], cell[0].row, cell[0].column, data );
9167		_fnInvalidate( ctx[0], cell[0].row, 'data', cell[0].column );
9168	
9169		return this;
9170	} );
9171	
9172	
9173	
9174	/**
9175	 * Get current ordering (sorting) that has been applied to the table.
9176	 *
9177	 * @returns {array} 2D array containing the sorting information for the first
9178	 *   table in the current context. Each element in the parent array represents
9179	 *   a column being sorted upon (i.e. multi-sorting with two columns would have
9180	 *   2 inner arrays). The inner arrays may have 2 or 3 elements. The first is
9181	 *   the column index that the sorting condition applies to, the second is the
9182	 *   direction of the sort (`desc` or `asc`) and, optionally, the third is the
9183	 *   index of the sorting order from the `column.sorting` initialisation array.
9184	 *//**
9185	 * Set the ordering for the table.
9186	 *
9187	 * @param {integer} order Column index to sort upon.
9188	 * @param {string} direction Direction of the sort to be applied (`asc` or `desc`)
9189	 * @returns {DataTables.Api} this
9190	 *//**
9191	 * Set the ordering for the table.
9192	 *
9193	 * @param {array} order 1D array of sorting information to be applied.
9194	 * @param {array} [...] Optional additional sorting conditions
9195	 * @returns {DataTables.Api} this
9196	 *//**
9197	 * Set the ordering for the table.
9198	 *
9199	 * @param {array} order 2D array of sorting information to be applied.
9200	 * @returns {DataTables.Api} this
9201	 */
9202	_api_register( 'order()', function ( order, dir ) {
9203		var ctx = this.context;
9204	
9205		if ( order === undefined ) {
9206			// get
9207			return ctx.length !== 0 ?
9208				ctx[0].aaSorting :
9209				undefined;
9210		}
9211	
9212		// set
9213		if ( typeof order === 'number' ) {
9214			// Simple column / direction passed in
9215			order = [ [ order, dir ] ];
9216		}
9217		else if ( order.length && ! Array.isArray( order[0] ) ) {
9218			// Arguments passed in (list of 1D arrays)
9219			order = Array.prototype.slice.call( arguments );
9220		}
9221		// otherwise a 2D array was passed in
9222	
9223		return this.iterator( 'table', function ( settings ) {
9224			settings.aaSorting = order.slice();
9225		} );
9226	} );
9227	
9228	
9229	/**
9230	 * Attach a sort listener to an element for a given column
9231	 *
9232	 * @param {node|jQuery|string} node Identifier for the element(s) to attach the
9233	 *   listener to. This can take the form of a single DOM node, a jQuery
9234	 *   collection of nodes or a jQuery selector which will identify the node(s).
9235	 * @param {integer} column the column that a click on this node will sort on
9236	 * @param {function} [callback] callback function when sort is run
9237	 * @returns {DataTables.Api} this
9238	 */
9239	_api_register( 'order.listener()', function ( node, column, callback ) {
9240		return this.iterator( 'table', function ( settings ) {
9241			_fnSortAttachListener( settings, node, column, callback );
9242		} );
9243	} );
9244	
9245	
9246	_api_register( 'order.fixed()', function ( set ) {
9247		if ( ! set ) {
9248			var ctx = this.context;
9249			var fixed = ctx.length ?
9250				ctx[0].aaSortingFixed :
9251				undefined;
9252	
9253			return Array.isArray( fixed ) ?
9254				{ pre: fixed } :
9255				fixed;
9256		}
9257	
9258		return this.iterator( 'table', function ( settings ) {
9259			settings.aaSortingFixed = $.extend( true, {}, set );
9260		} );
9261	} );
9262	
9263	
9264	// Order by the selected column(s)
9265	_api_register( [
9266		'columns().order()',
9267		'column().order()'
9268	], function ( dir ) {
9269		var that = this;
9270	
9271		return this.iterator( 'table', function ( settings, i ) {
9272			var sort = [];
9273	
9274			$.each( that[i], function (j, col) {
9275				sort.push( [ col, dir ] );
9276			} );
9277	
9278			settings.aaSorting = sort;
9279		} );
9280	} );
9281	
9282	
9283	
9284	_api_register( 'search()', function ( input, regex, smart, caseInsen ) {
9285		var ctx = this.context;
9286	
9287		if ( input === undefined ) {
9288			// get
9289			return ctx.length !== 0 ?
9290				ctx[0].oPreviousSearch.sSearch :
9291				undefined;
9292		}
9293	
9294		// set
9295		return this.iterator( 'table', function ( settings ) {
9296			if ( ! settings.oFeatures.bFilter ) {
9297				return;
9298			}
9299	
9300			_fnFilterComplete( settings, $.extend( {}, settings.oPreviousSearch, {
9301				"sSearch": input+"",
9302				"bRegex":  regex === null ? false : regex,
9303				"bSmart":  smart === null ? true  : smart,
9304				"bCaseInsensitive": caseInsen === null ? true : caseInsen
9305			} ), 1 );
9306		} );
9307	} );
9308	
9309	
9310	_api_registerPlural(
9311		'columns().search()',
9312		'column().search()',
9313		function ( input, regex, smart, caseInsen ) {
9314			return this.iterator( 'column', function ( settings, column ) {
9315				var preSearch = settings.aoPreSearchCols;
9316	
9317				if ( input === undefined ) {
9318					// get
9319					return preSearch[ column ].sSearch;
9320				}
9321	
9322				// set
9323				if ( ! settings.oFeatures.bFilter ) {
9324					return;
9325				}
9326	
9327				$.extend( preSearch[ column ], {
9328					"sSearch": input+"",
9329					"bRegex":  regex === null ? false : regex,
9330					"bSmart":  smart === null ? true  : smart,
9331					"bCaseInsensitive": caseInsen === null ? true : caseInsen
9332				} );
9333	
9334				_fnFilterComplete( settings, settings.oPreviousSearch, 1 );
9335			} );
9336		}
9337	);
9338	
9339	/*
9340	 * State API methods
9341	 */
9342	
9343	_api_register( 'state()', function () {
9344		return this.context.length ?
9345			this.context[0].oSavedState :
9346			null;
9347	} );
9348	
9349	
9350	_api_register( 'state.clear()', function () {
9351		return this.iterator( 'table', function ( settings ) {
9352			// Save an empty object
9353			settings.fnStateSaveCallback.call( settings.oInstance, settings, {} );
9354		} );
9355	} );
9356	
9357	
9358	_api_register( 'state.loaded()', function () {
9359		return this.context.length ?
9360			this.context[0].oLoadedState :
9361			null;
9362	} );
9363	
9364	
9365	_api_register( 'state.save()', function () {
9366		return this.iterator( 'table', function ( settings ) {
9367			_fnSaveState( settings );
9368		} );
9369	} );
9370	
9371	
9372	
9373	/**
9374	 * Set the jQuery or window object to be used by DataTables
9375	 *
9376	 * @param {*} module Library / container object
9377	 * @param {string} 
9377type Library or container type `lib` or `win`.
9378	 */
9379	DataTable.use = function (module, type) {
9380		if (type === 'lib' || module.fn) {
9381			$ = module;
9382		}
9383		else if (type == 'win' || module.document) {
9384			window = module;
9385			document = module.document
vendor: 10,052 bytes, lines 9385-9746
9385;
9386		}
9387	}
9388	
9389	/**
9390	 * CommonJS factory function pass through. This will check if the arguments
9391	 * given are a window object or a jQuery object. If so they are set
9392	 * accordingly.
9393	 * @param {*} root Window
9394	 * @param {*} jq jQUery
9395	 * @returns {boolean} Indicator
9396	 */
9397	DataTable.factory = function (root, jq) {
9398		var is = false;
9399	
9400		// Test if the first parameter is a window object
9401		if (root && root.document) {
9402			window = root;
9403			document = root.document;
9404		}
9405	
9406		// Test if the second parameter is a jQuery object
9407		if (jq && jq.fn && jq.fn.jquery) {
9408			$ = jq;
9409			is = true;
9410		}
9411	
9412		return is;
9413	}
9414	
9415	/**
9416	 * Provide a common method for plug-ins to check the version of DataTables being
9417	 * used, in order to ensure compatibility.
9418	 *
9419	 *  @param {string} version Version string to check for, in the format "X.Y.Z".
9420	 *    Note that the formats "X" and "X.Y" are also acceptable.
9421	 *  @returns {boolean} true if this version of DataTables is greater or equal to
9422	 *    the required version, or false if this version of DataTales is not
9423	 *    suitable
9424	 *  @static
9425	 *  @dtopt API-Static
9426	 *
9427	 *  @example
9428	 *    alert( $.fn.dataTable.versionCheck( '1.9.0' ) );
9429	 */
9430	DataTable.versionCheck = DataTable.fnVersionCheck = function( version )
9431	{
9432		var aThis = DataTable.version.split('.');
9433		var aThat = version.split('.');
9434		var iThis, iThat;
9435	
9436		for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) {
9437			iThis = parseInt( aThis[i], 10 ) || 0;
9438			iThat = parseInt( aThat[i], 10 ) || 0;
9439	
9440			// Parts are the same, keep comparing
9441			if (iThis === iThat) {
9442				continue;
9443			}
9444	
9445			// Parts are different, return immediately
9446			return iThis > iThat;
9447		}
9448	
9449		return true;
9450	};
9451	
9452	
9453	/**
9454	 * Check if a `<table>` node is a DataTable table already or not.
9455	 *
9456	 *  @param {node|jquery|string} table Table node, jQuery object or jQuery
9457	 *      selector for the table to test. Note that if more than more than one
9458	 *      table is passed on, only the first will be checked
9459	 *  @returns {boolean} true the table given is a DataTable, or false otherwise
9460	 *  @static
9461	 *  @dtopt API-Static
9462	 *
9463	 *  @example
9464	 *    if ( ! $.fn.DataTable.isDataTable( '#example' ) ) {
9465	 *      $('#example').dataTable();
9466	 *    }
9467	 */
9468	DataTable.isDataTable = DataTable.fnIsDataTable = function ( table )
9469	{
9470		var t = $(table).get(0);
9471		var is = false;
9472	
9473		if ( table instanceof DataTable.Api ) {
9474			return true;
9475		}
9476	
9477		$.each( DataTable.settings, function (i, o) {
9478			var head = o.nScrollHead ? $('table', o.nScrollHead)[0] : null;
9479			var foot = o.nScrollFoot ? $('table', o.nScrollFoot)[0] : null;
9480	
9481			if ( o.nTable === t || head === t || foot === t ) {
9482				is = true;
9483			}
9484		} );
9485	
9486		return is;
9487	};
9488	
9489	
9490	/**
9491	 * Get all DataTable tables that have been initialised - optionally you can
9492	 * select to get only currently visible tables.
9493	 *
9494	 *  @param {boolean} [visible=false] Flag to indicate if you want all (default)
9495	 *    or visible tables only.
9496	 *  @returns {array} Array of `table` nodes (not DataTable instances) which are
9497	 *    DataTables
9498	 *  @static
9499	 *  @dtopt API-Static
9500	 *
9501	 *  @example
9502	 *    $.each( $.fn.dataTable.tables(true), function () {
9503	 *      $(table).DataTable().columns.adjust();
9504	 *    } );
9505	 */
9506	DataTable.tables = DataTable.fnTables = function ( visible )
9507	{
9508		var api = false;
9509	
9510		if ( $.isPlainObject( visible ) ) {
9511			api = visible.api;
9512			visible = visible.visible;
9513		}
9514	
9515		var a = $.map( DataTable.settings, function (o) {
9516			if ( !visible || (visible && $(o.nTable).is(':visible')) ) {
9517				return o.nTable;
9518			}
9519		} );
9520	
9521		return api ?
9522			new _Api( a ) :
9523			a;
9524	};
9525	
9526	
9527	/**
9528	 * Convert from camel case parameters to Hungarian notation. This is made public
9529	 * for the extensions to provide the same ability as DataTables core to accept
9530	 * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase
9531	 * parameters.
9532	 *
9533	 *  @param {object} src The model object which holds all parameters that can be
9534	 *    mapped.
9535	 *  @param {object} user The object to convert from camel case to Hungarian.
9536	 *  @param {boolean} force When set to `true`, properties which already have a
9537	 *    Hungarian value in the `user` object will be overwritten. Otherwise they
9538	 *    won't be.
9539	 */
9540	DataTable.camelToHungarian = _fnCamelToHungarian;
9541	
9542	
9543	
9544	/**
9545	 *
9546	 */
9547	_api_register( '$()', function ( selector, opts ) {
9548		var
9549			rows   = this.rows( opts ).nodes(), // Get all rows
9550			jqRows = $(rows);
9551	
9552		return $( [].concat(
9553			jqRows.filter( selector ).toArray(),
9554			jqRows.find( selector ).toArray()
9555		) );
9556	} );
9557	
9558	
9559	// jQuery functions to operate on the tables
9560	$.each( [ 'on', 'one', 'off' ], function (i, key) {
9561		_api_register( key+'()', function ( /* event, handler */ ) {
9562			var args = Array.prototype.slice.call(arguments);
9563	
9564			// Add the `dt` namespace automatically if it isn't already present
9565			args[0] = $.map( args[0].split( /\s/ ), function ( e ) {
9566				return ! e.match(/\.dt\b/) ?
9567					e+'.dt' :
9568					e;
9569				} ).join( ' ' );
9570	
9571			var inst = $( this.tables().nodes() );
9572			inst[key].apply( inst, args );
9573			return this;
9574		} );
9575	} );
9576	
9577	
9578	_api_register( 'clear()', function () {
9579		return this.iterator( 'table', function ( settings ) {
9580			_fnClearTable( settings );
9581		} );
9582	} );
9583	
9584	
9585	_api_register( 'settings()', function () {
9586		return new _Api( this.context, this.context );
9587	} );
9588	
9589	
9590	_api_register( 'init()', function () {
9591		var ctx = this.context;
9592		return ctx.length ? ctx[0].oInit : null;
9593	} );
9594	
9595	
9596	_api_register( 'data()', function () {
9597		return this.iterator( 'table', function ( settings ) {
9598			return _pluck( settings.aoData, '_aData' );
9599		} ).flatten();
9600	} );
9601	
9602	
9603	_api_register( 'destroy()', function ( remove ) {
9604		remove = remove || false;
9605	
9606		return this.iterator( 'table', function ( settings ) {
9607			var classes   = settings.oClasses;
9608			var table     = settings.nTable;
9609			var tbody     = settings.nTBody;
9610			var thead     = settings.nTHead;
9611			var tfoot     = settings.nTFoot;
9612			var jqTable   = $(table);
9613			var jqTbody   = $(tbody);
9614			var jqWrapper = $(settings.nTableWrapper);
9615			var rows      = $.map( settings.aoData, function (r) { return r.nTr; } );
9616			var i, ien;
9617	
9618			// Flag to note that the table is currently being destroyed - no action
9619			// should be taken
9620			settings.bDestroying = true;
9621	
9622			// Fire off the destroy callbacks for plug-ins etc
9623			_fnCallbackFire( settings, "aoDestroyCallback", "destroy", [settings] );
9624	
9625			// If not being removed from the document, make all columns visible
9626			if ( ! remove ) {
9627				new _Api( settings ).columns().visible( true );
9628			}
9629	
9630			// Blitz all `DT` namespaced events (these are internal events, the
9631			// lowercase, `dt` events are user subscribed and they are responsible
9632			// for removing them
9633			jqWrapper.off('.DT').find(':not(tbody *)').off('.DT');
9634			$(window).off('.DT-'+settings.sInstance);
9635	
9636			// When scrolling we had to break the table up - restore it
9637			if ( table != thead.parentNode ) {
9638				jqTable.children('thead').detach();
9639				jqTable.append( thead );
9640			}
9641	
9642			if ( tfoot && table != tfoot.parentNode ) {
9643				jqTable.children('tfoot').detach();
9644				jqTable.append( tfoot );
9645			}
9646	
9647			settings.aaSorting = [];
9648			settings.aaSortingFixed = [];
9649			_fnSortingClasses( settings );
9650	
9651			$( rows ).removeClass( settings.asStripeClasses.join(' ') );
9652	
9653			$('th, td', thead).removeClass( classes.sSortable+' '+
9654				classes.sSortableAsc+' '+classes.sSortableDesc+' '+classes.sSortableNone
9655			);
9656	
9657			// Add the TR elements back into the table in their original order
9658			jqTbody.children().detach();
9659			jqTbody.append( rows );
9660	
9661			var orig = settings.nTableWrapper.parentNode;
9662	
9663			// Remove the DataTables generated nodes, events and classes
9664			var removedMethod = remove ? 'remove' : 'detach';
9665			jqTable[ removedMethod ]();
9666			jqWrapper[ removedMethod ]();
9667	
9668			// If we need to reattach the table to the document
9669			if ( ! remove && orig ) {
9670				// insertBefore acts like appendChild if !arg[1]
9671				orig.insertBefore( table, settings.nTableReinsertBefore );
9672	
9673				// Restore the width of the original table - was read from the style property,
9674				// so we can restore directly to that
9675				jqTable
9676					.css( 'width', settings.sDestroyWidth )
9677					.removeClass( classes.sTable );
9678	
9679				// If the were originally stripe classes - then we add them back here.
9680				// Note this is not fool proof (for example if not all rows had stripe
9681				// classes - but it's a good effort without getting carried away
9682				ien = settings.asDestroyStripes.length;
9683	
9684				if ( ien ) {
9685					jqTbody.children().each( function (i) {
9686						$(this).addClass( settings.asDestroyStripes[i % ien] );
9687					} );
9688				}
9689			}
9690	
9691			/* Remove the settings object from the settings array */
9692			var idx = $.inArray( settings, DataTable.settings );
9693			if ( idx !== -1 ) {
9694				DataTable.settings.splice( idx, 1 );
9695			}
9696		} );
9697	} );
9698	
9699	
9700	// Add the `every()` method for rows, columns and cells in a compact form
9701	$.each( [ 'column', 'row', 'cell' ], function ( i, type ) {
9702		_api_register( type+'s().every()', function ( fn ) {
9703			var opts = this.selector.opts;
9704			var api = this;
9705	
9706			return this.iterator( type, function ( settings, arg1, arg2, arg3, arg4 ) {
9707				// Rows and columns:
9708				//  arg1 - index
9709				//  arg2 - table counter
9710				//  arg3 - loop counter
9711				//  arg4 - undefined
9712				// Cells:
9713				//  arg1 - row index
9714				//  arg2 - column index
9715				//  arg3 - table counter
9716				//  arg4 - loop counter
9717				fn.call(
9718					api[ type ](
9719						arg1,
9720						type==='cell' ? arg2 : opts,
9721						type==='cell' ? opts : undefined
9722					),
9723					arg1, arg2, arg3, arg4
9724				);
9725			} );
9726		} );
9727	} );
9728	
9729	
9730	// i18n method for extensions to be able to use the language object from the
9731	// DataTable
9732	_api_register( 'i18n()', function ( token, def, plural ) {
9733		var ctx = this.context[0];
9734		var resolved = _fnGetObjectDataFn( token )( ctx.oLanguage );
9735	
9736		if ( resolved === undefined ) {
9737			resolved = def;
9738		}
9739	
9740		if ( plural !== undefined && $.isPlainObject( resolved ) ) {
9741			resolved = resolved[ plural ] !== undefined ?
9742				resolved[ plural ] :
9743				resolved._;
9744		}
9745	
9746		return 
9746resolved.replace( '%d', plural ); // nb: plural might be undefined,
9747	} );	
9748	/**
9749	 * Version string for plug-ins to check compatibility. Allowed format is
9750	 * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used
9751	 * only for non-release builds. See http://semver.org/ for more information.
9752	 *  @member
9753	 *  @type string
9754	 *  @default Version number
9755	 */
9756	DataTable.version = "1.13.4
vendor: 157,934 bytes, lines 9756-14898
9756";
9757	
9758	/**
9759	 * Private data store, containing all of the settings objects that are
9760	 * created for the tables on a given page.
9761	 *
9762	 * Note that the `DataTable.settings` object is aliased to
9763	 * `jQuery.fn.dataTableExt` through which it may be accessed and
9764	 * manipulated, or `jQuery.fn.dataTable.settings`.
9765	 *  @member
9766	 *  @type array
9767	 *  @default []
9768	 *  @private
9769	 */
9770	DataTable.settings = [];
9771	
9772	/**
9773	 * Object models container, for the various models that DataTables has
9774	 * available to it. These models define the objects that are used to hold
9775	 * the active state and configuration of the table.
9776	 *  @namespace
9777	 */
9778	DataTable.models = {};
9779	
9780	
9781	
9782	/**
9783	 * Template object for the way in which DataTables holds information about
9784	 * search information for the global filter and individual column filters.
9785	 *  @namespace
9786	 */
9787	DataTable.models.oSearch = {
9788		/**
9789		 * Flag to indicate if the filtering should be case insensitive or not
9790		 *  @type boolean
9791		 *  @default true
9792		 */
9793		"bCaseInsensitive": true,
9794	
9795		/**
9796		 * Applied search term
9797		 *  @type string
9798		 *  @default <i>Empty string</i>
9799		 */
9800		"sSearch": "",
9801	
9802		/**
9803		 * Flag to indicate if the search term should be interpreted as a
9804		 * regular expression (true) or not (false) and therefore and special
9805		 * regex characters escaped.
9806		 *  @type boolean
9807		 *  @default false
9808		 */
9809		"bRegex": false,
9810	
9811		/**
9812		 * Flag to indicate if DataTables is to use its smart filtering or not.
9813		 *  @type boolean
9814		 *  @default true
9815		 */
9816		"bSmart": true,
9817	
9818		/**
9819		 * Flag to indicate if DataTables should only trigger a search when
9820		 * the return key is pressed.
9821		 *  @type boolean
9822		 *  @default false
9823		 */
9824		"return": false
9825	};
9826	
9827	
9828	
9829	
9830	/**
9831	 * Template object for the way in which DataTables holds information about
9832	 * each individual row. This is the object format used for the settings
9833	 * aoData array.
9834	 *  @namespace
9835	 */
9836	DataTable.models.oRow = {
9837		/**
9838		 * TR element for the row
9839		 *  @type node
9840		 *  @default null
9841		 */
9842		"nTr": null,
9843	
9844		/**
9845		 * Array of TD elements for each row. This is null until the row has been
9846		 * created.
9847		 *  @type array nodes
9848		 *  @default []
9849		 */
9850		"anCells": null,
9851	
9852		/**
9853		 * Data object from the original data source for the row. This is either
9854		 * an array if using the traditional form of DataTables, or an object if
9855		 * using mData options. The exact type will depend on the passed in
9856		 * data from the data source, or will be an array if using DOM a data
9857		 * source.
9858		 *  @type array|object
9859		 *  @default []
9860		 */
9861		"_aData": [],
9862	
9863		/**
9864		 * Sorting data cache - this array is ostensibly the same length as the
9865		 * number of columns (although each index is generated only as it is
9866		 * needed), and holds the data that is used for sorting each column in the
9867		 * row. We do this cache generation at the start of the sort in order that
9868		 * the formatting of the sort data need be done only once for each cell
9869		 * per sort. This array should not be read from or written to by anything
9870		 * other than the master sorting methods.
9871		 *  @type array
9872		 *  @default null
9873		 *  @private
9874		 */
9875		"_aSortData": null,
9876	
9877		/**
9878		 * Per cell filtering data cache. As per the sort data cache, used to
9879		 * increase the performance of the filtering in DataTables
9880		 *  @type array
9881		 *  @default null
9882		 *  @private
9883		 */
9884		"_aFilterData": null,
9885	
9886		/**
9887		 * Filtering data cache. This is the same as the cell filtering cache, but
9888		 * in this case a string rather than an array. This is easily computed with
9889		 * a join on `_aFilterData`, but is provided as a cache so the join isn't
9890		 * needed on every search (memory traded for performance)
9891		 *  @type array
9892		 *  @default null
9893		 *  @private
9894		 */
9895		"_sFilterRow": null,
9896	
9897		/**
9898		 * Cache of the class name that DataTables has applied to the row, so we
9899		 * can quickly look at this variable rather than needing to do a DOM check
9900		 * on className for the nTr property.
9901		 *  @type string
9902		 *  @default <i>Empty string</i>
9903		 *  @private
9904		 */
9905		"_sRowStripe": "",
9906	
9907		/**
9908		 * Denote if the original data source was from the DOM, or the data source
9909		 * object. This is used for invalidating data, so DataTables can
9910		 * automatically read data from the original source, unless uninstructed
9911		 * otherwise.
9912		 *  @type string
9913		 *  @default null
9914		 *  @private
9915		 */
9916		"src": null,
9917	
9918		/**
9919		 * Index in the aoData array. This saves an indexOf lookup when we have the
9920		 * object, but want to know the index
9921		 *  @type integer
9922		 *  @default -1
9923		 *  @private
9924		 */
9925		"idx": -1
9926	};
9927	
9928	
9929	/**
9930	 * Template object for the column information object in DataTables. This object
9931	 * is held in the settings aoColumns array and contains all the information that
9932	 * DataTables needs about each individual column.
9933	 *
9934	 * Note that this object is related to {@link DataTable.defaults.column}
9935	 * but this one is the internal data store for DataTables's cache of columns.
9936	 * It should NOT be manipulated outside of DataTables. Any configuration should
9937	 * be done through the initialisation options.
9938	 *  @namespace
9939	 */
9940	DataTable.models.oColumn = {
9941		/**
9942		 * Column index. This could be worked out on-the-fly with $.inArray, but it
9943		 * is faster to just hold it as a variable
9944		 *  @type integer
9945		 *  @default null
9946		 */
9947		"idx": null,
9948	
9949		/**
9950		 * A list of the columns that sorting should occur on when this column
9951		 * is sorted. That this property is an array allows multi-column sorting
9952		 * to be defined for a column (for example first name / last name columns
9953		 * would benefit from this). The values are integers pointing to the
9954		 * columns to be sorted on (typically it will be a single integer pointing
9955		 * at itself, but that doesn't need to be the case).
9956		 *  @type array
9957		 */
9958		"aDataSort": null,
9959	
9960		/**
9961		 * Define the sorting directions that are applied to the column, in sequence
9962		 * as the column is repeatedly sorted upon - i.e. the first value is used
9963		 * as the sorting direction when the column if first sorted (clicked on).
9964		 * Sort it again (click again) and it will move on to the next index.
9965		 * Repeat until loop.
9966		 *  @type array
9967		 */
9968		"asSorting": null,
9969	
9970		/**
9971		 * Flag to indicate if the column is searchable, and thus should be included
9972		 * in the filtering or not.
9973		 *  @type boolean
9974		 */
9975		"bSearchable": null,
9976	
9977		/**
9978		 * Flag to indicate if the column is sortable or not.
9979		 *  @type boolean
9980		 */
9981		"bSortable": null,
9982	
9983		/**
9984		 * Flag to indicate if the column is currently visible in the table or not
9985		 *  @type boolean
9986		 */
9987		"bVisible": null,
9988	
9989		/**
9990		 * Store for manual type assignment using the `column.type` option. This
9991		 * is held in store so we can manipulate the column's `sType` property.
9992		 *  @type string
9993		 *  @default null
9994		 *  @private
9995		 */
9996		"_sManualType": null,
9997	
9998		/**
9999		 * Flag to indicate if HTML5 data attributes should be used as the data
10000		 * source for filtering or sorting. True is either are.
10001		 *  @type boolean
10002		 *  @default false
10003		 *  @private
10004		 */
10005		"_bAttrSrc": false,
10006	
10007		/**
10008		 * Developer definable function that is called whenever a cell is created (Ajax source,
10009		 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
10010		 * allowing you to modify the DOM element (add background colour for example) when the
10011		 * element is available.
10012		 *  @type function
10013		 *  @param {element} nTd The TD node that has been created
10014		 *  @param {*} sData The Data for the cell
10015		 *  @param {array|object} oData The data for the whole row
10016		 *  @param {int} iRow The row index for the aoData data store
10017		 *  @default null
10018		 */
10019		"fnCreatedCell": null,
10020	
10021		/**
10022		 * Function to get data from a cell in a column. You should <b>never</b>
10023		 * access data directly through _aData internally in DataTables - always use
10024		 * the method attached to this property. It allows mData to function as
10025		 * required. This function is automatically assigned by the column
10026		 * initialisation method
10027		 *  @type function
10028		 *  @param {array|object} oData The data array/object for the array
10029		 *    (i.e. aoData[]._aData)
10030		 *  @param {string} sSpecific The specific data type you want to get -
10031		 *    'display', 'type' 'filter' 'sort'
10032		 *  @returns {*} The data for the cell from the given row's data
10033		 *  @default null
10034		 */
10035		"fnGetData": null,
10036	
10037		/**
10038		 * Function to set data for a cell in the column. You should <b>never</b>
10039		 * set the data directly to _aData internally in DataTables - always use
10040		 * this method. It allows mData to function as required. This function
10041		 * is automatically assigned by the column initialisation method
10042		 *  @type function
10043		 *  @param {array|object} oData The data array/object for the array
10044		 *    (i.e. aoData[]._aData)
10045		 *  @param {*} sValue Value to set
10046		 *  @default null
10047		 */
10048		"fnSetData": null,
10049	
10050		/**
10051		 * Property to read the value for the cells in the column from the data
10052		 * source array / object. If null, then the default content is used, if a
10053		 * function is given then the return from the function is used.
10054		 *  @type function|int|string|null
10055		 *  @default null
10056		 */
10057		"mData": null,
10058	
10059		/**
10060		 * Partner property to mData which is used (only when defined) to get
10061		 * the data - i.e. it is basically the same as mData, but without the
10062		 * 'set' option, and also the data fed to it is the result from mData.
10063		 * This is the rendering method to match the data method of mData.
10064		 *  @type function|int|string|null
10065		 *  @default null
10066		 */
10067		"mRender": null,
10068	
10069		/**
10070		 * Unique header TH/TD element for this column - this is what the sorting
10071		 * listener is attached to (if sorting is enabled.)
10072		 *  @type node
10073		 *  @default null
10074		 */
10075		"nTh": null,
10076	
10077		/**
10078		 * Unique footer TH/TD element for this column (if there is one). Not used
10079		 * in DataTables as such, but can be used for plug-ins to reference the
10080		 * footer for each column.
10081		 *  @type node
10082		 *  @default null
10083		 */
10084		"nTf": null,
10085	
10086		/**
10087		 * The class to apply to all TD elements in the table's TBODY for the column
10088		 *  @type string
10089		 *  @default null
10090		 */
10091		"sClass": null,
10092	
10093		/**
10094		 * When DataTables calculates the column widths to assign to each column,
10095		 * it finds the longest string in each column and then constructs a
10096		 * temporary table and reads the widths from that. The problem with this
10097		 * is that "mmm" is much wider then "iiii", but the latter is a longer
10098		 * string - thus the calculation can go wrong (doing it properly and putting
10099		 * it into an DOM object and measuring that is horribly(!) slow). Thus as
10100		 * a "work around" we provide this option. It will append its value to the
10101		 * text that is found to be the longest string for the column - i.e. padding.
10102		 *  @type string
10103		 */
10104		"sContentPadding": null,
10105	
10106		/**
10107		 * Allows a default value to be given for a column's data, and will be used
10108		 * whenever a null data source is encountered (this can be because mData
10109		 * is set to null, or because the data source itself is null).
10110		 *  @type string
10111		 *  @default null
10112		 */
10113		"sDefaultContent": null,
10114	
10115		/**
10116		 * Name for the column, allowing reference to the column by name as well as
10117		 * by index (needs a lookup to work by name).
10118		 *  @type string
10119		 */
10120		"sName": null,
10121	
10122		/**
10123		 * Custom sorting data type - defines which of the available plug-ins in
10124		 * afnSortData the custom sorting will use - if any is defined.
10125		 *  @type string
10126		 *  @default std
10127		 */
10128		"sSortDataType": 'std',
10129	
10130		/**
10131		 * Class to be applied to the header element when sorting on this column
10132		 *  @type string
10133		 *  @default null
10134		 */
10135		"sSortingClass": null,
10136	
10137		/**
10138		 * Class to be applied to the header element when sorting on this column -
10139		 * when jQuery UI theming is used.
10140		 *  @type string
10141		 *  @default null
10142		 */
10143		"sSortingClassJUI": null,
10144	
10145		/**
10146		 * Title of the column - what is seen in the TH element (nTh).
10147		 *  @type string
10148		 */
10149		"sTitle": null,
10150	
10151		/**
10152		 * Column sorting and filtering type
10153		 *  @type string
10154		 *  @default null
10155		 */
10156		"sType": null,
10157	
10158		/**
10159		 * Width of the column
10160		 *  @type string
10161		 *  @default null
10162		 */
10163		"sWidth": null,
10164	
10165		/**
10166		 * Width of the column when it was first "encountered"
10167		 *  @type string
10168		 *  @default null
10169		 */
10170		"sWidthOrig": null
10171	};
10172	
10173	
10174	/*
10175	 * Developer note: The properties of the object below are given in Hungarian
10176	 * notation, that was used as the interface for DataTables prior to v1.10, however
10177	 * from v1.10 onwards the primary interface is camel case. In order to avoid
10178	 * breaking backwards compatibility utterly with this change, the Hungarian
10179	 * version is still, internally the primary interface, but is is not documented
10180	 * - hence the @name tags in each doc comment. This allows a Javascript function
10181	 * to create a map from Hungarian notation to camel case (going the other direction
10182	 * would require each property to be listed, which would add around 3K to the size
10183	 * of DataTables, while this method is about a 0.5K hit).
10184	 *
10185	 * Ultimately this does pave the way for Hungarian notation to be dropped
10186	 * completely, but that is a massive amount of work and will break current
10187	 * installs (therefore is on-hold until v2).
10188	 */
10189	
10190	/**
10191	 * Initialisation options that can be given to DataTables at initialisation
10192	 * time.
10193	 *  @namespace
10194	 */
10195	DataTable.defaults = {
10196		/**
10197		 * An array of data to use for the table, passed in at initialisation which
10198		 * will be used in preference to any data which is already in the DOM. This is
10199		 * particularly useful for constructing tables purely in Javascript, for
10200		 * example with a custom Ajax call.
10201		 *  @type array
10202		 *  @default null
10203		 *
10204		 *  @dtopt Option
10205		 *  @name DataTable.defaults.data
10206		 *
10207		 *  @example
10208		 *    // Using a 2D array data source
10209		 *    $(document).ready( function () {
10210		 *      $('#example').dataTable( {
10211		 *        "data": [
10212		 *          ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
10213		 *          ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
10214		 *        ],
10215		 *        "columns": [
10216		 *          { "title": "Engine" },
10217		 *          { "title": "Browser" },
10218		 *          { "title": "Platform" },
10219		 *          { "title": "Version" },
10220		 *          { "title": "Grade" }
10221		 *        ]
10222		 *      } );
10223		 *    } );
10224		 *
10225		 *  @example
10226		 *    // Using an array of objects as a data source (`data`)
10227		 *    $(document).ready( function () {
10228		 *      $('#example').dataTable( {
10229		 *        "data": [
10230		 *          {
10231		 *            "engine":   "Trident",
10232		 *            "browser":  "Internet Explorer 4.0",
10233		 *            "platform": "Win 95+",
10234		 *            "version":  4,
10235		 *            "grade":    "X"
10236		 *          },
10237		 *          {
10238		 *            "engine":   "Trident",
10239		 *            "browser":  "Internet Explorer 5.0",
10240		 *            "platform": "Win 95+",
10241		 *            "version":  5,
10242		 *            "grade":    "C"
10243		 *          }
10244		 *        ],
10245		 *        "columns": [
10246		 *          { "title": "Engine",   "data": "engine" },
10247		 *          { "title": "Browser",  "data": "browser" },
10248		 *          { "title": "Platform", "data": "platform" },
10249		 *          { "title": "Version",  "data": "version" },
10250		 *          { "title": "Grade",    "data": "grade" }
10251		 *        ]
10252		 *      } );
10253		 *    } );
10254		 */
10255		"aaData": null,
10256	
10257	
10258		/**
10259		 * If ordering is enabled, then DataTables will perform a first pass sort on
10260		 * initialisation. You can define which column(s) the sort is performed
10261		 * upon, and the sorting direction, with this variable. The `sorting` array
10262		 * should contain an array for each column to be sorted initially containing
10263		 * the column's index and a direction string ('asc' or 'desc').
10264		 *  @type array
10265		 *  @default [[0,'asc']]
10266		 *
10267		 *  @dtopt Option
10268		 *  @name DataTable.defaults.order
10269		 *
10270		 *  @example
10271		 *    // Sort by 3rd column first, and then 4th column
10272		 *    $(document).ready( function() {
10273		 *      $('#example').dataTable( {
10274		 *        "order": [[2,'asc'], [3,'desc']]
10275		 *      } );
10276		 *    } );
10277		 *
10278		 *    // No initial sorting
10279		 *    $(document).ready( function() {
10280		 *      $('#example').dataTable( {
10281		 *        "order": []
10282		 *      } );
10283		 *    } );
10284		 */
10285		"aaSorting": [[0,'asc']],
10286	
10287	
10288		/**
10289		 * This parameter is basically identical to the `sorting` parameter, but
10290		 * cannot be overridden by user interaction with the table. What this means
10291		 * is that you could have a column (visible or hidden) which the sorting
10292		 * will always be forced on first - any sorting after that (from the user)
10293		 * will then be performed as required. This can be useful for grouping rows
10294		 * together.
10295		 *  @type array
10296		 *  @default null
10297		 *
10298		 *  @dtopt Option
10299		 *  @name DataTable.defaults.orderFixed
10300		 *
10301		 *  @example
10302		 *    $(document).ready( function() {
10303		 *      $('#example').dataTable( {
10304		 *        "orderFixed": [[0,'asc']]
10305		 *      } );
10306		 *    } )
10307		 */
10308		"aaSortingFixed": [],
10309	
10310	
10311		/**
10312		 * DataTables can be instructed to load data to display in the table from a
10313		 * Ajax source. This option defines how that Ajax call is made and where to.
10314		 *
10315		 * The `ajax` property has three different modes of operation, depending on
10316		 * how it is defined. These are:
10317		 *
10318		 * * `string` - Set the URL from where the data should be loaded from.
10319		 * * `object` - Define properties for `jQuery.ajax`.
10320		 * * `function` - Custom data get function
10321		 *
10322		 * `string`
10323		 * --------
10324		 *
10325		 * As a string, the `ajax` property simply defines the URL from which
10326		 * DataTables will load data.
10327		 *
10328		 * `object`
10329		 * --------
10330		 *
10331		 * As an object, the parameters in the object are passed to
10332		 * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control
10333		 * of the Ajax request. DataTables has a number of default parameters which
10334		 * you can override using this option. Please refer to the jQuery
10335		 * documentation for a full description of the options available, although
10336		 * the following parameters provide additional options in DataTables or
10337		 * require special consideration:
10338		 *
10339		 * * `data` - As with jQuery, `data` can be provided as an object, but it
10340		 *   can also be used as a function to manipulate the data DataTables sends
10341		 *   to the server. The function takes a single parameter, an object of
10342		 *   parameters with the values that DataTables has readied for sending. An
10343		 *   object may be returned which will be merged into the DataTables
10344		 *   defaults, or you can add the items to the object that was passed in and
10345		 *   not return anything from the function. This supersedes `fnServerParams`
10346		 *   from DataTables 1.9-.
10347		 *
10348		 * * `dataSrc` - By default DataTables will look for the property `data` (or
10349		 *   `aaData` for compatibility with DataTables 1.9-) when obtaining data
10350		 *   from an Ajax source or for server-side processing - this parameter
10351		 *   allows that property to be changed. You can use Javascript dotted
10352		 *   object notation to get a data source for multiple levels of nesting, or
10353		 *   it my be used as a function. As a function it takes a single parameter,
10354		 *   the JSON returned from the server, which can be manipulated as
10355		 *   required, with the returned value being that used by DataTables as the
10356		 *   data source for the table. This supersedes `sAjaxDataProp` from
10357		 *   DataTables 1.9-.
10358		 *
10359		 * * `success` - Should not be overridden it is used internally in
10360		 *   DataTables. To manipulate / transform the data returned by the server
10361		 *   use `ajax.dataSrc`, or use `ajax` as a function (see below).
10362		 *
10363		 * `function`
10364		 * ----------
10365		 *
10366		 * As a function, making the Ajax call is left up to yourself allowing
10367		 * complete control of the Ajax request. Indeed, if desired, a method other
10368		 * than Ajax could be used to obtain the required data, such as Web storage
10369		 * or an AIR database.
10370		 *
10371		 * The function is given four parameters and no return is required. The
10372		 * parameters are:
10373		 *
10374		 * 1. _object_ - Data to send to the server
10375		 * 2. _function_ - Callback function that must be executed when the required
10376		 *    data has been obtained. That data should be passed into the callback
10377		 *    as the only parameter
10378		 * 3. _object_ - DataTables settings object for the table
10379		 *
10380		 * Note that this supersedes `fnServerData` from DataTables 1.9-.
10381		 *
10382		 *  @type string|object|function
10383		 *  @default null
10384		 *
10385		 *  @dtopt Option
10386		 *  @name DataTable.defaults.ajax
10387		 *  @since 1.10.0
10388		 *
10389		 * @example
10390		 *   // Get JSON data from a file via Ajax.
10391		 *   // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default).
10392		 *   $('#example').dataTable( {
10393		 *     "ajax": "data.json"
10394		 *   } );
10395		 *
10396		 * @example
10397		 *   // Get JSON data from a file via Ajax, using `dataSrc` to change
10398		 *   // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`)
10399		 *   $('#example').dataTable( {
10400		 *     "ajax": {
10401		 *       "url": "data.json",
10402		 *       "dataSrc": "tableData"
10403		 *     }
10404		 *   } );
10405		 *
10406		 * @example
10407		 *   // Get JSON data from a file via Ajax, using `dataSrc` to read data
10408		 *   // from a plain array rather than an array in an object
10409		 *   $('#example').dataTable( {
10410		 *     "ajax": {
10411		 *       "url": "data.json",
10412		 *       "dataSrc": ""
10413		 *     }
10414		 *   } );
10415		 *
10416		 * @example
10417		 *   // Manipulate the data returned from the server - add a link to data
10418		 *   // (note this can, should, be done using `render` for the column - this
10419		 *   // is just a simple example of how the data can be manipulated).
10420		 *   $('#example').dataTable( {
10421		 *     "ajax": {
10422		 *       "url": "data.json",
10423		 *       "dataSrc": function ( json ) {
10424		 *         for ( var i=0, ien=json.length ; i<ien ; i++ ) {
10425		 *           json[i][0] = '<a href="/message/'+json[i][0]+'>View message</a>';
10426		 *         }
10427		 *         return json;
10428		 *       }
10429		 *     }
10430		 *   } );
10431		 *
10432		 * @example
10433		 *   // Add data to the request
10434		 *   $('#example').dataTable( {
10435		 *     "ajax": {
10436		 *       "url": "data.json",
10437		 *       "data": function ( d ) {
10438		 *         return {
10439		 *           "extra_search": $('#extra').val()
10440		 *         };
10441		 *       }
10442		 *     }
10443		 *   } );
10444		 *
10445		 * @example
10446		 *   // Send request as POST
10447		 *   $('#example').dataTable( {
10448		 *     "ajax": {
10449		 *       "url": "data.json",
10450		 *       "type": "POST"
10451		 *     }
10452		 *   } );
10453		 *
10454		 * @example
10455		 *   // Get the data from localStorage (could interface with a form for
10456		 *   // adding, editing and removing rows).
10457		 *   $('#example').dataTable( {
10458		 *     "ajax": function (data, callback, settings) {
10459		 *       callback(
10460		 *         JSON.parse( localStorage.getItem('dataTablesData') )
10461		 *       );
10462		 *     }
10463		 *   } );
10464		 */
10465		"ajax": null,
10466	
10467	
10468		/**
10469		 * This parameter allows you to readily specify the entries in the length drop
10470		 * down menu that DataTables shows when pagination is enabled. It can be
10471		 * either a 1D array of options which will be used for both the displayed
10472		 * option and the value, or a 2D array which will use the array in the first
10473		 * position as the value, and the array in the second position as the
10474		 * displayed options (useful for language strings such as 'All').
10475		 *
10476		 * Note that the `pageLength` property will be automatically set to the
10477		 * first value given in this array, unless `pageLength` is also provided.
10478		 *  @type array
10479		 *  @default [ 10, 25, 50, 100 ]
10480		 *
10481		 *  @dtopt Option
10482		 *  @name DataTable.defaults.lengthMenu
10483		 *
10484		 *  @example
10485		 *    $(document).ready( function() {
10486		 *      $('#example').dataTable( {
10487		 *        "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
10488		 *      } );
10489		 *    } );
10490		 */
10491		"aLengthMenu": [ 10, 25, 50, 100 ],
10492	
10493	
10494		/**
10495		 * The `columns` option in the initialisation parameter allows you to define
10496		 * details about the way individual columns behave. For a full list of
10497		 * column options that can be set, please see
10498		 * {@link DataTable.defaults.column}. Note that if you use `columns` to
10499		 * define your columns, you must have an entry in the array for every single
10500		 * column that you have in your table (these can be null if you don't which
10501		 * to specify any options).
10502		 *  @member
10503		 *
10504		 *  @name DataTable.defaults.column
10505		 */
10506		"aoColumns": null,
10507	
10508		/**
10509		 * Very similar to `columns`, `columnDefs` allows you to target a specific
10510		 * column, multiple columns, or all columns, using the `targets` property of
10511		 * each object in the array. This allows great flexibility when creating
10512		 * tables, as the `columnDefs` arrays can be of any length, targeting the
10513		 * columns you specifically want. `columnDefs` may use any of the column
10514		 * options available: {@link DataTable.defaults.column}, but it _must_
10515		 * have `targets` defined in each object in the array. Values in the `targets`
10516		 * array may be:
10517		 *   <ul>
10518		 *     <li>a string - class name will be matched on the TH for the column</li>
10519		 *     <li>0 or a positive integer - column index counting from the left</li>
10520		 *     <li>a negative integer - column index counting from the right</li>
10521		 *     <li>the string "_all" - all columns (i.e. assign a default)</li>
10522		 *   </ul>
10523		 *  @member
10524		 *
10525		 *  @name DataTable.defaults.columnDefs
10526		 */
10527		"aoColumnDefs": null,
10528	
10529	
10530		/**
10531		 * Basically the same as `search`, this parameter defines the individual column
10532		 * filtering state at initialisation time. The array must be of the same size
10533		 * as the number of columns, and each element be an object with the parameters
10534		 * `search` and `escapeRegex` (the latter is optional). 'null' is also
10535		 * accepted and the default will be used.
10536		 *  @type array
10537		 *  @default []
10538		 *
10539		 *  @dtopt Option
10540		 *  @name DataTable.defaults.searchCols
10541		 *
10542		 *  @example
10543		 *    $(document).ready( function() {
10544		 *      $('#example').dataTable( {
10545		 *        "searchCols": [
10546		 *          null,
10547		 *          { "search": "My filter" },
10548		 *          null,
10549		 *          { "search": "^[0-9]", "escapeRegex": false }
10550		 *        ]
10551		 *      } );
10552		 *    } )
10553		 */
10554		"aoSearchCols": [],
10555	
10556	
10557		/**
10558		 * An array of CSS classes that should be applied to displayed rows. This
10559		 * array may be of any length, and DataTables will apply each class
10560		 * sequentially, looping when required.
10561		 *  @type array
10562		 *  @default null <i>Will take the values determined by the `oClasses.stripe*`
10563		 *    options</i>
10564		 *
10565		 *  @dtopt Option
10566		 *  @name DataTable.defaults.stripeClasses
10567		 *
10568		 *  @example
10569		 *    $(document).ready( function() {
10570		 *      $('#example').dataTable( {
10571		 *        "stripeClasses": [ 'strip1', 'strip2', 'strip3' ]
10572		 *      } );
10573		 *    } )
10574		 */
10575		"asStripeClasses": null,
10576	
10577	
10578		/**
10579		 * Enable or disable automatic column width calculation. This can be disabled
10580		 * as an optimisation (it takes some time to calculate the widths) if the
10581		 * tables widths are passed in using `columns`.
10582		 *  @type boolean
10583		 *  @default true
10584		 *
10585		 *  @dtopt Features
10586		 *  @name DataTable.defaults.autoWidth
10587		 *
10588		 *  @example
10589		 *    $(document).ready( function () {
10590		 *      $('#example').dataTable( {
10591		 *        "autoWidth": false
10592		 *      } );
10593		 *    } );
10594		 */
10595		"bAutoWidth": true,
10596	
10597	
10598		/**
10599		 * Deferred rendering can provide DataTables with a huge speed boost when you
10600		 * are using an Ajax or JS data source for the table. This option, when set to
10601		 * true, will cause DataTables to defer the creation of the table elements for
10602		 * each row until they are needed for a draw - saving a significant amount of
10603		 * time.
10604		 *  @type boolean
10605		 *  @default false
10606		 *
10607		 *  @dtopt Features
10608		 *  @name DataTable.defaults.deferRender
10609		 *
10610		 *  @example
10611		 *    $(document).ready( function() {
10612		 *      $('#example').dataTable( {
10613		 *        "ajax": "sources/arrays.txt",
10614		 *        "deferRender": true
10615		 *      } );
10616		 *    } );
10617		 */
10618		"bDeferRender": false,
10619	
10620	
10621		/**
10622		 * Replace a DataTable which matches the given selector and replace it with
10623		 * one which has the properties of the new initialisation object passed. If no
10624		 * table matches the selector, then the new DataTable will be constructed as
10625		 * per normal.
10626		 *  @type boolean
10627		 *  @default false
10628		 *
10629		 *  @dtopt Options
10630		 *  @name DataTable.defaults.destroy
10631		 *
10632		 *  @example
10633		 *    $(document).ready( function() {
10634		 *      $('#example').dataTable( {
10635		 *        "srollY": "200px",
10636		 *        "paginate": false
10637		 *      } );
10638		 *
10639		 *      // Some time later....
10640		 *      $('#example').dataTable( {
10641		 *        "filter": false,
10642		 *        "destroy": true
10643		 *      } );
10644		 *    } );
10645		 */
10646		"bDestroy": false,
10647	
10648	
10649		/**
10650		 * Enable or disable filtering of data. Filtering in DataTables is "smart" in
10651		 * that it allows the end user to input multiple words (space separated) and
10652		 * will match a row containing those words, even if not in the order that was
10653		 * specified (this allow matching across multiple columns). Note that if you
10654		 * wish to use filtering in DataTables this must remain 'true' - to remove the
10655		 * default filtering input box and retain filtering abilities, please use
10656		 * {@link DataTable.defaults.dom}.
10657		 *  @type boolean
10658		 *  @default true
10659		 *
10660		 *  @dtopt Features
10661		 *  @name DataTable.defaults.searching
10662		 *
10663		 *  @example
10664		 *    $(document).ready( function () {
10665		 *      $('#example').dataTable( {
10666		 *        "searching": false
10667		 *      } );
10668		 *    } );
10669		 */
10670		"bFilter": true,
10671	
10672	
10673		/**
10674		 * Enable or disable the table information display. This shows information
10675		 * about the data that is currently visible on the page, including information
10676		 * about filtered data if that action is being performed.
10677		 *  @type boolean
10678		 *  @default true
10679		 *
10680		 *  @dtopt Features
10681		 *  @name DataTable.defaults.info
10682		 *
10683		 *  @example
10684		 *    $(document).ready( function () {
10685		 *      $('#example').dataTable( {
10686		 *        "info": false
10687		 *      } );
10688		 *    } );
10689		 */
10690		"bInfo": true,
10691	
10692	
10693		/**
10694		 * Allows the end user to select the size of a formatted page from a select
10695		 * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`).
10696		 *  @type boolean
10697		 *  @default true
10698		 *
10699		 *  @dtopt Features
10700		 *  @name DataTable.defaults.lengthChange
10701		 *
10702		 *  @example
10703		 *    $(document).ready( function () {
10704		 *      $('#example').dataTable( {
10705		 *        "lengthChange": false
10706		 *      } );
10707		 *    } );
10708		 */
10709		"bLengthChange": true,
10710	
10711	
10712		/**
10713		 * Enable or disable pagination.
10714		 *  @type boolean
10715		 *  @default true
10716		 *
10717		 *  @dtopt Features
10718		 *  @name DataTable.defaults.paging
10719		 *
10720		 *  @example
10721		 *    $(document).ready( function () {
10722		 *      $('#example').dataTable( {
10723		 *        "paging": false
10724		 *      } );
10725		 *    } );
10726		 */
10727		"bPaginate": true,
10728	
10729	
10730		/**
10731		 * Enable or disable the display of a 'processing' indicator when the table is
10732		 * being processed (e.g. a sort). This is particularly useful for tables with
10733		 * large amounts of data where it can take a noticeable amount of time to sort
10734		 * the entries.
10735		 *  @type boolean
10736		 *  @default false
10737		 *
10738		 *  @dtopt Features
10739		 *  @name DataTable.defaults.processing
10740		 *
10741		 *  @example
10742		 *    $(document).ready( function () {
10743		 *      $('#example').dataTable( {
10744		 *        "processing": true
10745		 *      } );
10746		 *    } );
10747		 */
10748		"bProcessing": false,
10749	
10750	
10751		/**
10752		 * Retrieve the DataTables object for the given selector. Note that if the
10753		 * table has already been initialised, this parameter will cause DataTables
10754		 * to simply return the object that has already been set up - it will not take
10755		 * account of any changes you might have made to the initialisation object
10756		 * passed to DataTables (setting this parameter to true is an acknowledgement
10757		 * that you understand this). `destroy` can be used to reinitialise a table if
10758		 * you need.
10759		 *  @type boolean
10760		 *  @default false
10761		 *
10762		 *  @dtopt Options
10763		 *  @name DataTable.defaults.retrieve
10764		 *
10765		 *  @example
10766		 *    $(document).ready( function() {
10767		 *      initTable();
10768		 *      tableActions();
10769		 *    } );
10770		 *
10771		 *    function initTable ()
10772		 *    {
10773		 *      return $('#example').dataTable( {
10774		 *        "scrollY": "200px",
10775		 *        "paginate": false,
10776		 *        "retrieve": true
10777		 *      } );
10778		 *    }
10779		 *
10780		 *    function tableActions ()
10781		 *    {
10782		 *      var table = initTable();
10783		 *      // perform API operations with oTable
10784		 *    }
10785		 */
10786		"bRetrieve": false,
10787	
10788	
10789		/**
10790		 * When vertical (y) scrolling is enabled, DataTables will force the height of
10791		 * the table's viewport to the given height at all times (useful for layout).
10792		 * However, this can look odd when filtering data down to a small data set,
10793		 * and the footer is left "floating" further down. This parameter (when
10794		 * enabled) will cause DataTables to collapse the table's viewport down when
10795		 * the result set will fit within the given Y height.
10796		 *  @type boolean
10797		 *  @default false
10798		 *
10799		 *  @dtopt Options
10800		 *  @name DataTable.defaults.scrollCollapse
10801		 *
10802		 *  @example
10803		 *    $(document).ready( function() {
10804		 *      $('#example').dataTable( {
10805		 *        "scrollY": "200",
10806		 *        "scrollCollapse": true
10807		 *      } );
10808		 *    } );
10809		 */
10810		"bScrollCollapse": false,
10811	
10812	
10813		/**
10814		 * Configure DataTables to use server-side processing. Note that the
10815		 * `ajax` parameter must also be given in order to give DataTables a
10816		 * source to obtain the required data for each draw.
10817		 *  @type boolean
10818		 *  @default false
10819		 *
10820		 *  @dtopt Features
10821		 *  @dtopt Server-side
10822		 *  @name DataTable.defaults.serverSide
10823		 *
10824		 *  @example
10825		 *    $(document).ready( function () {
10826		 *      $('#example').dataTable( {
10827		 *        "serverSide": true,
10828		 *        "ajax": "xhr.php"
10829		 *      } );
10830		 *    } );
10831		 */
10832		"bServerSide": false,
10833	
10834	
10835		/**
10836		 * Enable or disable sorting of columns. Sorting of individual columns can be
10837		 * disabled by the `sortable` option for each column.
10838		 *  @type boolean
10839		 *  @default true
10840		 *
10841		 *  @dtopt Features
10842		 *  @name DataTable.defaults.ordering
10843		 *
10844		 *  @example
10845		 *    $(document).ready( function () {
10846		 *      $('#example').dataTable( {
10847		 *        "ordering": false
10848		 *      } );
10849		 *    } );
10850		 */
10851		"bSort": true,
10852	
10853	
10854		/**
10855		 * Enable or display DataTables' ability to sort multiple columns at the
10856		 * same time (activated by shift-click by the user).
10857		 *  @type boolean
10858		 *  @default true
10859		 *
10860		 *  @dtopt Options
10861		 *  @name DataTable.defaults.orderMulti
10862		 *
10863		 *  @example
10864		 *    // Disable multiple column sorting ability
10865		 *    $(document).ready( function () {
10866		 *      $('#example').dataTable( {
10867		 *        "orderMulti": false
10868		 *      } );
10869		 *    } );
10870		 */
10871		"bSortMulti": true,
10872	
10873	
10874		/**
10875		 * Allows control over whether DataTables should use the top (true) unique
10876		 * cell that is found for a single column, or the bottom (false - default).
10877		 * This is useful when using complex headers.
10878		 *  @type boolean
10879		 *  @default false
10880		 *
10881		 *  @dtopt Options
10882		 *  @name DataTable.defaults.orderCellsTop
10883		 *
10884		 *  @example
10885		 *    $(document).ready( function() {
10886		 *      $('#example').dataTable( {
10887		 *        "orderCellsTop": true
10888		 *      } );
10889		 *    } );
10890		 */
10891		"bSortCellsTop": false,
10892	
10893	
10894		/**
10895		 * Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and
10896		 * `sorting\_3` to the columns which are currently being sorted on. This is
10897		 * presented as a feature switch as it can increase processing time (while
10898		 * classes are removed and added) so for large data sets you might want to
10899		 * turn this off.
10900		 *  @type boolean
10901		 *  @default true
10902		 *
10903		 *  @dtopt Features
10904		 *  @name DataTable.defaults.orderClasses
10905		 *
10906		 *  @example
10907		 *    $(document).ready( function () {
10908		 *      $('#example').dataTable( {
10909		 *        "orderClasses": false
10910		 *      } );
10911		 *    } );
10912		 */
10913		"bSortClasses": true,
10914	
10915	
10916		/**
10917		 * Enable or disable state saving. When enabled HTML5 `localStorage` will be
10918		 * used to save table display information such as pagination information,
10919		 * display length, filtering and sorting. As such when the end user reloads
10920		 * the page the display display will match what thy had previously set up.
10921		 *
10922		 * Due to the use of `localStorage` the default state saving is not supported
10923		 * in IE6 or 7. If state saving is required in those browsers, use
10924		 * `stateSaveCallback` to provide a storage solution such as cookies.
10925		 *  @type boolean
10926		 *  @default false
10927		 *
10928		 *  @dtopt Features
10929		 *  @name DataTable.defaults.stateSave
10930		 *
10931		 *  @example
10932		 *    $(document).ready( function () {
10933		 *      $('#example').dataTable( {
10934		 *        "stateSave": true
10935		 *      } );
10936		 *    } );
10937		 */
10938		"bStateSave": false,
10939	
10940	
10941		/**
10942		 * This function is called when a TR element is created (and all TD child
10943		 * elements have been inserted), or registered if using a DOM source, allowing
10944		 * manipulation of the TR element (adding classes etc).
10945		 *  @type function
10946		 *  @param {node} row "TR" element for the current row
10947		 *  @param {array} data Raw data array for this row
10948		 *  @param {int} dataIndex The index of this row in the internal aoData array
10949		 *
10950		 *  @dtopt Callbacks
10951		 *  @name DataTable.defaults.createdRow
10952		 *
10953		 *  @example
10954		 *    $(document).ready( function() {
10955		 *      $('#example').dataTable( {
10956		 *        "createdRow": function( row, data, dataIndex ) {
10957		 *          // Bold the grade for all 'A' grade browsers
10958		 *          if ( data[4] == "A" )
10959		 *          {
10960		 *            $('td:eq(4)', row).html( '<b>A</b>' );
10961		 *          }
10962		 *        }
10963		 *      } );
10964		 *    } );
10965		 */
10966		"fnCreatedRow": null,
10967	
10968	
10969		/**
10970		 * This function is called on every 'draw' event, and allows you to
10971		 * dynamically modify any aspect you want about the created DOM.
10972		 *  @type function
10973		 *  @param {object} settings DataTables settings object
10974		 *
10975		 *  @dtopt Callbacks
10976		 *  @name DataTable.defaults.drawCallback
10977		 *
10978		 *  @example
10979		 *    $(document).ready( function() {
10980		 *      $('#example').dataTable( {
10981		 *        "drawCallback": function( settings ) {
10982		 *          alert( 'DataTables has redrawn the table' );
10983		 *        }
10984		 *      } );
10985		 *    } );
10986		 */
10987		"fnDrawCallback": null,
10988	
10989	
10990		/**
10991		 * Identical to fnHeaderCallback() but for the table footer this function
10992		 * allows you to modify the table footer on every 'draw' event.
10993		 *  @type function
10994		 *  @param {node} foot "TR" element for the footer
10995		 *  @param {array} data Full table data (as derived from the original HTML)
10996		 *  @param {int} start Index for the current display starting point in the
10997		 *    display array
10998		 *  @param {int} end Index for the current display ending point in the
10999		 *    display array
11000		 *  @param {array int} display Index array to translate the visual position
11001		 *    to the full data array
11002		 *
11003		 *  @dtopt Callbacks
11004		 *  @name DataTable.defaults.footerCallback
11005		 *
11006		 *  @example
11007		 *    $(document).ready( function() {
11008		 *      $('#example').dataTable( {
11009		 *        "footerCallback": function( tfoot, data, start, end, display ) {
11010		 *          tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start;
11011		 *        }
11012		 *      } );
11013		 *    } )
11014		 */
11015		"fnFooterCallback": null,
11016	
11017	
11018		/**
11019		 * When rendering large numbers in the information element for the table
11020		 * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
11021		 * to have a comma separator for the 'thousands' units (e.g. 1 million is
11022		 * rendered as "1,000,000") to help readability for the end user. This
11023		 * function will override the default method DataTables uses.
11024		 *  @type function
11025		 *  @member
11026		 *  @param {int} toFormat number to be formatted
11027		 *  @returns {string} formatted string for DataTables to show the number
11028		 *
11029		 *  @dtopt Callbacks
11030		 *  @name DataTable.defaults.formatNumber
11031		 *
11032		 *  @example
11033		 *    // Format a number using a single quote for the separator (note that
11034		 *    // this can also be done with the language.thousands option)
11035		 *    $(document).ready( function() {
11036		 *      $('#example').dataTable( {
11037		 *        "formatNumber": function ( toFormat ) {
11038		 *          return toFormat.toString().replace(
11039		 *            /\B(?=(\d{3})+(?!\d))/g, "'"
11040		 *          );
11041		 *        };
11042		 *      } );
11043		 *    } );
11044		 */
11045		"fnFormatNumber": function ( toFormat ) {
11046			return toFormat.toString().replace(
11047				/\B(?=(\d{3})+(?!\d))/g,
11048				this.oLanguage.sThousands
11049			);
11050		},
11051	
11052	
11053		/**
11054		 * This function is called on every 'draw' event, and allows you to
11055		 * dynamically modify the header row. This can be used to calculate and
11056		 * display useful information about the table.
11057		 *  @type function
11058		 *  @param {node} head "TR" element for the header
11059		 *  @param {array} data Full table data (as derived from the original HTML)
11060		 *  @param {int} start Index for the current display starting point in the
11061		 *    display array
11062		 *  @param {int} end Index for the current display ending point in the
11063		 *    display array
11064		 *  @param {array int} display Index array to translate the visual position
11065		 *    to the full data array
11066		 *
11067		 *  @dtopt Callbacks
11068		 *  @name DataTable.defaults.headerCallback
11069		 *
11070		 *  @example
11071		 *    $(document).ready( function() {
11072		 *      $('#example').dataTable( {
11073		 *        "fheaderCallback": function( head, data, start, end, display ) {
11074		 *          head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records";
11075		 *        }
11076		 *      } );
11077		 *    } )
11078		 */
11079		"fnHeaderCallback": null,
11080	
11081	
11082		/**
11083		 * The information element can be used to convey information about the current
11084		 * state of the table. Although the internationalisation options presented by
11085		 * DataTables are quite capable of dealing with most customisations, there may
11086		 * be times where you wish to customise the string further. This callback
11087		 * allows you to do exactly that.
11088		 *  @type function
11089		 *  @param {object} oSettings DataTables settings object
11090		 *  @param {int} start Starting position in data for the draw
11091		 *  @param {int} end End position in data for the draw
11092		 *  @param {int} max Total number of rows in the table (regardless of
11093		 *    filtering)
11094		 *  @param {int} total Total number of rows in the data set, after filtering
11095		 *  @param {string} pre The string that DataTables has formatted using it's
11096		 *    own rules
11097		 *  @returns {string} The string to be displayed in the information element.
11098		 *
11099		 *  @dtopt Callbacks
11100		 *  @name DataTable.defaults.infoCallback
11101		 *
11102		 *  @example
11103		 *    $('#example').dataTable( {
11104		 *      "infoCallback": function( settings, start, end, max, total, pre ) {
11105		 *        return start +" to "+ end;
11106		 *      }
11107		 *    } );
11108		 */
11109		"fnInfoCallback": null,
11110	
11111	
11112		/**
11113		 * Called when the table has been initialised. Normally DataTables will
11114		 * initialise sequentially and there will be no need for this function,
11115		 * however, this does not hold true when using external language information
11116		 * since that is obtained using an async XHR call.
11117		 *  @type function
11118		 *  @param {object} settings DataTables settings object
11119		 *  @param {object} json The JSON object request from the server - only
11120		 *    present if client-side Ajax sourced data is used
11121		 *
11122		 *  @dtopt Callbacks
11123		 *  @name DataTable.defaults.initComplete
11124		 *
11125		 *  @example
11126		 *    $(document).ready( function() {
11127		 *      $('#example').dataTable( {
11128		 *        "initComplete": function(settings, json) {
11129		 *          alert( 'DataTables has finished its initialisation.' );
11130		 *        }
11131		 *      } );
11132		 *    } )
11133		 */
11134		"fnInitComplete": null,
11135	
11136	
11137		/**
11138		 * Called at the very start of each table draw and can be used to cancel the
11139		 * draw by returning false, any other return (including undefined) results in
11140		 * the full draw occurring).
11141		 *  @type function
11142		 *  @param {object} settings DataTables settings object
11143		 *  @returns {boolean} False will cancel the draw, anything else (including no
11144		 *    return) will allow it to complete.
11145		 *
11146		 *  @dtopt Callbacks
11147		 *  @name DataTable.defaults.preDrawCallback
11148		 *
11149		 *  @example
11150		 *    $(document).ready( function() {
11151		 *      $('#example').dataTable( {
11152		 *        "preDrawCallback": function( settings ) {
11153		 *          if ( $('#test').val() == 1 ) {
11154		 *            return false;
11155		 *          }
11156		 *        }
11157		 *      } );
11158		 *    } );
11159		 */
11160		"fnPreDrawCallback": null,
11161	
11162	
11163		/**
11164		 * This function allows you to 'post process' each row after it have been
11165		 * generated for each table draw, but before it is rendered on screen. This
11166		 * function might be used for setting the row class name etc.
11167		 *  @type function
11168		 *  @param {node} row "TR" element for the current row
11169		 *  @param {array} data Raw data array for this row
11170		 *  @param {int} displayIndex The display index for the current table draw
11171		 *  @param {int} displayIndexFull The index of the data in the full list of
11172		 *    rows (after filtering)
11173		 *
11174		 *  @dtopt Callbacks
11175		 *  @name DataTable.defaults.rowCallback
11176		 *
11177		 *  @example
11178		 *    $(document).ready( function() {
11179		 *      $('#example').dataTable( {
11180		 *        "rowCallback": function( row, data, displayIndex, displayIndexFull ) {
11181		 *          // Bold the grade for all 'A' grade browsers
11182		 *          if ( data[4] == "A" ) {
11183		 *            $('td:eq(4)', row).html( '<b>A</b>' );
11184		 *          }
11185		 *        }
11186		 *      } );
11187		 *    } );
11188		 */
11189		"fnRowCallback": null,
11190	
11191	
11192		/**
11193		 * __Deprecated__ The functionality provided by this parameter has now been
11194		 * superseded by that provided through `ajax`, which should be used instead.
11195		 *
11196		 * This parameter allows you to override the default function which obtains
11197		 * the data from the server so something more suitable for your application.
11198		 * For example you could use POST data, or pull information from a Gears or
11199		 * AIR database.
11200		 *  @type function
11201		 *  @member
11202		 *  @param {string} source HTTP source to obtain the data from (`ajax`)
11203		 *  @param {array} data A key/value pair object containing the data to send
11204		 *    to the server
11205		 *  @param {function} callback to be called on completion of the data get
11206		 *    process that will draw the data on the page.
11207		 *  @param {object} settings DataTables settings object
11208		 *
11209		 *  @dtopt Callbacks
11210		 *  @dtopt Server-side
11211		 *  @name DataTable.defaults.serverData
11212		 *
11213		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11214		 */
11215		"fnServerData": null,
11216	
11217	
11218		/**
11219		 * __Deprecated__ The functionality provided by this parameter has now been
11220		 * superseded by that provided through `ajax`, which should be used instead.
11221		 *
11222		 *  It is often useful to send extra data to the server when making an Ajax
11223		 * request - for example custom filtering information, and this callback
11224		 * function makes it trivial to send extra information to the server. The
11225		 * passed in parameter is the data set that has been constructed by
11226		 * DataTables, and you can add to this or modify it as you require.
11227		 *  @type function
11228		 *  @param {array} data Data array (array of objects which are name/value
11229		 *    pairs) that has been constructed by DataTables and will be sent to the
11230		 *    server. In the case of Ajax sourced data with server-side processing
11231		 *    this will be an empty array, for server-side processing there will be a
11232		 *    significant number of parameters!
11233		 *  @returns {undefined} Ensure that you modify the data array passed in,
11234		 *    as this is passed by reference.
11235		 *
11236		 *  @dtopt Callbacks
11237		 *  @dtopt Server-side
11238		 *  @name DataTable.defaults.serverParams
11239		 *
11240		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11241		 */
11242		"fnServerParams": null,
11243	
11244	
11245		/**
11246		 * Load the table state. With this function you can define from where, and how, the
11247		 * state of a table is loaded. By default DataTables will load from `localStorage`
11248		 * but you might wish to use a server-side database or cookies.
11249		 *  @type function
11250		 *  @member
11251		 *  @param {object} settings DataTables settings object
11252		 *  @param {object} callback Callback that can be executed when done. It
11253		 *    should be passed the loaded state object.
11254		 *  @return {object} The DataTables state object to be loaded
11255		 *
11256		 *  @dtopt Callbacks
11257		 *  @name DataTable.defaults.stateLoadCallback
11258		 *
11259		 *  @example
11260		 *    $(document).ready( function() {
11261		 *      $('#example').dataTable( {
11262		 *        "stateSave": true,
11263		 *        "stateLoadCallback": function (settings, callback) {
11264		 *          $.ajax( {
11265		 *            "url": "/state_load",
11266		 *            "dataType": "json",
11267		 *            "success": function (json) {
11268		 *              callback( json );
11269		 *            }
11270		 *          } );
11271		 *        }
11272		 *      } );
11273		 *    } );
11274		 */
11275		"fnStateLoadCallback": function ( settings ) {
11276			try {
11277				return JSON.parse(
11278					(settings.iStateDuration === -1 ? sessionStorage : localStorage).getItem(
11279						'DataTables_'+settings.sInstance+'_'+location.pathname
11280					)
11281				);
11282			} catch (e) {
11283				return {};
11284			}
11285		},
11286	
11287	
11288		/**
11289		 * Callback which allows modification of the saved state prior to loading that state.
11290		 * This callback is called when the table is loading state from the stored data, but
11291		 * prior to the settings object being modified by the saved state. Note that for
11292		 * plug-in authors, you should use the `stateLoadParams` event to load parameters for
11293		 * a plug-in.
11294		 *  @type function
11295		 *  @param {object} settings DataTables settings object
11296		 *  @param {object} data The state object that is to be loaded
11297		 *
11298		 *  @dtopt Callbacks
11299		 *  @name DataTable.defaults.stateLoadParams
11300		 *
11301		 *  @example
11302		 *    // Remove a saved filter, so filtering is never loaded
11303		 *    $(document).ready( function() {
11304		 *      $('#example').dataTable( {
11305		 *        "stateSave": true,
11306		 *        "stateLoadParams": function (settings, data) {
11307		 *          data.oSearch.sSearch = "";
11308		 *        }
11309		 *      } );
11310		 *    } );
11311		 *
11312		 *  @example
11313		 *    // Disallow state loading by returning false
11314		 *    $(document).ready( function() {
11315		 *      $('#example').dataTable( {
11316		 *        "stateSave": true,
11317		 *        "stateLoadParams": function (settings, data) {
11318		 *          return false;
11319		 *        }
11320		 *      } );
11321		 *    } );
11322		 */
11323		"fnStateLoadParams": null,
11324	
11325	
11326		/**
11327		 * Callback that is called when the state has been loaded from the state saving method
11328		 * and the DataTables settings object has been modified as a result of the loaded state.
11329		 *  @type function
11330		 *  @param {object} settings DataTables settings object
11331		 *  @param {object} data The state object that was loaded
11332		 *
11333		 *  @dtopt Callbacks
11334		 *  @name DataTable.defaults.stateLoaded
11335		 *
11336		 *  @example
11337		 *    // Show an alert with the filtering value that was saved
11338		 *    $(document).ready( function() {
11339		 *      $('#example').dataTable( {
11340		 *        "stateSave": true,
11341		 *        "stateLoaded": function (settings, data) {
11342		 *          alert( 'Saved filter was: '+data.oSearch.sSearch );
11343		 *        }
11344		 *      } );
11345		 *    } );
11346		 */
11347		"fnStateLoaded": null,
11348	
11349	
11350		/**
11351		 * Save the table state. This function allows you to define where and how the state
11352		 * information for the table is stored By default DataTables will use `localStorage`
11353		 * but you might wish to use a server-side database or cookies.
11354		 *  @type function
11355		 *  @member
11356		 *  @param {object} settings DataTables settings object
11357		 *  @param {object} data The state object to be saved
11358		 *
11359		 *  @dtopt Callbacks
11360		 *  @name DataTable.defaults.stateSaveCallback
11361		 *
11362		 *  @example
11363		 *    $(document).ready( function() {
11364		 *      $('#example').dataTable( {
11365		 *        "stateSave": true,
11366		 *        "stateSaveCallback": function (settings, data) {
11367		 *          // Send an Ajax request to the server with the state object
11368		 *          $.ajax( {
11369		 *            "url": "/state_save",
11370		 *            "data": data,
11371		 *            "dataType": "json",
11372		 *            "method": "POST"
11373		 *            "success": function () {}
11374		 *          } );
11375		 *        }
11376		 *      } );
11377		 *    } );
11378		 */
11379		"fnStateSaveCallback": function ( settings, data ) {
11380			try {
11381				(settings.iStateDuration === -1 ? sessionStorage : localStorage).setItem(
11382					'DataTables_'+settings.sInstance+'_'+location.pathname,
11383					JSON.stringify( data )
11384				);
11385			} catch (e) {}
11386		},
11387	
11388	
11389		/**
11390		 * Callback which allows modification of the state to be saved. Called when the table
11391		 * has changed state a new state save is required. This method allows modification of
11392		 * the state saving object prior to actually doing the save, including addition or
11393		 * other state properties or modification. Note that for plug-in authors, you should
11394		 * use the `stateSaveParams` event to save parameters for a plug-in.
11395		 *  @type function
11396		 *  @param {object} settings DataTables settings object
11397		 *  @param {object} data The state object to be saved
11398		 *
11399		 *  @dtopt Callbacks
11400		 *  @name DataTable.defaults.stateSaveParams
11401		 *
11402		 *  @example
11403		 *    // Remove a saved filter, so filtering is never saved
11404		 *    $(document).ready( function() {
11405		 *      $('#example').dataTable( {
11406		 *        "stateSave": true,
11407		 *        "stateSaveParams": function (settings, data) {
11408		 *          data.oSearch.sSearch = "";
11409		 *        }
11410		 *      } );
11411		 *    } );
11412		 */
11413		"fnStateSaveParams": null,
11414	
11415	
11416		/**
11417		 * Duration for which the saved state information is considered valid. After this period
11418		 * has elapsed the state will be returned to the default.
11419		 * Value is given in seconds.
11420		 *  @type int
11421		 *  @default 7200 <i>(2 hours)</i>
11422		 *
11423		 *  @dtopt Options
11424		 *  @name DataTable.defaults.stateDuration
11425		 *
11426		 *  @example
11427		 *    $(document).ready( function() {
11428		 *      $('#example').dataTable( {
11429		 *        "stateDuration": 60*60*24; // 1 day
11430		 *      } );
11431		 *    } )
11432		 */
11433		"iStateDuration": 7200,
11434	
11435	
11436		/**
11437		 * When enabled DataTables will not make a request to the server for the first
11438		 * page draw - rather it will use the data already on the page (no sorting etc
11439		 * will be applied to it), thus saving on an XHR at load time. `deferLoading`
11440		 * is used to indicate that deferred loading is required, but it is also used
11441		 * to tell DataTables how many records there are in the full table (allowing
11442		 * the information element and pagination to be displayed correctly). In the case
11443		 * where a filtering is applied to the table on initial load, this can be
11444		 * indicated by giving the parameter as an array, where the first element is
11445		 * the number of records available after filtering and the second element is the
11446		 * number of records without filtering (allowing the table information element
11447		 * to be shown correctly).
11448		 *  @type int | array
11449		 *  @default null
11450		 *
11451		 *  @dtopt Options
11452		 *  @name DataTable.defaults.deferLoading
11453		 *
11454		 *  @example
11455		 *    // 57 records available in the table, no filtering applied
11456		 *    $(document).ready( function() {
11457		 *      $('#example').dataTable( {
11458		 *        "serverSide": true,
11459		 *        "ajax": "scripts/server_processing.php",
11460		 *        "deferLoading": 57
11461		 *      } );
11462		 *    } );
11463		 *
11464		 *  @example
11465		 *    // 57 records after filtering, 100 without filtering (an initial filter applied)
11466		 *    $(document).ready( function() {
11467		 *      $('#example').dataTable( {
11468		 *        "serverSide": true,
11469		 *        "ajax": "scripts/server_processing.php",
11470		 *        "deferLoading": [ 57, 100 ],
11471		 *        "search": {
11472		 *          "search": "my_filter"
11473		 *        }
11474		 *      } );
11475		 *    } );
11476		 */
11477		"iDeferLoading": null,
11478	
11479	
11480		/**
11481		 * Number of rows to display on a single page when using pagination. If
11482		 * feature enabled (`lengthChange`) then the end user will be able to override
11483		 * this to a custom setting using a pop-up menu.
11484		 *  @type int
11485		 *  @default 10
11486		 *
11487		 *  @dtopt Options
11488		 *  @name DataTable.defaults.pageLength
11489		 *
11490		 *  @example
11491		 *    $(document).ready( function() {
11492		 *      $('#example').dataTable( {
11493		 *        "pageLength": 50
11494		 *      } );
11495		 *    } )
11496		 */
11497		"iDisplayLength": 10,
11498	
11499	
11500		/**
11501		 * Define the starting point for data display when using DataTables with
11502		 * pagination. Note that this parameter is the number of records, rather than
11503		 * the page number, so if you have 10 records per page and want to start on
11504		 * the third page, it should be "20".
11505		 *  @type int
11506		 *  @default 0
11507		 *
11508		 *  @dtopt Options
11509		 *  @name DataTable.defaults.displayStart
11510		 *
11511		 *  @example
11512		 *    $(document).ready( function() {
11513		 *      $('#example').dataTable( {
11514		 *        "displayStart": 20
11515		 *      } );
11516		 *    } )
11517		 */
11518		"iDisplayStart": 0,
11519	
11520	
11521		/**
11522		 * By default DataTables allows keyboard navigation of the table (sorting, paging,
11523		 * and filtering) by adding a `tabindex` attribute to the required elements. This
11524		 * allows you to tab through the controls and press the enter key to activate them.
11525		 * The tabindex is default 0, meaning that the tab follows the flow of the document.
11526		 * You can overrule this using this parameter if you wish. Use a value of -1 to
11527		 * disable built-in keyboard navigation.
11528		 *  @type int
11529		 *  @default 0
11530		 *
11531		 *  @dtopt Options
11532		 *  @name DataTable.defaults.tabIndex
11533		 *
11534		 *  @example
11535		 *    $(document).ready( function() {
11536		 *      $('#example').dataTable( {
11537		 *        "tabIndex": 1
11538		 *      } );
11539		 *    } );
11540		 */
11541		"iTabIndex": 0,
11542	
11543	
11544		/**
11545		 * Classes that DataTables assigns to the various components and features
11546		 * that it adds to the HTML table. This allows classes to be configured
11547		 * during initialisation in addition to through the static
11548		 * {@link DataTable.ext.oStdClasses} object).
11549		 *  @namespace
11550		 *  @name DataTable.defaults.classes
11551		 */
11552		"oClasses": {},
11553	
11554	
11555		/**
11556		 * All strings that DataTables uses in the user interface that it creates
11557		 * are defined in this object, allowing you to modified them individually or
11558		 * completely replace them all as required.
11559		 *  @namespace
11560		 *  @name DataTable.defaults.language
11561		 */
11562		"oLanguage": {
11563			/**
11564			 * Strings that are used for WAI-ARIA labels and controls only (these are not
11565			 * actually visible on the page, but will be read by screenreaders, and thus
11566			 * must be internationalised as well).
11567			 *  @namespace
11568			 *  @name DataTable.defaults.language.aria
11569			 */
11570			"oAria": {
11571				/**
11572				 * ARIA label that is added to the table headers when the column may be
11573				 * sorted ascending by activing the column (click or return when focused).
11574				 * Note that the column header is prefixed to this string.
11575				 *  @type string
11576				 *  @default : activate to sort column ascending
11577				 *
11578				 *  @dtopt Language
11579				 *  @name DataTable.defaults.language.aria.sortAscending
11580				 *
11581				 *  @example
11582				 *    $(document).ready( function() {
11583				 *      $('#example').dataTable( {
11584				 *        "language": {
11585				 *          "aria": {
11586				 *            "sortAscending": " - click/return to sort ascending"
11587				 *          }
11588				 *        }
11589				 *      } );
11590				 *    } );
11591				 */
11592				"sSortAscending": ": activate to sort column ascending",
11593	
11594				/**
11595				 * ARIA label that is added to the table headers when the column may be
11596				 * sorted descending by activing the column (click or return when focused).
11597				 * Note that the column header is prefixed to this string.
11598				 *  @type string
11599				 *  @default : activate to sort column ascending
11600				 *
11601				 *  @dtopt Language
11602				 *  @name DataTable.defaults.language.aria.sortDescending
11603				 *
11604				 *  @example
11605				 *    $(document).ready( function() {
11606				 *      $('#example').dataTable( {
11607				 *        "language": {
11608				 *          "aria": {
11609				 *            "sortDescending": " - click/return to sort descending"
11610				 *          }
11611				 *        }
11612				 *      } );
11613				 *    } );
11614				 */
11615				"sSortDescending": ": activate to sort column descending"
11616			},
11617	
11618			/**
11619			 * Pagination string used by DataTables for the built-in pagination
11620			 * control types.
11621			 *  @namespace
11622			 *  @name DataTable.defaults.language.paginate
11623			 */
11624			"oPaginate": {
11625				/**
11626				 * Text to use when using the 'full_numbers' type of pagination for the
11627				 * button to take the user to the first page.
11628				 *  @type string
11629				 *  @default First
11630				 *
11631				 *  @dtopt Language
11632				 *  @name DataTable.defaults.language.paginate.first
11633				 *
11634				 *  @example
11635				 *    $(document).ready( function() {
11636				 *      $('#example').dataTable( {
11637				 *        "language": {
11638				 *          "paginate": {
11639				 *            "first": "First page"
11640				 *          }
11641				 *        }
11642				 *      } );
11643				 *    } );
11644				 */
11645				"sFirst": "First",
11646	
11647	
11648				/**
11649				 * Text to use when using the 'full_numbers' type of pagination for the
11650				 * button to take the user to the last page.
11651				 *  @type string
11652				 *  @default Last
11653				 *
11654				 *  @dtopt Language
11655				 *  @name DataTable.defaults.language.paginate.last
11656				 *
11657				 *  @example
11658				 *    $(document).ready( function() {
11659				 *      $('#example').dataTable( {
11660				 *        "language": {
11661				 *          "paginate": {
11662				 *            "last": "Last page"
11663				 *          }
11664				 *        }
11665				 *      } );
11666				 *    } );
11667				 */
11668				"sLast": "Last",
11669	
11670	
11671				/**
11672				 * Text to use for the 'next' pagination button (to take the user to the
11673				 * next page).
11674				 *  @type string
11675				 *  @default Next
11676				 *
11677				 *  @dtopt Language
11678				 *  @name DataTable.defaults.language.paginate.next
11679				 *
11680				 *  @example
11681				 *    $(document).ready( function() {
11682				 *      $('#example').dataTable( {
11683				 *        "language": {
11684				 *          "paginate": {
11685				 *            "next": "Next page"
11686				 *          }
11687				 *        }
11688				 *      } );
11689				 *    } );
11690				 */
11691				"sNext": "Next",
11692	
11693	
11694				/**
11695				 * Text to use for the 'previous' pagination button (to take the user to
11696				 * the previous page).
11697				 *  @type string
11698				 *  @default Previous
11699				 *
11700				 *  @dtopt Language
11701				 *  @name DataTable.defaults.language.paginate.previous
11702				 *
11703				 *  @example
11704				 *    $(document).ready( function() {
11705				 *      $('#example').dataTable( {
11706				 *        "language": {
11707				 *          "paginate": {
11708				 *            "previous": "Previous page"
11709				 *          }
11710				 *        }
11711				 *      } );
11712				 *    } );
11713				 */
11714				"sPrevious": "Previous"
11715			},
11716	
11717			/**
11718			 * This string is shown in preference to `zeroRecords` when the table is
11719			 * empty of data (regardless of filtering). Note that this is an optional
11720			 * parameter - if it is not given, the value of `zeroRecords` will be used
11721			 * instead (either the default or given value).
11722			 *  @type string
11723			 *  @default No data available in table
11724			 *
11725			 *  @dtopt Language
11726			 *  @name DataTable.defaults.language.emptyTable
11727			 *
11728			 *  @example
11729			 *    $(document).ready( function() {
11730			 *      $('#example').dataTable( {
11731			 *        "language": {
11732			 *          "emptyTable": "No data available in table"
11733			 *        }
11734			 *      } );
11735			 *    } );
11736			 */
11737			"sEmptyTable": "No data available in table",
11738	
11739	
11740			/**
11741			 * This string gives information to the end user about the information
11742			 * that is current on display on the page. The following tokens can be
11743			 * used in the string and will be dynamically replaced as the table
11744			 * display updates. This tokens can be placed anywhere in the string, or
11745			 * removed as needed by the language requires:
11746			 *
11747			 * * `\_START\_` - Display index of the first record on the current page
11748			 * * `\_END\_` - Display index of the last record on the current page
11749			 * * `\_TOTAL\_` - Number of records in the table after filtering
11750			 * * `\_MAX\_` - Number of records in the table without filtering
11751			 * * `\_PAGE\_` - Current page number
11752			 * * `\_PAGES\_` - Total number of pages of data in the table
11753			 *
11754			 *  @type string
11755			 *  @default Showing _START_ to _END_ of _TOTAL_ entries
11756			 *
11757			 *  @dtopt Language
11758			 *  @name DataTable.defaults.language.info
11759			 *
11760			 *  @example
11761			 *    $(document).ready( function() {
11762			 *      $('#example').dataTable( {
11763			 *        "language": {
11764			 *          "info": "Showing page _PAGE_ of _PAGES_"
11765			 *        }
11766			 *      } );
11767			 *    } );
11768			 */
11769			"sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
11770	
11771	
11772			/**
11773			 * Display information string for when the table is empty. Typically the
11774			 * format of this string should match `info`.
11775			 *  @type string
11776			 *  @default Showing 0 to 0 of 0 entries
11777			 *
11778			 *  @dtopt Language
11779			 *  @name DataTable.defaults.language.infoEmpty
11780			 *
11781			 *  @example
11782			 *    $(document).ready( function() {
11783			 *      $('#example').dataTable( {
11784			 *        "language": {
11785			 *          "infoEmpty": "No entries to show"
11786			 *        }
11787			 *      } );
11788			 *    } );
11789			 */
11790			"sInfoEmpty": "Showing 0 to 0 of 0 entries",
11791	
11792	
11793			/**
11794			 * When a user filters the information in a table, this string is appended
11795			 * to the information (`info`) to give an idea of how strong the filtering
11796			 * is. The variable _MAX_ is dynamically updated.
11797			 *  @type string
11798			 *  @default (filtered from _MAX_ total entries)
11799			 *
11800			 *  @dtopt Language
11801			 *  @name DataTable.defaults.language.infoFiltered
11802			 *
11803			 *  @example
11804			 *    $(document).ready( function() {
11805			 *      $('#example').dataTable( {
11806			 *        "language": {
11807			 *          "infoFiltered": " - filtering from _MAX_ records"
11808			 *        }
11809			 *      } );
11810			 *    } );
11811			 */
11812			"sInfoFiltered": "(filtered from _MAX_ total entries)",
11813	
11814	
11815			/**
11816			 * If can be useful to append extra information to the info string at times,
11817			 * and this variable does exactly that. This information will be appended to
11818			 * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are
11819			 * being used) at all times.
11820			 *  @type string
11821			 *  @default <i>Empty string</i>
11822			 *
11823			 *  @dtopt Language
11824			 *  @name DataTable.defaults.language.infoPostFix
11825			 *
11826			 *  @example
11827			 *    $(document).ready( function() {
11828			 *      $('#example').dataTable( {
11829			 *        "language": {
11830			 *          "infoPostFix": "All records shown are derived from real information."
11831			 *        }
11832			 *      } );
11833			 *    } );
11834			 */
11835			"sInfoPostFix": "",
11836	
11837	
11838			/**
11839			 * This decimal place operator is a little different from the other
11840			 * language options since DataTables doesn't output floating point
11841			 * numbers, so it won't ever use this for display of a number. Rather,
11842			 * what this parameter does is modify the sort methods of the table so
11843			 * that numbers which are in a format which has a character other than
11844			 * a period (`.`) as a decimal place will be sorted numerically.
11845			 *
11846			 * Note that numbers with different decimal places cannot be shown in
11847			 * the same table and still be sortable, the table must be consistent.
11848			 * However, multiple different tables on the page can use different
11849			 * decimal place characters.
11850			 *  @type string
11851			 *  @default 
11852			 *
11853			 *  @dtopt Language
11854			 *  @name DataTable.defaults.language.decimal
11855			 *
11856			 *  @example
11857			 *    $(document).ready( function() {
11858			 *      $('#example').dataTable( {
11859			 *        "language": {
11860			 *          "decimal": ","
11861			 *          "thousands": "."
11862			 *        }
11863			 *      } );
11864			 *    } );
11865			 */
11866			"sDecimal": "",
11867	
11868	
11869			/**
11870			 * DataTables has a build in number formatter (`formatNumber`) which is
11871			 * used to format large numbers that are used in the table information.
11872			 * By default a comma is used, but this can be trivially changed to any
11873			 * character you wish with this parameter.
11874			 *  @type string
11875			 *  @default ,
11876			 *
11877			 *  @dtopt Language
11878			 *  @name DataTable.defaults.language.thousands
11879			 *
11880			 *  @example
11881			 *    $(document).ready( function() {
11882			 *      $('#example').dataTable( {
11883			 *        "language": {
11884			 *          "thousands": "'"
11885			 *        }
11886			 *      } );
11887			 *    } );
11888			 */
11889			"sThousands": ",",
11890	
11891	
11892			/**
11893			 * Detail the action that will be taken when the drop down menu for the
11894			 * pagination length option is changed. The '_MENU_' variable is replaced
11895			 * with a default select list of 10, 25, 50 and 100, and can be replaced
11896			 * with a custom select box if required.
11897			 *  @type string
11898			 *  @default Show _MENU_ entries
11899			 *
11900			 *  @dtopt Language
11901			 *  @name DataTable.defaults.language.lengthMenu
11902			 *
11903			 *  @example
11904			 *    // Language change only
11905			 *    $(document).ready( function() {
11906			 *      $('#example').dataTable( {
11907			 *        "language": {
11908			 *          "lengthMenu": "Display _MENU_ records"
11909			 *        }
11910			 *      } );
11911			 *    } );
11912			 *
11913			 *  @example
11914			 *    // Language and options change
11915			 *    $(document).ready( function() {
11916			 *      $('#example').dataTable( {
11917			 *        "language": {
11918			 *          "lengthMenu": 'Display <select>'+
11919			 *            '<option value="10">10</option>'+
11920			 *            '<option value="20">20</option>'+
11921			 *            '<option value="30">30</option>'+
11922			 *            '<option value="40">40</option>'+
11923			 *            '<option value="50">50</option>'+
11924			 *            '<option value="-1">All</option>'+
11925			 *            '</select> records'
11926			 *        }
11927			 *      } );
11928			 *    } );
11929			 */
11930			"sLengthMenu": "Show _MENU_ entries",
11931	
11932	
11933			/**
11934			 * When using Ajax sourced data and during the first draw when DataTables is
11935			 * gathering the data, this message is shown in an empty row in the table to
11936			 * indicate to the end user the the data is being loaded. Note that this
11937			 * parameter is not used when loading data by server-side processing, just
11938			 * Ajax sourced data with client-side processing.
11939			 *  @type string
11940			 *  @default Loading...
11941			 *
11942			 *  @dtopt Language
11943			 *  @name DataTable.defaults.language.loadingRecords
11944			 *
11945			 *  @example
11946			 *    $(document).ready( function() {
11947			 *      $('#example').dataTable( {
11948			 *        "language": {
11949			 *          "loadingRecords": "Please wait - loading..."
11950			 *        }
11951			 *      } );
11952			 *    } );
11953			 */
11954			"sLoadingRecords": "Loading...",
11955	
11956	
11957			/**
11958			 * Text which is displayed when the table is processing a user action
11959			 * (usually a sort command or similar).
11960			 *  @type string
11961			 *
11962			 *  @dtopt Language
11963			 *  @name DataTable.defaults.language.processing
11964			 *
11965			 *  @example
11966			 *    $(document).ready( function() {
11967			 *      $('#example').dataTable( {
11968			 *        "language": {
11969			 *          "processing": "DataTables is currently busy"
11970			 *        }
11971			 *      } );
11972			 *    } );
11973			 */
11974			"sProcessing": "",
11975	
11976	
11977			/**
11978			 * Details the actions that will be taken when the user types into the
11979			 * filtering input text box. The variable "_INPUT_", if used in the string,
11980			 * is replaced with the HTML text box for the filtering input allowing
11981			 * control over where it appears in the string. If "_INPUT_" is not given
11982			 * then the input box is appended to the string automatically.
11983			 *  @type string
11984			 *  @default Search:
11985			 *
11986			 *  @dtopt Language
11987			 *  @name DataTable.defaults.language.search
11988			 *
11989			 *  @example
11990			 *    // Input text box will be appended at the end automatically
11991			 *    $(document).ready( function() {
11992			 *      $('#example').dataTable( {
11993			 *        "language": {
11994			 *          "search": "Filter records:"
11995			 *        }
11996			 *      } );
11997			 *    } );
11998			 *
11999			 *  @example
12000			 *    // Specify where the filter should appear
12001			 *    $(document).ready( function() {
12002			 *      $('#example').dataTable( {
12003			 *        "language": {
12004			 *          "search": "Apply filter _INPUT_ to table"
12005			 *        }
12006			 *      } );
12007			 *    } );
12008			 */
12009			"sSearch": "Search:",
12010	
12011	
12012			/**
12013			 * Assign a `placeholder` attribute to the search `input` element
12014			 *  @type string
12015			 *  @default 
12016			 *
12017			 *  @dtopt Language
12018			 *  @name DataTable.defaults.language.searchPlaceholder
12019			 */
12020			"sSearchPlaceholder": "",
12021	
12022	
12023			/**
12024			 * All of the language information can be stored in a file on the
12025			 * server-side, which DataTables will look up if this parameter is passed.
12026			 * It must store the URL of the language file, which is in a JSON format,
12027			 * and the object has the same properties as the oLanguage object in the
12028			 * initialiser object (i.e. the above parameters). Please refer to one of
12029			 * the example language files to see how this works in action.
12030			 *  @type string
12031			 *  @default <i>Empty string - i.e. disabled</i>
12032			 *
12033			 *  @dtopt Language
12034			 *  @name DataTable.defaults.language.url
12035			 *
12036			 *  @example
12037			 *    $(document).ready( function() {
12038			 *      $('#example').dataTable( {
12039			 *        "language": {
12040			 *          "url": "http://www.sprymedia.co.uk/dataTables/lang.txt"
12041			 *        }
12042			 *      } );
12043			 *    } );
12044			 */
12045			"sUrl": "",
12046	
12047	
12048			/**
12049			 * Text shown inside the table records when the is no information to be
12050			 * displayed after filtering. `emptyTable` is shown when there is simply no
12051			 * information in the table at all (regardless of filtering).
12052			 *  @type string
12053			 *  @default No matching records found
12054			 *
12055			 *  @dtopt Language
12056			 *  @name DataTable.defaults.language.zeroRecords
12057			 *
12058			 *  @example
12059			 *    $(document).ready( function() {
12060			 *      $('#example').dataTable( {
12061			 *        "language": {
12062			 *          "zeroRecords": "No records to display"
12063			 *        }
12064			 *      } );
12065			 *    } );
12066			 */
12067			"sZeroRecords": "No matching records found"
12068		},
12069	
12070	
12071		/**
12072		 * This parameter allows you to have define the global filtering state at
12073		 * initialisation time. As an object the `search` parameter must be
12074		 * defined, but all other parameters are optional. When `regex` is true,
12075		 * the search string will be treated as a regular expression, when false
12076		 * (default) it will be treated as a straight string. When `smart`
12077		 * DataTables will use it's smart filtering methods (to word match at
12078		 * any point in the data), when false this will not be done.
12079		 *  @namespace
12080		 *  @extends DataTable.models.oSearch
12081		 *
12082		 *  @dtopt Options
12083		 *  @name DataTable.defaults.search
12084		 *
12085		 *  @example
12086		 *    $(document).ready( function() {
12087		 *      $('#example').dataTable( {
12088		 *        "search": {"search": "Initial search"}
12089		 *      } );
12090		 *    } )
12091		 */
12092		"oSearch": $.extend( {}, DataTable.models.oSearch ),
12093	
12094	
12095		/**
12096		 * __Deprecated__ The functionality provided by this parameter has now been
12097		 * superseded by that provided through `ajax`, which should be used instead.
12098		 *
12099		 * By default DataTables will look for the property `data` (or `aaData` for
12100		 * compatibility with DataTables 1.9-) when obtaining data from an Ajax
12101		 * source or for server-side processing - this parameter allows that
12102		 * property to be changed. You can use Javascript dotted object notation to
12103		 * get a data source for multiple levels of nesting.
12104		 *  @type string
12105		 *  @default data
12106		 *
12107		 *  @dtopt Options
12108		 *  @dtopt Server-side
12109		 *  @name DataTable.defaults.ajaxDataProp
12110		 *
12111		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
12112		 */
12113		"sAjaxDataProp": "data",
12114	
12115	
12116		/**
12117		 * __Deprecated__ The functionality provided by this parameter has now been
12118		 * superseded by that provided through `ajax`, which should be used instead.
12119		 *
12120		 * You can instruct DataTables to load data from an external
12121		 * source using this parameter (use aData if you want to pass data in you
12122		 * already have). Simply provide a url a JSON object can be obtained from.
12123		 *  @type string
12124		 *  @default null
12125		 *
12126		 *  @dtopt Options
12127		 *  @dtopt Server-side
12128		 *  @name DataTable.defaults.ajaxSource
12129		 *
12130		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
12131		 */
12132		"sAjaxSource": null,
12133	
12134	
12135		/**
12136		 * This initialisation variable allows you to specify exactly where in the
12137		 * DOM you want DataTables to inject the various controls it adds to the page
12138		 * (for example you might want the pagination controls at the top of the
12139		 * table). DIV elements (with or without a custom class) can also be added to
12140		 * aid styling. The follow syntax is used:
12141		 *   <ul>
12142		 *     <li>The following options are allowed:
12143		 *       <ul>
12144		 *         <li>'l' - Length changing</li>
12145		 *         <li>'f' - Filtering input</li>
12146		 *         <li>'t' - The table!</li>
12147		 *         <li>'i' - Information</li>
12148		 *         <li>'p' - Pagination</li>
12149		 *         <li>'r' - pRocessing</li>
12150		 *       </ul>
12151		 *     </li>
12152		 *     <li>The following constants are allowed:
12153		 *       <ul>
12154		 *         <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>
12155		 *         <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>
12156		 *       </ul>
12157		 *     </li>
12158		 *     <li>The following syntax is expected:
12159		 *       <ul>
12160		 *         <li>'&lt;' and '&gt;' - div elements</li>
12161		 *         <li>'&lt;"class" and '&gt;' - div with a class</li>
12162		 *         <li>'&lt;"#id" and '&gt;' - div with an ID</li>
12163		 *       </ul>
12164		 *     </li>
12165		 *     <li>Examples:
12166		 *       <ul>
12167		 *         <li>'&lt;"wrapper"flipt&gt;'</li>
12168		 *         <li>'&lt;lf&lt;t&gt;ip&gt;'</li>
12169		 *       </ul>
12170		 *     </li>
12171		 *   </ul>
12172		 *  @type string
12173		 *  @default lfrtip <i>(when `jQueryUI` is false)</i> <b>or</b>
12174		 *    <"H"lfr>t<"F"ip> <i>(when `jQueryUI` is true)</i>
12175		 *
12176		 *  @dtopt Options
12177		 *  @name DataTable.defaults.dom
12178		 *
12179		 *  @example
12180		 *    $(document).ready( function() {
12181		 *      $('#example').dataTable( {
12182		 *        "dom": '&lt;"top"i&gt;rt&lt;"bottom"flp&gt;&lt;"clear"&gt;'
12183		 *      } );
12184		 *    } );
12185		 */
12186		"sDom": "lfrtip",
12187	
12188	
12189		/**
12190		 * Search delay option. This will throttle full table searches that use the
12191		 * DataTables provided search input element (it does not effect calls to
12192		 * `dt-api search()`, providing a delay before the search is made.
12193		 *  @type integer
12194		 *  @default 0
12195		 *
12196		 *  @dtopt Options
12197		 *  @name DataTable.defaults.searchDelay
12198		 *
12199		 *  @example
12200		 *    $(document).ready( function() {
12201		 *      $('#example').dataTable( {
12202		 *        "searchDelay": 200
12203		 *      } );
12204		 *    } )
12205		 */
12206		"searchDelay": null,
12207	
12208	
12209		/**
12210		 * DataTables features six different built-in options for the buttons to
12211		 * display for pagination control:
12212		 *
12213		 * * `numbers` - Page number buttons only
12214		 * * `simple` - 'Previous' and 'Next' buttons only
12215		 * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers
12216		 * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons
12217		 * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus page numbers
12218		 * * `first_last_numbers` - 'First' and 'Last' buttons, plus page numbers
12219		 *  
12220		 * Further methods can be added using {@link DataTable.ext.oPagination}.
12221		 *  @type string
12222		 *  @default simple_numbers
12223		 *
12224		 *  @dtopt Options
12225		 *  @name DataTable.defaults.pagingType
12226		 *
12227		 *  @example
12228		 *    $(document).ready( function() {
12229		 *      $('#example').dataTable( {
12230		 *        "pagingType": "full_numbers"
12231		 *      } );
12232		 *    } )
12233		 */
12234		"sPaginationType": "simple_numbers",
12235	
12236	
12237		/**
12238		 * Enable horizontal scrolling. When a table is too wide to fit into a
12239		 * certain layout, or you have a large number of columns in the table, you
12240		 * can enable x-scrolling to show the table in a viewport, which can be
12241		 * scrolled. This property can be `true` which will allow the table to
12242		 * scroll horizontally when needed, or any CSS unit, or a number (in which
12243		 * case it will be treated as a pixel measurement). Setting as simply `true`
12244		 * is recommended.
12245		 *  @type boolean|string
12246		 *  @default <i>blank string - i.e. disabled</i>
12247		 *
12248		 *  @dtopt Features
12249		 *  @name DataTable.defaults.scrollX
12250		 *
12251		 *  @example
12252		 *    $(document).ready( function() {
12253		 *      $('#example').dataTable( {
12254		 *        "scrollX": true,
12255		 *        "scrollCollapse": true
12256		 *      } );
12257		 *    } );
12258		 */
12259		"sScrollX": "",
12260	
12261	
12262		/**
12263		 * This property can be used to force a DataTable to use more width than it
12264		 * might otherwise do when x-scrolling is enabled. For example if you have a
12265		 * table which requires to be well spaced, this parameter is useful for
12266		 * "over-sizing" the table, and thus forcing scrolling. This property can by
12267		 * any CSS unit, or a number (in which case it will be treated as a pixel
12268		 * measurement).
12269		 *  @type string
12270		 *  @default <i>blank string - i.e. disabled</i>
12271		 *
12272		 *  @dtopt Options
12273		 *  @name DataTable.defaults.scrollXInner
12274		 *
12275		 *  @example
12276		 *    $(document).ready( function() {
12277		 *      $('#example').dataTable( {
12278		 *        "scrollX": "100%",
12279		 *        "scrollXInner": "110%"
12280		 *      } );
12281		 *    } );
12282		 */
12283		"sScrollXInner": "",
12284	
12285	
12286		/**
12287		 * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
12288		 * to the given height, and enable scrolling for any data which overflows the
12289		 * current viewport. This can be used as an alternative to paging to display
12290		 * a lot of data in a small area (although paging and scrolling can both be
12291		 * enabled at the same time). This property can be any CSS unit, or a number
12292		 * (in which case it will be treated as a pixel measurement).
12293		 *  @type string
12294		 *  @default <i>blank string - i.e. disabled</i>
12295		 *
12296		 *  @dtopt Features
12297		 *  @name DataTable.defaults.scrollY
12298		 *
12299		 *  @example
12300		 *    $(document).ready( function() {
12301		 *      $('#example').dataTable( {
12302		 *        "scrollY": "200px",
12303		 *        "paginate": false
12304		 *      } );
12305		 *    } );
12306		 */
12307		"sScrollY": "",
12308	
12309	
12310		/**
12311		 * __Deprecated__ The functionality provided by this parameter has now been
12312		 * superseded by that provided through `ajax`, which should be used instead.
12313		 *
12314		 * Set the HTTP method that is used to make the Ajax call for server-side
12315		 * processing or Ajax sourced data.
12316		 *  @type string
12317		 *  @default GET
12318		 *
12319		 *  @dtopt Options
12320		 *  @dtopt Server-side
12321		 *  @name DataTable.defaults.serverMethod
12322		 *
12323		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
12324		 */
12325		"sServerMethod": "GET",
12326	
12327	
12328		/**
12329		 * DataTables makes use of renderers when displaying HTML elements for
12330		 * a table. These renderers can be added or modified by plug-ins to
12331		 * generate suitable mark-up for a site. For example the Bootstrap
12332		 * integration plug-in for DataTables uses a paging button renderer to
12333		 * display pagination buttons in the mark-up required by Bootstrap.
12334		 *
12335		 * For further information about the renderers available see
12336		 * DataTable.ext.renderer
12337		 *  @type string|object
12338		 *  @default null
12339		 *
12340		 *  @name DataTable.defaults.renderer
12341		 *
12342		 */
12343		"renderer": null,
12344	
12345	
12346		/**
12347		 * Set the data property name that DataTables should use to get a row's id
12348		 * to set as the `id` property in the node.
12349		 *  @type string
12350		 *  @default DT_RowId
12351		 *
12352		 *  @name DataTable.defaults.rowId
12353		 */
12354		"rowId": "DT_RowId"
12355	};
12356	
12357	_fnHungarianMap( DataTable.defaults );
12358	
12359	
12360	
12361	/*
12362	 * Developer note - See note in model.defaults.js about the use of Hungarian
12363	 * notation and camel case.
12364	 */
12365	
12366	/**
12367	 * Column options that can be given to DataTables at initialisation time.
12368	 *  @namespace
12369	 */
12370	DataTable.defaults.column = {
12371		/**
12372		 * Define which column(s) an order will occur on for this column. This
12373		 * allows a column's ordering to take multiple columns into account when
12374		 * doing a sort or use the data from a different column. For example first
12375		 * name / last name columns make sense to do a multi-column sort over the
12376		 * two columns.
12377		 *  @type array|int
12378		 *  @default null <i>Takes the value of the column index automatically</i>
12379		 *
12380		 *  @name DataTable.defaults.column.orderData
12381		 *  @dtopt Columns
12382		 *
12383		 *  @example
12384		 *    // Using `columnDefs`
12385		 *    $(document).ready( function() {
12386		 *      $('#example').dataTable( {
12387		 *        "columnDefs": [
12388		 *          { "orderData": [ 0, 1 ], "targets": [ 0 ] },
12389		 *          { "orderData": [ 1, 0 ], "targets": [ 1 ] },
12390		 *          { "orderData": 2, "targets": [ 2 ] }
12391		 *        ]
12392		 *      } );
12393		 *    } );
12394		 *
12395		 *  @example
12396		 *    // Using `columns`
12397		 *    $(document).ready( function() {
12398		 *      $('#example').dataTable( {
12399		 *        "columns": [
12400		 *          { "orderData": [ 0, 1 ] },
12401		 *          { "orderData": [ 1, 0 ] },
12402		 *          { "orderData": 2 },
12403		 *          null,
12404		 *          null
12405		 *        ]
12406		 *      } );
12407		 *    } );
12408		 */
12409		"aDataSort": null,
12410		"iDataSort": -1,
12411	
12412	
12413		/**
12414		 * You can control the default ordering direction, and even alter the
12415		 * behaviour of the sort handler (i.e. only allow ascending ordering etc)
12416		 * using this parameter.
12417		 *  @type array
12418		 *  @default [ 'asc', 'desc' ]
12419		 *
12420		 *  @name DataTable.defaults.column.orderSequence
12421		 *  @dtopt Columns
12422		 *
12423		 *  @example
12424		 *    // Using `columnDefs`
12425		 *    $(document).ready( function() {
12426		 *      $('#example').dataTable( {
12427		 *        "columnDefs": [
12428		 *          { "orderSequence": [ "asc" ], "targets": [ 1 ] },
12429		 *          { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] },
12430		 *          { "orderSequence": [ "desc" ], "targets": [ 3 ] }
12431		 *        ]
12432		 *      } );
12433		 *    } );
12434		 *
12435		 *  @example
12436		 *    // Using `columns`
12437		 *    $(document).ready( function() {
12438		 *      $('#example').dataTable( {
12439		 *        "columns": [
12440		 *          null,
12441		 *          { "orderSequence": [ "asc" ] },
12442		 *          { "orderSequence": [ "desc", "asc", "asc" ] },
12443		 *          { "orderSequence": [ "desc" ] },
12444		 *          null
12445		 *        ]
12446		 *      } );
12447		 *    } );
12448		 */
12449		"asSorting": [ 'asc', 'desc' ],
12450	
12451	
12452		/**
12453		 * Enable or disable filtering on the data in this column.
12454		 *  @type boolean
12455		 *  @default true
12456		 *
12457		 *  @name DataTable.defaults.column.searchable
12458		 *  @dtopt Columns
12459		 *
12460		 *  @example
12461		 *    // Using `columnDefs`
12462		 *    $(document).ready( function() {
12463		 *      $('#example').dataTable( {
12464		 *        "columnDefs": [
12465		 *          { "searchable": false, "targets": [ 0 ] }
12466		 *        ] } );
12467		 *    } );
12468		 *
12469		 *  @example
12470		 *    // Using `columns`
12471		 *    $(document).ready( function() {
12472		 *      $('#example').dataTable( {
12473		 *        "columns": [
12474		 *          { "searchable": false },
12475		 *          null,
12476		 *          null,
12477		 *          null,
12478		 *          null
12479		 *        ] } );
12480		 *    } );
12481		 */
12482		"bSearchable": true,
12483	
12484	
12485		/**
12486		 * Enable or disable ordering on this column.
12487		 *  @type boolean
12488		 *  @default true
12489		 *
12490		 *  @name DataTable.defaults.column.orderable
12491		 *  @dtopt Columns
12492		 *
12493		 *  @example
12494		 *    // Using `columnDefs`
12495		 *    $(document).ready( function() {
12496		 *      $('#example').dataTable( {
12497		 *        "columnDefs": [
12498		 *          { "orderable": false, "targets": [ 0 ] }
12499		 *        ] } );
12500		 *    } );
12501		 *
12502		 *  @example
12503		 *    // Using `columns`
12504		 *    $(document).ready( function() {
12505		 *      $('#example').dataTable( {
12506		 *        "columns": [
12507		 *          { "orderable": false },
12508		 *          null,
12509		 *          null,
12510		 *          null,
12511		 *          null
12512		 *        ] } );
12513		 *    } );
12514		 */
12515		"bSortable": true,
12516	
12517	
12518		/**
12519		 * Enable or disable the display of this column.
12520		 *  @type boolean
12521		 *  @default true
12522		 *
12523		 *  @name DataTable.defaults.column.visible
12524		 *  @dtopt Columns
12525		 *
12526		 *  @example
12527		 *    // Using `columnDefs`
12528		 *    $(document).ready( function() {
12529		 *      $('#example').dataTable( {
12530		 *        "columnDefs": [
12531		 *          { "visible": false, "targets": [ 0 ] }
12532		 *        ] } );
12533		 *    } );
12534		 *
12535		 *  @example
12536		 *    // Using `columns`
12537		 *    $(document).ready( function() {
12538		 *      $('#example').dataTable( {
12539		 *        "columns": [
12540		 *          { "visible": false },
12541		 *          null,
12542		 *          null,
12543		 *          null,
12544		 *          null
12545		 *        ] } );
12546		 *    } );
12547		 */
12548		"bVisible": true,
12549	
12550	
12551		/**
12552		 * Developer definable function that is called whenever a cell is created (Ajax source,
12553		 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
12554		 * allowing you to modify the DOM element (add background colour for example) when the
12555		 * element is available.
12556		 *  @type function
12557		 *  @param {element} td The TD node that has been created
12558		 *  @param {*} cellData The Data for the cell
12559		 *  @param {array|object} rowData The data for the whole row
12560		 *  @param {int} row The row index for the aoData data store
12561		 *  @param {int} col The column index for aoColumns
12562		 *
12563		 *  @name DataTable.defaults.column.createdCell
12564		 *  @dtopt Columns
12565		 *
12566		 *  @example
12567		 *    $(document).ready( function() {
12568		 *      $('#example').dataTable( {
12569		 *        "columnDefs": [ {
12570		 *          "targets": [3],
12571		 *          "createdCell": function (td, cellData, rowData, row, col) {
12572		 *            if ( cellData == "1.7" ) {
12573		 *              $(td).css('color', 'blue')
12574		 *            }
12575		 *          }
12576		 *        } ]
12577		 *      });
12578		 *    } );
12579		 */
12580		"fnCreatedCell": null,
12581	
12582	
12583		/**
12584		 * This parameter has been replaced by `data` in DataTables to ensure naming
12585		 * consistency. `dataProp` can still be used, as there is backwards
12586		 * compatibility in DataTables for this option, but it is strongly
12587		 * recommended that you use `data` in preference to `dataProp`.
12588		 *  @name DataTable.defaults.column.dataProp
12589		 */
12590	
12591	
12592		/**
12593		 * This property can be used to read data from any data source property,
12594		 * including deeply nested objects / properties. `data` can be given in a
12595		 * number of different ways which effect its behaviour:
12596		 *
12597		 * * `integer` - treated as an array index for the data source. This is the
12598		 *   default that DataTables uses (incrementally increased for each column).
12599		 * * `string` - read an object property from the data source. There are
12600		 *   three 'special' options that can be used in the string to alter how
12601		 *   DataTables reads the data from the source object:
12602		 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
12603		 *      Javascript to read from nested objects, so to can the options
12604		 *      specified in `data`. For example: `browser.version` or
12605		 *      `browser.name`. If your object parameter name contains a period, use
12606		 *      `\\` to escape it - i.e. `first\\.name`.
12607		 *    * `[]` - Array notation. DataTables can automatically combine data
12608		 *      from and array source, joining the data with the characters provided
12609		 *      between the two brackets. For example: `name[, ]` would provide a
12610		 *      comma-space separated list from the source array. If no characters
12611		 *      are provided between the brackets, the original array source is
12612		 *      returned.
12613		 *    * `()` - Function notation. Adding `()` to the end of a parameter will
12614		 *      execute a function of the name given. For example: `browser()` for a
12615		 *      simple function on the data source, `browser.version()` for a
12616		 *      function in a nested property or even `browser().version` to get an
12617		 *      object property if the function called returns an object. Note that
12618		 *      function notation is recommended for use in `render` rather than
12619		 *      `data` as it is much simpler to use as a renderer.
12620		 * * `null` - use the original data source for the row rather than plucking
12621		 *   data directly from it. This action has effects on two other
12622		 *   initialisation options:
12623		 *    * `defaultContent` - When null is given as the `data` option and
12624		 *      `defaultContent` is specified for the column, the value defined by
12625		 *      `defaultContent` will be used for the cell.
12626		 *    * `render` - When null is used for the `data` option and the `render`
12627		 *      option is specified for the column, the whole data source for the
12628		 *      row is used for the renderer.
12629		 * * `function` - the function given will be executed whenever DataTables
12630		 *   needs to set or get the data for a cell in the column. The function
12631		 *   takes three parameters:
12632		 *    * Parameters:
12633		 *      * `{array|object}` The data source for the row
12634		 *      * `{string}` The type call data requested - this will be 'set' when
12635		 *        setting data or 'filter', 'display', 'type', 'sort' or undefined
12636		 *        when gathering data. Note that when `undefined` is given for the
12637		 *        type DataTables expects to get the raw data for the object back<
12638		 *      * `{*}` Data to set when the second parameter is 'set'.
12639		 *    * Return:
12640		 *      * The return value from the function is not required when 'set' is
12641		 *        the type of call, but otherwise the return is what will be used
12642		 *        for the data requested.
12643		 *
12644		 * Note that `data` is a getter and setter option. If you just require
12645		 * formatting of data for output, you will likely want to use `render` which
12646		 * is simply a getter and thus simpler to use.
12647		 *
12648		 * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The
12649		 * name change reflects the flexibility of this property and is consistent
12650		 * with the naming of mRender. If 'mDataProp' is given, then it will still
12651		 * be used by DataTables, as it automatically maps the old name to the new
12652		 * if required.
12653		 *
12654		 *  @type string|int|function|null
12655		 *  @default null <i>Use automatically calculated column index</i>
12656		 *
12657		 *  @name DataTable.defaults.column.data
12658		 *  @dtopt Columns
12659		 *
12660		 *  @example
12661		 *    // Read table data from objects
12662		 *    // JSON structure for each row:
12663		 *    //   {
12664		 *    //      "engine": {value},
12665		 *    //      "browser": {value},
12666		 *    //      "platform": {value},
12667		 *    //      "version": {value},
12668		 *    //      "grade": {value}
12669		 *    //   }
12670		 *    $(document).ready( function() {
12671		 *      $('#example').dataTable( {
12672		 *        "ajaxSource": "sources/objects.txt",
12673		 *        "columns": [
12674		 *          { "data": "engine" },
12675		 *          { "data": "browser" },
12676		 *          { "data": "platform" },
12677		 *          { "data": "version" },
12678		 *          { "data": "grade" }
12679		 *        ]
12680		 *      } );
12681		 *    } );
12682		 *
12683		 *  @example
12684		 *    // Read information from deeply nested objects
12685		 *    // JSON structure for each row:
12686		 *    //   {
12687		 *    //      "engine": {value},
12688		 *    //      "browser": {value},
12689		 *    //      "platform": {
12690		 *    //         "inner": {value}
12691		 *    //      },
12692		 *    //      "details": [
12693		 *    //         {value}, {value}
12694		 *    //      ]
12695		 *    //   }
12696		 *    $(document).ready( function() {
12697		 *      $('#example').dataTable( {
12698		 *        "ajaxSource": "sources/deep.txt",
12699		 *        "columns": [
12700		 *          { "data": "engine" },
12701		 *          { "data": "browser" },
12702		 *          { "data": "platform.inner" },
12703		 *          { "data": "details.0" },
12704		 *          { "data": "details.1" }
12705		 *        ]
12706		 *      } );
12707		 *    } );
12708		 *
12709		 *  @example
12710		 *    // Using `data` as a function to provide different information for
12711		 *    // sorting, filtering and display. In this case, currency (price)
12712		 *    $(document).ready( function() {
12713		 *      $('#example').dataTable( {
12714		 *        "columnDefs": [ {
12715		 *          "targets": [ 0 ],
12716		 *          "data": function ( source, type, val ) {
12717		 *            if (type === 'set') {
12718		 *              source.price = val;
12719		 *              // Store the computed display and filter values for efficiency
12720		 *              source.price_display = val=="" ? "" : "$"+numberFormat(val);
12721		 *              source.price_filter  = val=="" ? "" : "$"+numberFormat(val)+" "+val;
12722		 *              return;
12723		 *            }
12724		 *            else if (type === 'display') {
12725		 *              return source.price_display;
12726		 *            }
12727		 *            else if (type === 'filter') {
12728		 *              return source.price_filter;
12729		 *            }
12730		 *            // 'sort', 'type' and undefined all just use the integer
12731		 *            return source.price;
12732		 *          }
12733		 *        } ]
12734		 *      } );
12735		 *    } );
12736		 *
12737		 *  @example
12738		 *    // Using default content
12739		 *    $(document).ready( function() {
12740		 *      $('#example').dataTable( {
12741		 *        "columnDefs": [ {
12742		 *          "targets": [ 0 ],
12743		 *          "data": null,
12744		 *          "defaultContent": "Click to edit"
12745		 *        } ]
12746		 *      } );
12747		 *    } );
12748		 *
12749		 *  @example
12750		 *    // Using array notation - outputting a list from an array
12751		 *    $(document).ready( function() {
12752		 *      $('#example').dataTable( {
12753		 *        "columnDefs": [ {
12754		 *          "targets": [ 0 ],
12755		 *          "data": "name[, ]"
12756		 *        } ]
12757		 *      } );
12758		 *    } );
12759		 *
12760		 */
12761		"mData": null,
12762	
12763	
12764		/**
12765		 * This property is the rendering partner to `data` and it is suggested that
12766		 * when you want to manipulate data for display (including filtering,
12767		 * sorting etc) without altering the underlying data for the table, use this
12768		 * property. `render` can be considered to be the the read only companion to
12769		 * `data` which is read / write (then as such more complex). Like `data`
12770		 * this option can be given in a number of different ways to effect its
12771		 * behaviour:
12772		 *
12773		 * * `integer` - treated as an array index for the data source. This is the
12774		 *   default that DataTables uses (incrementally increased for each column).
12775		 * * `string` - read an object property from the data source. There are
12776		 *   three 'special' options that can be used in the string to alter how
12777		 *   DataTables reads the data from the source object:
12778		 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
12779		 *      Javascript to read from nested objects, so to can the options
12780		 *      specified in `data`. For example: `browser.version` or
12781		 *      `browser.name`. If your object parameter name contains a period, use
12782		 *      `\\` to escape it - i.e. `first\\.name`.
12783		 *    * `[]` - Array notation. DataTables can automatically combine data
12784		 *      from and array source, joining the data with the characters provided
12785		 *      between the two brackets. For example: `name[, ]` would provide a
12786		 *      comma-space separated list from the source array. If no characters
12787		 *      are provided between the brackets, the original array source is
12788		 *      returned.
12789		 *    * `()` - Function notation. Adding `()` to the end of a parameter will
12790		 *      execute a function of the name given. For example: `browser()` for a
12791		 *      simple function on the data source, `browser.version()` for a
12792		 *      function in a nested property or even `browser().version` to get an
12793		 *      object property if the function called returns an object.
12794		 * * `object` - use different data for the different data types requested by
12795		 *   DataTables ('filter', 'display', 'type' or 'sort'). The property names
12796		 *   of the object is the data type the property refers to and the value can
12797		 *   defined using an integer, string or function using the same rules as
12798		 *   `render` normally does. Note that an `_` option _must_ be specified.
12799		 *   This is the default value to use if you haven't specified a value for
12800		 *   the data type requested by DataTables.
12801		 * * `function` - the function given will be executed whenever DataTables
12802		 *   needs to set or get the data for a cell in the column. The function
12803		 *   takes three parameters:
12804		 *    * Parameters:
12805		 *      * {array|object} The data source for the row (based on `data`)
12806		 *      * {string} The type call data requested - this will be 'filter',
12807		 *        'display', 'type' or 'sort'.
12808		 *      * {array|object} The full data source for the row (not based on
12809		 *        `data`)
12810		 *    * Return:
12811		 *      * The return value from the function is what will be used for the
12812		 *        data requested.
12813		 *
12814		 *  @type string|int|function|object|null
12815		 *  @default null Use the data source value.
12816		 *
12817		 *  @name DataTable.defaults.column.render
12818		 *  @dtopt Columns
12819		 *
12820		 *  @example
12821		 *    // Create a comma separated list from an array of objects
12822		 *    $(document).ready( function() {
12823		 *      $('#example').dataTable( {
12824		 *        "ajaxSource": "sources/deep.txt",
12825		 *        "columns": [
12826		 *          { "data": "engine" },
12827		 *          { "data": "browser" },
12828		 *          {
12829		 *            "data": "platform",
12830		 *            "render": "[, ].name"
12831		 *          }
12832		 *        ]
12833		 *      } );
12834		 *    } );
12835		 *
12836		 *  @example
12837		 *    // Execute a function to obtain data
12838		 *    $(document).ready( function() {
12839		 *      $('#example').dataTable( {
12840		 *        "columnDefs": [ {
12841		 *          "targets": [ 0 ],
12842		 *          "data": null, // Use the full data source object for the renderer's source
12843		 *          "render": "browserName()"
12844		 *        } ]
12845		 *      } );
12846		 *    } );
12847		 *
12848		 *  @example
12849		 *    // As an object, extracting different data for the different types
12850		 *    // This would be used with a data source such as:
12851		 *    //   { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" }
12852		 *    // Here the `phone` integer is used for sorting and type detection, while `phone_filter`
12853		 *    // (which has both forms) is used for filtering for if a user inputs either format, while
12854		 *    // the formatted phone number is the one that is shown in the table.
12855		 *    $(document).ready( function() {
12856		 *      $('#example').dataTable( {
12857		 *        "columnDefs": [ {
12858		 *          "targets": [ 0 ],
12859		 *          "data": null, // Use the full data source object for the renderer's source
12860		 *          "render": {
12861		 *            "_": "phone",
12862		 *            "filter": "phone_filter",
12863		 *            "display": "phone_display"
12864		 *          }
12865		 *        } ]
12866		 *      } );
12867		 *    } );
12868		 *
12869		 *  @example
12870		 *    // Use as a function to create a link from the data source
12871		 *    $(document).ready( function() {
12872		 *      $('#example').dataTable( {
12873		 *        "columnDefs": [ {
12874		 *          "targets": [ 0 ],
12875		 *          "data": "download_link",
12876		 *          "render": function ( data, type, full ) {
12877		 *            return '<a href="'+data+'">Download</a>';
12878		 *          }
12879		 *        } ]
12880		 *      } );
12881		 *    } );
12882		 */
12883		"mRender": null,
12884	
12885	
12886		/**
12887		 * Change the cell type created for the column - either TD cells or TH cells. This
12888		 * can be useful as TH cells have semantic meaning in the table body, allowing them
12889		 * to act as a header for a row (you may wish to add scope='row' to the TH elements).
12890		 *  @type string
12891		 *  @default td
12892		 *
12893		 *  @name DataTable.defaults.column.cellType
12894		 *  @dtopt Columns
12895		 *
12896		 *  @example
12897		 *    // Make the first column use TH cells
12898		 *    $(document).ready( function() {
12899		 *      $('#example').dataTable( {
12900		 *        "columnDefs": [ {
12901		 *          "targets": [ 0 ],
12902		 *          "cellType": "th"
12903		 *        } ]
12904		 *      } );
12905		 *    } );
12906		 */
12907		"sCellType": "td",
12908	
12909	
12910		/**
12911		 * Class to give to each cell in this column.
12912		 *  @type string
12913		 *  @default <i>Empty string</i>
12914		 *
12915		 *  @name DataTable.defaults.column.class
12916		 *  @dtopt Columns
12917		 *
12918		 *  @example
12919		 *    // Using `columnDefs`
12920		 *    $(document).ready( function() {
12921		 *      $('#example').dataTable( {
12922		 *        "columnDefs": [
12923		 *          { "class": "my_class", "targets": [ 0 ] }
12924		 *        ]
12925		 *      } );
12926		 *    } );
12927		 *
12928		 *  @example
12929		 *    // Using `columns`
12930		 *    $(document).ready( function() {
12931		 *      $('#example').dataTable( {
12932		 *        "columns": [
12933		 *          { "class": "my_class" },
12934		 *          null,
12935		 *          null,
12936		 *          null,
12937		 *          null
12938		 *        ]
12939		 *      } );
12940		 *    } );
12941		 */
12942		"sClass": "",
12943	
12944		/**
12945		 * When DataTables calculates the column widths to assign to each column,
12946		 * it finds the longest string in each column and then constructs a
12947		 * temporary table and reads the widths from that. The problem with this
12948		 * is that "mmm" is much wider then "iiii", but the latter is a longer
12949		 * string - thus the calculation can go wrong (doing it properly and putting
12950		 * it into an DOM object and measuring that is horribly(!) slow). Thus as
12951		 * a "work around" we provide this option. It will append its value to the
12952		 * text that is found to be the longest string for the column - i.e. padding.
12953		 * Generally you shouldn't need this!
12954		 *  @type string
12955		 *  @default <i>Empty string<i>
12956		 *
12957		 *  @name DataTable.defaults.column.contentPadding
12958		 *  @dtopt Columns
12959		 *
12960		 *  @example
12961		 *    // Using `columns`
12962		 *    $(document).ready( function() {
12963		 *      $('#example').dataTable( {
12964		 *        "columns": [
12965		 *          null,
12966		 *          null,
12967		 *          null,
12968		 *          {
12969		 *            "contentPadding": "mmm"
12970		 *          }
12971		 *        ]
12972		 *      } );
12973		 *    } );
12974		 */
12975		"sContentPadding": "",
12976	
12977	
12978		/**
12979		 * Allows a default value to be given for a column's data, and will be used
12980		 * whenever a null data source is encountered (this can be because `data`
12981		 * is set to null, or because the data source itself is null).
12982		 *  @type string
12983		 *  @default null
12984		 *
12985		 *  @name DataTable.defaults.column.defaultContent
12986		 *  @dtopt Columns
12987		 *
12988		 *  @example
12989		 *    // Using `columnDefs`
12990		 *    $(document).ready( function() {
12991		 *      $('#example').dataTable( {
12992		 *        "columnDefs": [
12993		 *          {
12994		 *            "data": null,
12995		 *            "defaultContent": "Edit",
12996		 *            "targets": [ -1 ]
12997		 *          }
12998		 *        ]
12999		 *      } );
13000		 *    } );
13001		 *
13002		 *  @example
13003		 *    // Using `columns`
13004		 *    $(document).ready( function() {
13005		 *      $('#example').dataTable( {
13006		 *        "columns": [
13007		 *          null,
13008		 *          null,
13009		 *          null,
13010		 *          {
13011		 *            "data": null,
13012		 *            "defaultContent": "Edit"
13013		 *          }
13014		 *        ]
13015		 *      } );
13016		 *    } );
13017		 */
13018		"sDefaultContent": null,
13019	
13020	
13021		/**
13022		 * This parameter is only used in DataTables' server-side processing. It can
13023		 * be exceptionally useful to know what columns are being displayed on the
13024		 * client side, and to map these to database fields. When defined, the names
13025		 * also allow DataTables to reorder information from the server if it comes
13026		 * back in an unexpected order (i.e. if you switch your columns around on the
13027		 * client-side, your server-side code does not also need updating).
13028		 *  @type string
13029		 *  @default <i>Empty string</i>
13030		 *
13031		 *  @name DataTable.defaults.column.name
13032		 *  @dtopt Columns
13033		 *
13034		 *  @example
13035		 *    // Using `columnDefs`
13036		 *    $(document).ready( function() {
13037		 *      $('#example').dataTable( {
13038		 *        "columnDefs": [
13039		 *          { "name": "engine", "targets": [ 0 ] },
13040		 *          { "name": "browser", "targets": [ 1 ] },
13041		 *          { "name": "platform", "targets": [ 2 ] },
13042		 *          { "name": "version", "targets": [ 3 ] },
13043		 *          { "name": "grade", "targets": [ 4 ] }
13044		 *        ]
13045		 *      } );
13046		 *    } );
13047		 *
13048		 *  @example
13049		 *    // Using `columns`
13050		 *    $(document).ready( function() {
13051		 *      $('#example').dataTable( {
13052		 *        "columns": [
13053		 *          { "name": "engine" },
13054		 *          { "name": "browser" },
13055		 *          { "name": "platform" },
13056		 *          { "name": "version" },
13057		 *          { "name": "grade" }
13058		 *        ]
13059		 *      } );
13060		 *    } );
13061		 */
13062		"sName": "",
13063	
13064	
13065		/**
13066		 * Defines a data source type for the ordering which can be used to read
13067		 * real-time information from the table (updating the internally cached
13068		 * version) prior to ordering. This allows ordering to occur on user
13069		 * editable elements such as form inputs.
13070		 *  @type string
13071		 *  @default std
13072		 *
13073		 *  @name DataTable.defaults.column.orderDataType
13074		 *  @dtopt Columns
13075		 *
13076		 *  @example
13077		 *    // Using `columnDefs`
13078		 *    $(document).ready( function() {
13079		 *      $('#example').dataTable( {
13080		 *        "columnDefs": [
13081		 *          { "orderDataType": "dom-text", "targets": [ 2, 3 ] },
13082		 *          { "type": "numeric", "targets": [ 3 ] },
13083		 *          { "orderDataType": "dom-select", "targets": [ 4 ] },
13084		 *          { "orderDataType": "dom-checkbox", "targets": [ 5 ] }
13085		 *        ]
13086		 *      } );
13087		 *    } );
13088		 *
13089		 *  @example
13090		 *    // Using `columns`
13091		 *    $(document).ready( function() {
13092		 *      $('#example').dataTable( {
13093		 *        "columns": [
13094		 *          null,
13095		 *          null,
13096		 *          { "orderDataType": "dom-text" },
13097		 *          { "orderDataType": "dom-text", "type": "numeric" },
13098		 *          { "orderDataType": "dom-select" },
13099		 *          { "orderDataType": "dom-checkbox" }
13100		 *        ]
13101		 *      } );
13102		 *    } );
13103		 */
13104		"sSortDataType": "std",
13105	
13106	
13107		/**
13108		 * The title of this column.
13109		 *  @type string
13110		 *  @default null <i>Derived from the 'TH' value for this column in the
13111		 *    original HTML table.</i>
13112		 *
13113		 *  @name DataTable.defaults.column.title
13114		 *  @dtopt Columns
13115		 *
13116		 *  @example
13117		 *    // Using `columnDefs`
13118		 *    $(document).ready( function() {
13119		 *      $('#example').dataTable( {
13120		 *        "columnDefs": [
13121		 *          { "title": "My column title", "targets": [ 0 ] }
13122		 *        ]
13123		 *      } );
13124		 *    } );
13125		 *
13126		 *  @example
13127		 *    // Using `columns`
13128		 *    $(document).ready( function() {
13129		 *      $('#example').dataTable( {
13130		 *        "columns": [
13131		 *          { "title": "My column title" },
13132		 *          null,
13133		 *          null,
13134		 *          null,
13135		 *          null
13136		 *        ]
13137		 *      } );
13138		 *    } );
13139		 */
13140		"sTitle": null,
13141	
13142	
13143		/**
13144		 * The type allows you to specify how the data for this column will be
13145		 * ordered. Four types (string, numeric, date and html (which will strip
13146		 * HTML tags before ordering)) are currently available. Note that only date
13147		 * formats understood by Javascript's Date() object will be accepted as type
13148		 * date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string',
13149		 * 'numeric', 'date' or 'html' (by default). Further types can be adding
13150		 * through plug-ins.
13151		 *  @type string
13152		 *  @default null <i>Auto-detected from raw data</i>
13153		 *
13154		 *  @name DataTable.defaults.column.type
13155		 *  @dtopt Columns
13156		 *
13157		 *  @example
13158		 *    // Using `columnDefs`
13159		 *    $(document).ready( function() {
13160		 *      $('#example').dataTable( {
13161		 *        "columnDefs": [
13162		 *          { "type": "html", "targets": [ 0 ] }
13163		 *        ]
13164		 *      } );
13165		 *    } );
13166		 *
13167		 *  @example
13168		 *    // Using `columns`
13169		 *    $(document).ready( function() {
13170		 *      $('#example').dataTable( {
13171		 *        "columns": [
13172		 *          { "type": "html" },
13173		 *          null,
13174		 *          null,
13175		 *          null,
13176		 *          null
13177		 *        ]
13178		 *      } );
13179		 *    } );
13180		 */
13181		"sType": null,
13182	
13183	
13184		/**
13185		 * Defining the width of the column, this parameter may take any CSS value
13186		 * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not
13187		 * been given a specific width through this interface ensuring that the table
13188		 * remains readable.
13189		 *  @type string
13190		 *  @default null <i>Automatic</i>
13191		 *
13192		 *  @name DataTable.defaults.column.width
13193		 *  @dtopt Columns
13194		 *
13195		 *  @example
13196		 *    // Using `columnDefs`
13197		 *    $(document).ready( function() {
13198		 *      $('#example').dataTable( {
13199		 *        "columnDefs": [
13200		 *          { "width": "20%", "targets": [ 0 ] }
13201		 *        ]
13202		 *      } );
13203		 *    } );
13204		 *
13205		 *  @example
13206		 *    // Using `columns`
13207		 *    $(document).ready( function() {
13208		 *      $('#example').dataTable( {
13209		 *        "columns": [
13210		 *          { "width": "20%" },
13211		 *          null,
13212		 *          null,
13213		 *          null,
13214		 *          null
13215		 *        ]
13216		 *      } );
13217		 *    } );
13218		 */
13219		"sWidth": null
13220	};
13221	
13222	_fnHungarianMap( DataTable.defaults.column );
13223	
13224	
13225	
13226	/**
13227	 * DataTables settings object - this holds all the information needed for a
13228	 * given table, including configuration, data and current application of the
13229	 * table options. DataTables does not have a single instance for each DataTable
13230	 * with the settings attached to that instance, but rather instances of the
13231	 * DataTable "class" are created on-the-fly as needed (typically by a
13232	 * $().dataTable() call) and the settings object is then applied to that
13233	 * instance.
13234	 *
13235	 * Note that this object is related to {@link DataTable.defaults} but this
13236	 * one is the internal data store for DataTables's cache of columns. It should
13237	 * NOT be manipulated outside of DataTables. Any configuration should be done
13238	 * through the initialisation options.
13239	 *  @namespace
13240	 *  @todo Really should attach the settings object to individual instances so we
13241	 *    don't need to create new instances on each $().dataTable() call (if the
13242	 *    table already exists). It would also save passing oSettings around and
13243	 *    into every single function. However, this is a very significant
13244	 *    architecture change for DataTables and will almost certainly break
13245	 *    backwards compatibility with older installations. This is something that
13246	 *    will be done in 2.0.
13247	 */
13248	DataTable.models.oSettings = {
13249		/**
13250		 * Primary features of DataTables and their enablement state.
13251		 *  @namespace
13252		 */
13253		"oFeatures": {
13254	
13255			/**
13256			 * Flag to say if DataTables should automatically try to calculate the
13257			 * optimum table and columns widths (true) or not (false).
13258			 * Note that this parameter will be set by the initialisation routine. To
13259			 * set a default use {@link DataTable.defaults}.
13260			 *  @type boolean
13261			 */
13262			"bAutoWidth": null,
13263	
13264			/**
13265			 * Delay the creation of TR and TD elements until they are actually
13266			 * needed by a driven page draw. This can give a significant speed
13267			 * increase for Ajax source and Javascript source data, but makes no
13268			 * difference at all for DOM and server-side processing tables.
13269			 * Note that this parameter will be set by the initialisation routine. To
13270			 * set a default use {@link DataTable.defaults}.
13271			 *  @type boolean
13272			 */
13273			"bDeferRender": null,
13274	
13275			/**
13276			 * Enable filtering on the table or not. Note that if this is disabled
13277			 * then there is no filtering at all on the table, including fnFilter.
13278			 * To just remove the filtering input use sDom and remove the 'f' option.
13279			 * Note that this parameter will be set by the initialisation routine. To
13280			 * set a default use {@link DataTable.defaults}.
13281			 *  @type boolean
13282			 */
13283			"bFilter": null,
13284	
13285			/**
13286			 * Table information element (the 'Showing x of y records' div) enable
13287			 * flag.
13288			 * Note that this parameter will be set by the initialisation routine. To
13289			 * set a default use {@link DataTable.defaults}.
13290			 *  @type boolean
13291			 */
13292			"bInfo": null,
13293	
13294			/**
13295			 * Present a user control allowing the end user to change the page size
13296			 * when pagination is enabled.
13297			 * Note that this parameter will be set by the initialisation routine. To
13298			 * set a default use {@link DataTable.defaults}.
13299			 *  @type boolean
13300			 */
13301			"bLengthChange": null,
13302	
13303			/**
13304			 * Pagination enabled or not. Note that if this is disabled then length
13305			 * changing must also be disabled.
13306			 * Note that this parameter will be set by the initialisation routine. To
13307			 * set a default use {@link DataTable.defaults}.
13308			 *  @type boolean
13309			 */
13310			"bPaginate": null,
13311	
13312			/**
13313			 * Processing indicator enable flag whenever DataTables is enacting a
13314			 * user request - typically an Ajax request for server-side processing.
13315			 * Note that this parameter will be set by the initialisation routine. To
13316			 * set a default use {@link DataTable.defaults}.
13317			 *  @type boolean
13318			 */
13319			"bProcessing": null,
13320	
13321			/**
13322			 * Server-side processing enabled flag - when enabled DataTables will
13323			 * get all data from the server for every draw - there is no filtering,
13324			 * sorting or paging done on the client-side.
13325			 * Note that this parameter will be set by the initialisation routine. To
13326			 * set a default use {@link DataTable.defaults}.
13327			 *  @type boolean
13328			 */
13329			"bServerSide": null,
13330	
13331			/**
13332			 * Sorting enablement flag.
13333			 * Note that this parameter will be set by the initialisation routine. To
13334			 * set a default use {@link DataTable.defaults}.
13335			 *  @type boolean
13336			 */
13337			"bSort": null,
13338	
13339			/**
13340			 * Multi-column sorting
13341			 * Note that this parameter will be set by the initialisation routine. To
13342			 * set a default use {@link DataTable.defaults}.
13343			 *  @type boolean
13344			 */
13345			"bSortMulti": null,
13346	
13347			/**
13348			 * Apply a class to the columns which are being sorted to provide a
13349			 * visual highlight or not. This can slow things down when enabled since
13350			 * there is a lot of DOM interaction.
13351			 * Note that this parameter will be set by the initialisation routine. To
13352			 * set a default use {@link DataTable.defaults}.
13353			 *  @type boolean
13354			 */
13355			"bSortClasses": null,
13356	
13357			/**
13358			 * State saving enablement flag.
13359			 * Note that this parameter will be set by the initialisation routine. To
13360			 * set a default use {@link DataTable.defaults}.
13361			 *  @type boolean
13362			 */
13363			"bStateSave": null
13364		},
13365	
13366	
13367		/**
13368		 * Scrolling settings for a table.
13369		 *  @namespace
13370		 */
13371		"oScroll": {
13372			/**
13373			 * When the table is shorter in height than sScrollY, collapse the
13374			 * table container down to the height of the table (when true).
13375			 * Note that this parameter will be set by the initialisation routine. To
13376			 * set a default use {@link DataTable.defaults}.
13377			 *  @type boolean
13378			 */
13379			"bCollapse": null,
13380	
13381			/**
13382			 * Width of the scrollbar for the web-browser's platform. Calculated
13383			 * during table initialisation.
13384			 *  @type int
13385			 *  @default 0
13386			 */
13387			"iBarWidth": 0,
13388	
13389			/**
13390			 * Viewport width for horizontal scrolling. Horizontal scrolling is
13391			 * disabled if an empty string.
13392			 * Note that this parameter will be set by the initialisation routine. To
13393			 * set a default use {@link DataTable.defaults}.
13394			 *  @type string
13395			 */
13396			"sX": null,
13397	
13398			/**
13399			 * Width to expand the table to when using x-scrolling. Typically you
13400			 * should not need to use this.
13401			 * Note that this parameter will be set by the initialisation routine. To
13402			 * set a default use {@link DataTable.defaults}.
13403			 *  @type string
13404			 *  @deprecated
13405			 */
13406			"sXInner": null,
13407	
13408			/**
13409			 * Viewport height for vertical scrolling. Vertical scrolling is disabled
13410			 * if an empty string.
13411			 * Note that this parameter will be set by the initialisation routine. To
13412			 * set a default use {@link DataTable.defaults}.
13413			 *  @type string
13414			 */
13415			"sY": null
13416		},
13417	
13418		/**
13419		 * Language information for the table.
13420		 *  @namespace
13421		 *  @extends DataTable.defaults.oLanguage
13422		 */
13423		"oLanguage": {
13424			/**
13425			 * Information callback function. See
13426			 * {@link DataTable.defaults.fnInfoCallback}
13427			 *  @type function
13428			 *  @default null
13429			 */
13430			"fnInfoCallback": null
13431		},
13432	
13433		/**
13434		 * Browser support parameters
13435		 *  @namespace
13436		 */
13437		"oBrowser": {
13438			/**
13439			 * Indicate if the browser incorrectly calculates width:100% inside a
13440			 * scrolling element (IE6/7)
13441			 *  @type boolean
13442			 *  @default false
13443			 */
13444			"bScrollOversize": false,
13445	
13446			/**
13447			 * Determine if the vertical scrollbar is on the right or left of the
13448			 * scrolling container - needed for rtl language layout, although not
13449			 * all browsers move the scrollbar (Safari).
13450			 *  @type boolean
13451			 *  @default false
13452			 */
13453			"bScrollbarLeft": false,
13454	
13455			/**
13456			 * Flag for if `getBoundingClientRect` is fully supported or not
13457			 *  @type boolean
13458			 *  @default false
13459			 */
13460			"bBounding": false,
13461	
13462			/**
13463			 * Browser scrollbar width
13464			 *  @type integer
13465			 *  @default 0
13466			 */
13467			"barWidth": 0
13468		},
13469	
13470	
13471		"ajax": null,
13472	
13473	
13474		/**
13475		 * Array referencing the nodes which are used for the features. The
13476		 * parameters of this object match what is allowed by sDom - i.e.
13477		 *   <ul>
13478		 *     <li>'l' - Length changing</li>
13479		 *     <li>'f' - Filtering input</li>
13480		 *     <li>'t' - The table!</li>
13481		 *     <li>'i' - Information</li>
13482		 *     <li>'p' - Pagination</li>
13483		 *     <li>'r' - pRocessing</li>
13484		 *   </ul>
13485		 *  @type array
13486		 *  @default []
13487		 */
13488		"aanFeatures": [],
13489	
13490		/**
13491		 * Store data information - see {@link DataTable.models.oRow} for detailed
13492		 * information.
13493		 *  @type array
13494		 *  @default []
13495		 */
13496		"aoData": [],
13497	
13498		/**
13499		 * Array of indexes which are in the current display (after filtering etc)
13500		 *  @type array
13501		 *  @default []
13502		 */
13503		"aiDisplay": [],
13504	
13505		/**
13506		 * Array of indexes for display - no filtering
13507		 *  @type array
13508		 *  @default []
13509		 */
13510		"aiDisplayMaster": [],
13511	
13512		/**
13513		 * Map of row ids to data indexes
13514		 *  @type object
13515		 *  @default {}
13516		 */
13517		"aIds": {},
13518	
13519		/**
13520		 * Store information about each column that is in use
13521		 *  @type array
13522		 *  @default []
13523		 */
13524		"aoColumns": [],
13525	
13526		/**
13527		 * Store information about the table's header
13528		 *  @type array
13529		 *  @default []
13530		 */
13531		"aoHeader": [],
13532	
13533		/**
13534		 * Store information about the table's footer
13535		 *  @type array
13536		 *  @default []
13537		 */
13538		"aoFooter": [],
13539	
13540		/**
13541		 * Store the applied global search information in case we want to force a
13542		 * research or compare the old search to a new one.
13543		 * Note that this parameter will be set by the initialisation routine. To
13544		 * set a default use {@link DataTable.defaults}.
13545		 *  @namespace
13546		 *  @extends DataTable.models.oSearch
13547		 */
13548		"oPreviousSearch": {},
13549	
13550		/**
13551		 * Store the applied search for each column - see
13552		 * {@link DataTable.models.oSearch} for the format that is used for the
13553		 * filtering information for each column.
13554		 *  @type array
13555		 *  @default []
13556		 */
13557		"aoPreSearchCols": [],
13558	
13559		/**
13560		 * Sorting that is applied to the table. Note that the inner arrays are
13561		 * used in the following manner:
13562		 * <ul>
13563		 *   <li>Index 0 - column number</li>
13564		 *   <li>Index 1 - current sorting direction</li>
13565		 * </ul>
13566		 * Note that this parameter will be set by the initialisation routine. To
13567		 * set a default use {@link DataTable.defaults}.
13568		 *  @type array
13569		 *  @todo These inner arrays should really be objects
13570		 */
13571		"aaSorting": null,
13572	
13573		/**
13574		 * Sorting that is always applied to the table (i.e. prefixed in front of
13575		 * aaSorting).
13576		 * Note that this parameter will be set by the initialisation routine. To
13577		 * set a default use {@link DataTable.defaults}.
13578		 *  @type array
13579		 *  @default []
13580		 */
13581		"aaSortingFixed": [],
13582	
13583		/**
13584		 * Classes to use for the striping of a table.
13585		 * Note that this parameter will be set by the initialisation routine. To
13586		 * set a default use {@link DataTable.defaults}.
13587		 *  @type array
13588		 *  @default []
13589		 */
13590		"asStripeClasses": null,
13591	
13592		/**
13593		 * If restoring a table - we should restore its striping classes as well
13594		 *  @type array
13595		 *  @default []
13596		 */
13597		"asDestroyStripes": [],
13598	
13599		/**
13600		 * If restoring a table - we should restore its width
13601		 *  @type int
13602		 *  @default 0
13603		 */
13604		"sDestroyWidth": 0,
13605	
13606		/**
13607		 * Callback functions array for every time a row is inserted (i.e. on a draw).
13608		 *  @type array
13609		 *  @default []
13610		 */
13611		"aoRowCallback": [],
13612	
13613		/**
13614		 * Callback functions for the header on each draw.
13615		 *  @type array
13616		 *  @default []
13617		 */
13618		"aoHeaderCallback": [],
13619	
13620		/**
13621		 * Callback function for the footer on each draw.
13622		 *  @type array
13623		 *  @default []
13624		 */
13625		"aoFooterCallback": [],
13626	
13627		/**
13628		 * Array of callback functions for draw callback functions
13629		 *  @type array
13630		 *  @default []
13631		 */
13632		"aoDrawCallback": [],
13633	
13634		/**
13635		 * Array of callback functions for row created function
13636		 *  @type array
13637		 *  @default []
13638		 */
13639		"aoRowCreatedCallback": [],
13640	
13641		/**
13642		 * Callback functions for just before the table is redrawn. A return of
13643		 * false will be used to cancel the draw.
13644		 *  @type array
13645		 *  @default []
13646		 */
13647		"aoPreDrawCallback": [],
13648	
13649		/**
13650		 * Callback functions for when the table has been initialised.
13651		 *  @type array
13652		 *  @default []
13653		 */
13654		"aoInitComplete": [],
13655	
13656	
13657		/**
13658		 * Callbacks for modifying the settings to be stored for state saving, prior to
13659		 * saving state.
13660		 *  @type array
13661		 *  @default []
13662		 */
13663		"aoStateSaveParams": [],
13664	
13665		/**
13666		 * Callbacks for modifying the settings that have been stored for state saving
13667		 * prior to using the stored values to restore the state.
13668		 *  @type array
13669		 *  @default []
13670		 */
13671		"aoStateLoadParams": [],
13672	
13673		/**
13674		 * Callbacks for operating on the settings object once the saved state has been
13675		 * loaded
13676		 *  @type array
13677		 *  @default []
13678		 */
13679		"aoStateLoaded": [],
13680	
13681		/**
13682		 * Cache the table ID for quick access
13683		 *  @type string
13684		 *  @default <i>Empty string</i>
13685		 */
13686		"sTableId": "",
13687	
13688		/**
13689		 * The TABLE node for the main table
13690		 *  @type node
13691		 *  @default null
13692		 */
13693		"nTable": null,
13694	
13695		/**
13696		 * Permanent ref to the thead element
13697		 *  @type node
13698		 *  @default null
13699		 */
13700		"nTHead": null,
13701	
13702		/**
13703		 * Permanent ref to the tfoot element - if it exists
13704		 *  @type node
13705		 *  @default null
13706		 */
13707		"nTFoot": null,
13708	
13709		/**
13710		 * Permanent ref to the tbody element
13711		 *  @type node
13712		 *  @default null
13713		 */
13714		"nTBody": null,
13715	
13716		/**
13717		 * Cache the wrapper node (contains all DataTables controlled elements)
13718		 *  @type node
13719		 *  @default null
13720		 */
13721		"nTableWrapper": null,
13722	
13723		/**
13724		 * Indicate if when using server-side processing the loading of data
13725		 * should be deferred until the second draw.
13726		 * Note that this parameter will be set by the initialisation routine. To
13727		 * set a default use {@link DataTable.defaults}.
13728		 *  @type boolean
13729		 *  @default false
13730		 */
13731		"bDeferLoading": false,
13732	
13733		/**
13734		 * Indicate if all required information has been read in
13735		 *  @type boolean
13736		 *  @default false
13737		 */
13738		"bInitialised": false,
13739	
13740		/**
13741		 * Information about open rows. Each object in the array has the parameters
13742		 * 'nTr' and 'nParent'
13743		 *  @type array
13744		 *  @default []
13745		 */
13746		"aoOpenRows": [],
13747	
13748		/**
13749		 * Dictate the positioning of DataTables' control elements - see
13750		 * {@link DataTable.model.oInit.sDom}.
13751		 * Note that this parameter will be set by the initialisation routine. To
13752		 * set a default use {@link DataTable.defaults}.
13753		 *  @type string
13754		 *  @default null
13755		 */
13756		"sDom": null,
13757	
13758		/**
13759		 * Search delay (in mS)
13760		 *  @type integer
13761		 *  @default null
13762		 */
13763		"searchDelay": null,
13764	
13765		/**
13766		 * Which type of pagination should be used.
13767		 * Note that this parameter will be set by the initialisation routine. To
13768		 * set a default use {@link DataTable.defaults}.
13769		 *  @type string
13770		 *  @default two_button
13771		 */
13772		"sPaginationType": "two_button",
13773	
13774		/**
13775		 * The state duration (for `stateSave`) in seconds.
13776		 * Note that this parameter will be set by the initialisation routine. To
13777		 * set a default use {@link DataTable.defaults}.
13778		 *  @type int
13779		 *  @default 0
13780		 */
13781		"iStateDuration": 0,
13782	
13783		/**
13784		 * Array of callback functions for state saving. Each array element is an
13785		 * object with the following parameters:
13786		 *   <ul>
13787		 *     <li>function:fn - function to call. Takes two parameters, oSettings
13788		 *       and the JSON string to save that has been thus far created. Returns
13789		 *       a JSON string to be inserted into a json object
13790		 *       (i.e. '"param": [ 0, 1, 2]')</li>
13791		 *     <li>string:sName - name of callback</li>
13792		 *   </ul>
13793		 *  @type array
13794		 *  @default []
13795		 */
13796		"aoStateSave": [],
13797	
13798		/**
13799		 * Array of callback functions for state loading. Each array element is an
13800		 * object with the following parameters:
13801		 *   <ul>
13802		 *     <li>function:fn - function to call. Takes two parameters, oSettings
13803		 *       and the object stored. May return false to cancel state loading</li>
13804		 *     <li>string:sName - name of callback</li>
13805		 *   </ul>
13806		 *  @type array
13807		 *  @default []
13808		 */
13809		"aoStateLoad": [],
13810	
13811		/**
13812		 * State that was saved. Useful for back reference
13813		 *  @type object
13814		 *  @default null
13815		 */
13816		"oSavedState": null,
13817	
13818		/**
13819		 * State that was loaded. Useful for back reference
13820		 *  @type object
13821		 *  @default null
13822		 */
13823		"oLoadedState": null,
13824	
13825		/**
13826		 * Source url for AJAX data for the table.
13827		 * Note that this parameter will be set by the initialisation routine. To
13828		 * set a default use {@link DataTable.defaults}.
13829		 *  @type string
13830		 *  @default null
13831		 */
13832		"sAjaxSource": null,
13833	
13834		/**
13835		 * Property from a given object from which to read the table data from. This
13836		 * can be an empty string (when not server-side processing), in which case
13837		 * it is  assumed an an array is given directly.
13838		 * Note that this parameter will be set by the initialisation routine. To
13839		 * set a default use {@link DataTable.defaults}.
13840		 *  @type string
13841		 */
13842		"sAjaxDataProp": null,
13843	
13844		/**
13845		 * The last jQuery XHR object that was used for server-side data gathering.
13846		 * This can be used for working with the XHR information in one of the
13847		 * callbacks
13848		 *  @type object
13849		 *  @default null
13850		 */
13851		"jqXHR": null,
13852	
13853		/**
13854		 * JSON returned from the server in the last Ajax request
13855		 *  @type object
13856		 *  @default undefined
13857		 */
13858		"json": undefined,
13859	
13860		/**
13861		 * Data submitted as part of the last Ajax request
13862		 *  @type object
13863		 *  @default undefined
13864		 */
13865		"oAjaxData": undefined,
13866	
13867		/**
13868		 * Function to get the server-side data.
13869		 * Note that this parameter will be set by the initialisation routine. To
13870		 * set a default use {@link DataTable.defaults}.
13871		 *  @type function
13872		 */
13873		"fnServerData": null,
13874	
13875		/**
13876		 * Functions which are called prior to sending an Ajax request so extra
13877		 * parameters can easily be sent to the server
13878		 *  @type array
13879		 *  @default []
13880		 */
13881		"aoServerParams": [],
13882	
13883		/**
13884		 * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
13885		 * required).
13886		 * Note that this parameter will be set by the initialisation routine. To
13887		 * set a default use {@link DataTable.defaults}.
13888		 *  @type string
13889		 */
13890		"sServerMethod": null,
13891	
13892		/**
13893		 * Format numbers for display.
13894		 * Note that this parameter will be set by the initialisation routine. To
13895		 * set a default use {@link DataTable.defaults}.
13896		 *  @type function
13897		 */
13898		"fnFormatNumber": null,
13899	
13900		/**
13901		 * List of options that can be used for the user selectable length menu.
13902		 * Note that this parameter will be set by the initialisation routine. To
13903		 * set a default use {@link DataTable.defaults}.
13904		 *  @type array
13905		 *  @default []
13906		 */
13907		"aLengthMenu": null,
13908	
13909		/**
13910		 * Counter for the draws that the table does. Also used as a tracker for
13911		 * server-side processing
13912		 *  @type int
13913		 *  @default 0
13914		 */
13915		"iDraw": 0,
13916	
13917		/**
13918		 * Indicate if a redraw is being done - useful for Ajax
13919		 *  @type boolean
13920		 *  @default false
13921		 */
13922		"bDrawing": false,
13923	
13924		/**
13925		 * Draw index (iDraw) of the last error when parsing the returned data
13926		 *  @type int
13927		 *  @default -1
13928		 */
13929		"iDrawError": -1,
13930	
13931		/**
13932		 * Paging display length
13933		 *  @type int
13934		 *  @default 10
13935		 */
13936		"_iDisplayLength": 10,
13937	
13938		/**
13939		 * Paging start point - aiDisplay index
13940		 *  @type int
13941		 *  @default 0
13942		 */
13943		"_iDisplayStart": 0,
13944	
13945		/**
13946		 * Server-side processing - number of records in the result set
13947		 * (i.e. before filtering), Use fnRecordsTotal rather than
13948		 * this property to get the value of the number of records, regardless of
13949		 * the server-side processing setting.
13950		 *  @type int
13951		 *  @default 0
13952		 *  @private
13953		 */
13954		"_iRecordsTotal": 0,
13955	
13956		/**
13957		 * Server-side processing - number of records in the current display set
13958		 * (i.e. after filtering). Use fnRecordsDisplay rather than
13959		 * this property to get the value of the number of records, regardless of
13960		 * the server-side processing setting.
13961		 *  @type boolean
13962		 *  @default 0
13963		 *  @private
13964		 */
13965		"_iRecordsDisplay": 0,
13966	
13967		/**
13968		 * The classes to use for the table
13969		 *  @type object
13970		 *  @default {}
13971		 */
13972		"oClasses": {},
13973	
13974		/**
13975		 * Flag attached to the settings object so you can check in the draw
13976		 * callback if filtering has been done in the draw. Deprecated in favour of
13977		 * events.
13978		 *  @type boolean
13979		 *  @default false
13980		 *  @deprecated
13981		 */
13982		"bFiltered": false,
13983	
13984		/**
13985		 * Flag attached to the settings object so you can check in the draw
13986		 * callback if sorting has been done in the draw. Deprecated in favour of
13987		 * events.
13988		 *  @type boolean
13989		 *  @default false
13990		 *  @deprecated
13991		 */
13992		"bSorted": false,
13993	
13994		/**
13995		 * Indicate that if multiple rows are in the header and there is more than
13996		 * one unique cell per column, if the top one (true) or bottom one (false)
13997		 * should be used for sorting / title by DataTables.
13998		 * Note that this parameter will be set by the initialisation routine. To
13999		 * set a default use {@link DataTable.defaults}.
14000		 *  @type boolean
14001		 */
14002		"bSortCellsTop": null,
14003	
14004		/**
14005		 * Initialisation object that is used for the table
14006		 *  @type object
14007		 *  @default null
14008		 */
14009		"oInit": null,
14010	
14011		/**
14012		 * Destroy callback functions - for plug-ins to attach themselves to the
14013		 * destroy so they can clean up markup and events.
14014		 *  @type array
14015		 *  @default []
14016		 */
14017		"aoDestroyCallback": [],
14018	
14019	
14020		/**
14021		 * Get the number of records in the current record set, before filtering
14022		 *  @type function
14023		 */
14024		"fnRecordsTotal": function ()
14025		{
14026			return _fnDataSource( this ) == 'ssp' ?
14027				this._iRecordsTotal * 1 :
14028				this.aiDisplayMaster.length;
14029		},
14030	
14031		/**
14032		 * Get the number of records in the current record set, after filtering
14033		 *  @type function
14034		 */
14035		"fnRecordsDisplay": function ()
14036		{
14037			return _fnDataSource( this ) == 'ssp' ?
14038				this._iRecordsDisplay * 1 :
14039				this.aiDisplay.length;
14040		},
14041	
14042		/**
14043		 * Get the display end point - aiDisplay index
14044		 *  @type function
14045		 */
14046		"fnDisplayEnd": function ()
14047		{
14048			var
14049				len      = this._iDisplayLength,
14050				start    = this._iDisplayStart,
14051				calc     = start + len,
14052				records  = this.aiDisplay.length,
14053				features = this.oFeatures,
14054				paginate = features.bPaginate;
14055	
14056			if ( features.bServerSide ) {
14057				return paginate === false || len === -1 ?
14058					start + records :
14059					Math.min( start+len, this._iRecordsDisplay );
14060			}
14061			else {
14062				return ! paginate || calc>records || len===-1 ?
14063					records :
14064					calc;
14065			}
14066		},
14067	
14068		/**
14069		 * The DataTables object for this table
14070		 *  @type object
14071		 *  @default null
14072		 */
14073		"oInstance": null,
14074	
14075		/**
14076		 * Unique identifier for each instance of the DataTables object. If there
14077		 * is an ID on the table node, then it takes that value, otherwise an
14078		 * incrementing internal counter is used.
14079		 *  @type string
14080		 *  @default null
14081		 */
14082		"sInstance": null,
14083	
14084		/**
14085		 * tabindex attribute value that is added to DataTables control elements, allowing
14086		 * keyboard navigation of the table and its controls.
14087		 */
14088		"iTabIndex": 0,
14089	
14090		/**
14091		 * DIV container for the footer scrolling table if scrolling
14092		 */
14093		"nScrollHead": null,
14094	
14095		/**
14096		 * DIV container for the footer scrolling table if scrolling
14097		 */
14098		"nScrollFoot": null,
14099	
14100		/**
14101		 * Last applied sort
14102		 *  @type array
14103		 *  @default []
14104		 */
14105		"aLastSort": [],
14106	
14107		/**
14108		 * Stored plug-in instances
14109		 *  @type object
14110		 *  @default {}
14111		 */
14112		"oPlugins": {},
14113	
14114		/**
14115		 * Function used to get a row's id from the row's data
14116		 *  @type function
14117		 *  @default null
14118		 */
14119		"rowIdFn": null,
14120	
14121		/**
14122		 * Data location where to store a row's id
14123		 *  @type string
14124		 *  @default null
14125		 */
14126		"rowId": null
14127	};
14128	
14129	/**
14130	 * Extension object for DataTables that is used to provide all extension
14131	 * options.
14132	 *
14133	 * Note that the `DataTable.ext` object is available through
14134	 * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is
14135	 * also aliased to `jQuery.fn.dataTableExt` for historic reasons.
14136	 *  @namespace
14137	 *  @extends DataTable.models.ext
14138	 */
14139	
14140	
14141	/**
14142	 * DataTables extensions
14143	 * 
14144	 * This namespace acts as a collection area for plug-ins that can be used to
14145	 * extend DataTables capabilities. Indeed many of the build in methods
14146	 * use this method to provide their own capabilities (sorting methods for
14147	 * example).
14148	 *
14149	 * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy
14150	 * reasons
14151	 *
14152	 *  @namespace
14153	 */
14154	DataTable.ext = _ext = {
14155		/**
14156		 * Buttons. For use with the Buttons extension for DataTables. This is
14157		 * defined here so other extensions can define buttons regardless of load
14158		 * order. It is _not_ used by DataTables core.
14159		 *
14160		 *  @type object
14161		 *  @default {}
14162		 */
14163		buttons: {},
14164	
14165	
14166		/**
14167		 * Element class names
14168		 *
14169		 *  @type object
14170		 *  @default {}
14171		 */
14172		classes: {},
14173	
14174	
14175		/**
14176		 * DataTables build type (expanded by the download builder)
14177		 *
14178		 *  @type string
14179		 */
14180		builder: "-source-",
14181	
14182	
14183		/**
14184		 * Error reporting.
14185		 * 
14186		 * How should DataTables report an error. Can take the value 'alert',
14187		 * 'throw', 'none' or a function.
14188		 *
14189		 *  @type string|function
14190		 *  @default alert
14191		 */
14192		errMode: "alert",
14193	
14194	
14195		/**
14196		 * Feature plug-ins.
14197		 * 
14198		 * This is an array of objects which describe the feature plug-ins that are
14199		 * available to DataTables. These feature plug-ins are then available for
14200		 * use through the `dom` initialisation option.
14201		 * 
14202		 * Each feature plug-in is described by an object which must have the
14203		 * following properties:
14204		 * 
14205		 * * `fnInit` - function that is used to initialise the plug-in,
14206		 * * `cFeature` - a character so the feature can be enabled by the `dom`
14207		 *   instillation option. This is case sensitive.
14208		 *
14209		 * The `fnInit` function has the following input parameters:
14210		 *
14211		 * 1. `{object}` DataTables settings object: see
14212		 *    {@link DataTable.models.oSettings}
14213		 *
14214		 * And the following return is expected:
14215		 * 
14216		 * * {node|null} The element which contains your feature. Note that the
14217		 *   return may also be void if your plug-in does not require to inject any
14218		 *   DOM elements into DataTables control (`dom`) - for example this might
14219		 *   be useful when developing a plug-in which allows table control via
14220		 *   keyboard entry
14221		 *
14222		 *  @type array
14223		 *
14224		 *  @example
14225		 *    $.fn.dataTable.ext.features.push( {
14226		 *      "fnInit": function( oSettings ) {
14227		 *        return new TableTools( { "oDTSettings": oSettings } );
14228		 *      },
14229		 *      "cFeature": "T"
14230		 *    } );
14231		 */
14232		feature: [],
14233	
14234	
14235		/**
14236		 * Row searching.
14237		 * 
14238		 * This method of searching is complimentary to the default type based
14239		 * searching, and a lot more comprehensive as it allows you complete control
14240		 * over the searching logic. Each element in this array is a function
14241		 * (parameters described below) that is called for every row in the table,
14242		 * and your logic decides if it should be included in the searching data set
14243		 * or not.
14244		 *
14245		 * Searching functions have the following input parameters:
14246		 *
14247		 * 1. `{object}` DataTables settings object: see
14248		 *    {@link DataTable.models.oSettings}
14249		 * 2. `{array|object}` Data for the row to be processed (same as the
14250		 *    original format that was passed in as the data source, or an array
14251		 *    from a DOM data source
14252		 * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which
14253		 *    can be useful to retrieve the `TR` element if you need DOM interaction.
14254		 *
14255		 * And the following return is expected:
14256		 *
14257		 * * {boolean} Include the row in the searched result set (true) or not
14258		 *   (false)
14259		 *
14260		 * Note that as with the main search ability in DataTables, technically this
14261		 * is "filtering", since it is subtractive. However, for consistency in
14262		 * naming we call it searching here.
14263		 *
14264		 *  @type array
14265		 *  @default []
14266		 *
14267		 *  @example
14268		 *    // The following example shows custom search being applied to the
14269		 *    // fourth column (i.e. the data[3] index) based on two input values
14270		 *    // from the end-user, matching the data in a certain range.
14271		 *    $.fn.dataTable.ext.search.push(
14272		 *      function( settings, data, dataIndex ) {
14273		 *        var min = document.getElementById('min').value * 1;
14274		 *        var max = document.getElementById('max').value * 1;
14275		 *        var version = data[3] == "-" ? 0 : data[3]*1;
14276		 *
14277		 *        if ( min == "" && max == "" ) {
14278		 *          return true;
14279		 *        }
14280		 *        else if ( min == "" && version < max ) {
14281		 *          return true;
14282		 *        }
14283		 *        else if ( min < version && "" == max ) {
14284		 *          return true;
14285		 *        }
14286		 *        else if ( min < version && version < max ) {
14287		 *          return true;
14288		 *        }
14289		 *        return false;
14290		 *      }
14291		 *    );
14292		 */
14293		search: [],
14294	
14295	
14296		/**
14297		 * Selector extensions
14298		 *
14299		 * The `selector` option can be used to extend the options available for the
14300		 * selector modifier options (`selector-modifier` object data type) that
14301		 * each of the three built in selector types offer (row, column and cell +
14302		 * their plural counterparts). For example the Select extension uses this
14303		 * mechanism to provide an option to select only rows, columns and cells
14304		 * that have been marked as selected by the end user (`{selected: true}`),
14305		 * which can be used in conjunction with the existing built in selector
14306		 * options.
14307		 *
14308		 * Each property is an array to which functions can be pushed. The functions
14309		 * take three attributes:
14310		 *
14311		 * * Settings object for the host table
14312		 * * Options object (`selector-modifier` object type)
14313		 * * Array of selected item indexes
14314		 *
14315		 * The return is an array of the resulting item indexes after the custom
14316		 * selector has been applied.
14317		 *
14318		 *  @type object
14319		 */
14320		selector: {
14321			cell: [],
14322			column: [],
14323			row: []
14324		},
14325	
14326	
14327		/**
14328		 * Internal functions, exposed for used in plug-ins.
14329		 * 
14330		 * Please note that you should not need to use the internal methods for
14331		 * anything other than a plug-in (and even then, try to avoid if possible).
14332		 * The internal function may change between releases.
14333		 *
14334		 *  @type object
14335		 *  @default {}
14336		 */
14337		internal: {},
14338	
14339	
14340		/**
14341		 * Legacy configuration options. Enable and disable legacy options that
14342		 * are available in DataTables.
14343		 *
14344		 *  @type object
14345		 */
14346		legacy: {
14347			/**
14348			 * Enable / disable DataTables 1.9 compatible server-side processing
14349			 * requests
14350			 *
14351			 *  @type boolean
14352			 *  @default null
14353			 */
14354			ajax: null
14355		},
14356	
14357	
14358		/**
14359		 * Pagination plug-in methods.
14360		 * 
14361		 * Each entry in this object is a function and defines which buttons should
14362		 * be shown by the pagination rendering method that is used for the table:
14363		 * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the
14364		 * buttons are displayed in the document, while the functions here tell it
14365		 * what buttons to display. This is done by returning an array of button
14366		 * descriptions (what each button will do).
14367		 *
14368		 * Pagination types (the four built in options and any additional plug-in
14369		 * options defined here) can be used through the `paginationType`
14370		 * initialisation parameter.
14371		 *
14372		 * The functions defined take two parameters:
14373		 *
14374		 * 1. `{int} page` The current page index
14375		 * 2. `{int} pages` The number of pages in the table
14376		 *
14377		 * Each function is expected to return an array where each element of the
14378		 * array can be one of:
14379		 *
14380		 * * `first` - Jump to first page when activated
14381		 * * `last` - Jump to last page when activated
14382		 * * `previous` - Show previous page when activated
14383		 * * `next` - Show next page when activated
14384		 * * `{int}` - Show page of the index given
14385		 * * `{array}` - A nested array containing the above elements to add a
14386		 *   containing 'DIV' element (might be useful for styling).
14387		 *
14388		 * Note that DataTables v1.9- used this object slightly differently whereby
14389		 * an object with two functions would be defined for each plug-in. That
14390		 * ability is still supported by DataTables 1.10+ to provide backwards
14391		 * compatibility, but this option of use is now decremented and no longer
14392		 * documented in DataTables 1.10+.
14393		 *
14394		 *  @type object
14395		 *  @default {}
14396		 *
14397		 *  @example
14398		 *    // Show previous, next and current page buttons only
14399		 *    $.fn.dataTableExt.oPagination.current = function ( page, pages ) {
14400		 *      return [ 'previous', page, 'next' ];
14401		 *    };
14402		 */
14403		pager: {},
14404	
14405	
14406		renderer: {
14407			pageButton: {},
14408			header: {}
14409		},
14410	
14411	
14412		/**
14413		 * Ordering plug-ins - custom data source
14414		 * 
14415		 * The extension options for ordering of data available here is complimentary
14416		 * to the default type based ordering that DataTables typically uses. It
14417		 * allows much greater control over the the data that is being used to
14418		 * order a column, but is necessarily therefore more complex.
14419		 * 
14420		 * This type of ordering is useful if you want to do ordering based on data
14421		 * live from the DOM (for example the contents of an 'input' element) rather
14422		 * than just the static string that DataTables knows of.
14423		 * 
14424		 * The way these plug-ins work is that you create an array of the values you
14425		 * wish to be ordering for the column in question and then return that
14426		 * array. The data in the array much be in the index order of the rows in
14427		 * the table (not the currently ordering order!). Which order data gathering
14428		 * function is run here depends on the `dt-init columns.orderDataType`
14429		 * parameter that is used for the column (if any).
14430		 *
14431		 * The functions defined take two parameters:
14432		 *
14433		 * 1. `{object}` DataTables settings object: see
14434		 *    {@link DataTable.models.oSettings}
14435		 * 2. `{int}` Target column index
14436		 *
14437		 * Each function is expected to return an array:
14438		 *
14439		 * * `{array}` Data for the column to be ordering upon
14440		 *
14441		 *  @type array
14442		 *
14443		 *  @example
14444		 *    // Ordering using `input` node values
14445		 *    $.fn.dataTable.ext.order['dom-text'] = function  ( settings, col )
14446		 *    {
14447		 *      return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
14448		 *        return $('input', td).val();
14449		 *      } );
14450		 *    }
14451		 */
14452		order: {},
14453	
14454	
14455		/**
14456		 * Type based plug-ins.
14457		 *
14458		 * Each column in DataTables has a type assigned to it, either by automatic
14459		 * detection or by direct assignment using the `type` option for the column.
14460		 * The type of a column will effect how it is ordering and search (plug-ins
14461		 * can also make use of the column type if required).
14462		 *
14463		 * @namespace
14464		 */
14465		type: {
14466			/**
14467			 * Type detection functions.
14468			 *
14469			 * The functions defined in this object are used to automatically detect
14470			 * a column's type, making initialisation of DataTables super easy, even
14471			 * when complex data is in the table.
14472			 *
14473			 * The functions defined take two parameters:
14474			 *
14475		     *  1. `{*}` Data from the column cell to be analysed
14476		     *  2. `{settings}` DataTables settings object. This can be used to
14477		     *     perform context specific type detection - for example detection
14478		     *     based on language settings such as using a comma for a decimal
14479		     *     place. Generally speaking the options from the settings will not
14480		     *     be required
14481			 *
14482			 * Each function is expected to return:
14483			 *
14484			 * * `{string|null}` Data type detected, or null if unknown (and thus
14485			 *   pass it on to the other type detection functions.
14486			 *
14487			 *  @type array
14488			 *
14489			 *  @example
14490			 *    // Currency type detection plug-in:
14491			 *    $.fn.dataTable.ext.type.detect.push(
14492			 *      function ( data, settings ) {
14493			 *        // Check the numeric part
14494			 *        if ( ! data.substring(1).match(/[0-9]/) ) {
14495			 *          return null;
14496			 *        }
14497			 *
14498			 *        // Check prefixed by currency
14499			 *        if ( data.charAt(0) == '$' || data.charAt(0) == '&pound;' ) {
14500			 *          return 'currency';
14501			 *        }
14502			 *        return null;
14503			 *      }
14504			 *    );
14505			 */
14506			detect: [],
14507	
14508	
14509			/**
14510			 * Type based search formatting.
14511			 *
14512			 * The type based searching functions can be used to pre-format the
14513			 * data to be search on. For example, it can be used to strip HTML
14514			 * tags or to de-format telephone numbers for numeric only searching.
14515			 *
14516			 * Note that is a search is not defined for a column of a given type,
14517			 * no search formatting will be performed.
14518			 * 
14519			 * Pre-processing of searching data plug-ins - When you assign the sType
14520			 * for a column (or have it automatically detected for you by DataTables
14521			 * or a type detection plug-in), you will typically be using this for
14522			 * custom sorting, but it can also be used to provide custom searching
14523			 * by allowing you to pre-processing the data and returning the data in
14524			 * the format that should be searched upon. This is done by adding
14525			 * functions this object with a parameter name which matches the sType
14526			 * for that target column. This is the corollary of <i>afnSortData</i>
14527			 * for searching data.
14528			 *
14529			 * The functions defined take a single parameter:
14530			 *
14531		     *  1. `{*}` Data from the column cell to be prepared for searching
14532			 *
14533			 * Each function is expected to return:
14534			 *
14535			 * * `{string|null}` Formatted string that will be used for the searching.
14536			 *
14537			 *  @type object
14538			 *  @default {}
14539			 *
14540			 *  @example
14541			 *    $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) {
14542			 *      return d.replace(/\n/g," ").replace( /<.*?>/g, "" );
14543			 *    }
14544			 */
14545			search: {},
14546	
14547	
14548			/**
14549			 * Type based ordering.
14550			 *
14551			 * The column type tells DataTables what ordering to apply to the table
14552			 * when a column is sorted upon. The order for each type that is defined,
14553			 * is defined by the functions available in this object.
14554			 *
14555			 * Each ordering option can be described by three properties added to
14556			 * this object:
14557			 *
14558			 * * `{type}-pre` - Pre-formatting function
14559			 * * `{type}-asc` - Ascending order function
14560			 * * `{type}-desc` - Descending order function
14561			 *
14562			 * All three can be used together, only `{type}-pre` or only
14563			 * `{type}-asc` and `{type}-desc` together. It is generally recommended
14564			 * that only `{type}-pre` is used, as this provides the optimal
14565			 * implementation in terms of speed, although the others are provided
14566			 * for compatibility with existing Javascript sort functions.
14567			 *
14568			 * `{type}-pre`: Functions defined take a single parameter:
14569			 *
14570		     *  1. `{*}` Data from the column cell to be prepared for ordering
14571			 *
14572			 * And return:
14573			 *
14574			 * * `{*}` Data to be sorted upon
14575			 *
14576			 * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort
14577			 * functions, taking two parameters:
14578			 *
14579		     *  1. `{*}` Data to compare to the second parameter
14580		     *  2. `{*}` Data to compare to the first parameter
14581			 *
14582			 * And returning:
14583			 *
14584			 * * `{*}` Ordering match: <0 if first parameter should be sorted lower
14585			 *   than the second parameter, ===0 if the two parameters are equal and
14586			 *   >0 if the first parameter should be sorted height than the second
14587			 *   parameter.
14588			 * 
14589			 *  @type object
14590			 *  @default {}
14591			 *
14592			 *  @example
14593			 *    // Numeric ordering of formatted numbers with a pre-formatter
14594			 *    $.extend( $.fn.dataTable.ext.type.order, {
14595			 *      "string-pre": function(x) {
14596			 *        a = (a === "-" || a === "") ? 0 : a.replace( /[^\d\-\.]/g, "" );
14597			 *        return parseFloat( a );
14598			 *      }
14599			 *    } );
14600			 *
14601			 *  @example
14602			 *    // Case-sensitive string ordering, with no pre-formatting method
14603			 *    $.extend( $.fn.dataTable.ext.order, {
14604			 *      "string-case-asc": function(x,y) {
14605			 *        return ((x < y) ? -1 : ((x > y) ? 1 : 0));
14606			 *      },
14607			 *      "string-case-desc": function(x,y) {
14608			 *        return ((x < y) ? 1 : ((x > y) ? -1 : 0));
14609			 *      }
14610			 *    } );
14611			 */
14612			order: {}
14613		},
14614	
14615		/**
14616		 * Unique DataTables instance counter
14617		 *
14618		 * @type int
14619		 * @private
14620		 */
14621		_unique: 0,
14622	
14623	
14624		//
14625		// Depreciated
14626		// The following properties are retained for backwards compatibility only.
14627		// The should not be used in new projects and will be removed in a future
14628		// version
14629		//
14630	
14631		/**
14632		 * Version check function.
14633		 *  @type function
14634		 *  @depreciated Since 1.10
14635		 */
14636		fnVersionCheck: DataTable.fnVersionCheck,
14637	
14638	
14639		/**
14640		 * Index for what 'this' index API functions should use
14641		 *  @type int
14642		 *  @deprecated Since v1.10
14643		 */
14644		iApiIndex: 0,
14645	
14646	
14647		/**
14648		 * jQuery UI class container
14649		 *  @type object
14650		 *  @deprecated Since v1.10
14651		 */
14652		oJUIClasses: {},
14653	
14654	
14655		/**
14656		 * Software version
14657		 *  @type string
14658		 *  @deprecated Since v1.10
14659		 */
14660		sVersion: DataTable.version
14661	};
14662	
14663	
14664	//
14665	// Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts
14666	//
14667	$.extend( _ext, {
14668		afnFiltering: _ext.search,
14669		aTypes:       _ext.type.detect,
14670		ofnSearch:    _ext.type.search,
14671		oSort:        _ext.type.order,
14672		afnSortData:  _ext.order,
14673		aoFeatures:   _ext.feature,
14674		oApi:         _ext.internal,
14675		oStdClasses:  _ext.classes,
14676		oPagination:  _ext.pager
14677	} );
14678	
14679	
14680	$.extend( DataTable.ext.classes, {
14681		"sTable": "dataTable",
14682		"sNoFooter": "no-footer",
14683	
14684		/* Paging buttons */
14685		"sPageButton": "paginate_button",
14686		"sPageButtonActive": "current",
14687		"sPageButtonDisabled": "disabled",
14688	
14689		/* Striping classes */
14690		"sStripeOdd": "odd",
14691		"sStripeEven": "even",
14692	
14693		/* Empty row */
14694		"sRowEmpty": "dataTables_empty",
14695	
14696		/* Features */
14697		"sWrapper": "dataTables_wrapper",
14698		"sFilter": "dataTables_filter",
14699		"sInfo": "dataTables_info",
14700		"sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
14701		"sLength": "dataTables_length",
14702		"sProcessing": "dataTables_processing",
14703	
14704		/* Sorting */
14705		"sSortAsc": "sorting_asc",
14706		"sSortDesc": "sorting_desc",
14707		"sSortable": "sorting", /* Sortable in both directions */
14708		"sSortableAsc": "sorting_desc_disabled",
14709		"sSortableDesc": "sorting_asc_disabled",
14710		"sSortableNone": "sorting_disabled",
14711		"sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
14712	
14713		/* Filtering */
14714		"sFilterInput": "",
14715	
14716		/* Page length */
14717		"sLengthSelect": "",
14718	
14719		/* Scrolling */
14720		"sScrollWrapper": "dataTables_scroll",
14721		"sScrollHead": "dataTables_scrollHead",
14722		"sScrollHeadInner": "dataTables_scrollHeadInner",
14723		"sScrollBody": "dataTables_scrollBody",
14724		"sScrollFoot": "dataTables_scrollFoot",
14725		"sScrollFootInner": "dataTables_scrollFootInner",
14726	
14727		/* Misc */
14728		"sHeaderTH": "",
14729		"sFooterTH": "",
14730	
14731		// Deprecated
14732		"sSortJUIAsc": "",
14733		"sSortJUIDesc": "",
14734		"sSortJUI": "",
14735		"sSortJUIAscAllowed": "",
14736		"sSortJUIDescAllowed": "",
14737		"sSortJUIWrapper": "",
14738		"sSortIcon": "",
14739		"sJUIHeader": "",
14740		"sJUIFooter": ""
14741	} );
14742	
14743	
14744	var extPagination = DataTable.ext.pager;
14745	
14746	function _numbers ( page, pages ) {
14747		var
14748			numbers = [],
14749			buttons = extPagination.numbers_length,
14750			half = Math.floor( buttons / 2 ),
14751			i = 1;
14752	
14753		if ( pages <= buttons ) {
14754			numbers = _range( 0, pages );
14755		}
14756		else if ( page <= half ) {
14757			numbers = _range( 0, buttons-2 );
14758			numbers.push( 'ellipsis' );
14759			numbers.push( pages-1 );
14760		}
14761		else if ( page >= pages - 1 - half ) {
14762			numbers = _range( pages-(buttons-2), pages );
14763			numbers.splice( 0, 0, 'ellipsis' ); // no unshift in ie6
14764			numbers.splice( 0, 0, 0 );
14765		}
14766		else {
14767			numbers = _range( page-half+2, page+half-1 );
14768			numbers.push( 'ellipsis' );
14769			numbers.push( pages-1 );
14770			numbers.splice( 0, 0, 'ellipsis' );
14771			numbers.splice( 0, 0, 0 );
14772		}
14773	
14774		numbers.DT_el = 'span';
14775		return numbers;
14776	}
14777	
14778	
14779	$.extend( extPagination, {
14780		simple: function ( page, pages ) {
14781			return [ 'previous', 'next' ];
14782		},
14783	
14784		full: function ( page, pages ) {
14785			return [  'first', 'previous', 'next', 'last' ];
14786		},
14787	
14788		numbers: function ( page, pages ) {
14789			return [ _numbers(page, pages) ];
14790		},
14791	
14792		simple_numbers: function ( page, pages ) {
14793			return [ 'previous', _numbers(page, pages), 'next' ];
14794		},
14795	
14796		full_numbers: function ( page, pages ) {
14797			return [ 'first', 'previous', _numbers(page, pages), 'next', 'last' ];
14798		},
14799		
14800		first_last_numbers: function (page, pages) {
14801	 		return ['first', _numbers(page, pages), 'last'];
14802	 	},
14803	
14804		// For testing and plug-ins to use
14805		_numbers: _numbers,
14806	
14807		// Number of number buttons (including ellipsis) to show. _Must be odd!_
14808		numbers_length: 7
14809	} );
14810	
14811	
14812	$.extend( true, DataTable.ext.renderer, {
14813		pageButton: {
14814			_: function ( settings, host, idx, buttons, page, pages ) {
14815				var classes = settings.oClasses;
14816				var lang = settings.oLanguage.oPaginate;
14817				var aria = settings.oLanguage.oAria.paginate || {};
14818				var btnDisplay, btnClass;
14819	
14820				var attach = function( container, buttons ) {
14821					var i, ien, node, button, tabIndex;
14822					var disabledClass = classes.sPageButtonDisabled;
14823					var clickHandler = function ( e ) {
14824						_fnPageChange( settings, e.data.action, true );
14825					};
14826	
14827					for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
14828						button = buttons[i];
14829	
14830						if ( Array.isArray( button ) ) {
14831							var inner = $( '<'+(button.DT_el || 'div')+'/>' )
14832								.appendTo( container );
14833							attach( inner, button );
14834						}
14835						else {
14836							btnDisplay = null;
14837							btnClass = button;
14838							tabIndex = settings.iTabIndex;
14839	
14840							switch ( button ) {
14841								case 'ellipsis':
14842									container.append('<span class="ellipsis">&#x2026;</span>');
14843									break;
14844	
14845								case 'first':
14846									btnDisplay = lang.sFirst;
14847	
14848									if ( page === 0 ) {
14849										tabIndex = -1;
14850										btnClass += ' ' + disabledClass;
14851									}
14852									break;
14853	
14854								case 'previous':
14855									btnDisplay = lang.sPrevious;
14856	
14857									if ( page === 0 ) {
14858										tabIndex = -1;
14859										btnClass += ' ' + disabledClass;
14860									}
14861									break;
14862	
14863								case 'next':
14864									btnDisplay = lang.sNext;
14865	
14866									if ( pages === 0 || page === pages-1 ) {
14867										tabIndex = -1;
14868										btnClass += ' ' + disabledClass;
14869									}
14870									break;
14871	
14872								case 'last':
14873									btnDisplay = lang.sLast;
14874	
14875									if ( pages === 0 || page === pages-1 ) {
14876										tabIndex = -1;
14877										btnClass += ' ' + disabledClass;
14878									}
14879									break;
14880	
14881								default:
14882									btnDisplay = settings.fnFormatNumber( button + 1 );
14883									btnClass = page === button ?
14884										classes.sPageButtonActive : '';
14885									break;
14886							}
14887	
14888							if ( btnDisplay !== null ) {
14889								var tag = settings.oInit.pagingTag || 'a';
14890								var disabled = btnClass.indexOf(disabledClass) !== -1;
14891			
14892	
14893								node = $('<'+tag+'>', {
14894										'class': classes.sPageButton+' '+btnClass,
14895										'aria-controls': settings.sTableId,
14896										'aria-disabled': disabled ? 'true' : null,
14897										'aria-label': aria[ button ],
14898										'
14898aria-role': 'link',
14899										'aria-current': btnClass === classes.sPageButtonActive ? 'page' : null,
14900										'data-dt-idx': button,
14901										'tabindex': tabIndex,
14902										'id': idx === 0 && typeof button === 'string' ?
14903											settings.sTableId +'_'+ button :
14904											null
14905									} )
14906									.html( btnDisplay )
14907									.appendTo( container );
14908	
14909								_fnBindAction(
14910									node, {action: button}, clickHandler
14911								);
14912							}
14913						}
14914					}
14915				};
14916	
14917				// IE9 throws an 'unknown error' if document.activeElement is used
14918				// inside an iframe or frame. Try / catch the error. Not good for
14919				// accessibility, but neither are frames.
14920				var activeEl;
14921	
vendor: 2,993 bytes, lines 14922-15032
14922				try {
14923					// Because this approach is destroying and recreating the paging
14924					// elements, focus is lost on the select button which is bad for
14925					// accessibility. So we want to restore focus once the draw has
14926					// completed
14927					activeEl = $(host).find(document.activeElement).data('dt-idx');
14928				}
14929				catch (e) {}
14930	
14931				attach( $(host).empty(), buttons );
14932	
14933				if ( activeEl !== undefined ) {
14934					$(host).find( '[data-dt-idx='+activeEl+']' ).trigger('focus');
14935				}
14936			}
14937		}
14938	} );
14939	
14940	
14941	
14942	// Built in type detection. See model.ext.aTypes for information about
14943	// what is required from this methods.
14944	$.extend( DataTable.ext.type.detect, [
14945		// Plain numbers - first since V8 detects some plain numbers as dates
14946		// e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...).
14947		function ( d, settings )
14948		{
14949			var decimal = settings.oLanguage.sDecimal;
14950			return _isNumber( d, decimal ) ? 'num'+decimal : null;
14951		},
14952	
14953		// Dates (only those recognised by the browser's Date.parse)
14954		function ( d, settings )
14955		{
14956			// V8 tries _very_ hard to make a string passed into `Date.parse()`
14957			// valid, so we need to use a regex to restrict date formats. Use a
14958			// plug-in for anything other than ISO8601 style strings
14959			if ( d && !(d instanceof Date) && ! _re_date.test(d) ) {
14960				return null;
14961			}
14962			var parsed = Date.parse(d);
14963			return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null;
14964		},
14965	
14966		// Formatted numbers
14967		function ( d, settings )
14968		{
14969			var decimal = settings.oLanguage.sDecimal;
14970			return _isNumber( d, decimal, true ) ? 'num-fmt'+decimal : null;
14971		},
14972	
14973		// HTML numeric
14974		function ( d, settings )
14975		{
14976			var decimal = settings.oLanguage.sDecimal;
14977			return _htmlNumeric( d, decimal ) ? 'html-num'+decimal : null;
14978		},
14979	
14980		// HTML numeric, formatted
14981		function ( d, settings )
14982		{
14983			var decimal = settings.oLanguage.sDecimal;
14984			return _htmlNumeric( d, decimal, true ) ? 'html-num-fmt'+decimal : null;
14985		},
14986	
14987		// HTML (this is strict checking - there must be html)
14988		function ( d, settings )
14989		{
14990			return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ?
14991				'html' : null;
14992		}
14993	] );
14994	
14995	
14996	
14997	// Filter formatting functions. See model.ext.ofnSearch for information about
14998	// what is required from these methods.
14999	// 
15000	// Note that additional search methods are added for the html numbers and
15001	// html formatted numbers by `_addNumericSort()` when we know what the decimal
15002	// place is
15003	
15004	
15005	$.extend( DataTable.ext.type.search, {
15006		html: function ( data ) {
15007			return _empty(data) ?
15008				data :
15009				typeof data === 'string' ?
15010					data
15011						.replace( _re_new_lines, " " )
15012						.replace( _re_html, "" ) :
15013					'';
15014		},
15015	
15016		string: function ( data ) {
15017			return _empty(data) ?
15018				data :
15019				typeof data === 'string' ?
15020					data.replace( _re_new_lines, " " ) :
15021					data;
15022		}
15023	} );
15024	
15025	
15026	
15027	var __numericReplace = function ( d, decimalPlace, re1, re2 ) {
15028		if ( d !== 0 && (!d || d === '-') ) {
15029			return -Infinity;
15030		}
15031		
15032		let
vendor: 9,520 bytes, lines 15032-15406
15032 type = typeof d;
15033	
15034		if (type === 'number' || type === 'bigint') {
15035			return d;
15036		}
15037	
15038		// If a decimal place other than `.` is used, it needs to be given to the
15039		// function so we can detect it and replace with a `.` which is the only
15040		// decimal place Javascript recognises - it is not locale aware.
15041		if ( decimalPlace ) {
15042			d = _numToDecimal( d, decimalPlace );
15043		}
15044	
15045		if ( d.replace ) {
15046			if ( re1 ) {
15047				d = d.replace( re1, '' );
15048			}
15049	
15050			if ( re2 ) {
15051				d = d.replace( re2, '' );
15052			}
15053		}
15054	
15055		return d * 1;
15056	};
15057	
15058	
15059	// Add the numeric 'deformatting' functions for sorting and search. This is done
15060	// in a function to provide an easy ability for the language options to add
15061	// additional methods if a non-period decimal place is used.
15062	function _addNumericSort ( decimalPlace ) {
15063		$.each(
15064			{
15065				// Plain numbers
15066				"num": function ( d ) {
15067					return __numericReplace( d, decimalPlace );
15068				},
15069	
15070				// Formatted numbers
15071				"num-fmt": function ( d ) {
15072					return __numericReplace( d, decimalPlace, _re_formatted_numeric );
15073				},
15074	
15075				// HTML numeric
15076				"html-num": function ( d ) {
15077					return __numericReplace( d, decimalPlace, _re_html );
15078				},
15079	
15080				// HTML numeric, formatted
15081				"html-num-fmt": function ( d ) {
15082					return __numericReplace( d, decimalPlace, _re_html, _re_formatted_numeric );
15083				}
15084			},
15085			function ( key, fn ) {
15086				// Add the ordering method
15087				_ext.type.order[ key+decimalPlace+'-pre' ] = fn;
15088	
15089				// For HTML types add a search formatter that will strip the HTML
15090				if ( key.match(/^html\-/) ) {
15091					_ext.type.search[ key+decimalPlace ] = _ext.type.search.html;
15092				}
15093			}
15094		);
15095	}
15096	
15097	
15098	// Default sort methods
15099	$.extend( _ext.type.order, {
15100		// Dates
15101		"date-pre": function ( d ) {
15102			var ts = Date.parse( d );
15103			return isNaN(ts) ? -Infinity : ts;
15104		},
15105	
15106		// html
15107		"html-pre": function ( a ) {
15108			return _empty(a) ?
15109				'' :
15110				a.replace ?
15111					a.replace( /<.*?>/g, "" ).toLowerCase() :
15112					a+'';
15113		},
15114	
15115		// string
15116		"string-pre": function ( a ) {
15117			// This is a little complex, but faster than always calling toString,
15118			// http://jsperf.com/tostring-v-check
15119			return _empty(a) ?
15120				'' :
15121				typeof a === 'string' ?
15122					a.toLowerCase() :
15123					! a.toString ?
15124						'' :
15125						a.toString();
15126		},
15127	
15128		// string-asc and -desc are retained only for compatibility with the old
15129		// sort methods
15130		"string-asc": function ( x, y ) {
15131			return ((x < y) ? -1 : ((x > y) ? 1 : 0));
15132		},
15133	
15134		"string-desc": function ( x, y ) {
15135			return ((x < y) ? 1 : ((x > y) ? -1 : 0));
15136		}
15137	} );
15138	
15139	
15140	// Numeric sorting types - order doesn't matter here
15141	_addNumericSort( '' );
15142	
15143	
15144	$.extend( true, DataTable.ext.renderer, {
15145		header: {
15146			_: function ( settings, cell, column, classes ) {
15147				// No additional mark-up required
15148				// Attach a sort listener to update on sort - note that using the
15149				// `DT` namespace will allow the event to be removed automatically
15150				// on destroy, while the `dt` namespaced event is the one we are
15151				// listening for
15152				$(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
15153					if ( settings !== ctx ) { // need to check this this is the host
15154						return;               // table, not a nested one
15155					}
15156	
15157					var colIdx = column.idx;
15158	
15159					cell
15160						.removeClass(
15161							classes.sSortAsc +' '+
15162							classes.sSortDesc
15163						)
15164						.addClass( columns[ colIdx ] == 'asc' ?
15165							classes.sSortAsc : columns[ colIdx ] == 'desc' ?
15166								classes.sSortDesc :
15167								column.sSortingClass
15168						);
15169				} );
15170			},
15171	
15172			jqueryui: function ( settings, cell, column, classes ) {
15173				$('<div/>')
15174					.addClass( classes.sSortJUIWrapper )
15175					.append( cell.contents() )
15176					.append( $('<span/>')
15177						.addClass( classes.sSortIcon+' '+column.sSortingClassJUI )
15178					)
15179					.appendTo( cell );
15180	
15181				// Attach a sort listener to update on sort
15182				$(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
15183					if ( settings !== ctx ) {
15184						return;
15185					}
15186	
15187					var colIdx = column.idx;
15188	
15189					cell
15190						.removeClass( classes.sSortAsc +" "+classes.sSortDesc )
15191						.addClass( columns[ colIdx ] == 'asc' ?
15192							classes.sSortAsc : columns[ colIdx ] == 'desc' ?
15193								classes.sSortDesc :
15194								column.sSortingClass
15195						);
15196	
15197					cell
15198						.find( 'span.'+classes.sSortIcon )
15199						.removeClass(
15200							classes.sSortJUIAsc +" "+
15201							classes.sSortJUIDesc +" "+
15202							classes.sSortJUI +" "+
15203							classes.sSortJUIAscAllowed +" "+
15204							classes.sSortJUIDescAllowed
15205						)
15206						.addClass( columns[ colIdx ] == 'asc' ?
15207							classes.sSortJUIAsc : columns[ colIdx ] == 'desc' ?
15208								classes.sSortJUIDesc :
15209								column.sSortingClassJUI
15210						);
15211				} );
15212			}
15213		}
15214	} );
15215	
15216	/*
15217	 * Public helper functions. These aren't used internally by DataTables, or
15218	 * called by any of the options passed into DataTables, but they can be used
15219	 * externally by developers working with DataTables. They are helper functions
15220	 * to make working with DataTables a little bit easier.
15221	 */
15222	
15223	var __htmlEscapeEntities = function ( d ) {
15224		if (Array.isArray(d)) {
15225			d = d.join(',');
15226		}
15227	
15228		return typeof d === 'string' ?
15229			d
15230				.replace(/&/g, '&amp;')
15231				.replace(/</g, '&lt;')
15232				.replace(/>/g, '&gt;')
15233				.replace(/"/g, '&quot;') :
15234			d;
15235	};
15236	
15237	// Common logic for moment, luxon or a date action
15238	function __mld( dt, momentFn, luxonFn, dateFn, arg1 ) {
15239		if (window.moment) {
15240			return dt[momentFn]( arg1 );
15241		}
15242		else if (window.luxon) {
15243			return dt[luxonFn]( arg1 );
15244		}
15245		
15246		return dateFn ? dt[dateFn]( arg1 ) : dt;
15247	}
15248	
15249	
15250	var __mlWarning = false;
15251	function __mldObj (d, format, locale) {
15252		var dt;
15253	
15254		if (window.moment) {
15255			dt = window.moment.utc( d, format, locale, true );
15256	
15257			if (! dt.isValid()) {
15258				return null;
15259			}
15260		}
15261		else if (window.luxon) {
15262			dt = format && typeof d === 'string'
15263				? window.luxon.DateTime.fromFormat( d, format )
15264				: window.luxon.DateTime.fromISO( d );
15265	
15266			if (! dt.isValid) {
15267				return null;
15268			}
15269	
15270			dt.setLocale(locale);
15271		}
15272		else if (! format) {
15273			// No format given, must be ISO
15274			dt = new Date(d);
15275		}
15276		else {
15277			if (! __mlWarning) {
15278				alert('DataTables warning: Formatted date without Moment.js or Luxon - https://datatables.net/tn/17');
15279			}
15280	
15281			__mlWarning = true;
15282		}
15283	
15284		return dt;
15285	}
15286	
15287	// Wrapper for date, datetime and time which all operate the same way with the exception of
15288	// the output string for auto locale support
15289	function __mlHelper (localeString) {
15290		return function ( from, to, locale, def ) {
15291			// Luxon and Moment support
15292			// Argument shifting
15293			if ( arguments.length === 0 ) {
15294				locale = 'en';
15295				to = null; // means toLocaleString
15296				from = null; // means iso8601
15297			}
15298			else if ( arguments.length === 1 ) {
15299				locale = 'en';
15300				to = from;
15301				from = null;
15302			}
15303			else if ( arguments.length === 2 ) {
15304				locale = to;
15305				to = from;
15306				from = null;
15307			}
15308	
15309			var typeName = 'datetime-' + to;
15310	
15311			// Add type detection and sorting specific to this date format - we need to be able to identify
15312			// date type columns as such, rather than as numbers in extensions. Hence the need for this.
15313			if (! DataTable.ext.type.order[typeName]) {
15314				// The renderer will give the value to type detect as the type!
15315				DataTable.ext.type.detect.unshift(function (d) {
15316					return d === typeName ? typeName : false;
15317				});
15318	
15319				// The renderer gives us Moment, Luxon or Date obects for the sorting, all of which have a
15320				// `valueOf` which gives milliseconds epoch
15321				DataTable.ext.type.order[typeName + '-asc'] = function (a, b) {
15322					var x = a.valueOf();
15323					var y = b.valueOf();
15324	
15325					return x === y
15326						? 0
15327						: x < y
15328							? -1
15329							: 1;
15330				}
15331	
15332				DataTable.ext.type.order[typeName + '-desc'] = function (a, b) {
15333					var x = a.valueOf();
15334					var y = b.valueOf();
15335	
15336					return x === y
15337						? 0
15338						: x > y
15339							? -1
15340							: 1;
15341				}
15342			}
15343		
15344			return function ( d, type ) {
15345				// Allow for a default value
15346				if (d === null || d === undefined) {
15347					if (def === '--now') {
15348						// We treat everything as UTC further down, so no changes are
15349						// made, as such need to get the local date / time as if it were
15350						// UTC
15351						var local = new Date();
15352						d = new Date( Date.UTC(
15353							local.getFullYear(), local.getMonth(), local.getDate(),
15354							local.getHours(), local.getMinutes(), local.getSeconds()
15355						) );
15356					}
15357					else {
15358						d = '';
15359					}
15360				}
15361	
15362				if (type === 'type') {
15363					// Typing uses the type name for fast matching
15364					return typeName;
15365				}
15366	
15367				if (d === '') {
15368					return type !== 'sort'
15369						? ''
15370						: __mldObj('0000-01-01 00:00:00', null, locale);
15371				}
15372	
15373				// Shortcut. If `from` and `to` are the same, we are using the renderer to
15374				// format for ordering, not display - its already in the display format.
15375				if ( to !== null && from === to && type !== 'sort' && type !== 'type' && ! (d instanceof Date) ) {
15376					return d;
15377				}
15378	
15379				var dt = __mldObj(d, from, locale);
15380	
15381				if (dt === null) {
15382					return d;
15383				}
15384	
15385				if (type === 'sort') {
15386					return dt;
15387				}
15388				
15389				var formatted = to === null
15390					? __mld(dt, 'toDate', 'toJSDate', '')[localeString]()
15391					: __mld(dt, 'format', 'toFormat', 'toISOString', to);
15392	
15393				// XSS protection
15394				return type === 'display' ?
15395					__htmlEscapeEntities( formatted ) :
15396					formatted;
15397			};
15398		}
15399	}
15400	
15401	// Based on locale, determine standard number formatting
15402	// Fallback for legacy browsers is US English
15403	var __thousands = ',';
15404	var __decimal = '.';
15405	
15406	if (
vendor: 8,417 bytes, lines 15406-15686
15406Intl) {
15407		try {
15408			var num = new Intl.NumberFormat().formatToParts(100000.1);
15409		
15410			for (var i=0 ; i<num.length ; i++) {
15411				if (num[i].type === 'group') {
15412					__thousands = num[i].value;
15413				}
15414				else if (num[i].type === 'decimal') {
15415					__decimal = num[i].value;
15416				}
15417			}
15418		}
15419		catch (e) {
15420			// noop
15421		}
15422	}
15423	
15424	// Formatted date time detection - use by declaring the formats you are going to use
15425	DataTable.datetime = function ( format, locale ) {
15426		var typeName = 'datetime-detect-' + format;
15427	
15428		if (! locale) {
15429			locale = 'en';
15430		}
15431	
15432		if (! DataTable.ext.type.order[typeName]) {
15433			DataTable.ext.type.detect.unshift(function (d) {
15434				var dt = __mldObj(d, format, locale);
15435				return d === '' || dt ? typeName : false;
15436			});
15437	
15438			DataTable.ext.type.order[typeName + '-pre'] = function (d) {
15439				return __mldObj(d, format, locale) || 0;
15440			}
15441		}
15442	}
15443	
15444	/**
15445	 * Helpers for `columns.render`.
15446	 *
15447	 * The options defined here can be used with the `columns.render` initialisation
15448	 * option to provide a display renderer. The following functions are defined:
15449	 *
15450	 * * `number` - Will format numeric data (defined by `columns.data`) for
15451	 *   display, retaining the original unformatted data for sorting and filtering.
15452	 *   It takes 5 parameters:
15453	 *   * `string` - Thousands grouping separator
15454	 *   * `string` - Decimal point indicator
15455	 *   * `integer` - Number of decimal points to show
15456	 *   * `string` (optional) - Prefix.
15457	 *   * `string` (optional) - Postfix (/suffix).
15458	 * * `text` - Escape HTML to help prevent XSS attacks. It has no optional
15459	 *   parameters.
15460	 *
15461	 * @example
15462	 *   // Column definition using the number renderer
15463	 *   {
15464	 *     data: "salary",
15465	 *     render: $.fn.dataTable.render.number( '\'', '.', 0, '$' )
15466	 *   }
15467	 *
15468	 * @namespace
15469	 */
15470	DataTable.render = {
15471		date: __mlHelper('toLocaleDateString'),
15472		datetime: __mlHelper('toLocaleString'),
15473		time: __mlHelper('toLocaleTimeString'),
15474		number: function ( thousands, decimal, precision, prefix, postfix ) {
15475			// Auto locale detection
15476			if (thousands === null || thousands === undefined) {
15477				thousands = __thousands;
15478			}
15479	
15480			if (decimal === null || decimal === undefined) {
15481				decimal = __decimal;
15482			}
15483	
15484			return {
15485				display: function ( d ) {
15486					if ( typeof d !== 'number' && typeof d !== 'string' ) {
15487						return d;
15488					}
15489	
15490					if (d === '' || d === null) {
15491						return d;
15492					}
15493	
15494					var negative = d < 0 ? '-' : '';
15495					var flo = parseFloat( d );
15496	
15497					// If NaN then there isn't much formatting that we can do - just
15498					// return immediately, escaping any HTML (this was supposed to
15499					// be a number after all)
15500					if ( isNaN( flo ) ) {
15501						return __htmlEscapeEntities( d );
15502					}
15503	
15504					flo = flo.toFixed( precision );
15505					d = Math.abs( flo );
15506	
15507					var intPart = parseInt( d, 10 );
15508					var floatPart = precision ?
15509						decimal+(d - intPart).toFixed( precision ).substring( 2 ):
15510						'';
15511	
15512					// If zero, then can't have a negative prefix
15513					if (intPart === 0 && parseFloat(floatPart) === 0) {
15514						negative = '';
15515					}
15516	
15517					return negative + (prefix||'') +
15518						intPart.toString().replace(
15519							/\B(?=(\d{3})+(?!\d))/g, thousands
15520						) +
15521						floatPart +
15522						(postfix||'');
15523				}
15524			};
15525		},
15526	
15527		text: function () {
15528			return {
15529				display: __htmlEscapeEntities,
15530				filter: __htmlEscapeEntities
15531			};
15532		}
15533	};
15534	
15535	
15536	/*
15537	 * This is really a good bit rubbish this method of exposing the internal methods
15538	 * publicly... - To be fixed in 2.0 using methods on the prototype
15539	 */
15540	
15541	
15542	/**
15543	 * Create a wrapper function for exporting an internal functions to an external API.
15544	 *  @param {string} fn API function name
15545	 *  @returns {function} wrapped function
15546	 *  @memberof DataTable#internal
15547	 */
15548	function _fnExternApiFunc (fn)
15549	{
15550		return function() {
15551			var args = [_fnSettingsFromNode( this[DataTable.ext.iApiIndex] )].concat(
15552				Array.prototype.slice.call(arguments)
15553			);
15554			return DataTable.ext.internal[fn].apply( this, args );
15555		};
15556	}
15557	
15558	
15559	/**
15560	 * Reference to internal functions for use by plug-in developers. Note that
15561	 * these methods are references to internal functions and are considered to be
15562	 * private. If you use these methods, be aware that they are liable to change
15563	 * between versions.
15564	 *  @namespace
15565	 */
15566	$.extend( DataTable.ext.internal, {
15567		_fnExternApiFunc: _fnExternApiFunc,
15568		_fnBuildAjax: _fnBuildAjax,
15569		_fnAjaxUpdate: _fnAjaxUpdate,
15570		_fnAjaxParameters: _fnAjaxParameters,
15571		_fnAjaxUpdateDraw: _fnAjaxUpdateDraw,
15572		_fnAjaxDataSrc: _fnAjaxDataSrc,
15573		_fnAddColumn: _fnAddColumn,
15574		_fnColumnOptions: _fnColumnOptions,
15575		_fnAdjustColumnSizing: _fnAdjustColumnSizing,
15576		_fnVisibleToColumnIndex: _fnVisibleToColumnIndex,
15577		_fnColumnIndexToVisible: _fnColumnIndexToVisible,
15578		_fnVisbleColumns: _fnVisbleColumns,
15579		_fnGetColumns: _fnGetColumns,
15580		_fnColumnTypes: _fnColumnTypes,
15581		_fnApplyColumnDefs: _fnApplyColumnDefs,
15582		_fnHungarianMap: _fnHungarianMap,
15583		_fnCamelToHungarian: _fnCamelToHungarian,
15584		_fnLanguageCompat: _fnLanguageCompat,
15585		_fnBrowserDetect: _fnBrowserDetect,
15586		_fnAddData: _fnAddData,
15587		_fnAddTr: _fnAddTr,
15588		_fnNodeToDataIndex: _fnNodeToDataIndex,
15589		_fnNodeToColumnIndex: _fnNodeToColumnIndex,
15590		_fnGetCellData: _fnGetCellData,
15591		_fnSetCellData: _fnSetCellData,
15592		_fnSplitObjNotation: _fnSplitObjNotation,
15593		_fnGetObjectDataFn: _fnGetObjectDataFn,
15594		_fnSetObjectDataFn: _fnSetObjectDataFn,
15595		_fnGetDataMaster: _fnGetDataMaster,
15596		_fnClearTable: _fnClearTable,
15597		_fnDeleteIndex: _fnDeleteIndex,
15598		_fnInvalidate: _fnInvalidate,
15599		_fnGetRowElements: _fnGetRowElements,
15600		_fnCreateTr: _fnCreateTr,
15601		_fnBuildHead: _fnBuildHead,
15602		_fnDrawHead: _fnDrawHead,
15603		_fnDraw: _fnDraw,
15604		_fnReDraw: _fnReDraw,
15605		_fnAddOptionsHtml: _fnAddOptionsHtml,
15606		_fnDetectHeader: _fnDetectHeader,
15607		_fnGetUniqueThs: _fnGetUniqueThs,
15608		_fnFeatureHtmlFilter: _fnFeatureHtmlFilter,
15609		_fnFilterComplete: _fnFilterComplete,
15610		_fnFilterCustom: _fnFilterCustom,
15611		_fnFilterColumn: _fnFilterColumn,
15612		_fnFilter: _fnFilter,
15613		_fnFilterCreateSearch: _fnFilterCreateSearch,
15614		_fnEscapeRegex: _fnEscapeRegex,
15615		_fnFilterData: _fnFilterData,
15616		_fnFeatureHtmlInfo: _fnFeatureHtmlInfo,
15617		_fnUpdateInfo: _fnUpdateInfo,
15618		_fnInfoMacros: _fnInfoMacros,
15619		_fnInitialise: _fnInitialise,
15620		_fnInitComplete: _fnInitComplete,
15621		_fnLengthChange: _fnLengthChange,
15622		_fnFeatureHtmlLength: _fnFeatureHtmlLength,
15623		_fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate,
15624		_fnPageChange: _fnPageChange,
15625		_fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing,
15626		_fnProcessingDisplay: _fnProcessingDisplay,
15627		_fnFeatureHtmlTable: _fnFeatureHtmlTable,
15628		_fnScrollDraw: _fnScrollDraw,
15629		_fnApplyToChildren: _fnApplyToChildren,
15630		_fnCalculateColumnWidths: _fnCalculateColumnWidths,
15631		_fnThrottle: _fnThrottle,
15632		_fnConvertToWidth: _fnConvertToWidth,
15633		_fnGetWidestNode: _fnGetWidestNode,
15634		_fnGetMaxLenString: _fnGetMaxLenString,
15635		_fnStringToCss: _fnStringToCss,
15636		_fnSortFlatten: _fnSortFlatten,
15637		_fnSort: _fnSort,
15638		_fnSortAria: _fnSortAria,
15639		_fnSortListener: _fnSortListener,
15640		_fnSortAttachListener: _fnSortAttachListener,
15641		_fnSortingClasses: _fnSortingClasses,
15642		_fnSortData: _fnSortData,
15643		_fnSaveState: _fnSaveState,
15644		_fnLoadState: _fnLoadState,
15645		_fnImplementState: _fnImplementState,
15646		_fnSettingsFromNode: _fnSettingsFromNode,
15647		_fnLog: _fnLog,
15648		_fnMap: _fnMap,
15649		_fnBindAction: _fnBindAction,
15650		_fnCallbackReg: _fnCallbackReg,
15651		_fnCallbackFire: _fnCallbackFire,
15652		_fnLengthOverflow: _fnLengthOverflow,
15653		_fnRenderer: _fnRenderer,
15654		_fnDataSource: _fnDataSource,
15655		_fnRowAttributes: _fnRowAttributes,
15656		_fnExtend: _fnExtend,
15657		_fnCalculateEnd: function () {} // Used by a lot of plug-ins, but redundant
15658		                                // in 1.10, so this dead-end function is
15659		                                // added to prevent errors
15660	} );
15661	
15662	
15663	// jQuery access
15664	$.fn.dataTable = DataTable;
15665	
15666	// Provide access to the host jQuery object (circular reference)
15667	DataTable.$ = $;
15668	
15669	// Legacy aliases
15670	$.fn.dataTableSettings = DataTable.settings;
15671	$.fn.dataTableExt = DataTable.ext;
15672	
15673	// With a capital `D` we return a DataTables API instance rather than a
15674	// jQuery object
15675	$.fn.DataTable = function ( opts ) {
15676		return $(this).dataTable( opts ).api();
15677	};
15678	
15679	// All properties that are available to $.fn.dataTable should also be
15680	// available on $.fn.DataTable
15681	$.each( DataTable, function ( prop, val ) {
15682		$.fn.DataTable[ prop ] = val;
15683	} );
15684
15685	return DataTable;
15686}));

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.