PageSourceSearch

https://dreamcad.net/plugin/mongtree/admin/assets/vendor/jquery-datatables/media/js/jquery.dataTables.js

js dreamcad.net collected 2026-10-05 19:27:56 UTC 447,282 bytes, 15,278 lines download raw bytes

vendor: 447,282 bytes, lines 1-15278
1/*! DataTables 1.10.12
2 * ©2008-2015 SpryMedia Ltd - datatables.net/license
3 */
4
5/**
6 * @summary     DataTables
7 * @description Paginate, search and order HTML tables
8 * @version     1.10.12
9 * @file        jquery.dataTables.js
10 * @author      SpryMedia Ltd (www.sprymedia.co.uk)
11 * @contact     www.sprymedia.co.uk/contact
12 * @copyright   Copyright 2008-2015 SpryMedia Ltd.
13 *
14 * This source file is free software, available under the following license:
15 *   MIT license - http://datatables.net/license
16 *
17 * This source file is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
20 *
21 * For details please refer to: http://www.datatables.net
22 */
23
24/*jslint evil: true, undef: true, browser: true */
25/*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*/
26
27(function( factory ) {
28	"use strict";
29
30	if ( typeof define === 'function' && define.amd ) {
31		// AMD
32		define( ['jquery'], function ( $ ) {
33			return factory( $, window, document );
34		} );
35	}
36	else if ( typeof exports === 'object' ) {
37		// CommonJS
38		module.exports = function (root, $) {
39			if ( ! root ) {
40				// CommonJS environments without a window global must pass a
41				// root. This will give an error otherwise
42				root = window;
43			}
44
45			if ( ! $ ) {
46				$ = typeof window !== 'undefined' ? // jQuery's factory checks for a global window
47					require('jquery') :
48					require('jquery')( root );
49			}
50
51			return factory( $, root, root.document );
52		};
53	}
54	else {
55		// Browser
56		factory( jQuery, window, document );
57	}
58}
59(function( $, window, document, undefined ) {
60	"use strict";
61
62	/**
63	 * DataTables is a plug-in for the jQuery Javascript library. It is a highly
64	 * flexible tool, based upon the foundations of progressive enhancement,
65	 * which will add advanced interaction controls to any HTML table. For a
66	 * full list of features please refer to
67	 * [DataTables.net](href="http://datatables.net).
68	 *
69	 * Note that the `DataTable` object is not a global variable but is aliased
70	 * to `jQuery.fn.DataTable` and `jQuery.fn.dataTable` through which it may
71	 * be  accessed.
72	 *
73	 *  @class
74	 *  @param {object} [init={}] Configuration object for DataTables. Options
75	 *    are defined by {@link DataTable.defaults}
76	 *  @requires jQuery 1.7+
77	 *
78	 *  @example
79	 *    // Basic initialisation
80	 *    $(document).ready( function {
81	 *      $('#example').dataTable();
82	 *    } );
83	 *
84	 *  @example
85	 *    // Initialisation with configuration options - in this case, disable
86	 *    // pagination and sorting.
87	 *    $(document).ready( function {
88	 *      $('#example').dataTable( {
89	 *        "paginate": false,
90	 *        "sort": false
91	 *      } );
92	 *    } );
93	 */
94	var DataTable = function ( options )
95	{
96		/**
97		 * Perform a jQuery selector action on the table's TR elements (from the tbody) and
98		 * return the resulting jQuery object.
99		 *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
100		 *  @param {object} [oOpts] Optional parameters for modifying the rows to be included
101		 *  @param {string} [oOpts.filter=none] Select TR elements that meet the current filter
102		 *    criterion ("applied") or all TR elements (i.e. no filter).
103		 *  @param {string} [oOpts.order=current] Order of the TR elements in the processed array.
104		 *    Can be either 'current', whereby the current sorting of the table is used, or
105		 *    'original' whereby the original order the data was read into the table is used.
106		 *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
107		 *    ("current") or not ("all"). If 'current' is given, then order is assumed to be
108		 *    'current' and filter is 'applied', regardless of what they might be given as.
109		 *  @returns {object} jQuery object, filtered by the given selector.
110		 *  @dtopt API
111		 *  @deprecated Since v1.10
112		 *
113		 *  @example
114		 *    $(document).ready(function() {
115		 *      var oTable = $('#example').dataTable();
116		 *
117		 *      // Highlight every second row
118		 *      oTable.$('tr:odd').css('backgroundColor', 'blue');
119		 *    } );
120		 *
121		 *  @example
122		 *    $(document).ready(function() {
123		 *      var oTable = $('#example').dataTable();
124		 *
125		 *      // Filter to rows with 'Webkit' in them, add a background colour and then
126		 *      // remove the filter, thus highlighting the 'Webkit' rows only.
127		 *      oTable.fnFilter('Webkit');
128		 *      oTable.$('tr', {"search": "applied"}).css('backgroundColor', 'blue');
129		 *      oTable.fnFilter('');
130		 *    } );
131		 */
132		this.$ = function ( sSelector, oOpts )
133		{
134			return this.api(true).$( sSelector, oOpts );
135		};
136		
137		
138		/**
139		 * Almost identical to $ in operation, but in this case returns the data for the matched
140		 * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes
141		 * rather than any descendants, so the data can be obtained for the row/cell. If matching
142		 * rows are found, the data returned is the original data array/object that was used to
143		 * create the row (or a generated array if from a DOM source).
144		 *
145		 * This method is often useful in-combination with $ where both functions are given the
146		 * same parameters and the array indexes will match identically.
147		 *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
148		 *  @param {object} [oOpts] Optional parameters for modifying the rows to be included
149		 *  @param {string} [oOpts.filter=none] Select elements that meet the current filter
150		 *    criterion ("applied") or all elements (i.e. no filter).
151		 *  @param {string} [oOpts.order=current] Order of the data in the processed array.
152		 *    Can be either 'current', whereby the current sorting of the table is used, or
153		 *    'original' whereby the original order the data was read into the table is used.
154		 *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
155		 *    ("current") or not ("all"). If 'current' is given, then order is assumed to be
156		 *    'current' and filter is 'applied', regardless of what they might be given as.
157		 *  @returns {array} Data for the matched elements. If any elements, as a result of the
158		 *    selector, were not TR, TD or TH elements in the DataTable, they will have a null
159		 *    entry in the array.
160		 *  @dtopt API
161		 *  @deprecated Since v1.10
162		 *
163		 *  @example
164		 *    $(document).ready(function() {
165		 *      var oTable = $('#example').dataTable();
166		 *
167		 *      // Get the data from the first row in the table
168		 *      var data = oTable._('tr:first');
169		 *
170		 *      // Do something useful with the data
171		 *      alert( "First cell is: "+data[0] );
172		 *    } );
173		 *
174		 *  @example
175		 *    $(document).ready(function() {
176		 *      var oTable = $('#example').dataTable();
177		 *
178		 *      // Filter to 'Webkit' and get all data for
179		 *      oTable.fnFilter('Webkit');
180		 *      var data = oTable._('tr', {"search": "applied"});
181		 *
182		 *      // Do something with the data
183		 *      alert( data.length+" rows matched the search" );
184		 *    } );
185		 */
186		this._ = function ( sSelector, oOpts )
187		{
188			return this.api(true).rows( sSelector, oOpts ).data();
189		};
190		
191		
192		/**
193		 * Create a DataTables Api instance, with the currently selected tables for
194		 * the Api's context.
195		 * @param {boolean} [traditional=false] Set the API instance's context to be
196		 *   only the table referred to by the `DataTable.ext.iApiIndex` option, as was
197		 *   used in the API presented by DataTables 1.9- (i.e. the traditional mode),
198		 *   or if all tables captured in the jQuery object should be used.
199		 * @return {DataTables.Api}
200		 */
201		this.api = function ( traditional )
202		{
203			return traditional ?
204				new _Api(
205					_fnSettingsFromNode( this[ _ext.iApiIndex ] )
206				) :
207				new _Api( this );
208		};
209		
210		
211		/**
212		 * Add a single new row or multiple rows of data to the table. Please note
213		 * that this is suitable for client-side processing only - if you are using
214		 * server-side processing (i.e. "bServerSide": true), then to add data, you
215		 * must add it to the data source, i.e. the server-side, through an Ajax call.
216		 *  @param {array|object} data The data to be added to the table. This can be:
217		 *    <ul>
218		 *      <li>1D array of data - add a single row with the data provided</li>
219		 *      <li>2D array of arrays - add multiple rows in a single call</li>
220		 *      <li>object - data object when using <i>mData</i></li>
221		 *      <li>array of objects - multiple data objects when using <i>mData</i></li>
222		 *    </ul>
223		 *  @param {bool} [redraw=true] redraw the table or not
224		 *  @returns {array} An array of integers, representing the list of indexes in
225		 *    <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to
226		 *    the table.
227		 *  @dtopt API
228		 *  @deprecated Since v1.10
229		 *
230		 *  @example
231		 *    // Global var for counter
232		 *    var giCount = 2;
233		 *
234		 *    $(document).ready(function() {
235		 *      $('#example').dataTable();
236		 *    } );
237		 *
238		 *    function fnClickAddRow() {
239		 *      $('#example').dataTable().fnAddData( [
240		 *        giCount+".1",
241		 *        giCount+".2",
242		 *        giCount+".3",
243		 *        giCount+".4" ]
244		 *      );
245		 *
246		 *      giCount++;
247		 *    }
248		 */
249		this.fnAddData = function( data, redraw )
250		{
251			var api = this.api( true );
252		
253			/* Check if we want to add multiple rows or not */
254			var rows = $.isArray(data) && ( $.isArray(data[0]) || $.isPlainObject(data[0]) ) ?
255				api.rows.add( data ) :
256				api.row.add( data );
257		
258			if ( redraw === undefined || redraw ) {
259				api.draw();
260			}
261		
262			return rows.flatten().toArray();
263		};
264		
265		
266		/**
267		 * This function will make DataTables recalculate the column sizes, based on the data
268		 * contained in the table and the sizes applied to the columns (in the DOM, CSS or
269		 * through the sWidth parameter). This can be useful when the width of the table's
270		 * parent element changes (for example a window resize).
271		 *  @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to
272		 *  @dtopt API
273		 *  @deprecated Since v1.10
274		 *
275		 *  @example
276		 *    $(document).ready(function() {
277		 *      var oTable = $('#example').dataTable( {
278		 *        "sScrollY": "200px",
279		 *        "bPaginate": false
280		 *      } );
281		 *
282		 *      $(window).bind('resize', function () {
283		 *        oTable.fnAdjustColumnSizing();
284		 *      } );
285		 *    } );
286		 */
287		this.fnAdjustColumnSizing = function ( bRedraw )
288		{
289			var api = this.api( true ).columns.adjust();
290			var settings = api.settings()[0];
291			var scroll = settings.oScroll;
292		
293			if ( bRedraw === undefined || bRedraw ) {
294				api.draw( false );
295			}
296			else if ( scroll.sX !== "" || scroll.sY !== "" ) {
297				/* If not redrawing, but scrolling, we want to apply the new column sizes anyway */
298				_fnScrollDraw( settings );
299			}
300		};
301		
302		
303		/**
304		 * Quickly and simply clear a table
305		 *  @param {bool} [bRedraw=true] redraw the table or not
306		 *  @dtopt API
307		 *  @deprecated Since v1.10
308		 *
309		 *  @example
310		 *    $(document).ready(function() {
311		 *      var oTable = $('#example').dataTable();
312		 *
313		 *      // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...)
314		 *      oTable.fnClearTable();
315		 *    } );
316		 */
317		this.fnClearTable = function( bRedraw )
318		{
319			var api = this.api( true ).clear();
320		
321			if ( bRedraw === undefined || bRedraw ) {
322				api.draw();
323			}
324		};
325		
326		
327		/**
328		 * The exact opposite of 'opening' a row, this function will close any rows which
329		 * are currently 'open'.
330		 *  @param {node} nTr the table row to 'close'
331		 *  @returns {int} 0 on success, or 1 if failed (can't find the row)
332		 *  @dtopt API
333		 *  @deprecated Since v1.10
334		 *
335		 *  @example
336		 *    $(document).ready(function() {
337		 *      var oTable;
338		 *
339		 *      // 'open' an information row when a row is clicked on
340		 *      $('#example tbody tr').click( function () {
341		 *        if ( oTable.fnIsOpen(this) ) {
342		 *          oTable.fnClose( this );
343		 *        } else {
344		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
345		 *        }
346		 *      } );
347		 *
348		 *      oTable = $('#example').dataTable();
349		 *    } );
350		 */
351		this.fnClose = function( nTr )
352		{
353			this.api( true ).row( nTr ).child.hide();
354		};
355		
356		
357		/**
358		 * Remove a row for the table
359		 *  @param {mixed} target The index of the row from aoData to be deleted, or
360		 *    the TR element you want to delete
361		 *  @param {function|null} [callBack] Callback function
362		 *  @param {bool} [redraw=true] Redraw the table or not
363		 *  @returns {array} The row that was deleted
364		 *  @dtopt API
365		 *  @deprecated Since v1.10
366		 *
367		 *  @example
368		 *    $(document).ready(function() {
369		 *      var oTable = $('#example').dataTable();
370		 *
371		 *      // Immediately remove the first row
372		 *      oTable.fnDeleteRow( 0 );
373		 *    } );
374		 */
375		this.fnDeleteRow = function( target, callback, redraw )
376		{
377			var api = this.api( true );
378			var rows = api.rows( target );
379			var settings = rows.settings()[0];
380			var data = settings.aoData[ rows[0][0] ];
381		
382			rows.remove();
383		
384			if ( callback ) {
385				callback.call( this, settings, data );
386			}
387		
388			if ( redraw === undefined || redraw ) {
389				api.draw();
390			}
391		
392			return data;
393		};
394		
395		
396		/**
397		 * Restore the table to it's original state in the DOM by removing all of DataTables
398		 * enhancements, alterations to the DOM structure of the table and event listeners.
399		 *  @param {boolean} [remove=false] Completely remove the table from the DOM
400		 *  @dtopt API
401		 *  @deprecated Since v1.10
402		 *
403		 *  @example
404		 *    $(document).ready(function() {
405		 *      // This example is fairly pointless in reality, but shows how fnDestroy can be used
406		 *      var oTable = $('#example').dataTable();
407		 *      oTable.fnDestroy();
408		 *    } );
409		 */
410		this.fnDestroy = function ( remove )
411		{
412			this.api( true ).destroy( remove );
413		};
414		
415		
416		/**
417		 * Redraw the table
418		 *  @param {bool} [complete=true] Re-filter and resort (if enabled) the table before the draw.
419		 *  @dtopt API
420		 *  @deprecated Since v1.10
421		 *
422		 *  @example
423		 *    $(document).ready(function() {
424		 *      var oTable = $('#example').dataTable();
425		 *
426		 *      // Re-draw the table - you wouldn't want to do it here, but it's an example :-)
427		 *      oTable.fnDraw();
428		 *    } );
429		 */
430		this.fnDraw = function( complete )
431		{
432			// Note that this isn't an exact match to the old call to _fnDraw - it takes
433			// into account the new data, but can hold position.
434			this.api( true ).draw( complete );
435		};
436		
437		
438		/**
439		 * Filter the input based on data
440		 *  @param {string} sInput String to filter the table on
441		 *  @param {int|null} [iColumn] Column to limit filtering to
442		 *  @param {bool} [bRegex=false] Treat as regular expression or not
443		 *  @param {bool} [bSmart=true] Perform smart filtering or not
444		 *  @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es)
445		 *  @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false)
446		 *  @dtopt API
447		 *  @deprecated Since v1.10
448		 *
449		 *  @example
450		 *    $(document).ready(function() {
451		 *      var oTable = $('#example').dataTable();
452		 *
453		 *      // Sometime later - filter...
454		 *      oTable.fnFilter( 'test string' );
455		 *    } );
456		 */
457		this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive )
458		{
459			var api = this.api( true );
460		
461			if ( iColumn === null || iColumn === undefined ) {
462				api.search( sInput, bRegex, bSmart, bCaseInsensitive );
463			}
464			else {
465				api.column( iColumn ).search( sInput, bRegex, bSmart, bCaseInsensitive );
466			}
467		
468			api.draw();
469		};
470		
471		
472		/**
473		 * Get the data for the whole table, an individual row or an individual cell based on the
474		 * provided parameters.
475		 *  @param {int|node} [src] A TR row node, TD/TH cell node or an integer. If given as
476		 *    a TR node then the data source for the whole row will be returned. If given as a
477		 *    TD/TH cell node then iCol will be automatically calculated and the data for the
478		 *    cell returned. If given as an integer, then this is treated as the aoData internal
479		 *    data index for the row (see fnGetPosition) and the data for that row used.
480		 *  @param {int} [col] Optional column index that you want the data of.
481		 *  @returns {array|object|string} If mRow is undefined, then the data for all rows is
482		 *    returned. If mRow is defined, just data for that row, and is iCol is
483		 *    defined, only data for the designated cell is returned.
484		 *  @dtopt API
485		 *  @deprecated Since v1.10
486		 *
487		 *  @example
488		 *    // Row data
489		 *    $(document).ready(function() {
490		 *      oTable = $('#example').dataTable();
491		 *
492		 *      oTable.$('tr').click( function () {
493		 *        var data = oTable.fnGetData( this );
494		 *        // ... do something with the array / object of data for the row
495		 *      } );
496		 *    } );
497		 *
498		 *  @example
499		 *    // Individual cell data
500		 *    $(document).ready(function() {
501		 *      oTable = $('#example').dataTable();
502		 *
503		 *      oTable.$('td').click( function () {
504		 *        var sData = oTable.fnGetData( this );
505		 *        alert( 'The cell clicked on had the value of '+sData );
506		 *      } );
507		 *    } );
508		 */
509		this.fnGetData = function( src, col )
510		{
511			var api = this.api( true );
512		
513			if ( src !== undefined ) {
514				var type = src.nodeName ? src.nodeName.toLowerCase() : '';
515		
516				return col !== undefined || type == 'td' || type == 'th' ?
517					api.cell( src, col ).data() :
518					api.row( src ).data() || null;
519			}
520		
521			return api.data().toArray();
522		};
523		
524		
525		/**
526		 * Get an array of the TR nodes that are used in the table's body. Note that you will
527		 * typically want to use the '$' API method in preference to this as it is more
528		 * flexible.
529		 *  @param {int} [iRow] Optional row index for the TR element you want
530		 *  @returns {array|node} If iRow is undefined, returns an array of all TR elements
531		 *    in the table's body, or iRow is defined, just the TR element requested.
532		 *  @dtopt API
533		 *  @deprecated Since v1.10
534		 *
535		 *  @example
536		 *    $(document).ready(function() {
537		 *      var oTable = $('#example').dataTable();
538		 *
539		 *      // Get the nodes from the table
540		 *      var nNodes = oTable.fnGetNodes( );
541		 *    } );
542		 */
543		this.fnGetNodes = function( iRow )
544		{
545			var api = this.api( true );
546		
547			return iRow !== undefined ?
548				api.row( iRow ).node() :
549				api.rows().nodes().flatten().toArray();
550		};
551		
552		
553		/**
554		 * Get the array indexes of a particular cell from it's DOM element
555		 * and column index including hidden columns
556		 *  @param {node} node this can either be a TR, TD or TH in the table's body
557		 *  @returns {int} If nNode is given as a TR, then a single index is returned, or
558		 *    if given as a cell, an array of [row index, column index (visible),
559		 *    column index (all)] is given.
560		 *  @dtopt API
561		 *  @deprecated Since v1.10
562		 *
563		 *  @example
564		 *    $(document).ready(function() {
565		 *      $('#example tbody td').click( function () {
566		 *        // Get the position of the current data from the node
567		 *        var aPos = oTable.fnGetPosition( this );
568		 *
569		 *        // Get the data array for this row
570		 *        var aData = oTable.fnGetData( aPos[0] );
571		 *
572		 *        // Update the data array and return the value
573		 *        aData[ aPos[1] ] = 'clicked';
574		 *        this.innerHTML = 'clicked';
575		 *      } );
576		 *
577		 *      // Init DataTables
578		 *      oTable = $('#example').dataTable();
579		 *    } );
580		 */
581		this.fnGetPosition = function( node )
582		{
583			var api = this.api( true );
584			var nodeName = node.nodeName.toUpperCase();
585		
586			if ( nodeName == 'TR' ) {
587				return api.row( node ).index();
588			}
589			else if ( nodeName == 'TD' || nodeName == 'TH' ) {
590				var cell = api.cell( node ).index();
591		
592				return [
593					cell.row,
594					cell.columnVisible,
595					cell.column
596				];
597			}
598			return null;
599		};
600		
601		
602		/**
603		 * Check to see if a row is 'open' or not.
604		 *  @param {node} nTr the table row to check
605		 *  @returns {boolean} true if the row is currently open, false otherwise
606		 *  @dtopt API
607		 *  @deprecated Since v1.10
608		 *
609		 *  @example
610		 *    $(document).ready(function() {
611		 *      var oTable;
612		 *
613		 *      // 'open' an information row when a row is clicked on
614		 *      $('#example tbody tr').click( function () {
615		 *        if ( oTable.fnIsOpen(this) ) {
616		 *          oTable.fnClose( this );
617		 *        } else {
618		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
619		 *        }
620		 *      } );
621		 *
622		 *      oTable = $('#example').dataTable();
623		 *    } );
624		 */
625		this.fnIsOpen = function( nTr )
626		{
627			return this.api( true ).row( nTr ).child.isShown();
628		};
629		
630		
631		/**
632		 * This function will place a new row directly after a row which is currently
633		 * on display on the page, with the HTML contents that is passed into the
634		 * function. This can be used, for example, to ask for confirmation that a
635		 * particular record should be deleted.
636		 *  @param {node} nTr The table row to 'open'
637		 *  @param {string|node|jQuery} mHtml The HTML to put into the row
638		 *  @param {string} sClass Class to give the new TD cell
639		 *  @returns {node} The row opened. Note that if the table row passed in as the
640		 *    first parameter, is not found in the table, this method will silently
641		 *    return.
642		 *  @dtopt API
643		 *  @deprecated Since v1.10
644		 *
645		 *  @example
646		 *    $(document).ready(function() {
647		 *      var oTable;
648		 *
649		 *      // 'open' an information row when a row is clicked on
650		 *      $('#example tbody tr').click( function () {
651		 *        if ( oTable.fnIsOpen(this) ) {
652		 *          oTable.fnClose( this );
653		 *        } else {
654		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
655		 *        }
656		 *      } );
657		 *
658		 *      oTable = $('#example').dataTable();
659		 *    } );
660		 */
661		this.fnOpen = function( nTr, mHtml, sClass )
662		{
663			return this.api( true )
664				.row( nTr )
665				.child( mHtml, sClass )
666				.show()
667				.child()[0];
668		};
669		
670		
671		/**
672		 * Change the pagination - provides the internal logic for pagination in a simple API
673		 * function. With this function you can have a DataTables table go to the next,
674		 * previous, first or last pages.
675		 *  @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
676		 *    or page number to jump to (integer), note that page 0 is the first page.
677		 *  @param {bool} [bRedraw=true] Redraw the table or not
678		 *  @dtopt API
679		 *  @deprecated Since v1.10
680		 *
681		 *  @example
682		 *    $(document).ready(function() {
683		 *      var oTable = $('#example').dataTable();
684		 *      oTable.fnPageChange( 'next' );
685		 *    } );
686		 */
687		this.fnPageChange = function ( mAction, bRedraw )
688		{
689			var api = this.api( true ).page( mAction );
690		
691			if ( bRedraw === undefined || bRedraw ) {
692				api.draw(false);
693			}
694		};
695		
696		
697		/**
698		 * Show a particular column
699		 *  @param {int} iCol The column whose display should be changed
700		 *  @param {bool} bShow Show (true) or hide (false) the column
701		 *  @param {bool} [bRedraw=true] Redraw the table or not
702		 *  @dtopt API
703		 *  @deprecated Since v1.10
704		 *
705		 *  @example
706		 *    $(document).ready(function() {
707		 *      var oTable = $('#example').dataTable();
708		 *
709		 *      // Hide the second column after initialisation
710		 *      oTable.fnSetColumnVis( 1, false );
711		 *    } );
712		 */
713		this.fnSetColumnVis = function ( iCol, bShow, bRedraw )
714		{
715			var api = this.api( true ).column( iCol ).visible( bShow );
716		
717			if ( bRedraw === undefined || bRedraw ) {
718				api.columns.adjust().draw();
719			}
720		};
721		
722		
723		/**
724		 * Get the settings for a particular table for external manipulation
725		 *  @returns {object} DataTables settings object. See
726		 *    {@link DataTable.models.oSettings}
727		 *  @dtopt API
728		 *  @deprecated Since v1.10
729		 *
730		 *  @example
731		 *    $(document).ready(function() {
732		 *      var oTable = $('#example').dataTable();
733		 *      var oSettings = oTable.fnSettings();
734		 *
735		 *      // Show an example parameter from the settings
736		 *      alert( oSettings._iDisplayStart );
737		 *    } );
738		 */
739		this.fnSettings = function()
740		{
741			return _fnSettingsFromNode( this[_ext.iApiIndex] );
742		};
743		
744		
745		/**
746		 * Sort the table by a particular column
747		 *  @param {int} iCol the data index to sort on. Note that this will not match the
748		 *    'display index' if you have hidden data entries
749		 *  @dtopt API
750		 *  @deprecated Since v1.10
751		 *
752		 *  @example
753		 *    $(document).ready(function() {
754		 *      var oTable = $('#example').dataTable();
755		 *
756		 *      // Sort immediately with columns 0 and 1
757		 *      oTable.fnSort( [ [0,'asc'], [1,'asc'] ] );
758		 *    } );
759		 */
760		this.fnSort = function( aaSort )
761		{
762			this.api( true ).order( aaSort ).draw();
763		};
764		
765		
766		/**
767		 * Attach a sort listener to an element for a given column
768		 *  @param {node} nNode the element to attach the sort listener to
769		 *  @param {int} iColumn the column that a click on this node will sort on
770		 *  @param {function} [fnCallback] callback function when sort is run
771		 *  @dtopt API
772		 *  @deprecated Since v1.10
773		 *
774		 *  @example
775		 *    $(document).ready(function() {
776		 *      var oTable = $('#example').dataTable();
777		 *
778		 *      // Sort on column 1, when 'sorter' is clicked on
779		 *      oTable.fnSortListener( document.getElementById('sorter'), 1 );
780		 *    } );
781		 */
782		this.fnSortListener = function( nNode, iColumn, fnCallback )
783		{
784			this.api( true ).order.listener( nNode, iColumn, fnCallback );
785		};
786		
787		
788		/**
789		 * Update a table cell or row - this method will accept either a single value to
790		 * update the cell with, an array of values with one element for each column or
791		 * an object in the same format as the original data source. The function is
792		 * self-referencing in order to make the multi column updates easier.
793		 *  @param {object|array|string} mData Data to update the cell/row with
794		 *  @param {node|int} mRow TR element you want to update or the aoData index
795		 *  @param {int} [iColumn] The column to update, give as null or undefined to
796		 *    update a whole row.
797		 *  @param {bool} [bRedraw=true] Redraw the table or not
798		 *  @param {bool} [bAction=true] Perform pre-draw actions or not
799		 *  @returns {int} 0 on success, 1 on error
800		 *  @dtopt API
801		 *  @deprecated Since v1.10
802		 *
803		 *  @example
804		 *    $(document).ready(function() {
805		 *      var oTable = $('#example').dataTable();
806		 *      oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell
807		 *      oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], $('tbody tr')[0] ); // Row
808		 *    } );
809		 */
810		this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction )
811		{
812			var api = this.api( true );
813		
814			if ( iColumn === undefined || iColumn === null ) {
815				api.row( mRow ).data( mData );
816			}
817			else {
818				api.cell( mRow, iColumn ).data( mData );
819			}
820		
821			if ( bAction === undefined || bAction ) {
822				api.columns.adjust();
823			}
824		
825			if ( bRedraw === undefined || bRedraw ) {
826				api.draw();
827			}
828			return 0;
829		};
830		
831		
832		/**
833		 * Provide a common method for plug-ins to check the version of DataTables being used, in order
834		 * to ensure compatibility.
835		 *  @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the
836		 *    formats "X" and "X.Y" are also acceptable.
837		 *  @returns {boolean} true if this version of DataTables is greater or equal to the required
838		 *    version, or false if this version of DataTales is not suitable
839		 *  @method
840		 *  @dtopt API
841		 *  @deprecated Since v1.10
842		 *
843		 *  @example
844		 *    $(document).ready(function() {
845		 *      var oTable = $('#example').dataTable();
846		 *      alert( oTable.fnVersionCheck( '1.9.0' ) );
847		 *    } );
848		 */
849		this.fnVersionCheck = _ext.fnVersionCheck;
850		
851
852		var _that = this;
853		var emptyInit = options === undefined;
854		var len = this.length;
855
856		if ( emptyInit ) {
857			options = {};
858		}
859
860		this.oApi = this.internal = _ext.internal;
861
862		// Extend with old style plug-in API methods
863		for ( var fn in DataTable.ext.internal ) {
864			if ( fn ) {
865				this[fn] = _fnExternApiFunc(fn);
866			}
867		}
868
869		this.each(function() {
870			// For each initialisation we want to give it a clean initialisation
871			// object that can be bashed around
872			var o = {};
873			var oInit = len > 1 ? // optimisation for single table case
874				_fnExtend( o, options, true ) :
875				options;
876
877			/*global oInit,_that,emptyInit*/
878			var i=0, iLen, j, jLen, k, kLen;
879			var sId = this.getAttribute( 'id' );
880			var bInitHandedOff = false;
881			var defaults = DataTable.defaults;
882			var $this = $(this);
883			
884			
885			/* Sanity check */
886			if ( this.nodeName.toLowerCase() != 'table' )
887			{
888				_fnLog( null, 0, 'Non-table node initialisation ('+this.nodeName+')', 2 );
889				return;
890			}
891			
892			/* Backwards compatibility for the defaults */
893			_fnCompatOpts( defaults );
894			_fnCompatCols( defaults.column );
895			
896			/* Convert the camel-case defaults to Hungarian */
897			_fnCamelToHungarian( defaults, defaults, true );
898			_fnCamelToHungarian( defaults.column, defaults.column, true );
899			
900			/* Setting up the initialisation object */
901			_fnCamelToHungarian( defaults, $.extend( oInit, $this.data() ) );
902			
903			
904			
905			/* Check to see if we are re-initialising a table */
906			var allSettings = DataTable.settings;
907			for ( i=0, iLen=allSettings.length ; i<iLen ; i++ )
908			{
909				var s = allSettings[i];
910			
911				/* Base check on table node */
912				if ( s.nTable == this || s.nTHead.parentNode == this || (s.nTFoot && s.nTFoot.parentNode == this) )
913				{
914					var bRetrieve = oInit.bRetrieve !== undefined ? oInit.bRetrieve : defaults.bRetrieve;
915					var bDestroy = oInit.bDestroy !== undefined ? oInit.bDestroy : defaults.bDestroy;
916			
917					if ( emptyInit || bRetrieve )
918					{
919						return s.oInstance;
920					}
921					else if ( bDestroy )
922					{
923						s.oInstance.fnDestroy();
924						break;
925					}
926					else
927					{
928						_fnLog( s, 0, 'Cannot reinitialise DataTable', 3 );
929						return;
930					}
931				}
932			
933				/* If the element we are initialising has the same ID as a table which was previously
934				 * initialised, but the table nodes don't match (from before) then we destroy the old
935				 * instance by simply deleting it. This is under the assumption that the table has been
936				 * destroyed by other methods. Anyone using non-id selectors will need to do this manually
937				 */
938				if ( s.sTableId == this.id )
939				{
940					allSettings.splice( i, 1 );
941					break;
942				}
943			}
944			
945			/* Ensure the table has an ID - required for accessibility */
946			if ( sId === null || sId === "" )
947			{
948				sId = "DataTables_Table_"+(DataTable.ext._unique++);
949				this.id = sId;
950			}
951			
952			/* Create the settings object for this table and set some of the default parameters */
953			var oSettings = $.extend( true, {}, DataTable.models.oSettings, {
954				"sDestroyWidth": $this[0].style.width,
955				"sInstance":     sId,
956				"sTableId":      sId
957			} );
958			oSettings.nTable = this;
959			oSettings.oApi   = _that.internal;
960			oSettings.oInit  = oInit;
961			
962			allSettings.push( oSettings );
963			
964			// Need to add the instance after the instance after the settings object has been added
965			// to the settings array, so we can self reference the table instance if more than one
966			oSettings.oInstance = (_that.length===1) ? _that : $this.dataTable();
967			
968			// Backwards compatibility, before we apply all the defaults
969			_fnCompatOpts( oInit );
970			
971			if ( oInit.oLanguage )
972			{
973				_fnLanguageCompat( oInit.oLanguage );
974			}
975			
976			// If the length menu is given, but the init display length is not, use the length menu
977			if ( oInit.aLengthMenu && ! oInit.iDisplayLength )
978			{
979				oInit.iDisplayLength = $.isArray( oInit.aLengthMenu[0] ) ?
980					oInit.aLengthMenu[0][0] : oInit.aLengthMenu[0];
981			}
982			
983			// Apply the defaults and init options to make a single init object will all
984			// options defined from defaults and instance options.
985			oInit = _fnExtend( $.extend( true, {}, defaults ), oInit );
986			
987			
988			// Map the initialisation options onto the settings object
989			_fnMap( oSettings.oFeatures, oInit, [
990				"bPaginate",
991				"bLengthChange",
992				"bFilter",
993				"bSort",
994				"bSortMulti",
995				"bInfo",
996				"bProcessing",
997				"bAutoWidth",
998				"bSortClasses",
999				"bServerSide",
1000				"bDeferRender"
1001			] );
1002			_fnMap( oSettings, oInit, [
1003				"asStripeClasses",
1004				"ajax",
1005				"fnServerData",
1006				"fnFormatNumber",
1007				"sServerMethod",
1008				"aaSorting",
1009				"aaSortingFixed",
1010				"aLengthMenu",
1011				"sPaginationType",
1012				"sAjaxSource",
1013				"sAjaxDataProp",
1014				"iStateDuration",
1015				"sDom",
1016				"bSortCellsTop",
1017				"iTabIndex",
1018				"fnStateLoadCallback",
1019				"fnStateSaveCallback",
1020				"renderer",
1021				"searchDelay",
1022				"rowId",
1023				[ "iCookieDuration", "iStateDuration" ], // backwards compat
1024				[ "oSearch", "oPreviousSearch" ],
1025				[ "aoSearchCols", "aoPreSearchCols" ],
1026				[ "iDisplayLength", "_iDisplayLength" ],
1027				[ "bJQueryUI", "bJUI" ]
1028			] );
1029			_fnMap( oSettings.oScroll, oInit, [
1030				[ "sScrollX", "sX" ],
1031				[ "sScrollXInner", "sXInner" ],
1032				[ "sScrollY", "sY" ],
1033				[ "bScrollCollapse", "bCollapse" ]
1034			] );
1035			_fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" );
1036			
1037			/* Callback functions which are array driven */
1038			_fnCallbackReg( oSettings, 'aoDrawCallback',       oInit.fnDrawCallback,      'user' );
1039			_fnCallbackReg( oSettings, 'aoServerParams',       oInit.fnServerParams,      'user' );
1040			_fnCallbackReg( oSettings, 'aoStateSaveParams',    oInit.fnStateSaveParams,   'user' );
1041			_fnCallbackReg( oSettings, 'aoStateLoadParams',    oInit.fnStateLoadParams,   'user' );
1042			_fnCallbackReg( oSettings, 'aoStateLoaded',        oInit.fnStateLoaded,       'user' );
1043			_fnCallbackReg( oSettings, 'aoRowCallback',        oInit.fnRowCallback,       'user' );
1044			_fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow,        'user' );
1045			_fnCallbackReg( oSettings, 'aoHeaderCallback',     oInit.fnHeaderCallback,    'user' );
1046			_fnCallbackReg( oSettings, 'aoFooterCallback',     oInit.fnFooterCallback,    'user' );
1047			_fnCallbackReg( oSettings, 'aoInitComplete',       oInit.fnInitComplete,      'user' );
1048			_fnCallbackReg( oSettings, 'aoPreDrawCallback',    oInit.fnPreDrawCallback,   'user' );
1049			
1050			oSettings.rowIdFn = _fnGetObjectDataFn( oInit.rowId );
1051			
1052			/* Browser support detection */
1053			_fnBrowserDetect( oSettings );
1054			
1055			var oClasses = oSettings.oClasses;
1056			
1057			// @todo Remove in 1.11
1058			if ( oInit.bJQueryUI )
1059			{
1060				/* Use the JUI classes object for display. You could clone the oStdClasses object if
1061				 * you want to have multiple tables with multiple independent classes
1062				 */
1063				$.extend( oClasses, DataTable.ext.oJUIClasses, oInit.oClasses );
1064			
1065				if ( oInit.sDom === defaults.sDom && defaults.sDom === "lfrtip" )
1066				{
1067					/* Set the DOM to use a layout suitable for jQuery UI's theming */
1068					oSettings.sDom = '<"H"lfr>t<"F"ip>';
1069				}
1070			
1071				if ( ! oSettings.renderer ) {
1072					oSettings.renderer = 'jqueryui';
1073				}
1074				else if ( $.isPlainObject( oSettings.renderer ) && ! oSettings.renderer.header ) {
1075					oSettings.renderer.header = 'jqueryui';
1076				}
1077			}
1078			else
1079			{
1080				$.extend( oClasses, DataTable.ext.classes, oInit.oClasses );
1081			}
1082			$this.addClass( oClasses.sTable );
1083			
1084			
1085			if ( oSettings.iInitDisplayStart === undefined )
1086			{
1087				/* Display start point, taking into account the save saving */
1088				oSettings.iInitDisplayStart = oInit.iDisplayStart;
1089				oSettings._iDisplayStart = oInit.iDisplayStart;
1090			}
1091			
1092			if ( oInit.iDeferLoading !== null )
1093			{
1094				oSettings.bDeferLoading = true;
1095				var tmp = $.isArray( oInit.iDeferLoading );
1096				oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading;
1097				oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading;
1098			}
1099			
1100			/* Language definitions */
1101			var oLanguage = oSettings.oLanguage;
1102			$.extend( true, oLanguage, oInit.oLanguage );
1103			
1104			if ( oLanguage.sUrl !== "" )
1105			{
1106				/* Get the language definitions from a file - because this Ajax call makes the language
1107				 * get async to the remainder of this function we use bInitHandedOff to indicate that
1108				 * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor
1109				 */
1110				$.ajax( {
1111					dataType: 'json',
1112					url: oLanguage.sUrl,
1113					success: function ( json ) {
1114						_fnLanguageCompat( json );
1115						_fnCamelToHungarian( defaults.oLanguage, json );
1116						$.extend( true, oLanguage, json );
1117						_fnInitialise( oSettings );
1118					},
1119					error: function () {
1120						// Error occurred loading language file, continue on as best we can
1121						_fnInitialise( oSettings );
1122					}
1123				} );
1124				bInitHandedOff = true;
1125			}
1126			
1127			/*
1128			 * Stripes
1129			 */
1130			if ( oInit.asStripeClasses === null )
1131			{
1132				oSettings.asStripeClasses =[
1133					oClasses.sStripeOdd,
1134					oClasses.sStripeEven
1135				];
1136			}
1137			
1138			/* Remove row stripe classes if they are already on the table row */
1139			var stripeClasses = oSettings.asStripeClasses;
1140			var rowOne = $this.children('tbody').find('tr').eq(0);
1141			if ( $.inArray( true, $.map( stripeClasses, function(el, i) {
1142				return rowOne.hasClass(el);
1143			} ) ) !== -1 ) {
1144				$('tbody tr', this).removeClass( stripeClasses.join(' ') );
1145				oSettings.asDestroyStripes = stripeClasses.slice();
1146			}
1147			
1148			/*
1149			 * Columns
1150			 * See if we should load columns automatically or use defined ones
1151			 */
1152			var anThs = [];
1153			var aoColumnsInit;
1154			var nThead = this.getElementsByTagName('thead');
1155			if ( nThead.length !== 0 )
1156			{
1157				_fnDetectHeader( oSettings.aoHeader, nThead[0] );
1158				anThs = _fnGetUniqueThs( oSettings );
1159			}
1160			
1161			/* If not given a column array, generate one with nulls */
1162			if ( oInit.aoColumns === null )
1163			{
1164				aoColumnsInit = [];
1165				for ( i=0, iLen=anThs.length ; i<iLen ; i++ )
1166				{
1167					aoColumnsInit.push( null );
1168				}
1169			}
1170			else
1171			{
1172				aoColumnsInit = oInit.aoColumns;
1173			}
1174			
1175			/* Add the columns */
1176			for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ )
1177			{
1178				_fnAddColumn( oSettings, anThs ? anThs[i] : null );
1179			}
1180			
1181			/* Apply the column definitions */
1182			_fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) {
1183				_fnColumnOptions( oSettings, iCol, oDef );
1184			} );
1185			
1186			/* HTML5 attribute detection - build an mData object automatically if the
1187			 * attributes are found
1188			 */
1189			if ( rowOne.length ) {
1190				var a = function ( cell, name ) {
1191					return cell.getAttribute( 'data-'+name ) !== null ? name : null;
1192				};
1193			
1194				$( rowOne[0] ).children('th, td').each( function (i, cell) {
1195					var col = oSettings.aoColumns[i];
1196			
1197					if ( col.mData === i ) {
1198						var sort = a( cell, 'sort' ) || a( cell, 'order' );
1199						var filter = a( cell, 'filter' ) || a( cell, 'search' );
1200			
1201						if ( sort !== null || filter !== null ) {
1202							col.mData = {
1203								_:      i+'.display',
1204								sort:   sort !== null   ? i+'.@data-'+sort   : undefined,
1205								type:   sort !== null   ? i+'.@data-'+sort   : undefined,
1206								filter: filter !== null ? i+'.@data-'+filter : undefined
1207							};
1208			
1209							_fnColumnOptions( oSettings, i );
1210						}
1211					}
1212				} );
1213			}
1214			
1215			var features = oSettings.oFeatures;
1216			
1217			/* Must be done after everything which can be overridden by the state saving! */
1218			if ( oInit.bStateSave )
1219			{
1220				features.bStateSave = true;
1221				_fnLoadState( oSettings, oInit );
1222				_fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' );
1223			}
1224			
1225			
1226			/*
1227			 * Sorting
1228			 * @todo For modularisation (1.11) this needs to do into a sort start up handler
1229			 */
1230			
1231			// If aaSorting is not defined, then we use the first indicator in asSorting
1232			// in case that has been altered, so the default sort reflects that option
1233			if ( oInit.aaSorting === undefined )
1234			{
1235				var sorting = oSettings.aaSorting;
1236				for ( i=0, iLen=sorting.length ; i<iLen ; i++ )
1237				{
1238					sorting[i][1] = oSettings.aoColumns[ i ].asSorting[0];
1239				}
1240			}
1241			
1242			/* Do a first pass on the sorting classes (allows any size changes to be taken into
1243			 * account, and also will apply sorting disabled classes if disabled
1244			 */
1245			_fnSortingClasses( oSettings );
1246			
1247			if ( features.bSort )
1248			{
1249				_fnCallbackReg( oSettings, 'aoDrawCallback', function () {
1250					if ( oSettings.bSorted ) {
1251						var aSort = _fnSortFlatten( oSettings );
1252						var sortedColumns = {};
1253			
1254						$.each( aSort, function (i, val) {
1255							sortedColumns[ val.src ] = val.dir;
1256						} );
1257			
1258						_fnCallbackFire( oSettings, null, 'order', [oSettings, aSort, sortedColumns] );
1259						_fnSortAria( oSettings );
1260					}
1261				} );
1262			}
1263			
1264			_fnCallbackReg( oSettings, 'aoDrawCallback', function () {
1265				if ( oSettings.bSorted || _fnDataSource( oSettings ) === 'ssp' || features.bDeferRender ) {
1266					_fnSortingClasses( oSettings );
1267				}
1268			}, 'sc' );
1269			
1270			
1271			/*
1272			 * Final init
1273			 * Cache the header, body and footer as required, creating them if needed
1274			 */
1275			
1276			// Work around for Webkit bug 83867 - store the caption-side before removing from doc
1277			var captions = $this.children('caption').each( function () {
1278				this._captionSide = $this.css('caption-side');
1279			} );
1280			
1281			var thead = $this.children('thead');
1282			if ( thead.length === 0 )
1283			{
1284				thead = $('<thead/>').appendTo(this);
1285			}
1286			oSettings.nTHead = thead[0];
1287			
1288			var tbody = $this.children('tbody');
1289			if ( tbody.length === 0 )
1290			{
1291				tbody = $('<tbody/>').appendTo(this);
1292			}
1293			oSettings.nTBody = tbody[0];
1294			
1295			var tfoot = $this.children('tfoot');
1296			if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") )
1297			{
1298				// If we are a scrolling table, and no footer has been given, then we need to create
1299				// a tfoot element for the caption element to be appended to
1300				tfoot = $('<tfoot/>').appendTo(this);
1301			}
1302			
1303			if ( tfoot.length === 0 || tfoot.children().length === 0 ) {
1304				$this.addClass( oClasses.sNoFooter );
1305			}
1306			else if ( tfoot.length > 0 ) {
1307				oSettings.nTFoot = tfoot[0];
1308				_fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );
1309			}
1310			
1311			/* Check if there is data passing into the constructor */
1312			if ( oInit.aaData )
1313			{
1314				for ( i=0 ; i<oInit.aaData.length ; i++ )
1315				{
1316					_fnAddData( oSettings, oInit.aaData[ i ] );
1317				}
1318			}
1319			else if ( oSettings.bDeferLoading || _fnDataSource( oSettings ) == 'dom' )
1320			{
1321				/* Grab the data from the page - only do this when deferred loading or no Ajax
1322				 * source since there is no point in reading the DOM data if we are then going
1323				 * to replace it with Ajax data
1324				 */
1325				_fnAddTr( oSettings, $(oSettings.nTBody).children('tr') );
1326			}
1327			
1328			/* Copy the data index array */
1329			oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
1330			
1331			/* Initialisation complete - table can be drawn */
1332			oSettings.bInitialised = true;
1333			
1334			/* Check if we need to initialise the table (it might not have been handed off to the
1335			 * language processor)
1336			 */
1337			if ( bInitHandedOff === false )
1338			{
1339				_fnInitialise( oSettings );
1340			}
1341		} );
1342		_that = null;
1343		return this;
1344	};
1345
1346	
1347	/*
1348	 * It is useful to have variables which are scoped locally so only the
1349	 * DataTables functions can access them and they don't leak into global space.
1350	 * At the same time these functions are often useful over multiple files in the
1351	 * core and API, so we list, or at least document, all variables which are used
1352	 * by DataTables as private variables here. This also ensures that there is no
1353	 * clashing of variable names and that they can easily referenced for reuse.
1354	 */
1355	
1356	
1357	// Defined else where
1358	//  _selector_run
1359	//  _selector_opts
1360	//  _selector_first
1361	//  _selector_row_indexes
1362	
1363	var _ext; // DataTable.ext
1364	var _Api; // DataTable.Api
1365	var _api_register; // DataTable.Api.register
1366	var _api_registerPlural; // DataTable.Api.registerPlural
1367	
1368	var _re_dic = {};
1369	var _re_new_lines = /[\r\n]/g;
1370	var _re_html = /<.*?>/g;
1371	var _re_date_start = /^[\w\+\-]/;
1372	var _re_date_end = /[\w\+\-]$/;
1373	
1374	// Escape regular expression special characters
1375	var _re_escape_regex = new RegExp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' );
1376	
1377	// http://en.wikipedia.org/wiki/Foreign_exchange_market
1378	// - \u20BD - Russian ruble.
1379	// - \u20a9 - South Korean Won
1380	// - \u20BA - Turkish Lira
1381	// - \u20B9 - Indian Rupee
1382	// - R - Brazil (R$) and South Africa
1383	// - fr - Swiss Franc
1384	// - kr - Swedish krona, Norwegian krone and Danish krone
1385	// - \u2009 is thin space and \u202F is narrow no-break space, both used in many
1386	//   standards as thousands separators.
1387	var _re_formatted_numeric = /[',$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfk]/gi;
1388	
1389	
1390	var _empty = function ( d ) {
1391		return !d || d === true || d === '-' ? true : false;
1392	};
1393	
1394	
1395	var _intVal = function ( s ) {
1396		var integer = parseInt( s, 10 );
1397		return !isNaN(integer) && isFinite(s) ? integer : null;
1398	};
1399	
1400	// Convert from a formatted number with characters other than `.` as the
1401	// decimal place, to a Javascript number
1402	var _numToDecimal = function ( num, decimalPoint ) {
1403		// Cache created regular expressions for speed as this function is called often
1404		if ( ! _re_dic[ decimalPoint ] ) {
1405			_re_dic[ decimalPoint ] = new RegExp( _fnEscapeRegex( decimalPoint ), 'g' );
1406		}
1407		return typeof num === 'string' && decimalPoint !== '.' ?
1408			num.replace( /\./g, '' ).replace( _re_dic[ decimalPoint ], '.' ) :
1409			num;
1410	};
1411	
1412	
1413	var _isNumber = function ( d, decimalPoint, formatted ) {
1414		var strType = typeof d === 'string';
1415	
1416		// If empty return immediately so there must be a number if it is a
1417		// formatted string (this stops the string "k", or "kr", etc being detected
1418		// as a formatted number for currency
1419		if ( _empty( d ) ) {
1420			return true;
1421		}
1422	
1423		if ( decimalPoint && strType ) {
1424			d = _numToDecimal( d, decimalPoint );
1425		}
1426	
1427		if ( formatted && strType ) {
1428			d = d.replace( _re_formatted_numeric, '' );
1429		}
1430	
1431		return !isNaN( parseFloat(d) ) && isFinite( d );
1432	};
1433	
1434	
1435	// A string without HTML in it can be considered to be HTML still
1436	var _isHtml = function ( d ) {
1437		return _empty( d ) || typeof d === 'string';
1438	};
1439	
1440	
1441	var _htmlNumeric = function ( d, decimalPoint, formatted ) {
1442		if ( _empty( d ) ) {
1443			return true;
1444		}
1445	
1446		var html = _isHtml( d );
1447		return ! html ?
1448			null :
1449			_isNumber( _stripHtml( d ), decimalPoint, formatted ) ?
1450				true :
1451				null;
1452	};
1453	
1454	
1455	var _pluck = function ( a, prop, prop2 ) {
1456		var out = [];
1457		var i=0, ien=a.length;
1458	
1459		// Could have the test in the loop for slightly smaller code, but speed
1460		// is essential here
1461		if ( prop2 !== undefined ) {
1462			for ( ; i<ien ; i++ ) {
1463				if ( a[i] && a[i][ prop ] ) {
1464					out.push( a[i][ prop ][ prop2 ] );
1465				}
1466			}
1467		}
1468		else {
1469			for ( ; i<ien ; i++ ) {
1470				if ( a[i] ) {
1471					out.push( a[i][ prop ] );
1472				}
1473			}
1474		}
1475	
1476		return out;
1477	};
1478	
1479	
1480	// Basically the same as _pluck, but rather than looping over `a` we use `order`
1481	// as the indexes to pick from `a`
1482	var _pluck_order = function ( a, order, prop, prop2 )
1483	{
1484		var out = [];
1485		var i=0, ien=order.length;
1486	
1487		// Could have the test in the loop for slightly smaller code, but speed
1488		// is essential here
1489		if ( prop2 !== undefined ) {
1490			for ( ; i<ien ; i++ ) {
1491				if ( a[ order[i] ][ prop ] ) {
1492					out.push( a[ order[i] ][ prop ][ prop2 ] );
1493				}
1494			}
1495		}
1496		else {
1497			for ( ; i<ien ; i++ ) {
1498				out.push( a[ order[i] ][ prop ] );
1499			}
1500		}
1501	
1502		return out;
1503	};
1504	
1505	
1506	var _range = function ( len, start )
1507	{
1508		var out = [];
1509		var end;
1510	
1511		if ( start === undefined ) {
1512			start = 0;
1513			end = len;
1514		}
1515		else {
1516			end = start;
1517			start = len;
1518		}
1519	
1520		for ( var i=start ; i<end ; i++ ) {
1521			out.push( i );
1522		}
1523	
1524		return out;
1525	};
1526	
1527	
1528	var _removeEmpty = function ( a )
1529	{
1530		var out = [];
1531	
1532		for ( var i=0, ien=a.length ; i<ien ; i++ ) {
1533			if ( a[i] ) { // careful - will remove all falsy values!
1534				out.push( a[i] );
1535			}
1536		}
1537	
1538		return out;
1539	};
1540	
1541	
1542	var _stripHtml = function ( d ) {
1543		return d.replace( _re_html, '' );
1544	};
1545	
1546	
1547	/**
1548	 * Find the unique elements in a source array.
1549	 *
1550	 * @param  {array} src Source array
1551	 * @return {array} Array of unique items
1552	 * @ignore
1553	 */
1554	var _unique = function ( src )
1555	{
1556		// A faster unique method is to use object keys to identify used values,
1557		// but this doesn't work with arrays or objects, which we must also
1558		// consider. See jsperf.com/compare-array-unique-versions/4 for more
1559		// information.
1560		var
1561			out = [],
1562			val,
1563			i, ien=src.length,
1564			j, k=0;
1565	
1566		again: for ( i=0 ; i<ien ; i++ ) {
1567			val = src[i];
1568	
1569			for ( j=0 ; j<k ; j++ ) {
1570				if ( out[j] === val ) {
1571					continue again;
1572				}
1573			}
1574	
1575			out.push( val );
1576			k++;
1577		}
1578	
1579		return out;
1580	};
1581	
1582	
1583	/**
1584	 * DataTables utility methods
1585	 * 
1586	 * This namespace provides helper methods that DataTables uses internally to
1587	 * create a DataTable, but which are not exclusively used only for DataTables.
1588	 * These methods can be used by extension authors to save the duplication of
1589	 * code.
1590	 *
1591	 *  @namespace
1592	 */
1593	DataTable.util = {
1594		/**
1595		 * Throttle the calls to a function. Arguments and context are maintained
1596		 * for the throttled function.
1597		 *
1598		 * @param {function} fn Function to be called
1599		 * @param {integer} freq Call frequency in mS
1600		 * @return {function} Wrapped function
1601		 */
1602		throttle: function ( fn, freq ) {
1603			var
1604				frequency = freq !== undefined ? freq : 200,
1605				last,
1606				timer;
1607	
1608			return function () {
1609				var
1610					that = this,
1611					now  = +new Date(),
1612					args = arguments;
1613	
1614				if ( last && now < last + frequency ) {
1615					clearTimeout( timer );
1616	
1617					timer = setTimeout( function () {
1618						last = undefined;
1619						fn.apply( that, args );
1620					}, frequency );
1621				}
1622				else {
1623					last = now;
1624					fn.apply( that, args );
1625				}
1626			};
1627		},
1628	
1629	
1630		/**
1631		 * Escape a string such that it can be used in a regular expression
1632		 *
1633		 *  @param {string} val string to escape
1634		 *  @returns {string} escaped string
1635		 */
1636		escapeRegex: function ( val ) {
1637			return val.replace( _re_escape_regex, '\\$1' );
1638		}
1639	};
1640	
1641	
1642	
1643	/**
1644	 * Create a mapping object that allows camel case parameters to be looked up
1645	 * for their Hungarian counterparts. The mapping is stored in a private
1646	 * parameter called `_hungarianMap` which can be accessed on the source object.
1647	 *  @param {object} o
1648	 *  @memberof DataTable#oApi
1649	 */
1650	function _fnHungarianMap ( o )
1651	{
1652		var
1653			hungarian = 'a aa ai ao as b fn i m o s ',
1654			match,
1655			newKey,
1656			map = {};
1657	
1658		$.each( o, function (key, val) {
1659			match = key.match(/^([^A-Z]+?)([A-Z])/);
1660	
1661			if ( match && hungarian.indexOf(match[1]+' ') !== -1 )
1662			{
1663				newKey = key.replace( match[0], match[2].toLowerCase() );
1664				map[ newKey ] = key;
1665	
1666				if ( match[1] === 'o' )
1667				{
1668					_fnHungarianMap( o[key] );
1669				}
1670			}
1671		} );
1672	
1673		o._hungarianMap = map;
1674	}
1675	
1676	
1677	/**
1678	 * Convert from camel case parameters to Hungarian, based on a Hungarian map
1679	 * created by _fnHungarianMap.
1680	 *  @param {object} src The model object which holds all parameters that can be
1681	 *    mapped.
1682	 *  @param {object} user The object to convert from camel case to Hungarian.
1683	 *  @param {boolean} force When set to `true`, properties which already have a
1684	 *    Hungarian value in the `user` object will be overwritten. Otherwise they
1685	 *    won't be.
1686	 *  @memberof DataTable#oApi
1687	 */
1688	function _fnCamelToHungarian ( src, user, force )
1689	{
1690		if ( ! src._hungarianMap ) {
1691			_fnHungarianMap( src );
1692		}
1693	
1694		var hungarianKey;
1695	
1696		$.each( user, function (key, val) {
1697			hungarianKey = src._hungarianMap[ key ];
1698	
1699			if ( hungarianKey !== undefined && (force || user[hungarianKey] === undefined) )
1700			{
1701				// For objects, we need to buzz down into the object to copy parameters
1702				if ( hungarianKey.charAt(0) === 'o' )
1703				{
1704					// Copy the camelCase options over to the hungarian
1705					if ( ! user[ hungarianKey ] ) {
1706						user[ hungarianKey ] = {};
1707					}
1708					$.extend( true, user[hungarianKey], user[key] );
1709	
1710					_fnCamelToHungarian( src[hungarianKey], user[hungarianKey], force );
1711				}
1712				else {
1713					user[hungarianKey] = user[ key ];
1714				}
1715			}
1716		} );
1717	}
1718	
1719	
1720	/**
1721	 * Language compatibility - when certain options are given, and others aren't, we
1722	 * need to duplicate the values over, in order to provide backwards compatibility
1723	 * with older language files.
1724	 *  @param {object} oSettings dataTables settings object
1725	 *  @memberof DataTable#oApi
1726	 */
1727	function _fnLanguageCompat( lang )
1728	{
1729		var defaults = DataTable.defaults.oLanguage;
1730		var zeroRecords = lang.sZeroRecords;
1731	
1732		/* Backwards compatibility - if there is no sEmptyTable given, then use the same as
1733		 * sZeroRecords - assuming that is given.
1734		 */
1735		if ( ! lang.sEmptyTable && zeroRecords &&
1736			defaults.sEmptyTable === "No data available in table" )
1737		{
1738			_fnMap( lang, lang, 'sZeroRecords', 'sEmptyTable' );
1739		}
1740	
1741		/* Likewise with loading records */
1742		if ( ! lang.sLoadingRecords && zeroRecords &&
1743			defaults.sLoadingRecords === "Loading..." )
1744		{
1745			_fnMap( lang, lang, 'sZeroRecords', 'sLoadingRecords' );
1746		}
1747	
1748		// Old parameter name of the thousands separator mapped onto the new
1749		if ( lang.sInfoThousands ) {
1750			lang.sThousands = lang.sInfoThousands;
1751		}
1752	
1753		var decimal = lang.sDecimal;
1754		if ( decimal ) {
1755			_addNumericSort( decimal );
1756		}
1757	}
1758	
1759	
1760	/**
1761	 * Map one parameter onto another
1762	 *  @param {object} o Object to map
1763	 *  @param {*} knew The new parameter name
1764	 *  @param {*} old The old parameter name
1765	 */
1766	var _fnCompatMap = function ( o, knew, old ) {
1767		if ( o[ knew ] !== undefined ) {
1768			o[ old ] = o[ knew ];
1769		}
1770	};
1771	
1772	
1773	/**
1774	 * Provide backwards compatibility for the main DT options. Note that the new
1775	 * options are mapped onto the old parameters, so this is an external interface
1776	 * change only.
1777	 *  @param {object} init Object to map
1778	 */
1779	function _fnCompatOpts ( init )
1780	{
1781		_fnCompatMap( init, 'ordering',      'bSort' );
1782		_fnCompatMap( init, 'orderMulti',    'bSortMulti' );
1783		_fnCompatMap( init, 'orderClasses',  'bSortClasses' );
1784		_fnCompatMap( init, 'orderCellsTop', 'bSortCellsTop' );
1785		_fnCompatMap( init, 'order',         'aaSorting' );
1786		_fnCompatMap( init, 'orderFixed',    'aaSortingFixed' );
1787		_fnCompatMap( init, 'paging',        'bPaginate' );
1788		_fnCompatMap( init, 'pagingType',    'sPaginationType' );
1789		_fnCompatMap( init, 'pageLength',    'iDisplayLength' );
1790		_fnCompatMap( init, 'searching',     'bFilter' );
1791	
1792		// Boolean initialisation of x-scrolling
1793		if ( typeof init.sScrollX === 'boolean' ) {
1794			init.sScrollX = init.sScrollX ? '100%' : '';
1795		}
1796		if ( typeof init.scrollX === 'boolean' ) {
1797			init.scrollX = init.scrollX ? '100%' : '';
1798		}
1799	
1800		// Column search objects are in an array, so it needs to be converted
1801		// element by element
1802		var searchCols = init.aoSearchCols;
1803	
1804		if ( searchCols ) {
1805			for ( var i=0, ien=searchCols.length ; i<ien ; i++ ) {
1806				if ( searchCols[i] ) {
1807					_fnCamelToHungarian( DataTable.models.oSearch, searchCols[i] );
1808				}
1809			}
1810		}
1811	}
1812	
1813	
1814	/**
1815	 * Provide backwards compatibility for column options. Note that the new options
1816	 * are mapped onto the old parameters, so this is an external interface change
1817	 * only.
1818	 *  @param {object} init Object to map
1819	 */
1820	function _fnCompatCols ( init )
1821	{
1822		_fnCompatMap( init, 'orderable',     'bSortable' );
1823		_fnCompatMap( init, 'orderData',     'aDataSort' );
1824		_fnCompatMap( init, 'orderSequence', 'asSorting' );
1825		_fnCompatMap( init, 'orderDataType', 'sortDataType' );
1826	
1827		// orderData can be given as an integer
1828		var dataSort = init.aDataSort;
1829		if ( dataSort && ! $.isArray( dataSort ) ) {
1830			init.aDataSort = [ dataSort ];
1831		}
1832	}
1833	
1834	
1835	/**
1836	 * Browser feature detection for capabilities, quirks
1837	 *  @param {object} settings dataTables settings object
1838	 *  @memberof DataTable#oApi
1839	 */
1840	function _fnBrowserDetect( settings )
1841	{
1842		// We don't need to do this every time DataTables is constructed, the values
1843		// calculated are specific to the browser and OS configuration which we
1844		// don't expect to change between initialisations
1845		if ( ! DataTable.__browser ) {
1846			var browser = {};
1847			DataTable.__browser = browser;
1848	
1849			// Scrolling feature / quirks detection
1850			var n = $('<div/>')
1851				.css( {
1852					position: 'fixed',
1853					top: 0,
1854					left: 0,
1855					height: 1,
1856					width: 1,
1857					overflow: 'hidden'
1858				} )
1859				.append(
1860					$('<div/>')
1861						.css( {
1862							position: 'absolute',
1863							top: 1,
1864							left: 1,
1865							width: 100,
1866							overflow: 'scroll'
1867						} )
1868						.append(
1869							$('<div/>')
1870								.css( {
1871									width: '100%',
1872									height: 10
1873								} )
1874						)
1875				)
1876				.appendTo( 'body' );
1877	
1878			var outer = n.children();
1879			var inner = outer.children();
1880	
1881			// Numbers below, in order, are:
1882			// inner.offsetWidth, inner.clientWidth, outer.offsetWidth, outer.clientWidth
1883			//
1884			// IE6 XP:                           100 100 100  83
1885			// IE7 Vista:                        100 100 100  83
1886			// IE 8+ Windows:                     83  83 100  83
1887			// Evergreen Windows:                 83  83 100  83
1888			// Evergreen Mac with scrollbars:     85  85 100  85
1889			// Evergreen Mac without scrollbars: 100 100 100 100
1890	
1891			// Get scrollbar width
1892			browser.barWidth = outer[0].offsetWidth - outer[0].clientWidth;
1893	
1894			// IE6/7 will oversize a width 100% element inside a scrolling element, to
1895			// include the width of the scrollbar, while other browsers ensure the inner
1896			// element is contained without forcing scrolling
1897			browser.bScrollOversize = inner[0].offsetWidth === 100 && outer[0].clientWidth !== 100;
1898	
1899			// In rtl text layout, some browsers (most, but not all) will place the
1900			// scrollbar on the left, rather than the right.
1901			browser.bScrollbarLeft = Math.round( inner.offset().left ) !== 1;
1902	
1903			// IE8- don't provide height and width for getBoundingClientRect
1904			browser.bBounding = n[0].getBoundingClientRect().width ? true : false;
1905	
1906			n.remove();
1907		}
1908	
1909		$.extend( settings.oBrowser, DataTable.__browser );
1910		settings.oScroll.iBarWidth = DataTable.__browser.barWidth;
1911	}
1912	
1913	
1914	/**
1915	 * Array.prototype reduce[Right] method, used for browsers which don't support
1916	 * JS 1.6. Done this way to reduce code size, since we iterate either way
1917	 *  @param {object} settings dataTables settings object
1918	 *  @memberof DataTable#oApi
1919	 */
1920	function _fnReduce ( that, fn, init, start, end, inc )
1921	{
1922		var
1923			i = start,
1924			value,
1925			isSet = false;
1926	
1927		if ( init !== undefined ) {
1928			value = init;
1929			isSet = true;
1930		}
1931	
1932		while ( i !== end ) {
1933			if ( ! that.hasOwnProperty(i) ) {
1934				continue;
1935			}
1936	
1937			value = isSet ?
1938				fn( value, that[i], i, that ) :
1939				that[i];
1940	
1941			isSet = true;
1942			i += inc;
1943		}
1944	
1945		return value;
1946	}
1947	
1948	/**
1949	 * Add a column to the list used for the table with default values
1950	 *  @param {object} oSettings dataTables settings object
1951	 *  @param {node} nTh The th element for this column
1952	 *  @memberof DataTable#oApi
1953	 */
1954	function _fnAddColumn( oSettings, nTh )
1955	{
1956		// Add column to aoColumns array
1957		var oDefaults = DataTable.defaults.column;
1958		var iCol = oSettings.aoColumns.length;
1959		var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {
1960			"nTh": nTh ? nTh : document.createElement('th'),
1961			"sTitle":    oDefaults.sTitle    ? oDefaults.sTitle    : nTh ? nTh.innerHTML : '',
1962			"aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],
1963			"mData": oDefaults.mData ? oDefaults.mData : iCol,
1964			idx: iCol
1965		} );
1966		oSettings.aoColumns.push( oCol );
1967	
1968		// Add search object for column specific search. Note that the `searchCols[ iCol ]`
1969		// passed into extend can be undefined. This allows the user to give a default
1970		// with only some of the parameters defined, and also not give a default
1971		var searchCols = oSettings.aoPreSearchCols;
1972		searchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] );
1973	
1974		// Use the default column options function to initialise classes etc
1975		_fnColumnOptions( oSettings, iCol, $(nTh).data() );
1976	}
1977	
1978	
1979	/**
1980	 * Apply options for a column
1981	 *  @param {object} oSettings dataTables settings object
1982	 *  @param {int} iCol column index to consider
1983	 *  @param {object} oOptions object with sType, bVisible and bSearchable etc
1984	 *  @memberof DataTable#oApi
1985	 */
1986	function _fnColumnOptions( oSettings, iCol, oOptions )
1987	{
1988		var oCol = oSettings.aoColumns[ iCol ];
1989		var oClasses = oSettings.oClasses;
1990		var th = $(oCol.nTh);
1991	
1992		// Try to get width information from the DOM. We can't get it from CSS
1993		// as we'd need to parse the CSS stylesheet. `width` option can override
1994		if ( ! oCol.sWidthOrig ) {
1995			// Width attribute
1996			oCol.sWidthOrig = th.attr('width') || null;
1997	
1998			// Style attribute
1999			var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/);
2000			if ( t ) {
2001				oCol.sWidthOrig = t[1];
2002			}
2003		}
2004	
2005		/* User specified column options */
2006		if ( oOptions !== undefined && oOptions !== null )
2007		{
2008			// Backwards compatibility
2009			_fnCompatCols( oOptions );
2010	
2011			// Map camel case parameters to their Hungarian counterparts
2012			_fnCamelToHungarian( DataTable.defaults.column, oOptions );
2013	
2014			/* Backwards compatibility for mDataProp */
2015			if ( oOptions.mDataProp !== undefined && !oOptions.mData )
2016			{
2017				oOptions.mData = oOptions.mDataProp;
2018			}
2019	
2020			if ( oOptions.sType )
2021			{
2022				oCol._sManualType = oOptions.sType;
2023			}
2024	
2025			// `class` is a reserved word in Javascript, so we need to provide
2026			// the ability to use a valid name for the camel case input
2027			if ( oOptions.className && ! oOptions.sClass )
2028			{
2029				oOptions.sClass = oOptions.className;
2030			}
2031	
2032			$.extend( oCol, oOptions );
2033			_fnMap( oCol, oOptions, "sWidth", "sWidthOrig" );
2034	
2035			/* iDataSort to be applied (backwards compatibility), but aDataSort will take
2036			 * priority if defined
2037			 */
2038			if ( oOptions.iDataSort !== undefined )
2039			{
2040				oCol.aDataSort = [ oOptions.iDataSort ];
2041			}
2042			_fnMap( oCol, oOptions, "aDataSort" );
2043		}
2044	
2045		/* Cache the data get and set functions for speed */
2046		var mDataSrc = oCol.mData;
2047		var mData = _fnGetObjectDataFn( mDataSrc );
2048		var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null;
2049	
2050		var attrTest = function( src ) {
2051			return typeof src === 'string' && src.indexOf('@') !== -1;
2052		};
2053		oCol._bAttrSrc = $.isPlainObject( mDataSrc ) && (
2054			attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter)
2055		);
2056		oCol._setter = null;
2057	
2058		oCol.fnGetData = function (rowData, type, meta) {
2059			var innerData = mData( rowData, type, undefined, meta );
2060	
2061			return mRender && type ?
2062				mRender( innerData, type, rowData, meta ) :
2063				innerData;
2064		};
2065		oCol.fnSetData = function ( rowData, val, meta ) {
2066			return _fnSetObjectDataFn( mDataSrc )( rowData, val, meta );
2067		};
2068	
2069		// Indicate if DataTables should read DOM data as an object or array
2070		// Used in _fnGetRowElements
2071		if ( typeof mDataSrc !== 'number' ) {
2072			oSettings._rowReadObject = true;
2073		}
2074	
2075		/* Feature sorting overrides column specific when off */
2076		if ( !oSettings.oFeatures.bSort )
2077		{
2078			oCol.bSortable = false;
2079			th.addClass( oClasses.sSortableNone ); // Have to add class here as order event isn't called
2080		}
2081	
2082		/* Check that the class assignment is correct for sorting */
2083		var bAsc = $.inArray('asc', oCol.asSorting) !== -1;
2084		var bDesc = $.inArray('desc', oCol.asSorting) !== -1;
2085		if ( !oCol.bSortable || (!bAsc && !bDesc) )
2086		{
2087			oCol.sSortingClass = oClasses.sSortableNone;
2088			oCol.sSortingClassJUI = "";
2089		}
2090		else if ( bAsc && !bDesc )
2091		{
2092			oCol.sSortingClass = oClasses.sSortableAsc;
2093			oCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed;
2094		}
2095		else if ( !bAsc && bDesc )
2096		{
2097			oCol.sSortingClass = oClasses.sSortableDesc;
2098			oCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed;
2099		}
2100		else
2101		{
2102			oCol.sSortingClass = oClasses.sSortable;
2103			oCol.sSortingClassJUI = oClasses.sSortJUI;
2104		}
2105	}
2106	
2107	
2108	/**
2109	 * Adjust the table column widths for new data. Note: you would probably want to
2110	 * do a redraw after calling this function!
2111	 *  @param {object} settings dataTables settings object
2112	 *  @memberof DataTable#oApi
2113	 */
2114	function _fnAdjustColumnSizing ( settings )
2115	{
2116		/* Not interested in doing column width calculation if auto-width is disabled */
2117		if ( settings.oFeatures.bAutoWidth !== false )
2118		{
2119			var columns = settings.aoColumns;
2120	
2121			_fnCalculateColumnWidths( settings );
2122			for ( var i=0 , iLen=columns.length ; i<iLen ; i++ )
2123			{
2124				columns[i].nTh.style.width = columns[i].sWidth;
2125			}
2126		}
2127	
2128		var scroll = settings.oScroll;
2129		if ( scroll.sY !== '' || scroll.sX !== '')
2130		{
2131			_fnScrollDraw( settings );
2132		}
2133	
2134		_fnCallbackFire( settings, null, 'column-sizing', [settings] );
2135	}
2136	
2137	
2138	/**
2139	 * Covert the index of a visible column to the index in the data array (take account
2140	 * of hidden columns)
2141	 *  @param {object} oSettings dataTables settings object
2142	 *  @param {int} iMatch Visible column index to lookup
2143	 *  @returns {int} i the data index
2144	 *  @memberof DataTable#oApi
2145	 */
2146	function _fnVisibleToColumnIndex( oSettings, iMatch )
2147	{
2148		var aiVis = _fnGetColumns( oSettings, 'bVisible' );
2149	
2150		return typeof aiVis[iMatch] === 'number' ?
2151			aiVis[iMatch] :
2152			null;
2153	}
2154	
2155	
2156	/**
2157	 * Covert the index of an index in the data array and convert it to the visible
2158	 *   column index (take account of hidden columns)
2159	 *  @param {int} iMatch Column index to lookup
2160	 *  @param {object} oSettings dataTables settings object
2161	 *  @returns {int} i the data index
2162	 *  @memberof DataTable#oApi
2163	 */
2164	function _fnColumnIndexToVisible( oSettings, iMatch )
2165	{
2166		var aiVis = _fnGetColumns( oSettings, 'bVisible' );
2167		var iPos = $.inArray( iMatch, aiVis );
2168	
2169		return iPos !== -1 ? iPos : null;
2170	}
2171	
2172	
2173	/**
2174	 * Get the number of visible columns
2175	 *  @param {object} oSettings dataTables settings object
2176	 *  @returns {int} i the number of visible columns
2177	 *  @memberof DataTable#oApi
2178	 */
2179	function _fnVisbleColumns( oSettings )
2180	{
2181		var vis = 0;
2182	
2183		// No reduce in IE8, use a loop for now
2184		$.each( oSettings.aoColumns, function ( i, col ) {
2185			if ( col.bVisible && $(col.nTh).css('display') !== 'none' ) {
2186				vis++;
2187			}
2188		} );
2189	
2190		return vis;
2191	}
2192	
2193	
2194	/**
2195	 * Get an array of column indexes that match a given property
2196	 *  @param {object} oSettings dataTables settings object
2197	 *  @param {string} sParam Parameter in aoColumns to look for - typically
2198	 *    bVisible or bSearchable
2199	 *  @returns {array} Array of indexes with matched properties
2200	 *  @memberof DataTable#oApi
2201	 */
2202	function _fnGetColumns( oSettings, sParam )
2203	{
2204		var a = [];
2205	
2206		$.map( oSettings.aoColumns, function(val, i) {
2207			if ( val[sParam] ) {
2208				a.push( i );
2209			}
2210		} );
2211	
2212		return a;
2213	}
2214	
2215	
2216	/**
2217	 * Calculate the 'type' of a column
2218	 *  @param {object} settings dataTables settings object
2219	 *  @memberof DataTable#oApi
2220	 */
2221	function _fnColumnTypes ( settings )
2222	{
2223		var columns = settings.aoColumns;
2224		var data = settings.aoData;
2225		var types = DataTable.ext.type.detect;
2226		var i, ien, j, jen, k, ken;
2227		var col, cell, detectedType, cache;
2228	
2229		// For each column, spin over the 
2230		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
2231			col = columns[i];
2232			cache = [];
2233	
2234			if ( ! col.sType && col._sManualType ) {
2235				col.sType = col._sManualType;
2236			}
2237			else if ( ! col.sType ) {
2238				for ( j=0, jen=types.length ; j<jen ; j++ ) {
2239					for ( k=0, ken=data.length ; k<ken ; k++ ) {
2240						// Use a cache array so we only need to get the type data
2241						// from the formatter once (when using multiple detectors)
2242						if ( cache[k] === undefined ) {
2243							cache[k] = _fnGetCellData( settings, k, i, 'type' );
2244						}
2245	
2246						detectedType = types[j]( cache[k], settings );
2247	
2248						// If null, then this type can't apply to this column, so
2249						// rather than testing all cells, break out. There is an
2250						// exception for the last type which is `html`. We need to
2251						// scan all rows since it is possible to mix string and HTML
2252						// types
2253						if ( ! detectedType && j !== types.length-1 ) {
2254							break;
2255						}
2256	
2257						// Only a single match is needed for html type since it is
2258						// bottom of the pile and very similar to string
2259						if ( detectedType === 'html' ) {
2260							break;
2261						}
2262					}
2263	
2264					// Type is valid for all data points in the column - use this
2265					// type
2266					if ( detectedType ) {
2267						col.sType = detectedType;
2268						break;
2269					}
2270				}
2271	
2272				// Fall back - if no type was detected, always use string
2273				if ( ! col.sType ) {
2274					col.sType = 'string';
2275				}
2276			}
2277		}
2278	}
2279	
2280	
2281	/**
2282	 * Take the column definitions and static columns arrays and calculate how
2283	 * they relate to column indexes. The callback function will then apply the
2284	 * definition found for a column to a suitable configuration object.
2285	 *  @param {object} oSettings dataTables settings object
2286	 *  @param {array} aoColDefs The aoColumnDefs array that is to be applied
2287	 *  @param {array} aoCols The aoColumns array that defines columns individually
2288	 *  @param {function} fn Callback function - takes two parameters, the calculated
2289	 *    column index and the definition for that column.
2290	 *  @memberof DataTable#oApi
2291	 */
2292	function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )
2293	{
2294		var i, iLen, j, jLen, k, kLen, def;
2295		var columns = oSettings.aoColumns;
2296	
2297		// Column definitions with aTargets
2298		if ( aoColDefs )
2299		{
2300			/* Loop over the definitions array - loop in reverse so first instance has priority */
2301			for ( i=aoColDefs.length-1 ; i>=0 ; i-- )
2302			{
2303				def = aoColDefs[i];
2304	
2305				/* Each definition can target multiple columns, as it is an array */
2306				var aTargets = def.targets !== undefined ?
2307					def.targets :
2308					def.aTargets;
2309	
2310				if ( ! $.isArray( aTargets ) )
2311				{
2312					aTargets = [ aTargets ];
2313				}
2314	
2315				for ( j=0, jLen=aTargets.length ; j<jLen ; j++ )
2316				{
2317					if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 )
2318					{
2319						/* Add columns that we don't yet know about */
2320						while( columns.length <= aTargets[j] )
2321						{
2322							_fnAddColumn( oSettings );
2323						}
2324	
2325						/* Integer, basic index */
2326						fn( aTargets[j], def );
2327					}
2328					else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 )
2329					{
2330						/* Negative integer, right to left column counting */
2331						fn( columns.length+aTargets[j], def );
2332					}
2333					else if ( typeof aTargets[j] === 'string' )
2334					{
2335						/* Class name matching on TH element */
2336						for ( k=0, kLen=columns.length ; k<kLen ; k++ )
2337						{
2338							if ( aTargets[j] == "_all" ||
2339							     $(columns[k].nTh).hasClass( aTargets[j] ) )
2340							{
2341								fn( k, def );
2342							}
2343						}
2344					}
2345				}
2346			}
2347		}
2348	
2349		// Statically defined columns array
2350		if ( aoCols )
2351		{
2352			for ( i=0, iLen=aoCols.length ; i<iLen ; i++ )
2353			{
2354				fn( i, aoCols[i] );
2355			}
2356		}
2357	}
2358	
2359	/**
2360	 * Add a data array to the table, creating DOM node etc. This is the parallel to
2361	 * _fnGatherData, but for adding rows from a Javascript source, rather than a
2362	 * DOM source.
2363	 *  @param {object} oSettings dataTables settings object
2364	 *  @param {array} aData data array to be added
2365	 *  @param {node} [nTr] TR element to add to the table - optional. If not given,
2366	 *    DataTables will create a row automatically
2367	 *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
2368	 *    if nTr is.
2369	 *  @returns {int} >=0 if successful (index of new aoData entry), -1 if failed
2370	 *  @memberof DataTable#oApi
2371	 */
2372	function _fnAddData ( oSettings, aDataIn, nTr, anTds )
2373	{
2374		/* Create the object for storing information about this new row */
2375		var iRow = oSettings.aoData.length;
2376		var oData = $.extend( true, {}, DataTable.models.oRow, {
2377			src: nTr ? 'dom' : 'data',
2378			idx: iRow
2379		} );
2380	
2381		oData._aData = aDataIn;
2382		oSettings.aoData.push( oData );
2383	
2384		/* Create the cells */
2385		var nTd, sThisType;
2386		var columns = oSettings.aoColumns;
2387	
2388		// Invalidate the column types as the new data needs to be revalidated
2389		for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
2390		{
2391			columns[i].sType = null;
2392		}
2393	
2394		/* Add to the display array */
2395		oSettings.aiDisplayMaster.push( iRow );
2396	
2397		var id = oSettings.rowIdFn( aDataIn );
2398		if ( id !== undefined ) {
2399			oSettings.aIds[ id ] = oData;
2400		}
2401	
2402		/* Create the DOM information, or register it if already present */
2403		if ( nTr || ! oSettings.oFeatures.bDeferRender )
2404		{
2405			_fnCreateTr( oSettings, iRow, nTr, anTds );
2406		}
2407	
2408		return iRow;
2409	}
2410	
2411	
2412	/**
2413	 * Add one or more TR elements to the table. Generally we'd expect to
2414	 * use this for reading data from a DOM sourced table, but it could be
2415	 * used for an TR element. Note that if a TR is given, it is used (i.e.
2416	 * it is not cloned).
2417	 *  @param {object} settings dataTables settings object
2418	 *  @param {array|node|jQuery} trs The TR element(s) to add to the table
2419	 *  @returns {array} Array of indexes for the added rows
2420	 *  @memberof DataTable#oApi
2421	 */
2422	function _fnAddTr( settings, trs )
2423	{
2424		var row;
2425	
2426		// Allow an individual node to be passed in
2427		if ( ! (trs instanceof $) ) {
2428			trs = $(trs);
2429		}
2430	
2431		return trs.map( function (i, el) {
2432			row = _fnGetRowElements( settings, el );
2433			return _fnAddData( settings, row.data, el, row.cells );
2434		} );
2435	}
2436	
2437	
2438	/**
2439	 * Take a TR element and convert it to an index in aoData
2440	 *  @param {object} oSettings dataTables settings object
2441	 *  @param {node} n the TR element to find
2442	 *  @returns {int} index if the node is found, null if not
2443	 *  @memberof DataTable#oApi
2444	 */
2445	function _fnNodeToDataIndex( oSettings, n )
2446	{
2447		return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null;
2448	}
2449	
2450	
2451	/**
2452	 * Take a TD element and convert it into a column data index (not the visible index)
2453	 *  @param {object} oSettings dataTables settings object
2454	 *  @param {int} iRow The row number the TD/TH can be found in
2455	 *  @param {node} n The TD/TH element to find
2456	 *  @returns {int} index if the node is found, -1 if not
2457	 *  @memberof DataTable#oApi
2458	 */
2459	function _fnNodeToColumnIndex( oSettings, iRow, n )
2460	{
2461		return $.inArray( n, oSettings.aoData[ iRow ].anCells );
2462	}
2463	
2464	
2465	/**
2466	 * Get the data for a given cell from the internal cache, taking into account data mapping
2467	 *  @param {object} settings dataTables settings object
2468	 *  @param {int} rowIdx aoData row id
2469	 *  @param {int} colIdx Column index
2470	 *  @param {string} type data get type ('display', 'type' 'filter' 'sort')
2471	 *  @returns {*} Cell data
2472	 *  @memberof DataTable#oApi
2473	 */
2474	function _fnGetCellData( settings, rowIdx, colIdx, type )
2475	{
2476		var draw           = settings.iDraw;
2477		var col            = settings.aoColumns[colIdx];
2478		var rowData        = settings.aoData[rowIdx]._aData;
2479		var defaultContent = col.sDefaultContent;
2480		var cellData       = col.fnGetData( rowData, type, {
2481			settings: settings,
2482			row:      rowIdx,
2483			col:      colIdx
2484		} );
2485	
2486		if ( cellData === undefined ) {
2487			if ( settings.iDrawError != draw && defaultContent === null ) {
2488				_fnLog( settings, 0, "Requested unknown parameter "+
2489					(typeof col.mData=='function' ? '{function}' : "'"+col.mData+"'")+
2490					" for row "+rowIdx+", column "+colIdx, 4 );
2491				settings.iDrawError = draw;
2492			}
2493			return defaultContent;
2494		}
2495	
2496		// When the data source is null and a specific data type is requested (i.e.
2497		// not the original data), we can use default column data
2498		if ( (cellData === rowData || cellData === null) && defaultContent !== null && type !== undefined ) {
2499			cellData = defaultContent;
2500		}
2501		else if ( typeof cellData === 'function' ) {
2502			// If the data source is a function, then we run it and use the return,
2503			// executing in the scope of the data object (for instances)
2504			return cellData.call( rowData );
2505		}
2506	
2507		if ( cellData === null && type == 'display' ) {
2508			return '';
2509		}
2510		return cellData;
2511	}
2512	
2513	
2514	/**
2515	 * Set the value for a specific cell, into the internal data cache
2516	 *  @param {object} settings dataTables settings object
2517	 *  @param {int} rowIdx aoData row id
2518	 *  @param {int} colIdx Column index
2519	 *  @param {*} val Value to set
2520	 *  @memberof DataTable#oApi
2521	 */
2522	function _fnSetCellData( settings, rowIdx, colIdx, val )
2523	{
2524		var col     = settings.aoColumns[colIdx];
2525		var rowData = settings.aoData[rowIdx]._aData;
2526	
2527		col.fnSetData( rowData, val, {
2528			settings: settings,
2529			row:      rowIdx,
2530			col:      colIdx
2531		}  );
2532	}
2533	
2534	
2535	// Private variable that is used to match action syntax in the data property object
2536	var __reArray = /\[.*?\]$/;
2537	var __reFn = /\(\)$/;
2538	
2539	/**
2540	 * Split string on periods, taking into account escaped periods
2541	 * @param  {string} str String to split
2542	 * @return {array} Split string
2543	 */
2544	function _fnSplitObjNotation( str )
2545	{
2546		return $.map( str.match(/(\\.|[^\.])+/g) || [''], function ( s ) {
2547			return s.replace(/\\./g, '.');
2548		} );
2549	}
2550	
2551	
2552	/**
2553	 * Return a function that can be used to get data from a source object, taking
2554	 * into account the ability to use nested objects as a source
2555	 *  @param {string|int|function} mSource The data source for the object
2556	 *  @returns {function} Data get function
2557	 *  @memberof DataTable#oApi
2558	 */
2559	function _fnGetObjectDataFn( mSource )
2560	{
2561		if ( $.isPlainObject( mSource ) )
2562		{
2563			/* Build an object of get functions, and wrap them in a single call */
2564			var o = {};
2565			$.each( mSource, function (key, val) {
2566				if ( val ) {
2567					o[key] = _fnGetObjectDataFn( val );
2568				}
2569			} );
2570	
2571			return function (data, type, row, meta) {
2572				var t = o[type] || o._;
2573				return t !== undefined ?
2574					t(data, type, row, meta) :
2575					data;
2576			};
2577		}
2578		else if ( mSource === null )
2579		{
2580			/* Give an empty string for rendering / sorting etc */
2581			return function (data) { // type, row and meta also passed, but not used
2582				return data;
2583			};
2584		}
2585		else if ( typeof mSource === 'function' )
2586		{
2587			return function (data, type, row, meta) {
2588				return mSource( data, type, row, meta );
2589			};
2590		}
2591		else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
2592			      mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
2593		{
2594			/* If there is a . in the source string then the data source is in a
2595			 * nested object so we loop over the data for each level to get the next
2596			 * level down. On each loop we test for undefined, and if found immediately
2597			 * return. This allows entire objects to be missing and sDefaultContent to
2598			 * be used if defined, rather than throwing an error
2599			 */
2600			var fetchData = function (data, type, src) {
2601				var arrayNotation, funcNotation, out, innerSrc;
2602	
2603				if ( src !== "" )
2604				{
2605					var a = _fnSplitObjNotation( src );
2606	
2607					for ( var i=0, iLen=a.length ; i<iLen ; i++ )
2608					{
2609						// Check if we are dealing with special notation
2610						arrayNotation = a[i].match(__reArray);
2611						funcNotation = a[i].match(__reFn);
2612	
2613						if ( arrayNotation )
2614						{
2615							// Array notation
2616							a[i] = a[i].replace(__reArray, '');
2617	
2618							// Condition allows simply [] to be passed in
2619							if ( a[i] !== "" ) {
2620								data = data[ a[i] ];
2621							}
2622							out = [];
2623	
2624							// Get the remainder of the nested object to get
2625							a.splice( 0, i+1 );
2626							innerSrc = a.join('.');
2627	
2628							// Traverse each entry in the array getting the properties requested
2629							if ( $.isArray( data ) ) {
2630								for ( var j=0, jLen=data.length ; j<jLen ; j++ ) {
2631									out.push( fetchData( data[j], type, innerSrc ) );
2632								}
2633							}
2634	
2635							// If a string is given in between the array notation indicators, that
2636							// is used to join the strings together, otherwise an array is returned
2637							var join = arrayNotation[0].substring(1, arrayNotation[0].length-1);
2638							data = (join==="") ? out : out.join(join);
2639	
2640							// The inner call to fetchData has already traversed through the remainder
2641							// of the source requested, so we exit from the loop
2642							break;
2643						}
2644						else if ( funcNotation )
2645						{
2646							// Function call
2647							a[i] = a[i].replace(__reFn, '');
2648							data = data[ a[i] ]();
2649							continue;
2650						}
2651	
2652						if ( data === null || data[ a[i] ] === undefined )
2653						{
2654							return undefined;
2655						}
2656						data = data[ a[i] ];
2657					}
2658				}
2659	
2660				return data;
2661			};
2662	
2663			return function (data, type) { // row and meta also passed, but not used
2664				return fetchData( data, type, mSource );
2665			};
2666		}
2667		else
2668		{
2669			/* Array or flat object mapping */
2670			return function (data, type) { // row and meta also passed, but not used
2671				return data[mSource];
2672			};
2673		}
2674	}
2675	
2676	
2677	/**
2678	 * Return a function that can be used to set data from a source object, taking
2679	 * into account the ability to use nested objects as a source
2680	 *  @param {string|int|function} mSource The data source for the object
2681	 *  @returns {function} Data set function
2682	 *  @memberof DataTable#oApi
2683	 */
2684	function _fnSetObjectDataFn( mSource )
2685	{
2686		if ( $.isPlainObject( mSource ) )
2687		{
2688			/* Unlike get, only the underscore (global) option is used for for
2689			 * setting data since we don't know the type here. This is why an object
2690			 * option is not documented for `mData` (which is read/write), but it is
2691			 * for `mRender` which is read only.
2692			 */
2693			return _fnSetObjectDataFn( mSource._ );
2694		}
2695		else if ( mSource === null )
2696		{
2697			/* Nothing to do when the data source is null */
2698			return function () {};
2699		}
2700		else if ( typeof mSource === 'function' )
2701		{
2702			return function (data, val, meta) {
2703				mSource( data, 'set', val, meta );
2704			};
2705		}
2706		else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
2707			      mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
2708		{
2709			/* Like the get, we need to get data from a nested object */
2710			var setData = function (data, val, src) {
2711				var a = _fnSplitObjNotation( src ), b;
2712				var aLast = a[a.length-1];
2713				var arrayNotation, funcNotation, o, innerSrc;
2714	
2715				for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ )
2716				{
2717					// Check if we are dealing with an array notation request
2718					arrayNotation = a[i].match(__reArray);
2719					funcNotation = a[i].match(__reFn);
2720	
2721					if ( arrayNotation )
2722					{
2723						a[i] = a[i].replace(__reArray, '');
2724						data[ a[i] ] = [];
2725	
2726						// Get the remainder of the nested object to set so we can recurse
2727						b = a.slice();
2728						b.splice( 0, i+1 );
2729						innerSrc = b.join('.');
2730	
2731						// Traverse each entry in the array setting the properties requested
2732						if ( $.isArray( val ) )
2733						{
2734							for ( var j=0, jLen=val.length ; j<jLen ; j++ )
2735							{
2736								o = {};
2737								setData( o, val[j], innerSrc );
2738								data[ a[i] ].push( o );
2739							}
2740						}
2741						else
2742						{
2743							// We've been asked to save data to an array, but it
2744							// isn't array data to be saved. Best that can be done
2745							// is to just save the value.
2746							data[ a[i] ] = val;
2747						}
2748	
2749						// The inner call to setData has already traversed through the remainder
2750						// of the source and has set the data, thus we can exit here
2751						return;
2752					}
2753					else if ( funcNotation )
2754					{
2755						// Function call
2756						a[i] = a[i].replace(__reFn, '');
2757						data = data[ a[i] ]( val );
2758					}
2759	
2760					// If the nested object doesn't currently exist - since we are
2761					// trying to set the value - create it
2762					if ( data[ a[i] ] === null || data[ a[i] ] === undefined )
2763					{
2764						data[ a[i] ] = {};
2765					}
2766					data = data[ a[i] ];
2767				}
2768	
2769				// Last item in the input - i.e, the actual set
2770				if ( aLast.match(__reFn ) )
2771				{
2772					// Function call
2773					data = data[ aLast.replace(__reFn, '') ]( val );
2774				}
2775				else
2776				{
2777					// If array notation is used, we just want to strip it and use the property name
2778					// and assign the value. If it isn't used, then we get the result we want anyway
2779					data[ aLast.replace(__reArray, '') ] = val;
2780				}
2781			};
2782	
2783			return function (data, val) { // meta is also passed in, but not used
2784				return setData( data, val, mSource );
2785			};
2786		}
2787		else
2788		{
2789			/* Array or flat object mapping */
2790			return function (data, val) { // meta is also passed in, but not used
2791				data[mSource] = val;
2792			};
2793		}
2794	}
2795	
2796	
2797	/**
2798	 * Return an array with the full table data
2799	 *  @param {object} oSettings dataTables settings object
2800	 *  @returns array {array} aData Master data array
2801	 *  @memberof DataTable#oApi
2802	 */
2803	function _fnGetDataMaster ( settings )
2804	{
2805		return _pluck( settings.aoData, '_aData' );
2806	}
2807	
2808	
2809	/**
2810	 * Nuke the table
2811	 *  @param {object} oSettings dataTables settings object
2812	 *  @memberof DataTable#oApi
2813	 */
2814	function _fnClearTable( settings )
2815	{
2816		settings.aoData.length = 0;
2817		settings.aiDisplayMaster.length = 0;
2818		settings.aiDisplay.length = 0;
2819		settings.aIds = {};
2820	}
2821	
2822	
2823	 /**
2824	 * Take an array of integers (index array) and remove a target integer (value - not
2825	 * the key!)
2826	 *  @param {array} a Index array to target
2827	 *  @param {int} iTarget value to find
2828	 *  @memberof DataTable#oApi
2829	 */
2830	function _fnDeleteIndex( a, iTarget, splice )
2831	{
2832		var iTargetIndex = -1;
2833	
2834		for ( var i=0, iLen=a.length ; i<iLen ; i++ )
2835		{
2836			if ( a[i] == iTarget )
2837			{
2838				iTargetIndex = i;
2839			}
2840			else if ( a[i] > iTarget )
2841			{
2842				a[i]--;
2843			}
2844		}
2845	
2846		if ( iTargetIndex != -1 && splice === undefined )
2847		{
2848			a.splice( iTargetIndex, 1 );
2849		}
2850	}
2851	
2852	
2853	/**
2854	 * Mark cached data as invalid such that a re-read of the data will occur when
2855	 * the cached data is next requested. Also update from the data source object.
2856	 *
2857	 * @param {object} settings DataTables settings object
2858	 * @param {int}    rowIdx   Row index to invalidate
2859	 * @param {string} [src]    Source to invalidate from: undefined, 'auto', 'dom'
2860	 *     or 'data'
2861	 * @param {int}    [colIdx] Column index to invalidate. If undefined the whole
2862	 *     row will be invalidated
2863	 * @memberof DataTable#oApi
2864	 *
2865	 * @todo For the modularisation of v1.11 this will need to become a callback, so
2866	 *   the sort and filter methods can subscribe to it. That will required
2867	 *   initialisation options for sorting, which is why it is not already baked in
2868	 */
2869	function _fnInvalidate( settings, rowIdx, src, colIdx )
2870	{
2871		var row = settings.aoData[ rowIdx ];
2872		var i, ien;
2873		var cellWrite = function ( cell, col ) {
2874			// This is very frustrating, but in IE if you just write directly
2875			// to innerHTML, and elements that are overwritten are GC'ed,
2876			// even if there is a reference to them elsewhere
2877			while ( cell.childNodes.length ) {
2878				cell.removeChild( cell.firstChild );
2879			}
2880	
2881			cell.innerHTML = _fnGetCellData( settings, rowIdx, col, 'display' );
2882		};
2883	
2884		// Are we reading last data from DOM or the data object?
2885		if ( src === 'dom' || ((! src || src === 'auto') && row.src === 'dom') ) {
2886			// Read the data from the DOM
2887			row._aData = _fnGetRowElements(
2888					settings, row, colIdx, colIdx === undefined ? undefined : row._aData
2889				)
2890				.data;
2891		}
2892		else {
2893			// Reading from data object, update the DOM
2894			var cells = row.anCells;
2895	
2896			if ( cells ) {
2897				if ( colIdx !== undefined ) {
2898					cellWrite( cells[colIdx], colIdx );
2899				}
2900				else {
2901					for ( i=0, ien=cells.length ; i<ien ; i++ ) {
2902						cellWrite( cells[i], i );
2903					}
2904				}
2905			}
2906		}
2907	
2908		// For both row and cell invalidation, the cached data for sorting and
2909		// filtering is nulled out
2910		row._aSortData = null;
2911		row._aFilterData = null;
2912	
2913		// Invalidate the type for a specific column (if given) or all columns since
2914		// the data might have changed
2915		var cols = settings.aoColumns;
2916		if ( colIdx !== undefined ) {
2917			cols[ colIdx ].sType = null;
2918		}
2919		else {
2920			for ( i=0, ien=cols.length ; i<ien ; i++ ) {
2921				cols[i].sType = null;
2922			}
2923	
2924			// Update DataTables special `DT_*` attributes for the row
2925			_fnRowAttributes( settings, row );
2926		}
2927	}
2928	
2929	
2930	/**
2931	 * Build a data source object from an HTML row, reading the contents of the
2932	 * cells that are in the row.
2933	 *
2934	 * @param {object} settings DataTables settings object
2935	 * @param {node|object} TR element from which to read data or existing row
2936	 *   object from which to re-read the data from the cells
2937	 * @param {int} [colIdx] Optional column index
2938	 * @param {array|object} [d] Data source object. If `colIdx` is given then this
2939	 *   parameter should also be given and will be used to write the data into.
2940	 *   Only the column in question will be written
2941	 * @returns {object} Object with two parameters: `data` the data read, in
2942	 *   document order, and `cells` and array of nodes (they can be useful to the
2943	 *   caller, so rather than needing a second traversal to get them, just return
2944	 *   them from here).
2945	 * @memberof DataTable#oApi
2946	 */
2947	function _fnGetRowElements( settings, row, colIdx, d )
2948	{
2949		var
2950			tds = [],
2951			td = row.firstChild,
2952			name, col, o, i=0, contents,
2953			columns = settings.aoColumns,
2954			objectRead = settings._rowReadObject;
2955	
2956		// Allow the data object to be passed in, or construct
2957		d = d !== undefined ?
2958			d :
2959			objectRead ?
2960				{} :
2961				[];
2962	
2963		var attr = function ( str, td  ) {
2964			if ( typeof str === 'string' ) {
2965				var idx = str.indexOf('@');
2966	
2967				if ( idx !== -1 ) {
2968					var attr = str.substring( idx+1 );
2969					var setter = _fnSetObjectDataFn( str );
2970					setter( d, td.getAttribute( attr ) );
2971				}
2972			}
2973		};
2974	
2975		// Read data from a cell and store into the data object
2976		var cellProcess = function ( cell ) {
2977			if ( colIdx === undefined || colIdx === i ) {
2978				col = columns[i];
2979				contents = $.trim(cell.innerHTML);
2980	
2981				if ( col && col._bAttrSrc ) {
2982					var setter = _fnSetObjectDataFn( col.mData._ );
2983					setter( d, contents );
2984	
2985					attr( col.mData.sort, cell );
2986					attr( col.mData.type, cell );
2987					attr( col.mData.filter, cell );
2988				}
2989				else {
2990					// Depending on the `data` option for the columns the data can
2991					// be read to either an object or an array.
2992					if ( objectRead ) {
2993						if ( ! col._setter ) {
2994							// Cache the setter function
2995							col._setter = _fnSetObjectDataFn( col.mData );
2996						}
2997						col._setter( d, contents );
2998					}
2999					else {
3000						d[i] = contents;
3001					}
3002				}
3003			}
3004	
3005			i++;
3006		};
3007	
3008		if ( td ) {
3009			// `tr` element was passed in
3010			while ( td ) {
3011				name = td.nodeName.toUpperCase();
3012	
3013				if ( name == "TD" || name == "TH" ) {
3014					cellProcess( td );
3015					tds.push( td );
3016				}
3017	
3018				td = td.nextSibling;
3019			}
3020		}
3021		else {
3022			// Existing row object passed in
3023			tds = row.anCells;
3024	
3025			for ( var j=0, jen=tds.length ; j<jen ; j++ ) {
3026				cellProcess( tds[j] );
3027			}
3028		}
3029	
3030		// Read the ID from the DOM if present
3031		var rowNode = row.firstChild ? row : row.nTr;
3032	
3033		if ( rowNode ) {
3034			var id = rowNode.getAttribute( 'id' );
3035	
3036			if ( id ) {
3037				_fnSetObjectDataFn( settings.rowId )( d, id );
3038			}
3039		}
3040	
3041		return {
3042			data: d,
3043			cells: tds
3044		};
3045	}
3046	/**
3047	 * Create a new TR element (and it's TD children) for a row
3048	 *  @param {object} oSettings dataTables settings object
3049	 *  @param {int} iRow Row to consider
3050	 *  @param {node} [nTrIn] TR element to add to the table - optional. If not given,
3051	 *    DataTables will create a row automatically
3052	 *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
3053	 *    if nTr is.
3054	 *  @memberof DataTable#oApi
3055	 */
3056	function _fnCreateTr ( oSettings, iRow, nTrIn, anTds )
3057	{
3058		var
3059			row = oSettings.aoData[iRow],
3060			rowData = row._aData,
3061			cells = [],
3062			nTr, nTd, oCol,
3063			i, iLen;
3064	
3065		if ( row.nTr === null )
3066		{
3067			nTr = nTrIn || document.createElement('tr');
3068	
3069			row.nTr = nTr;
3070			row.anCells = cells;
3071	
3072			/* Use a private property on the node to allow reserve mapping from the node
3073			 * to the aoData array for fast look up
3074			 */
3075			nTr._DT_RowIndex = iRow;
3076	
3077			/* Special parameters can be given by the data source to be used on the row */
3078			_fnRowAttributes( oSettings, row );
3079	
3080			/* Process each column */
3081			for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
3082			{
3083				oCol = oSettings.aoColumns[i];
3084	
3085				nTd = nTrIn ? anTds[i] : document.createElement( oCol.sCellType );
3086				nTd._DT_CellIndex = {
3087					row: iRow,
3088					column: i
3089				};
3090				
3091				cells.push( nTd );
3092	
3093				// Need to create the HTML if new, or if a rendering function is defined
3094				if ( (!nTrIn || oCol.mRender || oCol.mData !== i) &&
3095					 (!$.isPlainObject(oCol.mData) || oCol.mData._ !== i+'.display')
3096				) {
3097					nTd.innerHTML = _fnGetCellData( oSettings, iRow, i, 'display' );
3098				}
3099	
3100				/* Add user defined class */
3101				if ( oCol.sClass )
3102				{
3103					nTd.className += ' '+oCol.sClass;
3104				}
3105	
3106				// Visibility - add or remove as required
3107				if ( oCol.bVisible && ! nTrIn )
3108				{
3109					nTr.appendChild( nTd );
3110				}
3111				else if ( ! oCol.bVisible && nTrIn )
3112				{
3113					nTd.parentNode.removeChild( nTd );
3114				}
3115	
3116				if ( oCol.fnCreatedCell )
3117				{
3118					oCol.fnCreatedCell.call( oSettings.oInstance,
3119						nTd, _fnGetCellData( oSettings, iRow, i ), rowData, iRow, i
3120					);
3121				}
3122			}
3123	
3124			_fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow] );
3125		}
3126	
3127		// Remove once webkit bug 131819 and Chromium bug 365619 have been resolved
3128		// and deployed
3129		row.nTr.setAttribute( 'role', 'row' );
3130	}
3131	
3132	
3133	/**
3134	 * Add attributes to a row based on the special `DT_*` parameters in a data
3135	 * source object.
3136	 *  @param {object} settings DataTables settings object
3137	 *  @param {object} DataTables row object for the row to be modified
3138	 *  @memberof DataTable#oApi
3139	 */
3140	function _fnRowAttributes( settings, row )
3141	{
3142		var tr = row.nTr;
3143		var data = row._aData;
3144	
3145		if ( tr ) {
3146			var id = settings.rowIdFn( data );
3147	
3148			if ( id ) {
3149				tr.id = id;
3150			}
3151	
3152			if ( data.DT_RowClass ) {
3153				// Remove any classes added by DT_RowClass before
3154				var a = data.DT_RowClass.split(' ');
3155				row.__rowc = row.__rowc ?
3156					_unique( row.__rowc.concat( a ) ) :
3157					a;
3158	
3159				$(tr)
3160					.removeClass( row.__rowc.join(' ') )
3161					.addClass( data.DT_RowClass );
3162			}
3163	
3164			if ( data.DT_RowAttr ) {
3165				$(tr).attr( data.DT_RowAttr );
3166			}
3167	
3168			if ( data.DT_RowData ) {
3169				$(tr).data( data.DT_RowData );
3170			}
3171		}
3172	}
3173	
3174	
3175	/**
3176	 * Create the HTML header for the table
3177	 *  @param {object} oSettings dataTables settings object
3178	 *  @memberof DataTable#oApi
3179	 */
3180	function _fnBuildHead( oSettings )
3181	{
3182		var i, ien, cell, row, column;
3183		var thead = oSettings.nTHead;
3184		var tfoot = oSettings.nTFoot;
3185		var createHeader = $('th, td', thead).length === 0;
3186		var classes = oSettings.oClasses;
3187		var columns = oSettings.aoColumns;
3188	
3189		if ( createHeader ) {
3190			row = $('<tr/>').appendTo( thead );
3191		}
3192	
3193		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
3194			column = columns[i];
3195			cell = $( column.nTh ).addClass( column.sClass );
3196	
3197			if ( createHeader ) {
3198				cell.appendTo( row );
3199			}
3200	
3201			// 1.11 move into sorting
3202			if ( oSettings.oFeatures.bSort ) {
3203				cell.addClass( column.sSortingClass );
3204	
3205				if ( column.bSortable !== false ) {
3206					cell
3207						.attr( 'tabindex', oSettings.iTabIndex )
3208						.attr( 'aria-controls', oSettings.sTableId );
3209	
3210					_fnSortAttachListener( oSettings, column.nTh, i );
3211				}
3212			}
3213	
3214			if ( column.sTitle != cell[0].innerHTML ) {
3215				cell.html( column.sTitle );
3216			}
3217	
3218			_fnRenderer( oSettings, 'header' )(
3219				oSettings, cell, column, classes
3220			);
3221		}
3222	
3223		if ( createHeader ) {
3224			_fnDetectHeader( oSettings.aoHeader, thead );
3225		}
3226		
3227		/* ARIA role for the rows */
3228	 	$(thead).find('>tr').attr('role', 'row');
3229	
3230		/* Deal with the footer - add classes if required */
3231		$(thead).find('>tr>th, >tr>td').addClass( classes.sHeaderTH );
3232		$(tfoot).find('>tr>th, >tr>td').addClass( classes.sFooterTH );
3233	
3234		// Cache the footer cells. Note that we only take the cells from the first
3235		// row in the footer. If there is more than one row the user wants to
3236		// interact with, they need to use the table().foot() method. Note also this
3237		// allows cells to be used for multiple columns using colspan
3238		if ( tfoot !== null ) {
3239			var cells = oSettings.aoFooter[0];
3240	
3241			for ( i=0, ien=cells.length ; i<ien ; i++ ) {
3242				column = columns[i];
3243				column.nTf = cells[i].cell;
3244	
3245				if ( column.sClass ) {
3246					$(column.nTf).addClass( column.sClass );
3247				}
3248			}
3249		}
3250	}
3251	
3252	
3253	/**
3254	 * Draw the header (or footer) element based on the column visibility states. The
3255	 * methodology here is to use the layout array from _fnDetectHeader, modified for
3256	 * the instantaneous column visibility, to construct the new layout. The grid is
3257	 * traversed over cell at a time in a rows x columns grid fashion, although each
3258	 * cell insert can cover multiple elements in the grid - which is tracks using the
3259	 * aApplied array. Cell inserts in the grid will only occur where there isn't
3260	 * already a cell in that position.
3261	 *  @param {object} oSettings dataTables settings object
3262	 *  @param array {objects} aoSource Layout array from _fnDetectHeader
3263	 *  @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,
3264	 *  @memberof DataTable#oApi
3265	 */
3266	function _fnDrawHead( oSettings, aoSource, bIncludeHidden )
3267	{
3268		var i, iLen, j, jLen, k, kLen, n, nLocalTr;
3269		var aoLocal = [];
3270		var aApplied = [];
3271		var iColumns = oSettings.aoColumns.length;
3272		var iRowspan, iColspan;
3273	
3274		if ( ! aoSource )
3275		{
3276			return;
3277		}
3278	
3279		if (  bIncludeHidden === undefined )
3280		{
3281			bIncludeHidden = false;
3282		}
3283	
3284		/* Make a copy of the master layout array, but without the visible columns in it */
3285		for ( i=0, iLen=aoSource.length ; i<iLen ; i++ )
3286		{
3287			aoLocal[i] = aoSource[i].slice();
3288			aoLocal[i].nTr = aoSource[i].nTr;
3289	
3290			/* Remove any columns which are currently hidden */
3291			for ( j=iColumns-1 ; j>=0 ; j-- )
3292			{
3293				if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden )
3294				{
3295					aoLocal[i].splice( j, 1 );
3296				}
3297			}
3298	
3299			/* Prep the applied array - it needs an element for each row */
3300			aApplied.push( [] );
3301		}
3302	
3303		for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ )
3304		{
3305			nLocalTr = aoLocal[i].nTr;
3306	
3307			/* All cells are going to be replaced, so empty out the row */
3308			if ( nLocalTr )
3309			{
3310				while( (n = nLocalTr.firstChild) )
3311				{
3312					nLocalTr.removeChild( n );
3313				}
3314			}
3315	
3316			for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ )
3317			{
3318				iRowspan = 1;
3319				iColspan = 1;
3320	
3321				/* Check to see if there is already a cell (row/colspan) covering our target
3322				 * insert point. If there is, then there is nothing to do.
3323				 */
3324				if ( aApplied[i][j] === undefined )
3325				{
3326					nLocalTr.appendChild( aoLocal[i][j].cell );
3327					aApplied[i][j] = 1;
3328	
3329					/* Expand the cell to cover as many rows as needed */
3330					while ( aoLocal[i+iRowspan] !== undefined &&
3331					        aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell )
3332					{
3333						aApplied[i+iRowspan][j] = 1;
3334						iRowspan++;
3335					}
3336	
3337					/* Expand the cell to cover as many columns as needed */
3338					while ( aoLocal[i][j+iColspan] !== undefined &&
3339					        aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell )
3340					{
3341						/* Must update the applied array over the rows for the columns */
3342						for ( k=0 ; k<iRowspan ; k++ )
3343						{
3344							aApplied[i+k][j+iColspan] = 1;
3345						}
3346						iColspan++;
3347					}
3348	
3349					/* Do the actual expansion in the DOM */
3350					$(aoLocal[i][j].cell)
3351						.attr('rowspan', iRowspan)
3352						.attr('colspan', iColspan);
3353				}
3354			}
3355		}
3356	}
3357	
3358	
3359	/**
3360	 * Insert the required TR nodes into the table for display
3361	 *  @param {object} oSettings dataTables settings object
3362	 *  @memberof DataTable#oApi
3363	 */
3364	function _fnDraw( oSettings )
3365	{
3366		/* Provide a pre-callback function which can be used to cancel the draw is false is returned */
3367		var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] );
3368		if ( $.inArray( false, aPreDraw ) !== -1 )
3369		{
3370			_fnProcessingDisplay( oSettings, false );
3371			return;
3372		}
3373	
3374		var i, iLen, n;
3375		var anRows = [];
3376		var iRowCount = 0;
3377		var asStripeClasses = oSettings.asStripeClasses;
3378		var iStripes = asStripeClasses.length;
3379		var iOpenRows = oSettings.aoOpenRows.length;
3380		var oLang = oSettings.oLanguage;
3381		var iInitDisplayStart = oSettings.iInitDisplayStart;
3382		var bServerSide = _fnDataSource( oSettings ) == 'ssp';
3383		var aiDisplay = oSettings.aiDisplay;
3384	
3385		oSettings.bDrawing = true;
3386	
3387		/* Check and see if we have an initial draw position from state saving */
3388		if ( iInitDisplayStart !== undefined && iInitDisplayStart !== -1 )
3389		{
3390			oSettings._iDisplayStart = bServerSide ?
3391				iInitDisplayStart :
3392				iInitDisplayStart >= oSettings.fnRecordsDisplay() ?
3393					0 :
3394					iInitDisplayStart;
3395	
3396			oSettings.iInitDisplayStart = -1;
3397		}
3398	
3399		var iDisplayStart = oSettings._iDisplayStart;
3400		var iDisplayEnd = oSettings.fnDisplayEnd();
3401	
3402		/* Server-side processing draw intercept */
3403		if ( oSettings.bDeferLoading )
3404		{
3405			oSettings.bDeferLoading = false;
3406			oSettings.iDraw++;
3407			_fnProcessingDisplay( oSettings, false );
3408		}
3409		else if ( !bServerSide )
3410		{
3411			oSettings.iDraw++;
3412		}
3413		else if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) )
3414		{
3415			return;
3416		}
3417	
3418		if ( aiDisplay.length !== 0 )
3419		{
3420			var iStart = bServerSide ? 0 : iDisplayStart;
3421			var iEnd = bServerSide ? oSettings.aoData.length : iDisplayEnd;
3422	
3423			for ( var j=iStart ; j<iEnd ; j++ )
3424			{
3425				var iDataIndex = aiDisplay[j];
3426				var aoData = oSettings.aoData[ iDataIndex ];
3427				if ( aoData.nTr === null )
3428				{
3429					_fnCreateTr( oSettings, iDataIndex );
3430				}
3431	
3432				var nRow = aoData.nTr;
3433	
3434				/* Remove the old striping classes and then add the new one */
3435				if ( iStripes !== 0 )
3436				{
3437					var sStripe = asStripeClasses[ iRowCount % iStripes ];
3438					if ( aoData._sRowStripe != sStripe )
3439					{
3440						$(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe );
3441						aoData._sRowStripe = sStripe;
3442					}
3443				}
3444	
3445				// Row callback functions - might want to manipulate the row
3446				// iRowCount and j are not currently documented. Are they at all
3447				// useful?
3448				_fnCallbackFire( oSettings, 'aoRowCallback', null,
3449					[nRow, aoData._aData, iRowCount, j] );
3450	
3451				anRows.push( nRow );
3452				iRowCount++;
3453			}
3454		}
3455		else
3456		{
3457			/* Table is empty - create a row with an empty message in it */
3458			var sZero = oLang.sZeroRecords;
3459			if ( oSettings.iDraw == 1 &&  _fnDataSource( oSettings ) == 'ajax' )
3460			{
3461				sZero = oLang.sLoadingRecords;
3462			}
3463			else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 )
3464			{
3465				sZero = oLang.sEmptyTable;
3466			}
3467	
3468			anRows[ 0 ] = $( '<tr/>', { 'class': iStripes ? asStripeClasses[0] : '' } )
3469				.append( $('<td />', {
3470					'valign':  'top',
3471					'colSpan': _fnVisbleColumns( oSettings ),
3472					'class':   oSettings.oClasses.sRowEmpty
3473				} ).html( sZero ) )[0];
3474		}
3475	
3476		/* Header and footer callbacks */
3477		_fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0],
3478			_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
3479	
3480		_fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0],
3481			_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
3482	
3483		var body = $(oSettings.nTBody);
3484	
3485		body.children().detach();
3486		body.append( $(anRows) );
3487	
3488		/* Call all required callback functions for the end of a draw */
3489		_fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] );
3490	
3491		/* Draw is complete, sorting and filtering must be as well */
3492		oSettings.bSorted = false;
3493		oSettings.bFiltered = false;
3494		oSettings.bDrawing = false;
3495	}
3496	
3497	
3498	/**
3499	 * Redraw the table - taking account of the various features which are enabled
3500	 *  @param {object} oSettings dataTables settings object
3501	 *  @param {boolean} [holdPosition] Keep the current paging position. By default
3502	 *    the paging is reset to the first page
3503	 *  @memberof DataTable#oApi
3504	 */
3505	function _fnReDraw( settings, holdPosition )
3506	{
3507		var
3508			features = settings.oFeatures,
3509			sort     = features.bSort,
3510			filter   = features.bFilter;
3511	
3512		if ( sort ) {
3513			_fnSort( settings );
3514		}
3515	
3516		if ( filter ) {
3517			_fnFilterComplete( settings, settings.oPreviousSearch );
3518		}
3519		else {
3520			// No filtering, so we want to just use the display master
3521			settings.aiDisplay = settings.aiDisplayMaster.slice();
3522		}
3523	
3524		if ( holdPosition !== true ) {
3525			settings._iDisplayStart = 0;
3526		}
3527	
3528		// Let any modules know about the draw hold position state (used by
3529		// scrolling internally)
3530		settings._drawHold = holdPosition;
3531	
3532		_fnDraw( settings );
3533	
3534		settings._drawHold = false;
3535	}
3536	
3537	
3538	/**
3539	 * Add the options to the page HTML for the table
3540	 *  @param {object} oSettings dataTables settings object
3541	 *  @memberof DataTable#oApi
3542	 */
3543	function _fnAddOptionsHtml ( oSettings )
3544	{
3545		var classes = oSettings.oClasses;
3546		var table = $(oSettings.nTable);
3547		var holding = $('<div/>').insertBefore( table ); // Holding element for speed
3548		var features = oSettings.oFeatures;
3549	
3550		// All DataTables are wrapped in a div
3551		var insert = $('<div/>', {
3552			id:      oSettings.sTableId+'_wrapper',
3553			'class': classes.sWrapper + (oSettings.nTFoot ? '' : ' '+classes.sNoFooter)
3554		} );
3555	
3556		oSettings.nHolding = holding[0];
3557		oSettings.nTableWrapper = insert[0];
3558		oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;
3559	
3560		/* Loop over the user set positioning and place the elements as needed */
3561		var aDom = oSettings.sDom.split('');
3562		var featureNode, cOption, nNewNode, cNext, sAttr, j;
3563		for ( var i=0 ; i<aDom.length ; i++ )
3564		{
3565			featureNode = null;
3566			cOption = aDom[i];
3567	
3568			if ( cOption == '<' )
3569			{
3570				/* New container div */
3571				nNewNode = $('<div/>')[0];
3572	
3573				/* Check to see if we should append an id and/or a class name to the container */
3574				cNext = aDom[i+1];
3575				if ( cNext == "'" || cNext == '"' )
3576				{
3577					sAttr = "";
3578					j = 2;
3579					while ( aDom[i+j] != cNext )
3580					{
3581						sAttr += aDom[i+j];
3582						j++;
3583					}
3584	
3585					/* Replace jQuery UI constants @todo depreciated */
3586					if ( sAttr == "H" )
3587					{
3588						sAttr = classes.sJUIHeader;
3589					}
3590					else if ( sAttr == "F" )
3591					{
3592						sAttr = classes.sJUIFooter;
3593					}
3594	
3595					/* The attribute can be in the format of "#id.class", "#id" or "class" This logic
3596					 * breaks the string into parts and applies them as needed
3597					 */
3598					if ( sAttr.indexOf('.') != -1 )
3599					{
3600						var aSplit = sAttr.split('.');
3601						nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);
3602						nNewNode.className = aSplit[1];
3603					}
3604					else if ( sAttr.charAt(0) == "#" )
3605					{
3606						nNewNode.id = sAttr.substr(1, sAttr.length-1);
3607					}
3608					else
3609					{
3610						nNewNode.className = sAttr;
3611					}
3612	
3613					i += j; /* Move along the position array */
3614				}
3615	
3616				insert.append( nNewNode );
3617				insert = $(nNewNode);
3618			}
3619			else if ( cOption == '>' )
3620			{
3621				/* End container div */
3622				insert = insert.parent();
3623			}
3624			// @todo Move options into their own plugins?
3625			else if ( cOption == 'l' && features.bPaginate && features.bLengthChange )
3626			{
3627				/* Length */
3628				featureNode = _fnFeatureHtmlLength( oSettings );
3629			}
3630			else if ( cOption == 'f' && features.bFilter )
3631			{
3632				/* Filter */
3633				featureNode = _fnFeatureHtmlFilter( oSettings );
3634			}
3635			else if ( cOption == 'r' && features.bProcessing )
3636			{
3637				/* pRocessing */
3638				featureNode = _fnFeatureHtmlProcessing( oSettings );
3639			}
3640			else if ( cOption == 't' )
3641			{
3642				/* Table */
3643				featureNode = _fnFeatureHtmlTable( oSettings );
3644			}
3645			else if ( cOption ==  'i' && features.bInfo )
3646			{
3647				/* Info */
3648				featureNode = _fnFeatureHtmlInfo( oSettings );
3649			}
3650			else if ( cOption == 'p' && features.bPaginate )
3651			{
3652				/* Pagination */
3653				featureNode = _fnFeatureHtmlPaginate( oSettings );
3654			}
3655			else if ( DataTable.ext.feature.length !== 0 )
3656			{
3657				/* Plug-in features */
3658				var aoFeatures = DataTable.ext.feature;
3659				for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )
3660				{
3661					if ( cOption == aoFeatures[k].cFeature )
3662					{
3663						featureNode = aoFeatures[k].fnInit( oSettings );
3664						break;
3665					}
3666				}
3667			}
3668	
3669			/* Add to the 2D features array */
3670			if ( featureNode )
3671			{
3672				var aanFeatures = oSettings.aanFeatures;
3673	
3674				if ( ! aanFeatures[cOption] )
3675				{
3676					aanFeatures[cOption] = [];
3677				}
3678	
3679				aanFeatures[cOption].push( featureNode );
3680				insert.append( featureNode );
3681			}
3682		}
3683	
3684		/* Built our DOM structure - replace the holding div with what we want */
3685		holding.replaceWith( insert );
3686		oSettings.nHolding = null;
3687	}
3688	
3689	
3690	/**
3691	 * Use the DOM source to create up an array of header cells. The idea here is to
3692	 * create a layout grid (array) of rows x columns, which contains a reference
3693	 * to the cell that that point in the grid (regardless of col/rowspan), such that
3694	 * any column / row could be removed and the new grid constructed
3695	 *  @param array {object} aLayout Array to store the calculated layout in
3696	 *  @param {node} nThead The header/footer element for the table
3697	 *  @memberof DataTable#oApi
3698	 */
3699	function _fnDetectHeader ( aLayout, nThead )
3700	{
3701		var nTrs = $(nThead).children('tr');
3702		var nTr, nCell;
3703		var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan;
3704		var bUnique;
3705		var fnShiftCol = function ( a, i, j ) {
3706			var k = a[i];
3707	                while ( k[j] ) {
3708				j++;
3709			}
3710			return j;
3711		};
3712	
3713		aLayout.splice( 0, aLayout.length );
3714	
3715		/* We know how many rows there are in the layout - so prep it */
3716		for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
3717		{
3718			aLayout.push( [] );
3719		}
3720	
3721		/* Calculate a layout array */
3722		for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
3723		{
3724			nTr = nTrs[i];
3725			iColumn = 0;
3726	
3727			/* For every cell in the row... */
3728			nCell = nTr.firstChild;
3729			while ( nCell ) {
3730				if ( nCell.nodeName.toUpperCase() == "TD" ||
3731				     nCell.nodeName.toUpperCase() == "TH" )
3732				{
3733					/* Get the col and rowspan attributes from the DOM and sanitise them */
3734					iColspan = nCell.getAttribute('colspan') * 1;
3735					iRowspan = nCell.getAttribute('rowspan') * 1;
3736					iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan;
3737					iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan;
3738	
3739					/* There might be colspan cells already in this row, so shift our target
3740					 * accordingly
3741					 */
3742					iColShifted = fnShiftCol( aLayout, i, iColumn );
3743	
3744					/* Cache calculation for unique columns */
3745					bUnique = iColspan === 1 ? true : false;
3746	
3747					/* If there is col / rowspan, copy the information into the layout grid */
3748					for ( l=0 ; l<iColspan ; l++ )
3749					{
3750						for ( k=0 ; k<iRowspan ; k++ )
3751						{
3752							aLayout[i+k][iColShifted+l] = {
3753								"cell": nCell,
3754								"unique": bUnique
3755							};
3756							aLayout[i+k].nTr = nTr;
3757						}
3758					}
3759				}
3760				nCell = nCell.nextSibling;
3761			}
3762		}
3763	}
3764	
3765	
3766	/**
3767	 * Get an array of unique th elements, one for each column
3768	 *  @param {object} oSettings dataTables settings object
3769	 *  @param {node} nHeader automatically detect the layout from this node - optional
3770	 *  @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional
3771	 *  @returns array {node} aReturn list of unique th's
3772	 *  @memberof DataTable#oApi
3773	 */
3774	function _fnGetUniqueThs ( oSettings, nHeader, aLayout )
3775	{
3776		var aReturn = [];
3777		if ( !aLayout )
3778		{
3779			aLayout = oSettings.aoHeader;
3780			if ( nHeader )
3781			{
3782				aLayout = [];
3783				_fnDetectHeader( aLayout, nHeader );
3784			}
3785		}
3786	
3787		for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ )
3788		{
3789			for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ )
3790			{
3791				if ( aLayout[i][j].unique &&
3792					 (!aReturn[j] || !oSettings.bSortCellsTop) )
3793				{
3794					aReturn[j] = aLayout[i][j].cell;
3795				}
3796			}
3797		}
3798	
3799		return aReturn;
3800	}
3801	
3802	/**
3803	 * Create an Ajax call based on the table's settings, taking into account that
3804	 * parameters can have multiple forms, and backwards compatibility.
3805	 *
3806	 * @param {object} oSettings dataTables settings object
3807	 * @param {array} data Data to send to the server, required by
3808	 *     DataTables - may be augmented by developer callbacks
3809	 * @param {function} fn Callback function to run when data is obtained
3810	 */
3811	function _fnBuildAjax( oSettings, data, fn )
3812	{
3813		// Compatibility with 1.9-, allow fnServerData and event to manipulate
3814		_fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [data] );
3815	
3816		// Convert to object based for 1.10+ if using the old array scheme which can
3817		// come from server-side processing or serverParams
3818		if ( data && $.isArray(data) ) {
3819			var tmp = {};
3820			var rbracket = /(.*?)\[\]$/;
3821	
3822			$.each( data, function (key, val) {
3823				var match = val.name.match(rbracket);
3824	
3825				if ( match ) {
3826					// Support for arrays
3827					var name = match[0];
3828	
3829					if ( ! tmp[ name ] ) {
3830						tmp[ name ] = [];
3831					}
3832					tmp[ name ].push( val.value );
3833				}
3834				else {
3835					tmp[val.name] = val.value;
3836				}
3837			} );
3838			data = tmp;
3839		}
3840	
3841		var ajaxData;
3842		var ajax = oSettings.ajax;
3843		var instance = oSettings.oInstance;
3844		var callback = function ( json ) {
3845			_fnCallbackFire( oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR] );
3846			fn( json );
3847		};
3848	
3849		if ( $.isPlainObject( ajax ) && ajax.data )
3850		{
3851			ajaxData = ajax.data;
3852	
3853			var newData = $.isFunction( ajaxData ) ?
3854				ajaxData( data, oSettings ) :  // fn can manipulate data or return
3855				ajaxData;                      // an object object or array to merge
3856	
3857			// If the function returned something, use that alone
3858			data = $.isFunction( ajaxData ) && newData ?
3859				newData :
3860				$.extend( true, data, newData );
3861	
3862			// Remove the data property as we've resolved it already and don't want
3863			// jQuery to do it again (it is restored at the end of the function)
3864			delete ajax.data;
3865		}
3866	
3867		var baseAjax = {
3868			"data": data,
3869			"success": function (json) {
3870				var error = json.error || json.sError;
3871				if ( error ) {
3872					_fnLog( oSettings, 0, error );
3873				}
3874	
3875				oSettings.json = json;
3876				callback( json );
3877			},
3878			"dataType": "json",
3879			"cache": false,
3880			"type": oSettings.sServerMethod,
3881			"error": function (xhr, error, thrown) {
3882				var ret = _fnCallbackFire( oSettings, null, 'xhr', [oSettings, null, oSettings.jqXHR] );
3883	
3884				if ( $.inArray( true, ret ) === -1 ) {
3885					if ( error == "parsererror" ) {
3886						_fnLog( oSettings, 0, 'Invalid JSON response', 1 );
3887					}
3888					else if ( xhr.readyState === 4 ) {
3889						_fnLog( oSettings, 0, 'Ajax error', 7 );
3890					}
3891				}
3892	
3893				_fnProcessingDisplay( oSettings, false );
3894			}
3895		};
3896	
3897		// Store the data submitted for the API
3898		oSettings.oAjaxData = data;
3899	
3900		// Allow plug-ins and external processes to modify the data
3901		_fnCallbackFire( oSettings, null, 'preXhr', [oSettings, data] );
3902	
3903		if ( oSettings.fnServerData )
3904		{
3905			// DataTables 1.9- compatibility
3906			oSettings.fnServerData.call( instance,
3907				oSettings.sAjaxSource,
3908				$.map( data, function (val, key) { // Need to convert back to 1.9 trad format
3909					return { name: key, value: val };
3910				} ),
3911				callback,
3912				oSettings
3913			);
3914		}
3915		else if ( oSettings.sAjaxSource || typeof ajax === 'string' )
3916		{
3917			// DataTables 1.9- compatibility
3918			oSettings.jqXHR = $.ajax( $.extend( baseAjax, {
3919				url: ajax || oSettings.sAjaxSource
3920			} ) );
3921		}
3922		else if ( $.isFunction( ajax ) )
3923		{
3924			// Is a function - let the caller define what needs to be done
3925			oSettings.jqXHR = ajax.call( instance, data, callback, oSettings );
3926		}
3927		else
3928		{
3929			// Object to extend the base settings
3930			oSettings.jqXHR = $.ajax( $.extend( baseAjax, ajax ) );
3931	
3932			// Restore for next time around
3933			ajax.data = ajaxData;
3934		}
3935	}
3936	
3937	
3938	/**
3939	 * Update the table using an Ajax call
3940	 *  @param {object} settings dataTables settings object
3941	 *  @returns {boolean} Block the table drawing or not
3942	 *  @memberof DataTable#oApi
3943	 */
3944	function _fnAjaxUpdate( settings )
3945	{
3946		if ( settings.bAjaxDataGet ) {
3947			settings.iDraw++;
3948			_fnProcessingDisplay( settings, true );
3949	
3950			_fnBuildAjax(
3951				settings,
3952				_fnAjaxParameters( settings ),
3953				function(json) {
3954					_fnAjaxUpdateDraw( settings, json );
3955				}
3956			);
3957	
3958			return false;
3959		}
3960		return true;
3961	}
3962	
3963	
3964	/**
3965	 * Build up the parameters in an object needed for a server-side processing
3966	 * request. Note that this is basically done twice, is different ways - a modern
3967	 * method which is used by default in DataTables 1.10 which uses objects and
3968	 * arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if
3969	 * the sAjaxSource option is used in the initialisation, or the legacyAjax
3970	 * option is set.
3971	 *  @param {object} oSettings dataTables settings object
3972	 *  @returns {bool} block the table drawing or not
3973	 *  @memberof DataTable#oApi
3974	 */
3975	function _fnAjaxParameters( settings )
3976	{
3977		var
3978			columns = settings.aoColumns,
3979			columnCount = columns.length,
3980			features = settings.oFeatures,
3981			preSearch = settings.oPreviousSearch,
3982			preColSearch = settings.aoPreSearchCols,
3983			i, data = [], dataProp, column, columnSearch,
3984			sort = _fnSortFlatten( settings ),
3985			displayStart = settings._iDisplayStart,
3986			displayLength = features.bPaginate !== false ?
3987				settings._iDisplayLength :
3988				-1;
3989	
3990		var param = function ( name, value ) {
3991			data.push( { 'name': name, 'value': value } );
3992		};
3993	
3994		// DataTables 1.9- compatible method
3995		param( 'sEcho',          settings.iDraw );
3996		param( 'iColumns',       columnCount );
3997		param( 'sColumns',       _pluck( columns, 'sName' ).join(',') );
3998		param( 'iDisplayStart',  displayStart );
3999		param( 'iDisplayLength', displayLength );
4000	
4001		// DataTables 1.10+ method
4002		var d = {
4003			draw:    settings.iDraw,
4004			columns: [],
4005			order:   [],
4006			start:   displayStart,
4007			length:  displayLength,
4008			search:  {
4009				value: preSearch.sSearch,
4010				regex: preSearch.bRegex
4011			}
4012		};
4013	
4014		for ( i=0 ; i<columnCount ; i++ ) {
4015			column = columns[i];
4016			columnSearch = preColSearch[i];
4017			dataProp = typeof column.mData=="function" ? 'function' : column.mData ;
4018	
4019			d.columns.push( {
4020				data:       dataProp,
4021				name:       column.sName,
4022				searchable: column.bSearchable,
4023				orderable:  column.bSortable,
4024				search:     {
4025					value: columnSearch.sSearch,
4026					regex: columnSearch.bRegex
4027				}
4028			} );
4029	
4030			param( "mDataProp_"+i, dataProp );
4031	
4032			if ( features.bFilter ) {
4033				param( 'sSearch_'+i,     columnSearch.sSearch );
4034				param( 'bRegex_'+i,      columnSearch.bRegex );
4035				param( 'bSearchable_'+i, column.bSearchable );
4036			}
4037	
4038			if ( features.bSort ) {
4039				param( 'bSortable_'+i, column.bSortable );
4040			}
4041		}
4042	
4043		if ( features.bFilter ) {
4044			param( 'sSearch', preSearch.sSearch );
4045			param( 'bRegex', preSearch.bRegex );
4046		}
4047	
4048		if ( features.bSort ) {
4049			$.each( sort, function ( i, val ) {
4050				d.order.push( { column: val.col, dir: val.dir } );
4051	
4052				param( 'iSortCol_'+i, val.col );
4053				param( 'sSortDir_'+i, val.dir );
4054			} );
4055	
4056			param( 'iSortingCols', sort.length );
4057		}
4058	
4059		// If the legacy.ajax parameter is null, then we automatically decide which
4060		// form to use, based on sAjaxSource
4061		var legacy = DataTable.ext.legacy.ajax;
4062		if ( legacy === null ) {
4063			return settings.sAjaxSource ? data : d;
4064		}
4065	
4066		// Otherwise, if legacy has been specified then we use that to decide on the
4067		// form
4068		return legacy ? data : d;
4069	}
4070	
4071	
4072	/**
4073	 * Data the data from the server (nuking the old) and redraw the table
4074	 *  @param {object} oSettings dataTables settings object
4075	 *  @param {object} json json data return from the server.
4076	 *  @param {string} json.sEcho Tracking flag for DataTables to match requests
4077	 *  @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering
4078	 *  @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering
4079	 *  @param {array} json.aaData The data to display on this page
4080	 *  @param {string} [json.sColumns] Column ordering (sName, comma separated)
4081	 *  @memberof DataTable#oApi
4082	 */
4083	function _fnAjaxUpdateDraw ( settings, json )
4084	{
4085		// v1.10 uses camelCase variables, while 1.9 uses Hungarian notation.
4086		// Support both
4087		var compat = function ( old, modern ) {
4088			return json[old] !== undefined ? json[old] : json[modern];
4089		};
4090	
4091		var data = _fnAjaxDataSrc( settings, json );
4092		var draw            = compat( 'sEcho',                'draw' );
4093		var recordsTotal    = compat( 'iTotalRecords',        'recordsTotal' );
4094		var recordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' );
4095	
4096		if ( draw ) {
4097			// Protect against out of sequence returns
4098			if ( draw*1 < settings.iDraw ) {
4099				return;
4100			}
4101			settings.iDraw = draw * 1;
4102		}
4103	
4104		_fnClearTable( settings );
4105		settings._iRecordsTotal   = parseInt(recordsTotal, 10);
4106		settings._iRecordsDisplay = parseInt(recordsFiltered, 10);
4107	
4108		for ( var i=0, ien=data.length ; i<ien ; i++ ) {
4109			_fnAddData( settings, data[i] );
4110		}
4111		settings.aiDisplay = settings.aiDisplayMaster.slice();
4112	
4113		settings.bAjaxDataGet = false;
4114		_fnDraw( settings );
4115	
4116		if ( ! settings._bInitComplete ) {
4117			_fnInitComplete( settings, json );
4118		}
4119	
4120		settings.bAjaxDataGet = true;
4121		_fnProcessingDisplay( settings, false );
4122	}
4123	
4124	
4125	/**
4126	 * Get the data from the JSON data source to use for drawing a table. Using
4127	 * `_fnGetObjectDataFn` allows the data to be sourced from a property of the
4128	 * source object, or from a processing function.
4129	 *  @param {object} oSettings dataTables settings object
4130	 *  @param  {object} json Data source object / array from the server
4131	 *  @return {array} Array of data to use
4132	 */
4133	function _fnAjaxDataSrc ( oSettings, json )
4134	{
4135		var dataSrc = $.isPlainObject( oSettings.ajax ) && oSettings.ajax.dataSrc !== undefined ?
4136			oSettings.ajax.dataSrc :
4137			oSettings.sAjaxDataProp; // Compatibility with 1.9-.
4138	
4139		// Compatibility with 1.9-. In order to read from aaData, check if the
4140		// default has been changed, if not, check for aaData
4141		if ( dataSrc === 'data' ) {
4142			return json.aaData || json[dataSrc];
4143		}
4144	
4145		return dataSrc !== "" ?
4146			_fnGetObjectDataFn( dataSrc )( json ) :
4147			json;
4148	}
4149	
4150	/**
4151	 * Generate the node required for filtering text
4152	 *  @returns {node} Filter control element
4153	 *  @param {object} oSettings dataTables settings object
4154	 *  @memberof DataTable#oApi
4155	 */
4156	function _fnFeatureHtmlFilter ( settings )
4157	{
4158		var classes = settings.oClasses;
4159		var tableId = settings.sTableId;
4160		var language = settings.oLanguage;
4161		var previousSearch = settings.oPreviousSearch;
4162		var features = settings.aanFeatures;
4163		var input = '<input type="search" class="'+classes.sFilterInput+'"/>';
4164	
4165		var str = language.sSearch;
4166		str = str.match(/_INPUT_/) ?
4167			str.replace('_INPUT_', input) :
4168			str+input;
4169	
4170		var filter = $('<div/>', {
4171				'id': ! features.f ? tableId+'_filter' : null,
4172				'class': classes.sFilter
4173			} )
4174			.append( $('<label/>' ).append( str ) );
4175	
4176		var searchFn = function() {
4177			/* Update all other filter input elements for the new display */
4178			var n = features.f;
4179			var val = !this.value ? "" : this.value; // mental IE8 fix :-(
4180	
4181			/* Now do the filter */
4182			if ( val != previousSearch.sSearch ) {
4183				_fnFilterComplete( settings, {
4184					"sSearch": val,
4185					"bRegex": previousSearch.bRegex,
4186					"bSmart": previousSearch.bSmart ,
4187					"bCaseInsensitive": previousSearch.bCaseInsensitive
4188				} );
4189	
4190				// Need to redraw, without resorting
4191				settings._iDisplayStart = 0;
4192				_fnDraw( settings );
4193			}
4194		};
4195	
4196		var searchDelay = settings.searchDelay !== null ?
4197			settings.searchDelay :
4198			_fnDataSource( settings ) === 'ssp' ?
4199				400 :
4200				0;
4201	
4202		var jqFilter = $('input', filter)
4203			.val( previousSearch.sSearch )
4204			.attr( 'placeholder', language.sSearchPlaceholder )
4205			.bind(
4206				'keyup.DT search.DT input.DT paste.DT cut.DT',
4207				searchDelay ?
4208					_fnThrottle( searchFn, searchDelay ) :
4209					searchFn
4210			)
4211			.bind( 'keypress.DT', function(e) {
4212				/* Prevent form submission */
4213				if ( e.keyCode == 13 ) {
4214					return false;
4215				}
4216			} )
4217			.attr('aria-controls', tableId);
4218	
4219		// Update the input elements whenever the table is filtered
4220		$(settings.nTable).on( 'search.dt.DT', function ( ev, s ) {
4221			if ( settings === s ) {
4222				// IE9 throws an 'unknown error' if document.activeElement is used
4223				// inside an iframe or frame...
4224				try {
4225					if ( jqFilter[0] !== document.activeElement ) {
4226						jqFilter.val( previousSearch.sSearch );
4227					}
4228				}
4229				catch ( e ) {}
4230			}
4231		} );
4232	
4233		return filter[0];
4234	}
4235	
4236	
4237	/**
4238	 * Filter the table using both the global filter and column based filtering
4239	 *  @param {object} oSettings dataTables settings object
4240	 *  @param {object} oSearch search information
4241	 *  @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)
4242	 *  @memberof DataTable#oApi
4243	 */
4244	function _fnFilterComplete ( oSettings, oInput, iForce )
4245	{
4246		var oPrevSearch = oSettings.oPreviousSearch;
4247		var aoPrevSearch = oSettings.aoPreSearchCols;
4248		var fnSaveFilter = function ( oFilter ) {
4249			/* Save the filtering values */
4250			oPrevSearch.sSearch = oFilter.sSearch;
4251			oPrevSearch.bRegex = oFilter.bRegex;
4252			oPrevSearch.bSmart = oFilter.bSmart;
4253			oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive;
4254		};
4255		var fnRegex = function ( o ) {
4256			// Backwards compatibility with the bEscapeRegex option
4257			return o.bEscapeRegex !== undefined ? !o.bEscapeRegex : o.bRegex;
4258		};
4259	
4260		// Resolve any column types that are unknown due to addition or invalidation
4261		// @todo As per sort - can this be moved into an event handler?
4262		_fnColumnTypes( oSettings );
4263	
4264		/* In server-side processing all filtering is done by the server, so no point hanging around here */
4265		if ( _fnDataSource( oSettings ) != 'ssp' )
4266		{
4267			/* Global filter */
4268			_fnFilter( oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive );
4269			fnSaveFilter( oInput );
4270	
4271			/* Now do the individual column filter */
4272			for ( var i=0 ; i<aoPrevSearch.length ; i++ )
4273			{
4274				_fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, fnRegex(aoPrevSearch[i]),
4275					aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive );
4276			}
4277	
4278			/* Custom filtering */
4279			_fnFilterCustom( oSettings );
4280		}
4281		else
4282		{
4283			fnSaveFilter( oInput );
4284		}
4285	
4286		/* Tell the draw function we have been filtering */
4287		oSettings.bFiltered = true;
4288		_fnCallbackFire( oSettings, null, 'search', [oSettings] );
4289	}
4290	
4291	
4292	/**
4293	 * Apply custom filtering functions
4294	 *  @param {object} oSettings dataTables settings object
4295	 *  @memberof DataTable#oApi
4296	 */
4297	function _fnFilterCustom( settings )
4298	{
4299		var filters = DataTable.ext.search;
4300		var displayRows = settings.aiDisplay;
4301		var row, rowIdx;
4302	
4303		for ( var i=0, ien=filters.length ; i<ien ; i++ ) {
4304			var rows = [];
4305	
4306			// Loop over each row and see if it should be included
4307			for ( var j=0, jen=displayRows.length ; j<jen ; j++ ) {
4308				rowIdx = displayRows[ j ];
4309				row = settings.aoData[ rowIdx ];
4310	
4311				if ( filters[i]( settings, row._aFilterData, rowIdx, row._aData, j ) ) {
4312					rows.push( rowIdx );
4313				}
4314			}
4315	
4316			// So the array reference doesn't break set the results into the
4317			// existing array
4318			displayRows.length = 0;
4319			$.merge( displayRows, rows );
4320		}
4321	}
4322	
4323	
4324	/**
4325	 * Filter the table on a per-column basis
4326	 *  @param {object} oSettings dataTables settings object
4327	 *  @param {string} sInput string to filter on
4328	 *  @param {int} iColumn column to filter
4329	 *  @param {bool} bRegex treat search string as a regular expression or not
4330	 *  @param {bool} bSmart use smart filtering or not
4331	 *  @param {bool} bCaseInsensitive Do case insenstive matching or not
4332	 *  @memberof DataTable#oApi
4333	 */
4334	function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, caseInsensitive )
4335	{
4336		if ( searchStr === '' ) {
4337			return;
4338		}
4339	
4340		var data;
4341		var display = settings.aiDisplay;
4342		var rpSearch = _fnFilterCreateSearch( searchStr, regex, smart, caseInsensitive );
4343	
4344		for ( var i=display.length-1 ; i>=0 ; i-- ) {
4345			data = settings.aoData[ display[i] ]._aFilterData[ colIdx ];
4346	
4347			if ( ! rpSearch.test( data ) ) {
4348				display.splice( i, 1 );
4349			}
4350		}
4351	}
4352	
4353	
4354	/**
4355	 * Filter the data table based on user input and draw the table
4356	 *  @param {object} settings dataTables settings object
4357	 *  @param {string} input string to filter on
4358	 *  @param {int} force optional - force a research of the master array (1) or not (undefined or 0)
4359	 *  @param {bool} regex treat as a regular expression or not
4360	 *  @param {bool} smart perform smart filtering or not
4361	 *  @param {bool} caseInsensitive Do case insenstive matching or not
4362	 *  @memberof DataTable#oApi
4363	 */
4364	function _fnFilter( settings, input, force, regex, smart, caseInsensitive )
4365	{
4366		var rpSearch = _fnFilterCreateSearch( input, regex, smart, caseInsensitive );
4367		var prevSearch = settings.oPreviousSearch.sSearch;
4368		var displayMaster = settings.aiDisplayMaster;
4369		var display, invalidated, i;
4370	
4371		// Need to take account of custom filtering functions - always filter
4372		if ( DataTable.ext.search.length !== 0 ) {
4373			force = true;
4374		}
4375	
4376		// Check if any of the rows were invalidated
4377		invalidated = _fnFilterData( settings );
4378	
4379		// If the input is blank - we just want the full data set
4380		if ( input.length <= 0 ) {
4381			settings.aiDisplay = displayMaster.slice();
4382		}
4383		else {
4384			// New search - start from the master array
4385			if ( invalidated ||
4386				 force ||
4387				 prevSearch.length > input.length ||
4388				 input.indexOf(prevSearch) !== 0 ||
4389				 settings.bSorted // On resort, the display master needs to be
4390				                  // re-filtered since indexes will have changed
4391			) {
4392				settings.aiDisplay = displayMaster.slice();
4393			}
4394	
4395			// Search the display array
4396			display = settings.aiDisplay;
4397	
4398			for ( i=display.length-1 ; i>=0 ; i-- ) {
4399				if ( ! rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) {
4400					display.splice( i, 1 );
4401				}
4402			}
4403		}
4404	}
4405	
4406	
4407	/**
4408	 * Build a regular expression object suitable for searching a table
4409	 *  @param {string} sSearch string to search for
4410	 *  @param {bool} bRegex treat as a regular expression or not
4411	 *  @param {bool} bSmart perform smart filtering or not
4412	 *  @param {bool} bCaseInsensitive Do case insensitive matching or not
4413	 *  @returns {RegExp} constructed object
4414	 *  @memberof DataTable#oApi
4415	 */
4416	function _fnFilterCreateSearch( search, regex, smart, caseInsensitive )
4417	{
4418		search = regex ?
4419			search :
4420			_fnEscapeRegex( search );
4421		
4422		if ( smart ) {
4423			/* For smart filtering we want to allow the search to work regardless of
4424			 * word order. We also want double quoted text to be preserved, so word
4425			 * order is important - a la google. So this is what we want to
4426			 * generate:
4427			 * 
4428			 * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$
4429			 */
4430			var a = $.map( search.match( /"[^"]+"|[^ ]+/g ) || [''], function ( word ) {
4431				if ( word.charAt(0) === '"' ) {
4432					var m = word.match( /^"(.*)"$/ );
4433					word = m ? m[1] : word;
4434				}
4435	
4436				return word.replace('"', '');
4437			} );
4438	
4439			search = '^(?=.*?'+a.join( ')(?=.*?' )+').*$';
4440		}
4441	
4442		return new RegExp( search, caseInsensitive ? 'i' : '' );
4443	}
4444	
4445	
4446	/**
4447	 * Escape a string such that it can be used in a regular expression
4448	 *  @param {string} sVal string to escape
4449	 *  @returns {string} escaped string
4450	 *  @memberof DataTable#oApi
4451	 */
4452	var _fnEscapeRegex = DataTable.util.escapeRegex;
4453	
4454	var __filter_div = $('<div>')[0];
4455	var __filter_div_textContent = __filter_div.textContent !== undefined;
4456	
4457	// Update the filtering data for each row if needed (by invalidation or first run)
4458	function _fnFilterData ( settings )
4459	{
4460		var columns = settings.aoColumns;
4461		var column;
4462		var i, j, ien, jen, filterData, cellData, row;
4463		var fomatters = DataTable.ext.type.search;
4464		var wasInvalidated = false;
4465	
4466		for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
4467			row = settings.aoData[i];
4468	
4469			if ( ! row._aFilterData ) {
4470				filterData = [];
4471	
4472				for ( j=0, jen=columns.length ; j<jen ; j++ ) {
4473					column = columns[j];
4474	
4475					if ( column.bSearchable ) {
4476						cellData = _fnGetCellData( settings, i, j, 'filter' );
4477	
4478						if ( fomatters[ column.sType ] ) {
4479							cellData = fomatters[ column.sType ]( cellData );
4480						}
4481	
4482						// Search in DataTables 1.10 is string based. In 1.11 this
4483						// should be altered to also allow strict type checking.
4484						if ( cellData === null ) {
4485							cellData = '';
4486						}
4487	
4488						if ( typeof cellData !== 'string' && cellData.toString ) {
4489							cellData = cellData.toString();
4490						}
4491					}
4492					else {
4493						cellData = '';
4494					}
4495	
4496					// If it looks like there is an HTML entity in the string,
4497					// attempt to decode it so sorting works as expected. Note that
4498					// we could use a single line of jQuery to do this, but the DOM
4499					// method used here is much faster http://jsperf.com/html-decode
4500					if ( cellData.indexOf && cellData.indexOf('&') !== -1 ) {
4501						__filter_div.innerHTML = cellData;
4502						cellData = __filter_div_textContent ?
4503							__filter_div.textContent :
4504							__filter_div.innerText;
4505					}
4506	
4507					if ( cellData.replace ) {
4508						cellData = cellData.replace(/[\r\n]/g, '');
4509					}
4510	
4511					filterData.push( cellData );
4512				}
4513	
4514				row._aFilterData = filterData;
4515				row._sFilterRow = filterData.join('  ');
4516				wasInvalidated = true;
4517			}
4518		}
4519	
4520		return wasInvalidated;
4521	}
4522	
4523	
4524	/**
4525	 * Convert from the internal Hungarian notation to camelCase for external
4526	 * interaction
4527	 *  @param {object} obj Object to convert
4528	 *  @returns {object} Inverted object
4529	 *  @memberof DataTable#oApi
4530	 */
4531	function _fnSearchToCamel ( obj )
4532	{
4533		return {
4534			search:          obj.sSearch,
4535			smart:           obj.bSmart,
4536			regex:           obj.bRegex,
4537			caseInsensitive: obj.bCaseInsensitive
4538		};
4539	}
4540	
4541	
4542	
4543	/**
4544	 * Convert from camelCase notation to the internal Hungarian. We could use the
4545	 * Hungarian convert function here, but this is cleaner
4546	 *  @param {object} obj Object to convert
4547	 *  @returns {object} Inverted object
4548	 *  @memberof DataTable#oApi
4549	 */
4550	function _fnSearchToHung ( obj )
4551	{
4552		return {
4553			sSearch:          obj.search,
4554			bSmart:           obj.smart,
4555			bRegex:           obj.regex,
4556			bCaseInsensitive: obj.caseInsensitive
4557		};
4558	}
4559	
4560	/**
4561	 * Generate the node required for the info display
4562	 *  @param {object} oSettings dataTables settings object
4563	 *  @returns {node} Information element
4564	 *  @memberof DataTable#oApi
4565	 */
4566	function _fnFeatureHtmlInfo ( settings )
4567	{
4568		var
4569			tid = settings.sTableId,
4570			nodes = settings.aanFeatures.i,
4571			n = $('<div/>', {
4572				'class': settings.oClasses.sInfo,
4573				'id': ! nodes ? tid+'_info' : null
4574			} );
4575	
4576		if ( ! nodes ) {
4577			// Update display on each draw
4578			settings.aoDrawCallback.push( {
4579				"fn": _fnUpdateInfo,
4580				"sName": "information"
4581			} );
4582	
4583			n
4584				.attr( 'role', 'status' )
4585				.attr( 'aria-live', 'polite' );
4586	
4587			// Table is described by our info div
4588			$(settings.nTable).attr( 'aria-describedby', tid+'_info' );
4589		}
4590	
4591		return n[0];
4592	}
4593	
4594	
4595	/**
4596	 * Update the information elements in the display
4597	 *  @param {object} settings dataTables settings object
4598	 *  @memberof DataTable#oApi
4599	 */
4600	function _fnUpdateInfo ( settings )
4601	{
4602		/* Show information about the table */
4603		var nodes = settings.aanFeatures.i;
4604		if ( nodes.length === 0 ) {
4605			return;
4606		}
4607	
4608		var
4609			lang  = settings.oLanguage,
4610			start = settings._iDisplayStart+1,
4611			end   = settings.fnDisplayEnd(),
4612			max   = settings.fnRecordsTotal(),
4613			total = settings.fnRecordsDisplay(),
4614			out   = total ?
4615				lang.sInfo :
4616				lang.sInfoEmpty;
4617	
4618		if ( total !== max ) {
4619			/* Record set after filtering */
4620			out += ' ' + lang.sInfoFiltered;
4621		}
4622	
4623		// Convert the macros
4624		out += lang.sInfoPostFix;
4625		out = _fnInfoMacros( settings, out );
4626	
4627		var callback = lang.fnInfoCallback;
4628		if ( callback !== null ) {
4629			out = callback.call( settings.oInstance,
4630				settings, start, end, max, total, out
4631			);
4632		}
4633	
4634		$(nodes).html( out );
4635	}
4636	
4637	
4638	function _fnInfoMacros ( settings, str )
4639	{
4640		// When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
4641		// internally
4642		var
4643			formatter  = settings.fnFormatNumber,
4644			start      = settings._iDisplayStart+1,
4645			len        = settings._iDisplayLength,
4646			vis        = settings.fnRecordsDisplay(),
4647			all        = len === -1;
4648	
4649		return str.
4650			replace(/_START_/g, formatter.call( settings, start ) ).
4651			replace(/_END_/g,   formatter.call( settings, settings.fnDisplayEnd() ) ).
4652			replace(/_MAX_/g,   formatter.call( settings, settings.fnRecordsTotal() ) ).
4653			replace(/_TOTAL_/g, formatter.call( settings, vis ) ).
4654			replace(/_PAGE_/g,  formatter.call( settings, all ? 1 : Math.ceil( start / len ) ) ).
4655			replace(/_PAGES_/g, formatter.call( settings, all ? 1 : Math.ceil( vis / len ) ) );
4656	}
4657	
4658	
4659	
4660	/**
4661	 * Draw the table for the first time, adding all required features
4662	 *  @param {object} settings dataTables settings object
4663	 *  @memberof DataTable#oApi
4664	 */
4665	function _fnInitialise ( settings )
4666	{
4667		var i, iLen, iAjaxStart=settings.iInitDisplayStart;
4668		var columns = settings.aoColumns, column;
4669		var features = settings.oFeatures;
4670		var deferLoading = settings.bDeferLoading; // value modified by the draw
4671	
4672		/* Ensure that the table data is fully initialised */
4673		if ( ! settings.bInitialised ) {
4674			setTimeout( function(){ _fnInitialise( settings ); }, 200 );
4675			return;
4676		}
4677	
4678		/* Show the display HTML options */
4679		_fnAddOptionsHtml( settings );
4680	
4681		/* Build and draw the header / footer for the table */
4682		_fnBuildHead( settings );
4683		_fnDrawHead( settings, settings.aoHeader );
4684		_fnDrawHead( settings, settings.aoFooter );
4685	
4686		/* Okay to show that something is going on now */
4687		_fnProcessingDisplay( settings, true );
4688	
4689		/* Calculate sizes for columns */
4690		if ( features.bAutoWidth ) {
4691			_fnCalculateColumnWidths( settings );
4692		}
4693	
4694		for ( i=0, iLen=columns.length ; i<iLen ; i++ ) {
4695			column = columns[i];
4696	
4697			if ( column.sWidth ) {
4698				column.nTh.style.width = _fnStringToCss( column.sWidth );
4699			}
4700		}
4701	
4702		_fnCallbackFire( settings, null, 'preInit', [settings] );
4703	
4704		// If there is default sorting required - let's do it. The sort function
4705		// will do the drawing for us. Otherwise we draw the table regardless of the
4706		// Ajax source - this allows the table to look initialised for Ajax sourcing
4707		// data (show 'loading' message possibly)
4708		_fnReDraw( settings );
4709	
4710		// Server-side processing init complete is done by _fnAjaxUpdateDraw
4711		var dataSrc = _fnDataSource( settings );
4712		if ( dataSrc != 'ssp' || deferLoading ) {
4713			// if there is an ajax source load the data
4714			if ( dataSrc == 'ajax' ) {
4715				_fnBuildAjax( settings, [], function(json) {
4716					var aData = _fnAjaxDataSrc( settings, json );
4717	
4718					// Got the data - add it to the table
4719					for ( i=0 ; i<aData.length ; i++ ) {
4720						_fnAddData( settings, aData[i] );
4721					}
4722	
4723					// Reset the init display for cookie saving. We've already done
4724					// a filter, and therefore cleared it before. So we need to make
4725					// it appear 'fresh'
4726					settings.iInitDisplayStart = iAjaxStart;
4727	
4728					_fnReDraw( settings );
4729	
4730					_fnProcessingDisplay( settings, false );
4731					_fnInitComplete( settings, json );
4732				}, settings );
4733			}
4734			else {
4735				_fnProcessingDisplay( settings, false );
4736				_fnInitComplete( settings );
4737			}
4738		}
4739	}
4740	
4741	
4742	/**
4743	 * Draw the table for the first time, adding all required features
4744	 *  @param {object} oSettings dataTables settings object
4745	 *  @param {object} [json] JSON from the server that completed the table, if using Ajax source
4746	 *    with client-side processing (optional)
4747	 *  @memberof DataTable#oApi
4748	 */
4749	function _fnInitComplete ( settings, json )
4750	{
4751		settings._bInitComplete = true;
4752	
4753		// When data was added after the initialisation (data or Ajax) we need to
4754		// calculate the column sizing
4755		if ( json || settings.oInit.aaData ) {
4756			_fnAdjustColumnSizing( settings );
4757		}
4758	
4759		_fnCallbackFire( settings, null, 'plugin-init', [settings, json] );
4760		_fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] );
4761	}
4762	
4763	
4764	function _fnLengthChange ( settings, val )
4765	{
4766		var len = parseInt( val, 10 );
4767		settings._iDisplayLength = len;
4768	
4769		_fnLengthOverflow( settings );
4770	
4771		// Fire length change event
4772		_fnCallbackFire( settings, null, 'length', [settings, len] );
4773	}
4774	
4775	
4776	/**
4777	 * Generate the node required for user display length changing
4778	 *  @param {object} settings dataTables settings object
4779	 *  @returns {node} Display length feature node
4780	 *  @memberof DataTable#oApi
4781	 */
4782	function _fnFeatureHtmlLength ( settings )
4783	{
4784		var
4785			classes  = settings.oClasses,
4786			tableId  = settings.sTableId,
4787			menu     = settings.aLengthMenu,
4788			d2       = $.isArray( menu[0] ),
4789			lengths  = d2 ? menu[0] : menu,
4790			language = d2 ? menu[1] : menu;
4791	
4792		var select = $('<select/>', {
4793			'name':          tableId+'_length',
4794			'aria-controls': tableId,
4795			'class':         classes.sLengthSelect
4796		} );
4797	
4798		for ( var i=0, ien=lengths.length ; i<ien ; i++ ) {
4799			select[0][ i ] = new Option( language[i], lengths[i] );
4800		}
4801	
4802		var div = $('<div><label/></div>').addClass( classes.sLength );
4803		if ( ! settings.aanFeatures.l ) {
4804			div[0].id = tableId+'_length';
4805		}
4806	
4807		div.children().append(
4808			settings.oLanguage.sLengthMenu.replace( '_MENU_', select[0].outerHTML )
4809		);
4810	
4811		// Can't use `select` variable as user might provide their own and the
4812		// reference is broken by the use of outerHTML
4813		$('select', div)
4814			.val( settings._iDisplayLength )
4815			.bind( 'change.DT', function(e) {
4816				_fnLengthChange( settings, $(this).val() );
4817				_fnDraw( settings );
4818			} );
4819	
4820		// Update node value whenever anything changes the table's length
4821		$(settings.nTable).bind( 'length.dt.DT', function (e, s, len) {
4822			if ( settings === s ) {
4823				$('select', div).val( len );
4824			}
4825		} );
4826	
4827		return div[0];
4828	}
4829	
4830	
4831	
4832	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
4833	 * Note that most of the paging logic is done in
4834	 * DataTable.ext.pager
4835	 */
4836	
4837	/**
4838	 * Generate the node required for default pagination
4839	 *  @param {object} oSettings dataTables settings object
4840	 *  @returns {node} Pagination feature node
4841	 *  @memberof DataTable#oApi
4842	 */
4843	function _fnFeatureHtmlPaginate ( settings )
4844	{
4845		var
4846			type   = settings.sPaginationType,
4847			plugin = DataTable.ext.pager[ type ],
4848			modern = typeof plugin === 'function',
4849			redraw = function( settings ) {
4850				_fnDraw( settings );
4851			},
4852			node = $('<div/>').addClass( settings.oClasses.sPaging + type )[0],
4853			features = settings.aanFeatures;
4854	
4855		if ( ! modern ) {
4856			plugin.fnInit( settings, node, redraw );
4857		}
4858	
4859		/* Add a draw callback for the pagination on first instance, to update the paging display */
4860		if ( ! features.p )
4861		{
4862			node.id = settings.sTableId+'_paginate';
4863	
4864			settings.aoDrawCallback.push( {
4865				"fn": function( settings ) {
4866					if ( modern ) {
4867						var
4868							start      = settings._iDisplayStart,
4869							len        = settings._iDisplayLength,
4870							visRecords = settings.fnRecordsDisplay(),
4871							all        = len === -1,
4872							page = all ? 0 : Math.ceil( start / len ),
4873							pages = all ? 1 : Math.ceil( visRecords / len ),
4874							buttons = plugin(page, pages),
4875							i, ien;
4876	
4877						for ( i=0, ien=features.p.length ; i<ien ; i++ ) {
4878							_fnRenderer( settings, 'pageButton' )(
4879								settings, features.p[i], i, buttons, page, pages
4880							);
4881						}
4882					}
4883					else {
4884						plugin.fnUpdate( settings, redraw );
4885					}
4886				},
4887				"sName": "pagination"
4888			} );
4889		}
4890	
4891		return node;
4892	}
4893	
4894	
4895	/**
4896	 * Alter the display settings to change the page
4897	 *  @param {object} settings DataTables settings object
4898	 *  @param {string|int} action Paging action to take: "first", "previous",
4899	 *    "next" or "last" or page number to jump to (integer)
4900	 *  @param [bool] redraw Automatically draw the update or not
4901	 *  @returns {bool} true page has changed, false - no change
4902	 *  @memberof DataTable#oApi
4903	 */
4904	function _fnPageChange ( settings, action, redraw )
4905	{
4906		var
4907			start     = settings._iDisplayStart,
4908			len       = settings._iDisplayLength,
4909			records   = settings.fnRecordsDisplay();
4910	
4911		if ( records === 0 || len === -1 )
4912		{
4913			start = 0;
4914		}
4915		else if ( typeof action === "number" )
4916		{
4917			start = action * len;
4918	
4919			if ( start > records )
4920			{
4921				start = 0;
4922			}
4923		}
4924		else if ( action == "first" )
4925		{
4926			start = 0;
4927		}
4928		else if ( action == "previous" )
4929		{
4930			start = len >= 0 ?
4931				start - len :
4932				0;
4933	
4934			if ( start < 0 )
4935			{
4936			  start = 0;
4937			}
4938		}
4939		else if ( action == "next" )
4940		{
4941			if ( start + len < records )
4942			{
4943				start += len;
4944			}
4945		}
4946		else if ( action == "last" )
4947		{
4948			start = Math.floor( (records-1) / len) * len;
4949		}
4950		else
4951		{
4952			_fnLog( settings, 0, "Unknown paging action: "+action, 5 );
4953		}
4954	
4955		var changed = settings._iDisplayStart !== start;
4956		settings._iDisplayStart = start;
4957	
4958		if ( changed ) {
4959			_fnCallbackFire( settings, null, 'page', [settings] );
4960	
4961			if ( redraw ) {
4962				_fnDraw( settings );
4963			}
4964		}
4965	
4966		return changed;
4967	}
4968	
4969	
4970	
4971	/**
4972	 * Generate the node required for the processing node
4973	 *  @param {object} settings dataTables settings object
4974	 *  @returns {node} Processing element
4975	 *  @memberof DataTable#oApi
4976	 */
4977	function _fnFeatureHtmlProcessing ( settings )
4978	{
4979		return $('<div/>', {
4980				'id': ! settings.aanFeatures.r ? settings.sTableId+'_processing' : null,
4981				'class': settings.oClasses.sProcessing
4982			} )
4983			.html( settings.oLanguage.sProcessing )
4984			.insertBefore( settings.nTable )[0];
4985	}
4986	
4987	
4988	/**
4989	 * Display or hide the processing indicator
4990	 *  @param {object} settings dataTables settings object
4991	 *  @param {bool} show Show the processing indicator (true) or not (false)
4992	 *  @memberof DataTable#oApi
4993	 */
4994	function _fnProcessingDisplay ( settings, show )
4995	{
4996		if ( settings.oFeatures.bProcessing ) {
4997			$(settings.aanFeatures.r).css( 'display', show ? 'block' : 'none' );
4998		}
4999	
5000		_fnCallbackFire( settings, null, 'processing', [settings, show] );
5001	}
5002	
5003	/**
5004	 * Add any control elements for the table - specifically scrolling
5005	 *  @param {object} settings dataTables settings object
5006	 *  @returns {node} Node to add to the DOM
5007	 *  @memberof DataTable#oApi
5008	 */
5009	function _fnFeatureHtmlTable ( settings )
5010	{
5011		var table = $(settings.nTable);
5012	
5013		// Add the ARIA grid role to the table
5014		table.attr( 'role', 'grid' );
5015	
5016		// Scrolling from here on in
5017		var scroll = settings.oScroll;
5018	
5019		if ( scroll.sX === '' && scroll.sY === '' ) {
5020			return settings.nTable;
5021		}
5022	
5023		var scrollX = scroll.sX;
5024		var scrollY = scroll.sY;
5025		var classes = settings.oClasses;
5026		var caption = table.children('caption');
5027		var captionSide = caption.length ? caption[0]._captionSide : null;
5028		var headerClone = $( table[0].cloneNode(false) );
5029		var footerClone = $( table[0].cloneNode(false) );
5030		var footer = table.children('tfoot');
5031		var _div = '<div/>';
5032		var size = function ( s ) {
5033			return !s ? null : _fnStringToCss( s );
5034		};
5035	
5036		if ( ! footer.length ) {
5037			footer = null;
5038		}
5039	
5040		/*
5041		 * The HTML structure that we want to generate in this function is:
5042		 *  div - scroller
5043		 *    div - scroll head
5044		 *      div - scroll head inner
5045		 *        table - scroll head table
5046		 *          thead - thead
5047		 *    div - scroll body
5048		 *      table - table (master table)
5049		 *        thead - thead clone for sizing
5050		 *        tbody - tbody
5051		 *    div - scroll foot
5052		 *      div - scroll foot inner
5053		 *        table - scroll foot table
5054		 *          tfoot - tfoot
5055		 */
5056		var scroller = $( _div, { 'class': classes.sScrollWrapper } )
5057			.append(
5058				$(_div, { 'class': classes.sScrollHead } )
5059					.css( {
5060						overflow: 'hidden',
5061						position: 'relative',
5062						border: 0,
5063						width: scrollX ? size(scrollX) : '100%'
5064					} )
5065					.append(
5066						$(_div, { 'class': classes.sScrollHeadInner } )
5067							.css( {
5068								'box-sizing': 'content-box',
5069								width: scroll.sXInner || '100%'
5070							} )
5071							.append(
5072								headerClone
5073									.removeAttr('id')
5074									.css( 'margin-left', 0 )
5075									.append( captionSide === 'top' ? caption : null )
5076									.append(
5077										table.children('thead')
5078									)
5079							)
5080					)
5081			)
5082			.append(
5083				$(_div, { 'class': classes.sScrollBody } )
5084					.css( {
5085						position: 'relative',
5086						overflow: 'auto',
5087						width: size( scrollX )
5088					} )
5089					.append( table )
5090			);
5091	
5092		if ( footer ) {
5093			scroller.append(
5094				$(_div, { 'class': classes.sScrollFoot } )
5095					.css( {
5096						overflow: 'hidden',
5097						border: 0,
5098						width: scrollX ? size(scrollX) : '100%'
5099					} )
5100					.append(
5101						$(_div, { 'class': classes.sScrollFootInner } )
5102							.append(
5103								footerClone
5104									.removeAttr('id')
5105									.css( 'margin-left', 0 )
5106									.append( captionSide === 'bottom' ? caption : null )
5107									.append(
5108										table.children('tfoot')
5109									)
5110							)
5111					)
5112			);
5113		}
5114	
5115		var children = scroller.children();
5116		var scrollHead = children[0];
5117		var scrollBody = children[1];
5118		var scrollFoot = footer ? children[2] : null;
5119	
5120		// When the body is scrolled, then we also want to scroll the headers
5121		if ( scrollX ) {
5122			$(scrollBody).on( 'scroll.DT', function (e) {
5123				var scrollLeft = this.scrollLeft;
5124	
5125				scrollHead.scrollLeft = scrollLeft;
5126	
5127				if ( footer ) {
5128					scrollFoot.scrollLeft = scrollLeft;
5129				}
5130			} );
5131		}
5132	
5133		$(scrollBody).css(
5134			scrollY && scroll.bCollapse ? 'max-height' : 'height', 
5135			scrollY
5136		);
5137	
5138		settings.nScrollHead = scrollHead;
5139		settings.nScrollBody = scrollBody;
5140		settings.nScrollFoot = scrollFoot;
5141	
5142		// On redraw - align columns
5143		settings.aoDrawCallback.push( {
5144			"fn": _fnScrollDraw,
5145			"sName": "scrolling"
5146		} );
5147	
5148		return scroller[0];
5149	}
5150	
5151	
5152	
5153	/**
5154	 * Update the header, footer and body tables for resizing - i.e. column
5155	 * alignment.
5156	 *
5157	 * Welcome to the most horrible function DataTables. The process that this
5158	 * function follows is basically:
5159	 *   1. Re-create the table inside the scrolling div
5160	 *   2. Take live measurements from the DOM
5161	 *   3. Apply the measurements to align the columns
5162	 *   4. Clean up
5163	 *
5164	 *  @param {object} settings dataTables settings object
5165	 *  @memberof DataTable#oApi
5166	 */
5167	function _fnScrollDraw ( settings )
5168	{
5169		// Given that this is such a monster function, a lot of variables are use
5170		// to try and keep the minimised size as small as possible
5171		var
5172			scroll         = settings.oScroll,
5173			scrollX        = scroll.sX,
5174			scrollXInner   = scroll.sXInner,
5175			scrollY        = scroll.sY,
5176			barWidth       = scroll.iBarWidth,
5177			divHeader      = $(settings.nScrollHead),
5178			divHeaderStyle = divHeader[0].style,
5179			divHeaderInner = divHeader.children('div'),
5180			divHeaderInnerStyle = divHeaderInner[0].style,
5181			divHeaderTable = divHeaderInner.children('table'),
5182			divBodyEl      = settings.nScrollBody,
5183			divBody        = $(divBodyEl),
5184			divBodyStyle   = divBodyEl.style,
5185			divFooter      = $(settings.nScrollFoot),
5186			divFooterInner = divFooter.children('div'),
5187			divFooterTable = divFooterInner.children('table'),
5188			header         = $(settings.nTHead),
5189			table          = $(settings.nTable),
5190			tableEl        = table[0],
5191			tableStyle     = tableEl.style,
5192			footer         = settings.nTFoot ? $(settings.nTFoot) : null,
5193			browser        = settings.oBrowser,
5194			ie67           = browser.bScrollOversize,
5195			dtHeaderCells  = _pluck( settings.aoColumns, 'nTh' ),
5196			headerTrgEls, footerTrgEls,
5197			headerSrcEls, footerSrcEls,
5198			headerCopy, footerCopy,
5199			headerWidths=[], footerWidths=[],
5200			headerContent=[], footerContent=[],
5201			idx, correction, sanityWidth,
5202			zeroOut = function(nSizer) {
5203				var style = nSizer.style;
5204				style.paddingTop = "0";
5205				style.paddingBottom = "0";
5206				style.borderTopWidth = "0";
5207				style.borderBottomWidth = "0";
5208				style.height = 0;
5209			};
5210	
5211		// If the scrollbar visibility has changed from the last draw, we need to
5212		// adjust the column sizes as the table width will have changed to account
5213		// for the scrollbar
5214		var scrollBarVis = divBodyEl.scrollHeight > divBodyEl.clientHeight;
5215		
5216		if ( settings.scrollBarVis !== scrollBarVis && settings.scrollBarVis !== undefined ) {
5217			settings.scrollBarVis = scrollBarVis;
5218			_fnAdjustColumnSizing( settings );
5219			return; // adjust column sizing will call this function again
5220		}
5221		else {
5222			settings.scrollBarVis = scrollBarVis;
5223		}
5224	
5225		/*
5226		 * 1. Re-create the table inside the scrolling div
5227		 */
5228	
5229		// Remove the old minimised thead and tfoot elements in the inner table
5230		table.children('thead, tfoot').remove();
5231	
5232		if ( footer ) {
5233			footerCopy = footer.clone().prependTo( table );
5234			footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized
5235			footerSrcEls = footerCopy.find('tr');
5236		}
5237	
5238		// Clone the current header and footer elements and then place it into the inner table
5239		headerCopy = header.clone().prependTo( table );
5240		headerTrgEls = header.find('tr'); // original header is in its own table
5241		headerSrcEls = headerCopy.find('tr');
5242		headerCopy.find('th, td').removeAttr('tabindex');
5243	
5244	
5245		/*
5246		 * 2. Take live measurements from the DOM - do not alter the DOM itself!
5247		 */
5248	
5249		// Remove old sizing and apply the calculated column widths
5250		// Get the unique column headers in the newly created (cloned) header. We want to apply the
5251		// calculated sizes to this header
5252		if ( ! scrollX )
5253		{
5254			divBodyStyle.width = '100%';
5255			divHeader[0].style.width = '100%';
5256		}
5257	
5258		$.each( _fnGetUniqueThs( settings, headerCopy ), function ( i, el ) {
5259			idx = _fnVisibleToColumnIndex( settings, i );
5260			el.style.width = settings.aoColumns[idx].sWidth;
5261		} );
5262	
5263		if ( footer ) {
5264			_fnApplyToChildren( function(n) {
5265				n.style.width = "";
5266			}, footerSrcEls );
5267		}
5268	
5269		// Size the table as a whole
5270		sanityWidth = table.outerWidth();
5271		if ( scrollX === "" ) {
5272			// No x scrolling
5273			tableStyle.width = "100%";
5274	
5275			// IE7 will make the width of the table when 100% include the scrollbar
5276			// - which is shouldn't. When there is a scrollbar we need to take this
5277			// into account.
5278			if ( ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight ||
5279				divBody.css('overflow-y') == "scroll")
5280			) {
5281				tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth);
5282			}
5283	
5284			// Recalculate the sanity width
5285			sanityWidth = table.outerWidth();
5286		}
5287		else if ( scrollXInner !== "" ) {
5288			// legacy x scroll inner has been given - use it
5289			tableStyle.width = _fnStringToCss(scrollXInner);
5290	
5291			// Recalculate the sanity width
5292			sanityWidth = table.outerWidth();
5293		}
5294	
5295		// Hidden header should have zero height, so remove padding and borders. Then
5296		// set the width based on the real headers
5297	
5298		// Apply all styles in one pass
5299		_fnApplyToChildren( zeroOut, headerSrcEls );
5300	
5301		// Read all widths in next pass
5302		_fnApplyToChildren( function(nSizer) {
5303			headerContent.push( nSizer.innerHTML );
5304			headerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
5305		}, headerSrcEls );
5306	
5307		// Apply all widths in final pass
5308		_fnApplyToChildren( function(nToSize, i) {
5309			// Only apply widths to the DataTables detected header cells - this
5310			// prevents complex headers from having contradictory sizes applied
5311			if ( $.inArray( nToSize, dtHeaderCells ) !== -1 ) {
5312				nToSize.style.width = headerWidths[i];
5313			}
5314		}, headerTrgEls );
5315	
5316		$(headerSrcEls).height(0);
5317	
5318		/* Same again with the footer if we have one */
5319		if ( footer )
5320		{
5321			_fnApplyToChildren( zeroOut, footerSrcEls );
5322	
5323			_fnApplyToChildren( function(nSizer) {
5324				footerContent.push( nSizer.innerHTML );
5325				footerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
5326			}, footerSrcEls );
5327	
5328			_fnApplyToChildren( function(nToSize, i) {
5329				nToSize.style.width = footerWidths[i];
5330			}, footerTrgEls );
5331	
5332			$(footerSrcEls).height(0);
5333		}
5334	
5335	
5336		/*
5337		 * 3. Apply the measurements
5338		 */
5339	
5340		// "Hide" the header and footer that we used for the sizing. We need to keep
5341		// the content of the cell so that the width applied to the header and body
5342		// both match, but we want to hide it completely. We want to also fix their
5343		// width to what they currently are
5344		_fnApplyToChildren( function(nSizer, i) {
5345			nSizer.innerHTML = '<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+headerContent[i]+'</div>';
5346			nSizer.style.width = headerWidths[i];
5347		}, headerSrcEls );
5348	
5349		if ( footer )
5350		{
5351			_fnApplyToChildren( function(nSizer, i) {
5352				nSizer.innerHTML = '<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+footerContent[i]+'</div>';
5353				nSizer.style.width = footerWidths[i];
5354			}, footerSrcEls );
5355		}
5356	
5357		// Sanity check that the table is of a sensible width. If not then we are going to get
5358		// misalignment - try to prevent this by not allowing the table to shrink below its min width
5359		if ( table.outerWidth() < sanityWidth )
5360		{
5361			// The min width depends upon if we have a vertical scrollbar visible or not */
5362			correction = ((divBodyEl.scrollHeight > divBodyEl.offsetHeight ||
5363				divBody.css('overflow-y') == "scroll")) ?
5364					sanityWidth+barWidth :
5365					sanityWidth;
5366	
5367			// IE6/7 are a law unto themselves...
5368			if ( ie67 && (divBodyEl.scrollHeight >
5369				divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll")
5370			) {
5371				tableStyle.width = _fnStringToCss( correction-barWidth );
5372			}
5373	
5374			// And give the user a warning that we've stopped the table getting too small
5375			if ( scrollX === "" || scrollXInner !== "" ) {
5376				_fnLog( settings, 1, 'Possible column misalignment', 6 );
5377			}
5378		}
5379		else
5380		{
5381			correction = '100%';
5382		}
5383	
5384		// Apply to the container elements
5385		divBodyStyle.width = _fnStringToCss( correction );
5386		divHeaderStyle.width = _fnStringToCss( correction );
5387	
5388		if ( footer ) {
5389			settings.nScrollFoot.style.width = _fnStringToCss( correction );
5390		}
5391	
5392	
5393		/*
5394		 * 4. Clean up
5395		 */
5396		if ( ! scrollY ) {
5397			/* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
5398			 * the scrollbar height from the visible display, rather than adding it on. We need to
5399			 * set the height in order to sort this. Don't want to do it in any other browsers.
5400			 */
5401			if ( ie67 ) {
5402				divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+barWidth );
5403			}
5404		}
5405	
5406		/* Finally set the width's of the header and footer tables */
5407		var iOuterWidth = table.outerWidth();
5408		divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth );
5409		divHeaderInnerStyle.width = _fnStringToCss( iOuterWidth );
5410	
5411		// Figure out if there are scrollbar present - if so then we need a the header and footer to
5412		// provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
5413		var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll";
5414		var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' );
5415		divHeaderInnerStyle[ padding ] = bScrolling ? barWidth+"px" : "0px";
5416	
5417		if ( footer ) {
5418			divFooterTable[0].style.width = _fnStringToCss( iOuterWidth );
5419			divFooterInner[0].style.width = _fnStringToCss( iOuterWidth );
5420			divFooterInner[0].style[padding] = bScrolling ? barWidth+"px" : "0px";
5421		}
5422	
5423		// Correct DOM ordering for colgroup - comes before the thead
5424		table.children('colgroup').insertBefore( table.children('thead') );
5425	
5426		/* Adjust the position of the header in case we loose the y-scrollbar */
5427		divBody.scroll();
5428	
5429		// If sorting or filtering has occurred, jump the scrolling back to the top
5430		// only if we aren't holding the position
5431		if ( (settings.bSorted || settings.bFiltered) && ! settings._drawHold ) {
5432			divBodyEl.scrollTop = 0;
5433		}
5434	}
5435	
5436	
5437	
5438	/**
5439	 * Apply a given function to the display child nodes of an element array (typically
5440	 * TD children of TR rows
5441	 *  @param {function} fn Method to apply to the objects
5442	 *  @param array {nodes} an1 List of elements to look through for display children
5443	 *  @param array {nodes} an2 Another list (identical structure to the first) - optional
5444	 *  @memberof DataTable#oApi
5445	 */
5446	function _fnApplyToChildren( fn, an1, an2 )
5447	{
5448		var index=0, i=0, iLen=an1.length;
5449		var nNode1, nNode2;
5450	
5451		while ( i < iLen ) {
5452			nNode1 = an1[i].firstChild;
5453			nNode2 = an2 ? an2[i].firstChild : null;
5454	
5455			while ( nNode1 ) {
5456				if ( nNode1.nodeType === 1 ) {
5457					if ( an2 ) {
5458						fn( nNode1, nNode2, index );
5459					}
5460					else {
5461						fn( nNode1, index );
5462					}
5463	
5464					index++;
5465				}
5466	
5467				nNode1 = nNode1.nextSibling;
5468				nNode2 = an2 ? nNode2.nextSibling : null;
5469			}
5470	
5471			i++;
5472		}
5473	}
5474	
5475	
5476	
5477	var __re_html_remove = /<.*?>/g;
5478	
5479	
5480	/**
5481	 * Calculate the width of columns for the table
5482	 *  @param {object} oSettings dataTables settings object
5483	 *  @memberof DataTable#oApi
5484	 */
5485	function _fnCalculateColumnWidths ( oSettings )
5486	{
5487		var
5488			table = oSettings.nTable,
5489			columns = oSettings.aoColumns,
5490			scroll = oSettings.oScroll,
5491			scrollY = scroll.sY,
5492			scrollX = scroll.sX,
5493			scrollXInner = scroll.sXInner,
5494			columnCount = columns.length,
5495			visibleColumns = _fnGetColumns( oSettings, 'bVisible' ),
5496			headerCells = $('th', oSettings.nTHead),
5497			tableWidthAttr = table.getAttribute('width'), // from DOM element
5498			tableContainer = table.parentNode,
5499			userInputs = false,
5500			i, column, columnIdx, width, outerWidth,
5501			browser = oSettings.oBrowser,
5502			ie67 = browser.bScrollOversize;
5503	
5504		var styleWidth = table.style.width;
5505		if ( styleWidth && styleWidth.indexOf('%') !== -1 ) {
5506			tableWidthAttr = styleWidth;
5507		}
5508	
5509		/* Convert any user input sizes into pixel sizes */
5510		for ( i=0 ; i<visibleColumns.length ; i++ ) {
5511			column = columns[ visibleColumns[i] ];
5512	
5513			if ( column.sWidth !== null ) {
5514				column.sWidth = _fnConvertToWidth( column.sWidthOrig, tableContainer );
5515	
5516				userInputs = true;
5517			}
5518		}
5519	
5520		/* If the number of columns in the DOM equals the number that we have to
5521		 * process in DataTables, then we can use the offsets that are created by
5522		 * the web- browser. No custom sizes can be set in order for this to happen,
5523		 * nor scrolling used
5524		 */
5525		if ( ie67 || ! userInputs && ! scrollX && ! scrollY &&
5526		     columnCount == _fnVisbleColumns( oSettings ) &&
5527		     columnCount == headerCells.length
5528		) {
5529			for ( i=0 ; i<columnCount ; i++ ) {
5530				var colIdx = _fnVisibleToColumnIndex( oSettings, i );
5531	
5532				if ( colIdx !== null ) {
5533					columns[ colIdx ].sWidth = _fnStringToCss( headerCells.eq(i).width() );
5534				}
5535			}
5536		}
5537		else
5538		{
5539			// Otherwise construct a single row, worst case, table with the widest
5540			// node in the data, assign any user defined widths, then insert it into
5541			// the DOM and allow the browser to do all the hard work of calculating
5542			// table widths
5543			var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table
5544				.css( 'visibility', 'hidden' )
5545				.removeAttr( 'id' );
5546	
5547			// Clean up the table body
5548			tmpTable.find('tbody tr').remove();
5549			var tr = $('<tr/>').appendTo( tmpTable.find('tbody') );
5550	
5551			// Clone the table header and footer - we can't use the header / footer
5552			// from the cloned table, since if scrolling is active, the table's
5553			// real header and footer are contained in different table tags
5554			tmpTable.find('thead, tfoot').remove();
5555			tmpTable
5556				.append( $(oSettings.nTHead).clone() )
5557				.append( $(oSettings.nTFoot).clone() );
5558	
5559			// Remove any assigned widths from the footer (from scrolling)
5560			tmpTable.find('tfoot th, tfoot td').css('width', '');
5561	
5562			// Apply custom sizing to the cloned header
5563			headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] );
5564	
5565			for ( i=0 ; i<visibleColumns.length ; i++ ) {
5566				column = columns[ visibleColumns[i] ];
5567	
5568				headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ?
5569					_fnStringToCss( column.sWidthOrig ) :
5570					'';
5571	
5572				// For scrollX we need to force the column width otherwise the
5573				// browser will collapse it. If this width is smaller than the
5574				// width the column requires, then it will have no effect
5575				if ( column.sWidthOrig && scrollX ) {
5576					$( headerCells[i] ).append( $('<div/>').css( {
5577						width: column.sWidthOrig,
5578						margin: 0,
5579						padding: 0,
5580						border: 0,
5581						height: 1
5582					} ) );
5583				}
5584			}
5585	
5586			// Find the widest cell for each column and put it into the table
5587			if ( oSettings.aoData.length ) {
5588				for ( i=0 ; i<visibleColumns.length ; i++ ) {
5589					columnIdx = visibleColumns[i];
5590					column = columns[ columnIdx ];
5591	
5592					$( _fnGetWidestNode( oSettings, columnIdx ) )
5593						.clone( false )
5594						.append( column.sContentPadding )
5595						.appendTo( tr );
5596				}
5597			}
5598	
5599			// Tidy the temporary table - remove name attributes so there aren't
5600			// duplicated in the dom (radio elements for example)
5601			$('[name]', tmpTable).removeAttr('name');
5602	
5603			// Table has been built, attach to the document so we can work with it.
5604			// A holding element is used, positioned at the top of the container
5605			// with minimal height, so it has no effect on if the container scrolls
5606			// or not. Otherwise it might trigger scrolling when it actually isn't
5607			// needed
5608			var holder = $('<div/>').css( scrollX || scrollY ?
5609					{
5610						position: 'absolute',
5611						top: 0,
5612						left: 0,
5613						height: 1,
5614						right: 0,
5615						overflow: 'hidden'
5616					} :
5617					{}
5618				)
5619				.append( tmpTable )
5620				.appendTo( tableContainer );
5621	
5622			// When scrolling (X or Y) we want to set the width of the table as 
5623			// appropriate. However, when not scrolling leave the table width as it
5624			// is. This results in slightly different, but I think correct behaviour
5625			if ( scrollX && scrollXInner ) {
5626				tmpTable.width( scrollXInner );
5627			}
5628			else if ( scrollX ) {
5629				tmpTable.css( 'width', 'auto' );
5630				tmpTable.removeAttr('width');
5631	
5632				// If there is no width attribute or style, then allow the table to
5633				// collapse
5634				if ( tmpTable.width() < tableContainer.clientWidth && tableWidthAttr ) {
5635					tmpTable.width( tableContainer.clientWidth );
5636				}
5637			}
5638			else if ( scrollY ) {
5639				tmpTable.width( tableContainer.clientWidth );
5640			}
5641			else if ( tableWidthAttr ) {
5642				tmpTable.width( tableWidthAttr );
5643			}
5644	
5645			// Get the width of each column in the constructed table - we need to
5646			// know the inner width (so it can be assigned to the other table's
5647			// cells) and the outer width so we can calculate the full width of the
5648			// table. This is safe since DataTables requires a unique cell for each
5649			// column, but if ever a header can span multiple columns, this will
5650			// need to be modified.
5651			var total = 0;
5652			for ( i=0 ; i<visibleColumns.length ; i++ ) {
5653				var cell = $(headerCells[i]);
5654				var border = cell.outerWidth() - cell.width();
5655	
5656				// Use getBounding... where possible (not IE8-) because it can give
5657				// sub-pixel accuracy, which we then want to round up!
5658				var bounding = browser.bBounding ?
5659					Math.ceil( headerCells[i].getBoundingClientRect().width ) :
5660					cell.outerWidth();
5661	
5662				// Total is tracked to remove any sub-pixel errors as the outerWidth
5663				// of the table might not equal the total given here (IE!).
5664				total += bounding;
5665	
5666				// Width for each column to use
5667				columns[ visibleColumns[i] ].sWidth = _fnStringToCss( bounding - border );
5668			}
5669	
5670			table.style.width = _fnStringToCss( total );
5671	
5672			// Finished with the table - ditch it
5673			holder.remove();
5674		}
5675	
5676		// If there is a width attr, we want to attach an event listener which
5677		// allows the table sizing to automatically adjust when the window is
5678		// resized. Use the width attr rather than CSS, since we can't know if the
5679		// CSS is a relative value or absolute - DOM read is always px.
5680		if ( tableWidthAttr ) {
5681			table.style.width = _fnStringToCss( tableWidthAttr );
5682		}
5683	
5684		if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) {
5685			var bindResize = function () {
5686				$(window).bind('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {
5687					_fnAdjustColumnSizing( oSettings );
5688				} ) );
5689			};
5690	
5691			// IE6/7 will crash if we bind a resize event handler on page load.
5692			// To be removed in 1.11 which drops IE6/7 support
5693			if ( ie67 ) {
5694				setTimeout( bindResize, 1000 );
5695			}
5696			else {
5697				bindResize();
5698			}
5699	
5700			oSettings._reszEvt = true;
5701		}
5702	}
5703	
5704	
5705	/**
5706	 * Throttle the calls to a function. Arguments and context are maintained for
5707	 * the throttled function
5708	 *  @param {function} fn Function to be called
5709	 *  @param {int} [freq=200] call frequency in mS
5710	 *  @returns {function} wrapped function
5711	 *  @memberof DataTable#oApi
5712	 */
5713	var _fnThrottle = DataTable.util.throttle;
5714	
5715	
5716	/**
5717	 * Convert a CSS unit width to pixels (e.g. 2em)
5718	 *  @param {string} width width to be converted
5719	 *  @param {node} parent parent to get the with for (required for relative widths) - optional
5720	 *  @returns {int} width in pixels
5721	 *  @memberof DataTable#oApi
5722	 */
5723	function _fnConvertToWidth ( width, parent )
5724	{
5725		if ( ! width ) {
5726			return 0;
5727		}
5728	
5729		var n = $('<div/>')
5730			.css( 'width', _fnStringToCss( width ) )
5731			.appendTo( parent || document.body );
5732	
5733		var val = n[0].offsetWidth;
5734		n.remove();
5735	
5736		return val;
5737	}
5738	
5739	
5740	/**
5741	 * Get the widest node
5742	 *  @param {object} settings dataTables settings object
5743	 *  @param {int} colIdx column of interest
5744	 *  @returns {node} widest table node
5745	 *  @memberof DataTable#oApi
5746	 */
5747	function _fnGetWidestNode( settings, colIdx )
5748	{
5749		var idx = _fnGetMaxLenString( settings, colIdx );
5750		if ( idx < 0 ) {
5751			return null;
5752		}
5753	
5754		var data = settings.aoData[ idx ];
5755		return ! data.nTr ? // Might not have been created when deferred rendering
5756			$('<td/>').html( _fnGetCellData( settings, idx, colIdx, 'display' ) )[0] :
5757			data.anCells[ colIdx ];
5758	}
5759	
5760	
5761	/**
5762	 * Get the maximum strlen for each data column
5763	 *  @param {object} settings dataTables settings object
5764	 *  @param {int} colIdx column of interest
5765	 *  @returns {string} max string length for each column
5766	 *  @memberof DataTable#oApi
5767	 */
5768	function _fnGetMaxLenString( settings, colIdx )
5769	{
5770		var s, max=-1, maxIdx = -1;
5771	
5772		for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
5773			s = _fnGetCellData( settings, i, colIdx, 'display' )+'';
5774			s = s.replace( __re_html_remove, '' );
5775			s = s.replace( /&nbsp;/g, ' ' );
5776	
5777			if ( s.length > max ) {
5778				max = s.length;
5779				maxIdx = i;
5780			}
5781		}
5782	
5783		return maxIdx;
5784	}
5785	
5786	
5787	/**
5788	 * Append a CSS unit (only if required) to a string
5789	 *  @param {string} value to css-ify
5790	 *  @returns {string} value with css unit
5791	 *  @memberof DataTable#oApi
5792	 */
5793	function _fnStringToCss( s )
5794	{
5795		if ( s === null ) {
5796			return '0px';
5797		}
5798	
5799		if ( typeof s == 'number' ) {
5800			return s < 0 ?
5801				'0px' :
5802				s+'px';
5803		}
5804	
5805		// Check it has a unit character already
5806		return s.match(/\d$/) ?
5807			s+'px' :
5808			s;
5809	}
5810	
5811	
5812	
5813	function _fnSortFlatten ( settings )
5814	{
5815		var
5816			i, iLen, k, kLen,
5817			aSort = [],
5818			aiOrig = [],
5819			aoColumns = settings.aoColumns,
5820			aDataSort, iCol, sType, srcCol,
5821			fixed = settings.aaSortingFixed,
5822			fixedObj = $.isPlainObject( fixed ),
5823			nestedSort = [],
5824			add = function ( a ) {
5825				if ( a.length && ! $.isArray( a[0] ) ) {
5826					// 1D array
5827					nestedSort.push( a );
5828				}
5829				else {
5830					// 2D array
5831					$.merge( nestedSort, a );
5832				}
5833			};
5834	
5835		// Build the sort array, with pre-fix and post-fix options if they have been
5836		// specified
5837		if ( $.isArray( fixed ) ) {
5838			add( fixed );
5839		}
5840	
5841		if ( fixedObj && fixed.pre ) {
5842			add( fixed.pre );
5843		}
5844	
5845		add( settings.aaSorting );
5846	
5847		if (fixedObj && fixed.post ) {
5848			add( fixed.post );
5849		}
5850	
5851		for ( i=0 ; i<nestedSort.length ; i++ )
5852		{
5853			srcCol = nestedSort[i][0];
5854			aDataSort = aoColumns[ srcCol ].aDataSort;
5855	
5856			for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ )
5857			{
5858				iCol = aDataSort[k];
5859				sType = aoColumns[ iCol ].sType || 'string';
5860	
5861				if ( nestedSort[i]._idx === undefined ) {
5862					nestedSort[i]._idx = $.inArray( nestedSort[i][1], aoColumns[iCol].asSorting );
5863				}
5864	
5865				aSort.push( {
5866					src:       srcCol,
5867					col:       iCol,
5868					dir:       nestedSort[i][1],
5869					index:     nestedSort[i]._idx,
5870					type:      sType,
5871					formatter: DataTable.ext.type.order[ sType+"-pre" ]
5872				} );
5873			}
5874		}
5875	
5876		return aSort;
5877	}
5878	
5879	/**
5880	 * Change the order of the table
5881	 *  @param {object} oSettings dataTables settings object
5882	 *  @memberof DataTable#oApi
5883	 *  @todo This really needs split up!
5884	 */
5885	function _fnSort ( oSettings )
5886	{
5887		var
5888			i, ien, iLen, j, jLen, k, kLen,
5889			sDataType, nTh,
5890			aiOrig = [],
5891			oExtSort = DataTable.ext.type.order,
5892			aoData = oSettings.aoData,
5893			aoColumns = oSettings.aoColumns,
5894			aDataSort, data, iCol, sType, oSort,
5895			formatters = 0,
5896			sortCol,
5897			displayMaster = oSettings.aiDisplayMaster,
5898			aSort;
5899	
5900		// Resolve any column types that are unknown due to addition or invalidation
5901		// @todo Can this be moved into a 'data-ready' handler which is called when
5902		//   data is going to be used in the table?
5903		_fnColumnTypes( oSettings );
5904	
5905		aSort = _fnSortFlatten( oSettings );
5906	
5907		for ( i=0, ien=aSort.length ; i<ien ; i++ ) {
5908			sortCol = aSort[i];
5909	
5910			// Track if we can use the fast sort algorithm
5911			if ( sortCol.formatter ) {
5912				formatters++;
5913			}
5914	
5915			// Load the data needed for the sort, for each cell
5916			_fnSortData( oSettings, sortCol.col );
5917		}
5918	
5919		/* No sorting required if server-side or no sorting array */
5920		if ( _fnDataSource( oSettings ) != 'ssp' && aSort.length !== 0 )
5921		{
5922			// Create a value - key array of the current row positions such that we can use their
5923			// current position during the sort, if values match, in order to perform stable sorting
5924			for ( i=0, iLen=displayMaster.length ; i<iLen ; i++ ) {
5925				aiOrig[ displayMaster[i] ] = i;
5926			}
5927	
5928			/* Do the sort - here we want multi-column sorting based on a given data source (column)
5929			 * and sorting function (from oSort) in a certain direction. It's reasonably complex to
5930			 * follow on it's own, but this is what we want (example two column sorting):
5931			 *  fnLocalSorting = function(a,b){
5932			 *    var iTest;
5933			 *    iTest = oSort['string-asc']('data11', 'data12');
5934			 *      if (iTest !== 0)
5935			 *        return iTest;
5936			 *    iTest = oSort['numeric-desc']('data21', 'data22');
5937			 *    if (iTest !== 0)
5938			 *      return iTest;
5939			 *    return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
5940			 *  }
5941			 * Basically we have a test for each sorting column, if the data in that column is equal,
5942			 * test the next column. If all columns match, then we use a numeric sort on the row
5943			 * positions in the original data array to provide a stable sort.
5944			 *
5945			 * Note - I know it seems excessive to have two sorting methods, but the first is around
5946			 * 15% faster, so the second is only maintained for backwards compatibility with sorting
5947			 * methods which do not have a pre-sort formatting function.
5948			 */
5949			if ( formatters === aSort.length ) {
5950				// All sort types have formatting functions
5951				displayMaster.sort( function ( a, b ) {
5952					var
5953						x, y, k, test, sort,
5954						len=aSort.length,
5955						dataA = aoData[a]._aSortData,
5956						dataB = aoData[b]._aSortData;
5957	
5958					for ( k=0 ; k<len ; k++ ) {
5959						sort = aSort[k];
5960	
5961						x = dataA[ sort.col ];
5962						y = dataB[ sort.col ];
5963	
5964						test = x<y ? -1 : x>y ? 1 : 0;
5965						if ( test !== 0 ) {
5966							return sort.dir === 'asc' ? test : -test;
5967						}
5968					}
5969	
5970					x = aiOrig[a];
5971					y = aiOrig[b];
5972					return x<y ? -1 : x>y ? 1 : 0;
5973				} );
5974			}
5975			else {
5976				// Depreciated - remove in 1.11 (providing a plug-in option)
5977				// Not all sort types have formatting methods, so we have to call their sorting
5978				// methods.
5979				displayMaster.sort( function ( a, b ) {
5980					var
5981						x, y, k, l, test, sort, fn,
5982						len=aSort.length,
5983						dataA = aoData[a]._aSortData,
5984						dataB = aoData[b]._aSortData;
5985	
5986					for ( k=0 ; k<len ; k++ ) {
5987						sort = aSort[k];
5988	
5989						x = dataA[ sort.col ];
5990						y = dataB[ sort.col ];
5991	
5992						fn = oExtSort[ sort.type+"-"+sort.dir ] || oExtSort[ "string-"+sort.dir ];
5993						test = fn( x, y );
5994						if ( test !== 0 ) {
5995							return test;
5996						}
5997					}
5998	
5999					x = aiOrig[a];
6000					y = aiOrig[b];
6001					return x<y ? -1 : x>y ? 1 : 0;
6002				} );
6003			}
6004		}
6005	
6006		/* Tell the draw function that we have sorted the data */
6007		oSettings.bSorted = true;
6008	}
6009	
6010	
6011	function _fnSortAria ( settings )
6012	{
6013		var label;
6014		var nextSort;
6015		var columns = settings.aoColumns;
6016		var aSort = _fnSortFlatten( settings );
6017		var oAria = settings.oLanguage.oAria;
6018	
6019		// ARIA attributes - need to loop all columns, to update all (removing old
6020		// attributes as needed)
6021		for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
6022		{
6023			var col = columns[i];
6024			var asSorting = col.asSorting;
6025			var sTitle = col.sTitle.replace( /<.*?>/g, "" );
6026			var th = col.nTh;
6027	
6028			// IE7 is throwing an error when setting these properties with jQuery's
6029			// attr() and removeAttr() methods...
6030			th.removeAttribute('aria-sort');
6031	
6032			/* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
6033			if ( col.bSortable ) {
6034				if ( aSort.length > 0 && aSort[0].col == i ) {
6035					th.setAttribute('aria-sort', aSort[0].dir=="asc" ? "ascending" : "descending" );
6036					nextSort = asSorting[ aSort[0].index+1 ] || asSorting[0];
6037				}
6038				else {
6039					nextSort = asSorting[0];
6040				}
6041	
6042				label = sTitle + ( nextSort === "asc" ?
6043					oAria.sSortAscending :
6044					oAria.sSortDescending
6045				);
6046			}
6047			else {
6048				label = sTitle;
6049			}
6050	
6051			th.setAttribute('aria-label', label);
6052		}
6053	}
6054	
6055	
6056	/**
6057	 * Function to run on user sort request
6058	 *  @param {object} settings dataTables settings object
6059	 *  @param {node} attachTo node to attach the handler to
6060	 *  @param {int} colIdx column sorting index
6061	 *  @param {boolean} [append=false] Append the requested sort to the existing
6062	 *    sort if true (i.e. multi-column sort)
6063	 *  @param {function} [callback] callback function
6064	 *  @memberof DataTable#oApi
6065	 */
6066	function _fnSortListener ( settings, colIdx, append, callback )
6067	{
6068		var col = settings.aoColumns[ colIdx ];
6069		var sorting = settings.aaSorting;
6070		var asSorting = col.asSorting;
6071		var nextSortIdx;
6072		var next = function ( a, overflow ) {
6073			var idx = a._idx;
6074			if ( idx === undefined ) {
6075				idx = $.inArray( a[1], asSorting );
6076			}
6077	
6078			return idx+1 < asSorting.length ?
6079				idx+1 :
6080				overflow ?
6081					null :
6082					0;
6083		};
6084	
6085		// Convert to 2D array if needed
6086		if ( typeof sorting[0] === 'number' ) {
6087			sorting = settings.aaSorting = [ sorting ];
6088		}
6089	
6090		// If appending the sort then we are multi-column sorting
6091		if ( append && settings.oFeatures.bSortMulti ) {
6092			// Are we already doing some kind of sort on this column?
6093			var sortIdx = $.inArray( colIdx, _pluck(sorting, '0') );
6094	
6095			if ( sortIdx !== -1 ) {
6096				// Yes, modify the sort
6097				nextSortIdx = next( sorting[sortIdx], true );
6098	
6099				if ( nextSortIdx === null && sorting.length === 1 ) {
6100					nextSortIdx = 0; // can't remove sorting completely
6101				}
6102	
6103				if ( nextSortIdx === null ) {
6104					sorting.splice( sortIdx, 1 );
6105				}
6106				else {
6107					sorting[sortIdx][1] = asSorting[ nextSortIdx ];
6108					sorting[sortIdx]._idx = nextSortIdx;
6109				}
6110			}
6111			else {
6112				// No sort on this column yet
6113				sorting.push( [ colIdx, asSorting[0], 0 ] );
6114				sorting[sorting.length-1]._idx = 0;
6115			}
6116		}
6117		else if ( sorting.length && sorting[0][0] == colIdx ) {
6118			// Single column - already sorting on this column, modify the sort
6119			nextSortIdx = next( sorting[0] );
6120	
6121			sorting.length = 1;
6122			sorting[0][1] = asSorting[ nextSortIdx ];
6123			sorting[0]._idx = nextSortIdx;
6124		}
6125		else {
6126			// Single column - sort only on this column
6127			sorting.length = 0;
6128			sorting.push( [ colIdx, asSorting[0] ] );
6129			sorting[0]._idx = 0;
6130		}
6131	
6132		// Run the sort by calling a full redraw
6133		_fnReDraw( settings );
6134	
6135		// callback used for async user interaction
6136		if ( typeof callback == 'function' ) {
6137			callback( settings );
6138		}
6139	}
6140	
6141	
6142	/**
6143	 * Attach a sort handler (click) to a node
6144	 *  @param {object} settings dataTables settings object
6145	 *  @param {node} attachTo node to attach the handler to
6146	 *  @param {int} colIdx column sorting index
6147	 *  @param {function} [callback] callback function
6148	 *  @memberof DataTable#oApi
6149	 */
6150	function _fnSortAttachListener ( settings, attachTo, colIdx, callback )
6151	{
6152		var col = settings.aoColumns[ colIdx ];
6153	
6154		_fnBindAction( attachTo, {}, function (e) {
6155			/* If the column is not sortable - don't to anything */
6156			if ( col.bSortable === false ) {
6157				return;
6158			}
6159	
6160			// If processing is enabled use a timeout to allow the processing
6161			// display to be shown - otherwise to it synchronously
6162			if ( settings.oFeatures.bProcessing ) {
6163				_fnProcessingDisplay( settings, true );
6164	
6165				setTimeout( function() {
6166					_fnSortListener( settings, colIdx, e.shiftKey, callback );
6167	
6168					// In server-side processing, the draw callback will remove the
6169					// processing display
6170					if ( _fnDataSource( settings ) !== 'ssp' ) {
6171						_fnProcessingDisplay( settings, false );
6172					}
6173				}, 0 );
6174			}
6175			else {
6176				_fnSortListener( settings, colIdx, e.shiftKey, callback );
6177			}
6178		} );
6179	}
6180	
6181	
6182	/**
6183	 * Set the sorting classes on table's body, Note: it is safe to call this function
6184	 * when bSort and bSortClasses are false
6185	 *  @param {object} oSettings dataTables settings object
6186	 *  @memberof DataTable#oApi
6187	 */
6188	function _fnSortingClasses( settings )
6189	{
6190		var oldSort = settings.aLastSort;
6191		var sortClass = settings.oClasses.sSortColumn;
6192		var sort = _fnSortFlatten( settings );
6193		var features = settings.oFeatures;
6194		var i, ien, colIdx;
6195	
6196		if ( features.bSort && features.bSortClasses ) {
6197			// Remove old sorting classes
6198			for ( i=0, ien=oldSort.length ; i<ien ; i++ ) {
6199				colIdx = oldSort[i].src;
6200	
6201				// Remove column sorting
6202				$( _pluck( settings.aoData, 'anCells', colIdx ) )
6203					.removeClass( sortClass + (i<2 ? i+1 : 3) );
6204			}
6205	
6206			// Add new column sorting
6207			for ( i=0, ien=sort.length ; i<ien ; i++ ) {
6208				colIdx = sort[i].src;
6209	
6210				$( _pluck( settings.aoData, 'anCells', colIdx ) )
6211					.addClass( sortClass + (i<2 ? i+1 : 3) );
6212			}
6213		}
6214	
6215		settings.aLastSort = sort;
6216	}
6217	
6218	
6219	// Get the data to sort a column, be it from cache, fresh (populating the
6220	// cache), or from a sort formatter
6221	function _fnSortData( settings, idx )
6222	{
6223		// Custom sorting function - provided by the sort data type
6224		var column = settings.aoColumns[ idx ];
6225		var customSort = DataTable.ext.order[ column.sSortDataType ];
6226		var customData;
6227	
6228		if ( customSort ) {
6229			customData = customSort.call( settings.oInstance, settings, idx,
6230				_fnColumnIndexToVisible( settings, idx )
6231			);
6232		}
6233	
6234		// Use / populate cache
6235		var row, cellData;
6236		var formatter = DataTable.ext.type.order[ column.sType+"-pre" ];
6237	
6238		for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
6239			row = settings.aoData[i];
6240	
6241			if ( ! row._aSortData ) {
6242				row._aSortData = [];
6243			}
6244	
6245			if ( ! row._aSortData[idx] || customSort ) {
6246				cellData = customSort ?
6247					customData[i] : // If there was a custom sort function, use data from there
6248					_fnGetCellData( settings, i, idx, 'sort' );
6249	
6250				row._aSortData[ idx ] = formatter ?
6251					formatter( cellData ) :
6252					cellData;
6253			}
6254		}
6255	}
6256	
6257	
6258	
6259	/**
6260	 * Save the state of a table
6261	 *  @param {object} oSettings dataTables settings object
6262	 *  @memberof DataTable#oApi
6263	 */
6264	function _fnSaveState ( settings )
6265	{
6266		if ( !settings.oFeatures.bStateSave || settings.bDestroying )
6267		{
6268			return;
6269		}
6270	
6271		/* Store the interesting variables */
6272		var state = {
6273			time:    +new Date(),
6274			start:   settings._iDisplayStart,
6275			length:  settings._iDisplayLength,
6276			order:   $.extend( true, [], settings.aaSorting ),
6277			search:  _fnSearchToCamel( settings.oPreviousSearch ),
6278			columns: $.map( settings.aoColumns, function ( col, i ) {
6279				return {
6280					visible: col.bVisible,
6281					search: _fnSearchToCamel( settings.aoPreSearchCols[i] )
6282				};
6283			} )
6284		};
6285	
6286		_fnCallbackFire( settings, "aoStateSaveParams", 'stateSaveParams', [settings, state] );
6287	
6288		settings.oSavedState = state;
6289		settings.fnStateSaveCallback.call( settings.oInstance, settings, state );
6290	}
6291	
6292	
6293	/**
6294	 * Attempt to load a saved table state
6295	 *  @param {object} oSettings dataTables settings object
6296	 *  @param {object} oInit DataTables init object so we can override settings
6297	 *  @memberof DataTable#oApi
6298	 */
6299	function _fnLoadState ( settings, oInit )
6300	{
6301		var i, ien;
6302		var columns = settings.aoColumns;
6303	
6304		if ( ! settings.oFeatures.bStateSave ) {
6305			return;
6306		}
6307	
6308		var state = settings.fnStateLoadCallback.call( settings.oInstance, settings );
6309		if ( ! state || ! state.time ) {
6310			return;
6311		}
6312	
6313		/* Allow custom and plug-in manipulation functions to alter the saved data set and
6314		 * cancelling of loading by returning false
6315		 */
6316		var abStateLoad = _fnCallbackFire( settings, 'aoStateLoadParams', 'stateLoadParams', [settings, state] );
6317		if ( $.inArray( false, abStateLoad ) !== -1 ) {
6318			return;
6319		}
6320	
6321		/* Reject old data */
6322		var duration = settings.iStateDuration;
6323		if ( duration > 0 && state.time < +new Date() - (duration*1000) ) {
6324			return;
6325		}
6326	
6327		// Number of columns have changed - all bets are off, no restore of settings
6328		if ( columns.length !== state.columns.length ) {
6329			return;
6330		}
6331	
6332		// Store the saved state so it might be accessed at any time
6333		settings.oLoadedState = $.extend( true, {}, state );
6334	
6335		// Restore key features - todo - for 1.11 this needs to be done by
6336		// subscribed events
6337		if ( state.start !== undefined ) {
6338			settings._iDisplayStart    = state.start;
6339			settings.iInitDisplayStart = state.start;
6340		}
6341		if ( state.length !== undefined ) {
6342			settings._iDisplayLength   = state.length;
6343		}
6344	
6345		// Order
6346		if ( state.order !== undefined ) {
6347			settings.aaSorting = [];
6348			$.each( state.order, function ( i, col ) {
6349				settings.aaSorting.push( col[0] >= columns.length ?
6350					[ 0, col[1] ] :
6351					col
6352				);
6353			} );
6354		}
6355	
6356		// Search
6357		if ( state.search !== undefined ) {
6358			$.extend( settings.oPreviousSearch, _fnSearchToHung( state.search ) );
6359		}
6360	
6361		// Columns
6362		for ( i=0, ien=state.columns.length ; i<ien ; i++ ) {
6363			var col = state.columns[i];
6364	
6365			// Visibility
6366			if ( col.visible !== undefined ) {
6367				columns[i].bVisible = col.visible;
6368			}
6369	
6370			// Search
6371			if ( col.search !== undefined ) {
6372				$.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) );
6373			}
6374		}
6375	
6376		_fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, state] );
6377	}
6378	
6379	
6380	/**
6381	 * Return the settings object for a particular table
6382	 *  @param {node} table table we are using as a dataTable
6383	 *  @returns {object} Settings object - or null if not found
6384	 *  @memberof DataTable#oApi
6385	 */
6386	function _fnSettingsFromNode ( table )
6387	{
6388		var settings = DataTable.settings;
6389		var idx = $.inArray( table, _pluck( settings, 'nTable' ) );
6390	
6391		return idx !== -1 ?
6392			settings[ idx ] :
6393			null;
6394	}
6395	
6396	
6397	/**
6398	 * Log an error message
6399	 *  @param {object} settings dataTables settings object
6400	 *  @param {int} level log error messages, or display them to the user
6401	 *  @param {string} msg error message
6402	 *  @param {int} tn Technical note id to get more information about the error.
6403	 *  @memberof DataTable#oApi
6404	 */
6405	function _fnLog( settings, level, msg, tn )
6406	{
6407		msg = 'DataTables warning: '+
6408			(settings ? 'table id='+settings.sTableId+' - ' : '')+msg;
6409	
6410		if ( tn ) {
6411			msg += '. For more information about this error, please see '+
6412			'http://datatables.net/tn/'+tn;
6413		}
6414	
6415		if ( ! level  ) {
6416			// Backwards compatibility pre 1.10
6417			var ext = DataTable.ext;
6418			var type = ext.sErrMode || ext.errMode;
6419	
6420			if ( settings ) {
6421				_fnCallbackFire( settings, null, 'error', [ settings, tn, msg ] );
6422			}
6423	
6424			if ( type == 'alert' ) {
6425				alert( msg );
6426			}
6427			else if ( type == 'throw' ) {
6428				throw new Error(msg);
6429			}
6430			else if ( typeof type == 'function' ) {
6431				type( settings, tn, msg );
6432			}
6433		}
6434		else if ( window.console && console.log ) {
6435			console.log( msg );
6436		}
6437	}
6438	
6439	
6440	/**
6441	 * See if a property is defined on one object, if so assign it to the other object
6442	 *  @param {object} ret target object
6443	 *  @param {object} src source object
6444	 *  @param {string} name property
6445	 *  @param {string} [mappedName] name to map too - optional, name used if not given
6446	 *  @memberof DataTable#oApi
6447	 */
6448	function _fnMap( ret, src, name, mappedName )
6449	{
6450		if ( $.isArray( name ) ) {
6451			$.each( name, function (i, val) {
6452				if ( $.isArray( val ) ) {
6453					_fnMap( ret, src, val[0], val[1] );
6454				}
6455				else {
6456					_fnMap( ret, src, val );
6457				}
6458			} );
6459	
6460			return;
6461		}
6462	
6463		if ( mappedName === undefined ) {
6464			mappedName = name;
6465		}
6466	
6467		if ( src[name] !== undefined ) {
6468			ret[mappedName] = src[name];
6469		}
6470	}
6471	
6472	
6473	/**
6474	 * Extend objects - very similar to jQuery.extend, but deep copy objects, and
6475	 * shallow copy arrays. The reason we need to do this, is that we don't want to
6476	 * deep copy array init values (such as aaSorting) since the dev wouldn't be
6477	 * able to override them, but we do want to deep copy arrays.
6478	 *  @param {object} out Object to extend
6479	 *  @param {object} extender Object from which the properties will be applied to
6480	 *      out
6481	 *  @param {boolean} breakRefs If true, then arrays will be sliced to take an
6482	 *      independent copy with the exception of the `data` or `aaData` parameters
6483	 *      if they are present. This is so you can pass in a collection to
6484	 *      DataTables and have that used as your data source without breaking the
6485	 *      references
6486	 *  @returns {object} out Reference, just for convenience - out === the return.
6487	 *  @memberof DataTable#oApi
6488	 *  @todo This doesn't take account of arrays inside the deep copied objects.
6489	 */
6490	function _fnExtend( out, extender, breakRefs )
6491	{
6492		var val;
6493	
6494		for ( var prop in extender ) {
6495			if ( extender.hasOwnProperty(prop) ) {
6496				val = extender[prop];
6497	
6498				if ( $.isPlainObject( val ) ) {
6499					if ( ! $.isPlainObject( out[prop] ) ) {
6500						out[prop] = {};
6501					}
6502					$.extend( true, out[prop], val );
6503				}
6504				else if ( breakRefs && prop !== 'data' && prop !== 'aaData' && $.isArray(val) ) {
6505					out[prop] = val.slice();
6506				}
6507				else {
6508					out[prop] = val;
6509				}
6510			}
6511		}
6512	
6513		return out;
6514	}
6515	
6516	
6517	/**
6518	 * Bind an event handers to allow a click or return key to activate the callback.
6519	 * This is good for accessibility since a return on the keyboard will have the
6520	 * same effect as a click, if the element has focus.
6521	 *  @param {element} n Element to bind the action to
6522	 *  @param {object} oData Data object to pass to the triggered function
6523	 *  @param {function} fn Callback function for when the event is triggered
6524	 *  @memberof DataTable#oApi
6525	 */
6526	function _fnBindAction( n, oData, fn )
6527	{
6528		$(n)
6529			.bind( 'click.DT', oData, function (e) {
6530					n.blur(); // Remove focus outline for mouse users
6531					fn(e);
6532				} )
6533			.bind( 'keypress.DT', oData, function (e){
6534					if ( e.which === 13 ) {
6535						e.preventDefault();
6536						fn(e);
6537					}
6538				} )
6539			.bind( 'selectstart.DT', function () {
6540					/* Take the brutal approach to cancelling text selection */
6541					return false;
6542				} );
6543	}
6544	
6545	
6546	/**
6547	 * Register a callback function. Easily allows a callback function to be added to
6548	 * an array store of callback functions that can then all be called together.
6549	 *  @param {object} oSettings dataTables settings object
6550	 *  @param {string} sStore Name of the array storage for the callbacks in oSettings
6551	 *  @param {function} fn Function to be called back
6552	 *  @param {string} sName Identifying name for the callback (i.e. a label)
6553	 *  @memberof DataTable#oApi
6554	 */
6555	function _fnCallbackReg( oSettings, sStore, fn, sName )
6556	{
6557		if ( fn )
6558		{
6559			oSettings[sStore].push( {
6560				"fn": fn,
6561				"sName": sName
6562			} );
6563		}
6564	}
6565	
6566	
6567	/**
6568	 * Fire callback functions and trigger events. Note that the loop over the
6569	 * callback array store is done backwards! Further note that you do not want to
6570	 * fire off triggers in time sensitive applications (for example cell creation)
6571	 * as its slow.
6572	 *  @param {object} settings dataTables settings object
6573	 *  @param {string} callbackArr Name of the array storage for the callbacks in
6574	 *      oSettings
6575	 *  @param {string} eventName Name of the jQuery custom event to trigger. If
6576	 *      null no trigger is fired
6577	 *  @param {array} args Array of arguments to pass to the callback function /
6578	 *      trigger
6579	 *  @memberof DataTable#oApi
6580	 */
6581	function _fnCallbackFire( settings, callbackArr, eventName, args )
6582	{
6583		var ret = [];
6584	
6585		if ( callbackArr ) {
6586			ret = $.map( settings[callbackArr].slice().reverse(), function (val, i) {
6587				return val.fn.apply( settings.oInstance, args );
6588			} );
6589		}
6590	
6591		if ( eventName !== null ) {
6592			var e = $.Event( eventName+'.dt' );
6593	
6594			$(settings.nTable).trigger( e, args );
6595	
6596			ret.push( e.result );
6597		}
6598	
6599		return ret;
6600	}
6601	
6602	
6603	function _fnLengthOverflow ( settings )
6604	{
6605		var
6606			start = settings._iDisplayStart,
6607			end = settings.fnDisplayEnd(),
6608			len = settings._iDisplayLength;
6609	
6610		/* If we have space to show extra rows (backing up from the end point - then do so */
6611		if ( start >= end )
6612		{
6613			start = end - len;
6614		}
6615	
6616		// Keep the start record on the current page
6617		start -= (start % len);
6618	
6619		if ( len === -1 || start < 0 )
6620		{
6621			start = 0;
6622		}
6623	
6624		settings._iDisplayStart = start;
6625	}
6626	
6627	
6628	function _fnRenderer( settings, type )
6629	{
6630		var renderer = settings.renderer;
6631		var host = DataTable.ext.renderer[type];
6632	
6633		if ( $.isPlainObject( renderer ) && renderer[type] ) {
6634			// Specific renderer for this type. If available use it, otherwise use
6635			// the default.
6636			return host[renderer[type]] || host._;
6637		}
6638		else if ( typeof renderer === 'string' ) {
6639			// Common renderer - if there is one available for this type use it,
6640			// otherwise use the default
6641			return host[renderer] || host._;
6642		}
6643	
6644		// Use the default
6645		return host._;
6646	}
6647	
6648	
6649	/**
6650	 * Detect the data source being used for the table. Used to simplify the code
6651	 * a little (ajax) and to make it compress a little smaller.
6652	 *
6653	 *  @param {object} settings dataTables settings object
6654	 *  @returns {string} Data source
6655	 *  @memberof DataTable#oApi
6656	 */
6657	function _fnDataSource ( settings )
6658	{
6659		if ( settings.oFeatures.bServerSide ) {
6660			return 'ssp';
6661		}
6662		else if ( settings.ajax || settings.sAjaxSource ) {
6663			return 'ajax';
6664		}
6665		return 'dom';
6666	}
6667	
6668
6669	
6670	
6671	/**
6672	 * Computed structure of the DataTables API, defined by the options passed to
6673	 * `DataTable.Api.register()` when building the API.
6674	 *
6675	 * The structure is built in order to speed creation and extension of the Api
6676	 * objects since the extensions are effectively pre-parsed.
6677	 *
6678	 * The array is an array of objects with the following structure, where this
6679	 * base array represents the Api prototype base:
6680	 *
6681	 *     [
6682	 *       {
6683	 *         name:      'data'                -- string   - Property name
6684	 *         val:       function () {},       -- function - Api method (or undefined if just an object
6685	 *         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
6686	 *         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
6687	 *       },
6688	 *       {
6689	 *         name:     'row'
6690	 *         val:       {},
6691	 *         methodExt: [ ... ],
6692	 *         propExt:   [
6693	 *           {
6694	 *             name:      'data'
6695	 *             val:       function () {},
6696	 *             methodExt: [ ... ],
6697	 *             propExt:   [ ... ]
6698	 *           },
6699	 *           ...
6700	 *         ]
6701	 *       }
6702	 *     ]
6703	 *
6704	 * @type {Array}
6705	 * @ignore
6706	 */
6707	var __apiStruct = [];
6708	
6709	
6710	/**
6711	 * `Array.prototype` reference.
6712	 *
6713	 * @type object
6714	 * @ignore
6715	 */
6716	var __arrayProto = Array.prototype;
6717	
6718	
6719	/**
6720	 * Abstraction for `context` parameter of the `Api` constructor to allow it to
6721	 * take several different forms for ease of use.
6722	 *
6723	 * Each of the input parameter types will be converted to a DataTables settings
6724	 * object where possible.
6725	 *
6726	 * @param  {string|node|jQuery|object} mixed DataTable identifier. Can be one
6727	 *   of:
6728	 *
6729	 *   * `string` - jQuery selector. Any DataTables' matching the given selector
6730	 *     with be found and used.
6731	 *   * `node` - `TABLE` node which has already been formed into a DataTable.
6732	 *   * `jQuery` - A jQuery object of `TABLE` nodes.
6733	 *   * `object` - DataTables settings object
6734	 *   * `DataTables.Api` - API instance
6735	 * @return {array|null} Matching DataTables settings objects. `null` or
6736	 *   `undefined` is returned if no matching DataTable is found.
6737	 * @ignore
6738	 */
6739	var _toSettings = function ( mixed )
6740	{
6741		var idx, jq;
6742		var settings = DataTable.settings;
6743		var tables = $.map( settings, function (el, i) {
6744			return el.nTable;
6745		} );
6746	
6747		if ( ! mixed ) {
6748			return [];
6749		}
6750		else if ( mixed.nTable && mixed.oApi ) {
6751			// DataTables settings object
6752			return [ mixed ];
6753		}
6754		else if ( mixed.nodeName && mixed.nodeName.toLowerCase() === 'table' ) {
6755			// Table node
6756			idx = $.inArray( mixed, tables );
6757			return idx !== -1 ? [ settings[idx] ] : null;
6758		}
6759		else if ( mixed && typeof mixed.settings === 'function' ) {
6760			return mixed.settings().toArray();
6761		}
6762		else if ( typeof mixed === 'string' ) {
6763			// jQuery selector
6764			jq = $(mixed);
6765		}
6766		else if ( mixed instanceof $ ) {
6767			// jQuery object (also DataTables instance)
6768			jq = mixed;
6769		}
6770	
6771		if ( jq ) {
6772			return jq.map( function(i) {
6773				idx = $.inArray( this, tables );
6774				return idx !== -1 ? settings[idx] : null;
6775			} ).toArray();
6776		}
6777	};
6778	
6779	
6780	/**
6781	 * DataTables API class - used to control and interface with  one or more
6782	 * DataTables enhanced tables.
6783	 *
6784	 * The API class is heavily based on jQuery, presenting a chainable interface
6785	 * that you can use to interact with tables. Each instance of the API class has
6786	 * a "context" - i.e. the tables that it will operate on. This could be a single
6787	 * table, all tables on a page or a sub-set thereof.
6788	 *
6789	 * Additionally the API is designed to allow you to easily work with the data in
6790	 * the tables, retrieving and manipulating it as required. This is done by
6791	 * presenting the API class as an array like interface. The contents of the
6792	 * array depend upon the actions requested by each method (for example
6793	 * `rows().nodes()` will return an array of nodes, while `rows().data()` will
6794	 * return an array of objects or arrays depending upon your table's
6795	 * configuration). The API object has a number of array like methods (`push`,
6796	 * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`,
6797	 * `unique` etc) to assist your working with the data held in a table.
6798	 *
6799	 * Most methods (those which return an Api instance) are chainable, which means
6800	 * the return from a method call also has all of the methods available that the
6801	 * top level object had. For example, these two calls are equivalent:
6802	 *
6803	 *     // Not chained
6804	 *     api.row.add( {...} );
6805	 *     api.draw();
6806	 *
6807	 *     // Chained
6808	 *     api.row.add( {...} ).draw();
6809	 *
6810	 * @class DataTable.Api
6811	 * @param {array|object|string|jQuery} context DataTable identifier. This is
6812	 *   used to define which DataTables enhanced tables this API will operate on.
6813	 *   Can be one of:
6814	 *
6815	 *   * `string` - jQuery selector. Any DataTables' matching the given selector
6816	 *     with be found and used.
6817	 *   * `node` - `TABLE` node which has already been formed into a DataTable.
6818	 *   * `jQuery` - A jQuery object of `TABLE` nodes.
6819	 *   * `object` - DataTables settings object
6820	 * @param {array} [data] Data to initialise the Api instance with.
6821	 *
6822	 * @example
6823	 *   // Direct initialisation during DataTables construction
6824	 *   var api = $('#example').DataTable();
6825	 *
6826	 * @example
6827	 *   // Initialisation using a DataTables jQuery object
6828	 *   var api = $('#example').dataTable().api();
6829	 *
6830	 * @example
6831	 *   // Initialisation as a constructor
6832	 *   var api = new $.fn.DataTable.Api( 'table.dataTable' );
6833	 */
6834	_Api = function ( context, data )
6835	{
6836		if ( ! (this instanceof _Api) ) {
6837			return new _Api( context, data );
6838		}
6839	
6840		var settings = [];
6841		var ctxSettings = function ( o ) {
6842			var a = _toSettings( o );
6843			if ( a ) {
6844				settings = settings.concat( a );
6845			}
6846		};
6847	
6848		if ( $.isArray( context ) ) {
6849			for ( var i=0, ien=context.length ; i<ien ; i++ ) {
6850				ctxSettings( context[i] );
6851			}
6852		}
6853		else {
6854			ctxSettings( context );
6855		}
6856	
6857		// Remove duplicates
6858		this.context = _unique( settings );
6859	
6860		// Initial data
6861		if ( data ) {
6862			$.merge( this, data );
6863		}
6864	
6865		// selector
6866		this.selector = {
6867			rows: null,
6868			cols: null,
6869			opts: null
6870		};
6871	
6872		_Api.extend( this, this, __apiStruct );
6873	};
6874	
6875	DataTable.Api = _Api;
6876	
6877	// Don't destroy the existing prototype, just extend it. Required for jQuery 2's
6878	// isPlainObject.
6879	$.extend( _Api.prototype, {
6880		any: function ()
6881		{
6882			return this.count() !== 0;
6883		},
6884	
6885	
6886		concat:  __arrayProto.concat,
6887	
6888	
6889		context: [], // array of table settings objects
6890	
6891	
6892		count: function ()
6893		{
6894			return this.flatten().length;
6895		},
6896	
6897	
6898		each: function ( fn )
6899		{
6900			for ( var i=0, ien=this.length ; i<ien; i++ ) {
6901				fn.call( this, this[i], i, this );
6902			}
6903	
6904			return this;
6905		},
6906	
6907	
6908		eq: function ( idx )
6909		{
6910			var ctx = this.context;
6911	
6912			return ctx.length > idx ?
6913				new _Api( ctx[idx], this[idx] ) :
6914				null;
6915		},
6916	
6917	
6918		filter: function ( fn )
6919		{
6920			var a = [];
6921	
6922			if ( __arrayProto.filter ) {
6923				a = __arrayProto.filter.call( this, fn, this );
6924			}
6925			else {
6926				// Compatibility for browsers without EMCA-252-5 (JS 1.6)
6927				for ( var i=0, ien=this.length ; i<ien ; i++ ) {
6928					if ( fn.call( this, this[i], i, this ) ) {
6929						a.push( this[i] );
6930					}
6931				}
6932			}
6933	
6934			return new _Api( this.context, a );
6935		},
6936	
6937	
6938		flatten: function ()
6939		{
6940			var a = [];
6941			return new _Api( this.context, a.concat.apply( a, this.toArray() ) );
6942		},
6943	
6944	
6945		join:    __arrayProto.join,
6946	
6947	
6948		indexOf: __arrayProto.indexOf || function (obj, start)
6949		{
6950			for ( var i=(start || 0), ien=this.length ; i<ien ; i++ ) {
6951				if ( this[i] === obj ) {
6952					return i;
6953				}
6954			}
6955			return -1;
6956		},
6957	
6958		iterator: function ( flatten, type, fn, alwaysNew ) {
6959			var
6960				a = [], ret,
6961				i, ien, j, jen,
6962				context = this.context,
6963				rows, items, item,
6964				selector = this.selector;
6965	
6966			// Argument shifting
6967			if ( typeof flatten === 'string' ) {
6968				alwaysNew = fn;
6969				fn = type;
6970				type = flatten;
6971				flatten = false;
6972			}
6973	
6974			for ( i=0, ien=context.length ; i<ien ; i++ ) {
6975				var apiInst = new _Api( context[i] );
6976	
6977				if ( type === 'table' ) {
6978					ret = fn.call( apiInst, context[i], i );
6979	
6980					if ( ret !== undefined ) {
6981						a.push( ret );
6982					}
6983				}
6984				else if ( type === 'columns' || type === 'rows' ) {
6985					// this has same length as context - one entry for each table
6986					ret = fn.call( apiInst, context[i], this[i], i );
6987	
6988					if ( ret !== undefined ) {
6989						a.push( ret );
6990					}
6991				}
6992				else if ( type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell' ) {
6993					// columns and rows share the same structure.
6994					// 'this' is an array of column indexes for each context
6995					items = this[i];
6996	
6997					if ( type === 'column-rows' ) {
6998						rows = _selector_row_indexes( context[i], selector.opts );
6999					}
7000	
7001					for ( j=0, jen=items.length ; j<jen ; j++ ) {
7002						item = items[j];
7003	
7004						if ( type === 'cell' ) {
7005							ret = fn.call( apiInst, context[i], item.row, item.column, i, j );
7006						}
7007						else {
7008							ret = fn.call( apiInst, context[i], item, i, j, rows );
7009						}
7010	
7011						if ( ret !== undefined ) {
7012							a.push( ret );
7013						}
7014					}
7015				}
7016			}
7017	
7018			if ( a.length || alwaysNew ) {
7019				var api = new _Api( context, flatten ? a.concat.apply( [], a ) : a );
7020				var apiSelector = api.selector;
7021				apiSelector.rows = selector.rows;
7022				apiSelector.cols = selector.cols;
7023				apiSelector.opts = selector.opts;
7024				return api;
7025			}
7026			return this;
7027		},
7028	
7029	
7030		lastIndexOf: __arrayProto.lastIndexOf || function (obj, start)
7031		{
7032			// Bit cheeky...
7033			return this.indexOf.apply( this.toArray.reverse(), arguments );
7034		},
7035	
7036	
7037		length:  0,
7038	
7039	
7040		map: function ( fn )
7041		{
7042			var a = [];
7043	
7044			if ( __arrayProto.map ) {
7045				a = __arrayProto.map.call( this, fn, this );
7046			}
7047			else {
7048				// Compatibility for browsers without EMCA-252-5 (JS 1.6)
7049				for ( var i=0, ien=this.length ; i<ien ; i++ ) {
7050					a.push( fn.call( this, this[i], i ) );
7051				}
7052			}
7053	
7054			return new _Api( this.context, a );
7055		},
7056	
7057	
7058		pluck: function ( prop )
7059		{
7060			return this.map( function ( el ) {
7061				return el[ prop ];
7062			} );
7063		},
7064	
7065		pop:     __arrayProto.pop,
7066	
7067	
7068		push:    __arrayProto.push,
7069	
7070	
7071		// Does not return an API instance
7072		reduce: __arrayProto.reduce || function ( fn, init )
7073		{
7074			return _fnReduce( this, fn, init, 0, this.length, 1 );
7075		},
7076	
7077	
7078		reduceRight: __arrayProto.reduceRight || function ( fn, init )
7079		{
7080			return _fnReduce( this, fn, init, this.length-1, -1, -1 );
7081		},
7082	
7083	
7084		reverse: __arrayProto.reverse,
7085	
7086	
7087		// Object with rows, columns and opts
7088		selector: null,
7089	
7090	
7091		shift:   __arrayProto.shift,
7092	
7093	
7094		sort:    __arrayProto.sort, // ? name - order?
7095	
7096	
7097		splice:  __arrayProto.splice,
7098	
7099	
7100		toArray: function ()
7101		{
7102			return __arrayProto.slice.call( this );
7103		},
7104	
7105	
7106		to$: function ()
7107		{
7108			return $( this );
7109		},
7110	
7111	
7112		toJQuery: function ()
7113		{
7114			return $( this );
7115		},
7116	
7117	
7118		unique: function ()
7119		{
7120			return new _Api( this.context, _unique(this) );
7121		},
7122	
7123	
7124		unshift: __arrayProto.unshift
7125	} );
7126	
7127	
7128	_Api.extend = function ( scope, obj, ext )
7129	{
7130		// Only extend API instances and static properties of the API
7131		if ( ! ext.length || ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) {
7132			return;
7133		}
7134	
7135		var
7136			i, ien,
7137			j, jen,
7138			struct, inner,
7139			methodScoping = function ( scope, fn, struc ) {
7140				return function () {
7141					var ret = fn.apply( scope, arguments );
7142	
7143					// Method extension
7144					_Api.extend( ret, ret, struc.methodExt );
7145					return ret;
7146				};
7147			};
7148	
7149		for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7150			struct = ext[i];
7151	
7152			// Value
7153			obj[ struct.name ] = typeof struct.val === 'function' ?
7154				methodScoping( scope, struct.val, struct ) :
7155				$.isPlainObject( struct.val ) ?
7156					{} :
7157					struct.val;
7158	
7159			obj[ struct.name ].__dt_wrapper = true;
7160	
7161			// Property extension
7162			_Api.extend( scope, obj[ struct.name ], struct.propExt );
7163		}
7164	};
7165	
7166	
7167	// @todo - Is there need for an augment function?
7168	// _Api.augment = function ( inst, name )
7169	// {
7170	// 	// Find src object in the structure from the name
7171	// 	var parts = name.split('.');
7172	
7173	// 	_Api.extend( inst, obj );
7174	// };
7175	
7176	
7177	//     [
7178	//       {
7179	//         name:      'data'                -- string   - Property name
7180	//         val:       function () {},       -- function - Api method (or undefined if just an object
7181	//         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
7182	//         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
7183	//       },
7184	//       {
7185	//         name:     'row'
7186	//         val:       {},
7187	//         methodExt: [ ... ],
7188	//         propExt:   [
7189	//           {
7190	//             name:      'data'
7191	//             val:       function () {},
7192	//             methodExt: [ ... ],
7193	//             propExt:   [ ... ]
7194	//           },
7195	//           ...
7196	//         ]
7197	//       }
7198	//     ]
7199	
7200	_Api.register = _api_register = function ( name, val )
7201	{
7202		if ( $.isArray( name ) ) {
7203			for ( var j=0, jen=name.length ; j<jen ; j++ ) {
7204				_Api.register( name[j], val );
7205			}
7206			return;
7207		}
7208	
7209		var
7210			i, ien,
7211			heir = name.split('.'),
7212			struct = __apiStruct,
7213			key, method;
7214	
7215		var find = function ( src, name ) {
7216			for ( var i=0, ien=src.length ; i<ien ; i++ ) {
7217				if ( src[i].name === name ) {
7218					return src[i];
7219				}
7220			}
7221			return null;
7222		};
7223	
7224		for ( i=0, ien=heir.length ; i<ien ; i++ ) {
7225			method = heir[i].indexOf('()') !== -1;
7226			key = method ?
7227				heir[i].replace('()', '') :
7228				heir[i];
7229	
7230			var src = find( struct, key );
7231			if ( ! src ) {
7232				src = {
7233					name:      key,
7234					val:       {},
7235					methodExt: [],
7236					propExt:   []
7237				};
7238				struct.push( src );
7239			}
7240	
7241			if ( i === ien-1 ) {
7242				src.val = val;
7243			}
7244			else {
7245				struct = method ?
7246					src.methodExt :
7247					src.propExt;
7248			}
7249		}
7250	};
7251	
7252	
7253	_Api.registerPlural = _api_registerPlural = function ( pluralName, singularName, val ) {
7254		_Api.register( pluralName, val );
7255	
7256		_Api.register( singularName, function () {
7257			var ret = val.apply( this, arguments );
7258	
7259			if ( ret === this ) {
7260				// Returned item is the API instance that was passed in, return it
7261				return this;
7262			}
7263			else if ( ret instanceof _Api ) {
7264				// New API instance returned, want the value from the first item
7265				// in the returned array for the singular result.
7266				return ret.length ?
7267					$.isArray( ret[0] ) ?
7268						new _Api( ret.context, ret[0] ) : // Array results are 'enhanced'
7269						ret[0] :
7270					undefined;
7271			}
7272	
7273			// Non-API return - just fire it back
7274			return ret;
7275		} );
7276	};
7277	
7278	
7279	/**
7280	 * Selector for HTML tables. Apply the given selector to the give array of
7281	 * DataTables settings objects.
7282	 *
7283	 * @param {string|integer} [selector] jQuery selector string or integer
7284	 * @param  {array} Array of DataTables settings objects to be filtered
7285	 * @return {array}
7286	 * @ignore
7287	 */
7288	var __table_selector = function ( selector, a )
7289	{
7290		// Integer is used to pick out a table by index
7291		if ( typeof selector === 'number' ) {
7292			return [ a[ selector ] ];
7293		}
7294	
7295		// Perform a jQuery selector on the table nodes
7296		var nodes = $.map( a, function (el, i) {
7297			return el.nTable;
7298		} );
7299	
7300		return $(nodes)
7301			.filter( selector )
7302			.map( function (i) {
7303				// Need to translate back from the table node to the settings
7304				var idx = $.inArray( this, nodes );
7305				return a[ idx ];
7306			} )
7307			.toArray();
7308	};
7309	
7310	
7311	
7312	/**
7313	 * Context selector for the API's context (i.e. the tables the API instance
7314	 * refers to.
7315	 *
7316	 * @name    DataTable.Api#tables
7317	 * @param {string|integer} [selector] Selector to pick which tables the iterator
7318	 *   should operate on. If not given, all tables in the current context are
7319	 *   used. This can be given as a jQuery selector (for example `':gt(0)'`) to
7320	 *   select multiple tables or as an integer to select a single table.
7321	 * @returns {DataTable.Api} Returns a new API instance if a selector is given.
7322	 */
7323	_api_register( 'tables()', function ( selector ) {
7324		// A new instance is created if there was a selector specified
7325		return selector ?
7326			new _Api( __table_selector( selector, this.context ) ) :
7327			this;
7328	} );
7329	
7330	
7331	_api_register( 'table()', function ( selector ) {
7332		var tables = this.tables( selector );
7333		var ctx = tables.context;
7334	
7335		// Truncate to the first matched table
7336		return ctx.length ?
7337			new _Api( ctx[0] ) :
7338			tables;
7339	} );
7340	
7341	
7342	_api_registerPlural( 'tables().nodes()', 'table().node()' , function () {
7343		return this.iterator( 'table', function ( ctx ) {
7344			return ctx.nTable;
7345		}, 1 );
7346	} );
7347	
7348	
7349	_api_registerPlural( 'tables().body()', 'table().body()' , function () {
7350		return this.iterator( 'table', function ( ctx ) {
7351			return ctx.nTBody;
7352		}, 1 );
7353	} );
7354	
7355	
7356	_api_registerPlural( 'tables().header()', 'table().header()' , function () {
7357		return this.iterator( 'table', function ( ctx ) {
7358			return ctx.nTHead;
7359		}, 1 );
7360	} );
7361	
7362	
7363	_api_registerPlural( 'tables().footer()', 'table().footer()' , function () {
7364		return this.iterator( 'table', function ( ctx ) {
7365			return ctx.nTFoot;
7366		}, 1 );
7367	} );
7368	
7369	
7370	_api_registerPlural( 'tables().containers()', 'table().container()' , function () {
7371		return this.iterator( 'table', function ( ctx ) {
7372			return ctx.nTableWrapper;
7373		}, 1 );
7374	} );
7375	
7376	
7377	
7378	/**
7379	 * Redraw the tables in the current context.
7380	 */
7381	_api_register( 'draw()', function ( paging ) {
7382		return this.iterator( 'table', function ( settings ) {
7383			if ( paging === 'page' ) {
7384				_fnDraw( settings );
7385			}
7386			else {
7387				if ( typeof paging === 'string' ) {
7388					paging = paging === 'full-hold' ?
7389						false :
7390						true;
7391				}
7392	
7393				_fnReDraw( settings, paging===false );
7394			}
7395		} );
7396	} );
7397	
7398	
7399	
7400	/**
7401	 * Get the current page index.
7402	 *
7403	 * @return {integer} Current page index (zero based)
7404	 *//**
7405	 * Set the current page.
7406	 *
7407	 * Note that if you attempt to show a page which does not exist, DataTables will
7408	 * not throw an error, but rather reset the paging.
7409	 *
7410	 * @param {integer|string} action The paging action to take. This can be one of:
7411	 *  * `integer` - The page index to jump to
7412	 *  * `string` - An action to take:
7413	 *    * `first` - Jump to first page.
7414	 *    * `next` - Jump to the next page
7415	 *    * `previous` - Jump to previous page
7416	 *    * `last` - Jump to the last page.
7417	 * @returns {DataTables.Api} this
7418	 */
7419	_api_register( 'page()', function ( action ) {
7420		if ( action === undefined ) {
7421			return this.page.info().page; // not an expensive call
7422		}
7423	
7424		// else, have an action to take on all tables
7425		return this.iterator( 'table', function ( settings ) {
7426			_fnPageChange( settings, action );
7427		} );
7428	} );
7429	
7430	
7431	/**
7432	 * Paging information for the first table in the current context.
7433	 *
7434	 * If you require paging information for another table, use the `table()` method
7435	 * with a suitable selector.
7436	 *
7437	 * @return {object} Object with the following properties set:
7438	 *  * `page` - Current page index (zero based - i.e. the first page is `0`)
7439	 *  * `pages` - Total number of pages
7440	 *  * `start` - Display index for the first record shown on the current page
7441	 *  * `end` - Display index for the last record shown on the current page
7442	 *  * `length` - Display length (number of records). Note that generally `start
7443	 *    + length = end`, but this is not always true, for example if there are
7444	 *    only 2 records to show on the final page, with a length of 10.
7445	 *  * `recordsTotal` - Full data set length
7446	 *  * `recordsDisplay` - Data set length once the current filtering criterion
7447	 *    are applied.
7448	 */
7449	_api_register( 'page.info()', function ( action ) {
7450		if ( this.context.length === 0 ) {
7451			return undefined;
7452		}
7453	
7454		var
7455			settings   = this.context[0],
7456			start      = settings._iDisplayStart,
7457			len        = settings.oFeatures.bPaginate ? settings._iDisplayLength : -1,
7458			visRecords = settings.fnRecordsDisplay(),
7459			all        = len === -1;
7460	
7461		return {
7462			"page":           all ? 0 : Math.floor( start / len ),
7463			"pages":          all ? 1 : Math.ceil( visRecords / len ),
7464			"start":          start,
7465			"end":            settings.fnDisplayEnd(),
7466			"length":         len,
7467			"recordsTotal":   settings.fnRecordsTotal(),
7468			"recordsDisplay": visRecords,
7469			"serverSide":     _fnDataSource( settings ) === 'ssp'
7470		};
7471	} );
7472	
7473	
7474	/**
7475	 * Get the current page length.
7476	 *
7477	 * @return {integer} Current page length. Note `-1` indicates that all records
7478	 *   are to be shown.
7479	 *//**
7480	 * Set the current page length.
7481	 *
7482	 * @param {integer} Page length to set. Use `-1` to show all records.
7483	 * @returns {DataTables.Api} this
7484	 */
7485	_api_register( 'page.len()', function ( len ) {
7486		// Note that we can't call this function 'length()' because `length`
7487		// is a Javascript property of functions which defines how many arguments
7488		// the function expects.
7489		if ( len === undefined ) {
7490			return this.context.length !== 0 ?
7491				this.context[0]._iDisplayLength :
7492				undefined;
7493		}
7494	
7495		// else, set the page length
7496		return this.iterator( 'table', function ( settings ) {
7497			_fnLengthChange( settings, len );
7498		} );
7499	} );
7500	
7501	
7502	
7503	var __reload = function ( settings, holdPosition, callback ) {
7504		// Use the draw event to trigger a callback
7505		if ( callback ) {
7506			var api = new _Api( settings );
7507	
7508			api.one( 'draw', function () {
7509				callback( api.ajax.json() );
7510			} );
7511		}
7512	
7513		if ( _fnDataSource( settings ) == 'ssp' ) {
7514			_fnReDraw( settings, holdPosition );
7515		}
7516		else {
7517			_fnProcessingDisplay( settings, true );
7518	
7519			// Cancel an existing request
7520			var xhr = settings.jqXHR;
7521			if ( xhr && xhr.readyState !== 4 ) {
7522				xhr.abort();
7523			}
7524	
7525			// Trigger xhr
7526			_fnBuildAjax( settings, [], function( json ) {
7527				_fnClearTable( settings );
7528	
7529				var data = _fnAjaxDataSrc( settings, json );
7530				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7531					_fnAddData( settings, data[i] );
7532				}
7533	
7534				_fnReDraw( settings, holdPosition );
7535				_fnProcessingDisplay( settings, false );
7536			} );
7537		}
7538	};
7539	
7540	
7541	/**
7542	 * Get the JSON response from the last Ajax request that DataTables made to the
7543	 * server. Note that this returns the JSON from the first table in the current
7544	 * context.
7545	 *
7546	 * @return {object} JSON received from the server.
7547	 */
7548	_api_register( 'ajax.json()', function () {
7549		var ctx = this.context;
7550	
7551		if ( ctx.length > 0 ) {
7552			return ctx[0].json;
7553		}
7554	
7555		// else return undefined;
7556	} );
7557	
7558	
7559	/**
7560	 * Get the data submitted in the last Ajax request
7561	 */
7562	_api_register( 'ajax.params()', function () {
7563		var ctx = this.context;
7564	
7565		if ( ctx.length > 0 ) {
7566			return ctx[0].oAjaxData;
7567		}
7568	
7569		// else return undefined;
7570	} );
7571	
7572	
7573	/**
7574	 * Reload tables from the Ajax data source. Note that this function will
7575	 * automatically re-draw the table when the remote data has been loaded.
7576	 *
7577	 * @param {boolean} [reset=true] Reset (default) or hold the current paging
7578	 *   position. A full re-sort and re-filter is performed when this method is
7579	 *   called, which is why the pagination reset is the default action.
7580	 * @returns {DataTables.Api} this
7581	 */
7582	_api_register( 'ajax.reload()', function ( callback, resetPaging ) {
7583		return this.iterator( 'table', function (settings) {
7584			__reload( settings, resetPaging===false, callback );
7585		} );
7586	} );
7587	
7588	
7589	/**
7590	 * Get the current Ajax URL. Note that this returns the URL from the first
7591	 * table in the current context.
7592	 *
7593	 * @return {string} Current Ajax source URL
7594	 *//**
7595	 * Set the Ajax URL. Note that this will set the URL for all tables in the
7596	 * current context.
7597	 *
7598	 * @param {string} url URL to set.
7599	 * @returns {DataTables.Api} this
7600	 */
7601	_api_register( 'ajax.url()', function ( url ) {
7602		var ctx = this.context;
7603	
7604		if ( url === undefined ) {
7605			// get
7606			if ( ctx.length === 0 ) {
7607				return undefined;
7608			}
7609			ctx = ctx[0];
7610	
7611			return ctx.ajax ?
7612				$.isPlainObject( ctx.ajax ) ?
7613					ctx.ajax.url :
7614					ctx.ajax :
7615				ctx.sAjaxSource;
7616		}
7617	
7618		// set
7619		return this.iterator( 'table', function ( settings ) {
7620			if ( $.isPlainObject( settings.ajax ) ) {
7621				settings.ajax.url = url;
7622			}
7623			else {
7624				settings.ajax = url;
7625			}
7626			// No need to consider sAjaxSource here since DataTables gives priority
7627			// to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any
7628			// value of `sAjaxSource` redundant.
7629		} );
7630	} );
7631	
7632	
7633	/**
7634	 * Load data from the newly set Ajax URL. Note that this method is only
7635	 * available when `ajax.url()` is used to set a URL. Additionally, this method
7636	 * has the same effect as calling `ajax.reload()` but is provided for
7637	 * convenience when setting a new URL. Like `ajax.reload()` it will
7638	 * automatically redraw the table once the remote data has been loaded.
7639	 *
7640	 * @returns {DataTables.Api} this
7641	 */
7642	_api_register( 'ajax.url().load()', function ( callback, resetPaging ) {
7643		// Same as a reload, but makes sense to present it for easy access after a
7644		// url change
7645		return this.iterator( 'table', function ( ctx ) {
7646			__reload( ctx, resetPaging===false, callback );
7647		} );
7648	} );
7649	
7650	
7651	
7652	
7653	var _selector_run = function ( type, selector, selectFn, settings, opts )
7654	{
7655		var
7656			out = [], res,
7657			a, i, ien, j, jen,
7658			selectorType = typeof selector;
7659	
7660		// Can't just check for isArray here, as an API or jQuery instance might be
7661		// given with their array like look
7662		if ( ! selector || selectorType === 'string' || selectorType === 'function' || selector.length === undefined ) {
7663			selector = [ selector ];
7664		}
7665	
7666		for ( i=0, ien=selector.length ; i<ien ; i++ ) {
7667			a = selector[i] && selector[i].split ?
7668				selector[i].split(',') :
7669				[ selector[i] ];
7670	
7671			for ( j=0, jen=a.length ; j<jen ; j++ ) {
7672				res = selectFn( typeof a[j] === 'string' ? $.trim(a[j]) : a[j] );
7673	
7674				if ( res && res.length ) {
7675					out = out.concat( res );
7676				}
7677			}
7678		}
7679	
7680		// selector extensions
7681		var ext = _ext.selector[ type ];
7682		if ( ext.length ) {
7683			for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7684				out = ext[i]( settings, opts, out );
7685			}
7686		}
7687	
7688		return _unique( out );
7689	};
7690	
7691	
7692	var _selector_opts = function ( opts )
7693	{
7694		if ( ! opts ) {
7695			opts = {};
7696		}
7697	
7698		// Backwards compatibility for 1.9- which used the terminology filter rather
7699		// than search
7700		if ( opts.filter && opts.search === undefined ) {
7701			opts.search = opts.filter;
7702		}
7703	
7704		return $.extend( {
7705			search: 'none',
7706			order: 'current',
7707			page: 'all'
7708		}, opts );
7709	};
7710	
7711	
7712	var _selector_first = function ( inst )
7713	{
7714		// Reduce the API instance to the first item found
7715		for ( var i=0, ien=inst.length ; i<ien ; i++ ) {
7716			if ( inst[i].length > 0 ) {
7717				// Assign the first element to the first item in the instance
7718				// and truncate the instance and context
7719				inst[0] = inst[i];
7720				inst[0].length = 1;
7721				inst.length = 1;
7722				inst.context = [ inst.context[i] ];
7723	
7724				return inst;
7725			}
7726		}
7727	
7728		// Not found - return an empty instance
7729		inst.length = 0;
7730		return inst;
7731	};
7732	
7733	
7734	var _selector_row_indexes = function ( settings, opts )
7735	{
7736		var
7737			i, ien, tmp, a=[],
7738			displayFiltered = settings.aiDisplay,
7739			displayMaster = settings.aiDisplayMaster;
7740	
7741		var
7742			search = opts.search,  // none, applied, removed
7743			order  = opts.order,   // applied, current, index (original - compatibility with 1.9)
7744			page   = opts.page;    // all, current
7745	
7746		if ( _fnDataSource( settings ) == 'ssp' ) {
7747			// In server-side processing mode, most options are irrelevant since
7748			// rows not shown don't exist and the index order is the applied order
7749			// Removed is a special case - for consistency just return an empty
7750			// array
7751			return search === 'removed' ?
7752				[] :
7753				_range( 0, displayMaster.length );
7754		}
7755		else if ( page == 'current' ) {
7756			// Current page implies that order=current and fitler=applied, since it is
7757			// fairly senseless otherwise, regardless of what order and search actually
7758			// are
7759			for ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i<ien ; i++ ) {
7760				a.push( displayFiltered[i] );
7761			}
7762		}
7763		else if ( order == 'current' || order == 'applied' ) {
7764			a = search == 'none' ?
7765				displayMaster.slice() :                      // no search
7766				search == 'applied' ?
7767					displayFiltered.slice() :                // applied search
7768					$.map( displayMaster, function (el, i) { // removed search
7769						return $.inArray( el, displayFiltered ) === -1 ? el : null;
7770					} );
7771		}
7772		else if ( order == 'index' || order == 'original' ) {
7773			for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
7774				if ( search == 'none' ) {
7775					a.push( i );
7776				}
7777				else { // applied | removed
7778					tmp = $.inArray( i, displayFiltered );
7779	
7780					if ((tmp === -1 && search == 'removed') ||
7781						(tmp >= 0   && search == 'applied') )
7782					{
7783						a.push( i );
7784					}
7785				}
7786			}
7787		}
7788	
7789		return a;
7790	};
7791	
7792	
7793	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
7794	 * Rows
7795	 *
7796	 * {}          - no selector - use all available rows
7797	 * {integer}   - row aoData index
7798	 * {node}      - TR node
7799	 * {string}    - jQuery selector to apply to the TR elements
7800	 * {array}     - jQuery array of nodes, or simply an array of TR nodes
7801	 *
7802	 */
7803	
7804	
7805	var __row_selector = function ( settings, selector, opts )
7806	{
7807		var run = function ( sel ) {
7808			var selInt = _intVal( sel );
7809			var i, ien;
7810	
7811			// Short cut - selector is a number and no options provided (default is
7812			// all records, so no need to check if the index is in there, since it
7813			// must be - dev error if the index doesn't exist).
7814			if ( selInt !== null && ! opts ) {
7815				return [ selInt ];
7816			}
7817	
7818			var rows = _selector_row_indexes( settings, opts );
7819	
7820			if ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) {
7821				// Selector - integer
7822				return [ selInt ];
7823			}
7824			else if ( ! sel ) {
7825				// Selector - none
7826				return rows;
7827			}
7828	
7829			// Selector - function
7830			if ( typeof sel === 'function' ) {
7831				return $.map( rows, function (idx) {
7832					var row = settings.aoData[ idx ];
7833					return sel( idx, row._aData, row.nTr ) ? idx : null;
7834				} );
7835			}
7836	
7837			// Get nodes in the order from the `rows` array with null values removed
7838			var nodes = _removeEmpty(
7839				_pluck_order( settings.aoData, rows, 'nTr' )
7840			);
7841	
7842			// Selector - node
7843			if ( sel.nodeName ) {
7844				if ( sel._DT_RowIndex !== undefined ) {
7845					return [ sel._DT_RowIndex ]; // Property added by DT for fast lookup
7846				}
7847				else if ( sel._DT_CellIndex ) {
7848					return [ sel._DT_CellIndex.row ];
7849				}
7850				else {
7851					var host = $(sel).closest('*[data-dt-row]');
7852					return host.length ?
7853						[ host.data('dt-row') ] :
7854						[];
7855				}
7856			}
7857	
7858			// ID selector. Want to always be able to select rows by id, regardless
7859			// of if the tr element has been created or not, so can't rely upon
7860			// jQuery here - hence a custom implementation. This does not match
7861			// Sizzle's fast selector or HTML4 - in HTML5 the ID can be anything,
7862			// but to select it using a CSS selector engine (like Sizzle or
7863			// querySelect) it would need to need to be escaped for some characters.
7864			// DataTables simplifies this for row selectors since you can select
7865			// only a row. A # indicates an id any anything that follows is the id -
7866			// unescaped.
7867			if ( typeof sel === 'string' && sel.charAt(0) === '#' ) {
7868				// get row index from id
7869				var rowObj = settings.aIds[ sel.replace( /^#/, '' ) ];
7870				if ( rowObj !== undefined ) {
7871					return [ rowObj.idx ];
7872				}
7873	
7874				// need to fall through to jQuery in case there is DOM id that
7875				// matches
7876			}
7877	
7878			// Selector - jQuery selector string, array of nodes or jQuery object/
7879			// As jQuery's .filter() allows jQuery objects to be passed in filter,
7880			// it also allows arrays, so this will cope with all three options
7881			return $(nodes)
7882				.filter( sel )
7883				.map( function () {
7884					return this._DT_RowIndex;
7885				} )
7886				.toArray();
7887		};
7888	
7889		return _selector_run( 'row', selector, run, settings, opts );
7890	};
7891	
7892	
7893	_api_register( 'rows()', function ( selector, opts ) {
7894		// argument shifting
7895		if ( selector === undefined ) {
7896			selector = '';
7897		}
7898		else if ( $.isPlainObject( selector ) ) {
7899			opts = selector;
7900			selector = '';
7901		}
7902	
7903		opts = _selector_opts( opts );
7904	
7905		var inst = this.iterator( 'table', function ( settings ) {
7906			return __row_selector( settings, selector, opts );
7907		}, 1 );
7908	
7909		// Want argument shifting here and in __row_selector?
7910		inst.selector.rows = selector;
7911		inst.selector.opts = opts;
7912	
7913		return inst;
7914	} );
7915	
7916	_api_register( 'rows().nodes()', function () {
7917		return this.iterator( 'row', function ( settings, row ) {
7918			return settings.aoData[ row ].nTr || undefined;
7919		}, 1 );
7920	} );
7921	
7922	_api_register( 'rows().data()', function () {
7923		return this.iterator( true, 'rows', function ( settings, rows ) {
7924			return _pluck_order( settings.aoData, rows, '_aData' );
7925		}, 1 );
7926	} );
7927	
7928	_api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) {
7929		return this.iterator( 'row', function ( settings, row ) {
7930			var r = settings.aoData[ row ];
7931			return type === 'search' ? r._aFilterData : r._aSortData;
7932		}, 1 );
7933	} );
7934	
7935	_api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) {
7936		return this.iterator( 'row', function ( settings, row ) {
7937			_fnInvalidate( settings, row, src );
7938		} );
7939	} );
7940	
7941	_api_registerPlural( 'rows().indexes()', 'row().index()', function () {
7942		return this.iterator( 'row', function ( settings, row ) {
7943			return row;
7944		}, 1 );
7945	} );
7946	
7947	_api_registerPlural( 'rows().ids()', 'row().id()', function ( hash ) {
7948		var a = [];
7949		var context = this.context;
7950	
7951		// `iterator` will drop undefined values, but in this case we want them
7952		for ( var i=0, ien=context.length ; i<ien ; i++ ) {
7953			for ( var j=0, jen=this[i].length ; j<jen ; j++ ) {
7954				var id = context[i].rowIdFn( context[i].aoData[ this[i][j] ]._aData );
7955				a.push( (hash === true ? '#' : '' )+ id );
7956			}
7957		}
7958	
7959		return new _Api( context, a );
7960	} );
7961	
7962	_api_registerPlural( 'rows().remove()', 'row().remove()', function () {
7963		var that = this;
7964	
7965		this.iterator( 'row', function ( settings, row, thatIdx ) {
7966			var data = settings.aoData;
7967			var rowData = data[ row ];
7968			var i, ien, j, jen;
7969			var loopRow, loopCells;
7970	
7971			data.splice( row, 1 );
7972	
7973			// Update the cached indexes
7974			for ( i=0, ien=data.length ; i<ien ; i++ ) {
7975				loopRow = data[i];
7976				loopCells = loopRow.anCells;
7977	
7978				// Rows
7979				if ( loopRow.nTr !== null ) {
7980					loopRow.nTr._DT_RowIndex = i;
7981				}
7982	
7983				// Cells
7984				if ( loopCells !== null ) {
7985					for ( j=0, jen=loopCells.length ; j<jen ; j++ ) {
7986						loopCells[j]._DT_CellIndex.row = i;
7987					}
7988				}
7989			}
7990	
7991			// Delete from the display arrays
7992			_fnDeleteIndex( settings.aiDisplayMaster, row );
7993			_fnDeleteIndex( settings.aiDisplay, row );
7994			_fnDeleteIndex( that[ thatIdx ], row, false ); // maintain local indexes
7995	
7996			// Check for an 'overflow' they case for displaying the table
7997			_fnLengthOverflow( settings );
7998	
7999			// Remove the row's ID reference if there is one
8000			var id = settings.rowIdFn( rowData._aData );
8001			if ( id !== undefined ) {
8002				delete settings.aIds[ id ];
8003			}
8004		} );
8005	
8006		this.iterator( 'table', function ( settings ) {
8007			for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
8008				settings.aoData[i].idx = i;
8009			}
8010		} );
8011	
8012		return this;
8013	} );
8014	
8015	
8016	_api_register( 'rows.add()', function ( rows ) {
8017		var newRows = this.iterator( 'table', function ( settings ) {
8018				var row, i, ien;
8019				var out = [];
8020	
8021				for ( i=0, ien=rows.length ; i<ien ; i++ ) {
8022					row = rows[i];
8023	
8024					if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
8025						out.push( _fnAddTr( settings, row )[0] );
8026					}
8027					else {
8028						out.push( _fnAddData( settings, row ) );
8029					}
8030				}
8031	
8032				return out;
8033			}, 1 );
8034	
8035		// Return an Api.rows() extended instance, so rows().nodes() etc can be used
8036		var modRows = this.rows( -1 );
8037		modRows.pop();
8038		$.merge( modRows, newRows );
8039	
8040		return modRows;
8041	} );
8042	
8043	
8044	
8045	
8046	
8047	/**
8048	 *
8049	 */
8050	_api_register( 'row()', function ( selector, opts ) {
8051		return _selector_first( this.rows( selector, opts ) );
8052	} );
8053	
8054	
8055	_api_register( 'row().data()', function ( data ) {
8056		var ctx = this.context;
8057	
8058		if ( data === undefined ) {
8059			// Get
8060			return ctx.length && this.length ?
8061				ctx[0].aoData[ this[0] ]._aData :
8062				undefined;
8063		}
8064	
8065		// Set
8066		ctx[0].aoData[ this[0] ]._aData = data;
8067	
8068		// Automatically invalidate
8069		_fnInvalidate( ctx[0], this[0], 'data' );
8070	
8071		return this;
8072	} );
8073	
8074	
8075	_api_register( 'row().node()', function () {
8076		var ctx = this.context;
8077	
8078		return ctx.length && this.length ?
8079			ctx[0].aoData[ this[0] ].nTr || null :
8080			null;
8081	} );
8082	
8083	
8084	_api_register( 'row.add()', function ( row ) {
8085		// Allow a jQuery object to be passed in - only a single row is added from
8086		// it though - the first element in the set
8087		if ( row instanceof $ && row.length ) {
8088			row = row[0];
8089		}
8090	
8091		var rows = this.iterator( 'table', function ( settings ) {
8092			if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
8093				return _fnAddTr( settings, row )[0];
8094			}
8095			return _fnAddData( settings, row );
8096		} );
8097	
8098		// Return an Api.rows() extended instance, with the newly added row selected
8099		return this.row( rows[0] );
8100	} );
8101	
8102	
8103	
8104	var __details_add = function ( ctx, row, data, klass )
8105	{
8106		// Convert to array of TR elements
8107		var rows = [];
8108		var addRow = function ( r, k ) {
8109			// Recursion to allow for arrays of jQuery objects
8110			if ( $.isArray( r ) || r instanceof $ ) {
8111				for ( var i=0, ien=r.length ; i<ien ; i++ ) {
8112					addRow( r[i], k );
8113				}
8114				return;
8115			}
8116	
8117			// If we get a TR element, then just add it directly - up to the dev
8118			// to add the correct number of columns etc
8119			if ( r.nodeName && r.nodeName.toLowerCase() === 'tr' ) {
8120				rows.push( r );
8121			}
8122			else {
8123				// Otherwise create a row with a wrapper
8124				var created = $('<tr><td/></tr>').addClass( k );
8125				$('td', created)
8126					.addClass( k )
8127					.html( r )
8128					[0].colSpan = _fnVisbleColumns( ctx );
8129	
8130				rows.push( created[0] );
8131			}
8132		};
8133	
8134		addRow( data, klass );
8135	
8136		if ( row._details ) {
8137			row._details.remove();
8138		}
8139	
8140		row._details = $(rows);
8141	
8142		// If the children were already shown, that state should be retained
8143		if ( row._detailsShow ) {
8144			row._details.insertAfter( row.nTr );
8145		}
8146	};
8147	
8148	
8149	var __details_remove = function ( api, idx )
8150	{
8151		var ctx = api.context;
8152	
8153		if ( ctx.length ) {
8154			var row = ctx[0].aoData[ idx !== undefined ? idx : api[0] ];
8155	
8156			if ( row && row._details ) {
8157				row._details.remove();
8158	
8159				row._detailsShow = undefined;
8160				row._details = undefined;
8161			}
8162		}
8163	};
8164	
8165	
8166	var __details_display = function ( api, show ) {
8167		var ctx = api.context;
8168	
8169		if ( ctx.length && api.length ) {
8170			var row = ctx[0].aoData[ api[0] ];
8171	
8172			if ( row._details ) {
8173				row._detailsShow = show;
8174	
8175				if ( show ) {
8176					row._details.insertAfter( row.nTr );
8177				}
8178				else {
8179					row._details.detach();
8180				}
8181	
8182				__details_events( ctx[0] );
8183			}
8184		}
8185	};
8186	
8187	
8188	var __details_events = function ( settings )
8189	{
8190		var api = new _Api( settings );
8191		var namespace = '.dt.DT_details';
8192		var drawEvent = 'draw'+namespace;
8193		var colvisEvent = 'column-visibility'+namespace;
8194		var destroyEvent = 'destroy'+namespace;
8195		var data = settings.aoData;
8196	
8197		api.off( drawEvent +' '+ colvisEvent +' '+ destroyEvent );
8198	
8199		if ( _pluck( data, '_details' ).length > 0 ) {
8200			// On each draw, insert the required elements into the document
8201			api.on( drawEvent, function ( e, ctx ) {
8202				if ( settings !== ctx ) {
8203					return;
8204				}
8205	
8206				api.rows( {page:'current'} ).eq(0).each( function (idx) {
8207					// Internal data grab
8208					var row = data[ idx ];
8209	
8210					if ( row._detailsShow ) {
8211						row._details.insertAfter( row.nTr );
8212					}
8213				} );
8214			} );
8215	
8216			// Column visibility change - update the colspan
8217			api.on( colvisEvent, function ( e, ctx, idx, vis ) {
8218				if ( settings !== ctx ) {
8219					return;
8220				}
8221	
8222				// Update the colspan for the details rows (note, only if it already has
8223				// a colspan)
8224				var row, visible = _fnVisbleColumns( ctx );
8225	
8226				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
8227					row = data[i];
8228	
8229					if ( row._details ) {
8230						row._details.children('td[colspan]').attr('colspan', visible );
8231					}
8232				}
8233			} );
8234	
8235			// Table destroyed - nuke any child rows
8236			api.on( destroyEvent, function ( e, ctx ) {
8237				if ( settings !== ctx ) {
8238					return;
8239				}
8240	
8241				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
8242					if ( data[i]._details ) {
8243						__details_remove( api, i );
8244					}
8245				}
8246			} );
8247		}
8248	};
8249	
8250	// Strings for the method names to help minification
8251	var _emp = '';
8252	var _child_obj = _emp+'row().child';
8253	var _child_mth = _child_obj+'()';
8254	
8255	// data can be:
8256	//  tr
8257	//  string
8258	//  jQuery or array of any of the above
8259	_api_register( _child_mth, function ( data, klass ) {
8260		var ctx = this.context;
8261	
8262		if ( data === undefined ) {
8263			// get
8264			return ctx.length && this.length ?
8265				ctx[0].aoData[ this[0] ]._details :
8266				undefined;
8267		}
8268		else if ( data === true ) {
8269			// show
8270			this.child.show();
8271		}
8272		else if ( data === false ) {
8273			// remove
8274			__details_remove( this );
8275		}
8276		else if ( ctx.length && this.length ) {
8277			// set
8278			__details_add( ctx[0], ctx[0].aoData[ this[0] ], data, klass );
8279		}
8280	
8281		return this;
8282	} );
8283	
8284	
8285	_api_register( [
8286		_child_obj+'.show()',
8287		_child_mth+'.show()' // only when `child()` was called with parameters (without
8288	], function ( show ) {   // it returns an object and this method is not executed)
8289		__details_display( this, true );
8290		return this;
8291	} );
8292	
8293	
8294	_api_register( [
8295		_child_obj+'.hide()',
8296		_child_mth+'.hide()' // only when `child()` was called with parameters (without
8297	], function () {         // it returns an object and this method is not executed)
8298		__details_display( this, false );
8299		return this;
8300	} );
8301	
8302	
8303	_api_register( [
8304		_child_obj+'.remove()',
8305		_child_mth+'.remove()' // only when `child()` was called with parameters (without
8306	], function () {           // it returns an object and this method is not executed)
8307		__details_remove( this );
8308		return this;
8309	} );
8310	
8311	
8312	_api_register( _child_obj+'.isShown()', function () {
8313		var ctx = this.context;
8314	
8315		if ( ctx.length && this.length ) {
8316			// _detailsShown as false or undefined will fall through to return false
8317			return ctx[0].aoData[ this[0] ]._detailsShow || false;
8318		}
8319		return false;
8320	} );
8321	
8322	
8323	
8324	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
8325	 * Columns
8326	 *
8327	 * {integer}           - column index (>=0 count from left, <0 count from right)
8328	 * "{integer}:visIdx"  - visible column index (i.e. translate to column index)  (>=0 count from left, <0 count from right)
8329	 * "{integer}:visible" - alias for {integer}:visIdx  (>=0 count from left, <0 count from right)
8330	 * "{string}:name"     - column name
8331	 * "{string}"          - jQuery selector on column header nodes
8332	 *
8333	 */
8334	
8335	// can be an array of these items, comma separated list, or an array of comma
8336	// separated lists
8337	
8338	var __re_column_selector = /^(.+):(name|visIdx|visible)$/;
8339	
8340	
8341	// r1 and r2 are redundant - but it means that the parameters match for the
8342	// iterator callback in columns().data()
8343	var __columnData = function ( settings, column, r1, r2, rows ) {
8344		var a = [];
8345		for ( var row=0, ien=rows.length ; row<ien ; row++ ) {
8346			a.push( _fnGetCellData( settings, rows[row], column ) );
8347		}
8348		return a;
8349	};
8350	
8351	
8352	var __column_selector = function ( settings, selector, opts )
8353	{
8354		var
8355			columns = settings.aoColumns,
8356			names = _pluck( columns, 'sName' ),
8357			nodes = _pluck( columns, 'nTh' );
8358	
8359		var run = function ( s ) {
8360			var selInt = _intVal( s );
8361	
8362			// Selector - all
8363			if ( s === '' ) {
8364				return _range( columns.length );
8365			}
8366	
8367			// Selector - index
8368			if ( selInt !== null ) {
8369				return [ selInt >= 0 ?
8370					selInt : // Count from left
8371					columns.length + selInt // Count from right (+ because its a negative value)
8372				];
8373			}
8374	
8375			// Selector = function
8376			if ( typeof s === 'function' ) {
8377				var rows = _selector_row_indexes( settings, opts );
8378	
8379				return $.map( columns, function (col, idx) {
8380					return s(
8381							idx,
8382							__columnData( settings, idx, 0, 0, rows ),
8383							nodes[ idx ]
8384						) ? idx : null;
8385				} );
8386			}
8387	
8388			// jQuery or string selector
8389			var match = typeof s === 'string' ?
8390				s.match( __re_column_selector ) :
8391				'';
8392	
8393			if ( match ) {
8394				switch( match[2] ) {
8395					case 'visIdx':
8396					case 'visible':
8397						var idx = parseInt( match[1], 10 );
8398						// Visible index given, convert to column index
8399						if ( idx < 0 ) {
8400							// Counting from the right
8401							var visColumns = $.map( columns, function (col,i) {
8402								return col.bVisible ? i : null;
8403							} );
8404							return [ visColumns[ visColumns.length + idx ] ];
8405						}
8406						// Counting from the left
8407						return [ _fnVisibleToColumnIndex( settings, idx ) ];
8408	
8409					case 'name':
8410						// match by name. `names` is column index complete and in order
8411						return $.map( names, function (name, i) {
8412							return name === match[1] ? i : null;
8413						} );
8414	
8415					default:
8416						return [];
8417				}
8418			}
8419	
8420			// Cell in the table body
8421			if ( s.nodeName && s._DT_CellIndex ) {
8422				return [ s._DT_CellIndex.column ];
8423			}
8424	
8425			// jQuery selector on the TH elements for the columns
8426			var jqResult = $( nodes )
8427				.filter( s )
8428				.map( function () {
8429					return $.inArray( this, nodes ); // `nodes` is column index complete and in order
8430				} )
8431				.toArray();
8432	
8433			if ( jqResult.length || ! s.nodeName ) {
8434				return jqResult;
8435			}
8436	
8437			// Otherwise a node which might have a `dt-column` data attribute, or be
8438			// a child or such an element
8439			var host = $(s).closest('*[data-dt-column]');
8440			return host.length ?
8441				[ host.data('dt-column') ] :
8442				[];
8443		};
8444	
8445		return _selector_run( 'column', selector, run, settings, opts );
8446	};
8447	
8448	
8449	var __setColumnVis = function ( settings, column, vis ) {
8450		var
8451			cols = settings.aoColumns,
8452			col  = cols[ column ],
8453			data = settings.aoData,
8454			row, cells, i, ien, tr;
8455	
8456		// Get
8457		if ( vis === undefined ) {
8458			return col.bVisible;
8459		}
8460	
8461		// Set
8462		// No change
8463		if ( col.bVisible === vis ) {
8464			return;
8465		}
8466	
8467		if ( vis ) {
8468			// Insert column
8469			// Need to decide if we should use appendChild or insertBefore
8470			var insertBefore = $.inArray( true, _pluck(cols, 'bVisible'), column+1 );
8471	
8472			for ( i=0, ien=data.length ; i<ien ; i++ ) {
8473				tr = data[i].nTr;
8474				cells = data[i].anCells;
8475	
8476				if ( tr ) {
8477					// insertBefore can act like appendChild if 2nd arg is null
8478					tr.insertBefore( cells[ column ], cells[ insertBefore ] || null );
8479				}
8480			}
8481		}
8482		else {
8483			// Remove column
8484			$( _pluck( settings.aoData, 'anCells', column ) ).detach();
8485		}
8486	
8487		// Common actions
8488		col.bVisible = vis;
8489		_fnDrawHead( settings, settings.aoHeader );
8490		_fnDrawHead( settings, settings.aoFooter );
8491	
8492		_fnSaveState( settings );
8493	};
8494	
8495	
8496	_api_register( 'columns()', function ( selector, opts ) {
8497		// argument shifting
8498		if ( selector === undefined ) {
8499			selector = '';
8500		}
8501		else if ( $.isPlainObject( selector ) ) {
8502			opts = selector;
8503			selector = '';
8504		}
8505	
8506		opts = _selector_opts( opts );
8507	
8508		var inst = this.iterator( 'table', function ( settings ) {
8509			return __column_selector( settings, selector, opts );
8510		}, 1 );
8511	
8512		// Want argument shifting here and in _row_selector?
8513		inst.selector.cols = selector;
8514		inst.selector.opts = opts;
8515	
8516		return inst;
8517	} );
8518	
8519	_api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) {
8520		return this.iterator( 'column', function ( settings, column ) {
8521			return settings.aoColumns[column].nTh;
8522		}, 1 );
8523	} );
8524	
8525	_api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) {
8526		return this.iterator( 'column', function ( settings, column ) {
8527			return settings.aoColumns[column].nTf;
8528		}, 1 );
8529	} );
8530	
8531	_api_registerPlural( 'columns().data()', 'column().data()', function () {
8532		return this.iterator( 'column-rows', __columnData, 1 );
8533	} );
8534	
8535	_api_registerPlural( 'columns().dataSrc()', 'column().dataSrc()', function () {
8536		return this.iterator( 'column', function ( settings, column ) {
8537			return settings.aoColumns[column].mData;
8538		}, 1 );
8539	} );
8540	
8541	_api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) {
8542		return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8543			return _pluck_order( settings.aoData, rows,
8544				type === 'search' ? '_aFilterData' : '_aSortData', column
8545			);
8546		}, 1 );
8547	} );
8548	
8549	_api_registerPlural( 'columns().nodes()', 'column().nodes()', function () {
8550		return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8551			return _pluck_order( settings.aoData, rows, 'anCells', column ) ;
8552		}, 1 );
8553	} );
8554	
8555	_api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis, calc ) {
8556		var ret = this.iterator( 'column', function ( settings, column ) {
8557			if ( vis === undefined ) {
8558				return settings.aoColumns[ column ].bVisible;
8559			} // else
8560			__setColumnVis( settings, column, vis );
8561		} );
8562	
8563		// Group the column visibility changes
8564		if ( vis !== undefined ) {
8565			// Second loop once the first is done for events
8566			this.iterator( 'column', function ( settings, column ) {
8567				_fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis, calc] );
8568			} );
8569	
8570			if ( calc === undefined || calc ) {
8571				this.columns.adjust();
8572			}
8573		}
8574	
8575		return ret;
8576	} );
8577	
8578	_api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) {
8579		return this.iterator( 'column', function ( settings, column ) {
8580			return type === 'visible' ?
8581				_fnColumnIndexToVisible( settings, column ) :
8582				column;
8583		}, 1 );
8584	} );
8585	
8586	_api_register( 'columns.adjust()', function () {
8587		return this.iterator( 'table', function ( settings ) {
8588			_fnAdjustColumnSizing( settings );
8589		}, 1 );
8590	} );
8591	
8592	_api_register( 'column.index()', function ( type, idx ) {
8593		if ( this.context.length !== 0 ) {
8594			var ctx = this.context[0];
8595	
8596			if ( type === 'fromVisible' || type === 'toData' ) {
8597				return _fnVisibleToColumnIndex( ctx, idx );
8598			}
8599			else if ( type === 'fromData' || type === 'toVisible' ) {
8600				return _fnColumnIndexToVisible( ctx, idx );
8601			}
8602		}
8603	} );
8604	
8605	_api_register( 'column()', function ( selector, opts ) {
8606		return _selector_first( this.columns( selector, opts ) );
8607	} );
8608	
8609	
8610	
8611	var __cell_selector = function ( settings, selector, opts )
8612	{
8613		var data = settings.aoData;
8614		var rows = _selector_row_indexes( settings, opts );
8615		var cells = _removeEmpty( _pluck_order( data, rows, 'anCells' ) );
8616		var allCells = $( [].concat.apply([], cells) );
8617		var row;
8618		var columns = settings.aoColumns.length;
8619		var a, i, ien, j, o, host;
8620	
8621		var run = function ( s ) {
8622			var fnSelector = typeof s === 'function';
8623	
8624			if ( s === null || s === undefined || fnSelector ) {
8625				// All cells and function selectors
8626				a = [];
8627	
8628				for ( i=0, ien=rows.length ; i<ien ; i++ ) {
8629					row = rows[i];
8630	
8631					for ( j=0 ; j<columns ; j++ ) {
8632						o = {
8633							row: row,
8634							column: j
8635						};
8636	
8637						if ( fnSelector ) {
8638							// Selector - function
8639							host = data[ row ];
8640	
8641							if ( s( o, _fnGetCellData(settings, row, j), host.anCells ? host.anCells[j] : null ) ) {
8642								a.push( o );
8643							}
8644						}
8645						else {
8646							// Selector - all
8647							a.push( o );
8648						}
8649					}
8650				}
8651	
8652				return a;
8653			}
8654			
8655			// Selector - index
8656			if ( $.isPlainObject( s ) ) {
8657				return [s];
8658			}
8659	
8660			// Selector - jQuery filtered cells
8661			var jqResult = allCells
8662				.filter( s )
8663				.map( function (i, el) {
8664					return { // use a new object, in case someone changes the values
8665						row:    el._DT_CellIndex.row,
8666						column: el._DT_CellIndex.column
8667	 				};
8668				} )
8669				.toArray();
8670	
8671			if ( jqResult.length || ! s.nodeName ) {
8672				return jqResult;
8673			}
8674	
8675			// Otherwise the selector is a node, and there is one last option - the
8676			// element might be a child of an element which has dt-row and dt-column
8677			// data attributes
8678			host = $(s).closest('*[data-dt-row]');
8679			return host.length ?
8680				[ {
8681					row: host.data('dt-row'),
8682					column: host.data('dt-column')
8683				} ] :
8684				[];
8685		};
8686	
8687		return _selector_run( 'cell', selector, run, settings, opts );
8688	};
8689	
8690	
8691	
8692	
8693	_api_register( 'cells()', function ( rowSelector, columnSelector, opts ) {
8694		// Argument shifting
8695		if ( $.isPlainObject( rowSelector ) ) {
8696			// Indexes
8697			if ( rowSelector.row === undefined ) {
8698				// Selector options in first parameter
8699				opts = rowSelector;
8700				rowSelector = null;
8701			}
8702			else {
8703				// Cell index objects in first parameter
8704				opts = columnSelector;
8705				columnSelector = null;
8706			}
8707		}
8708		if ( $.isPlainObject( columnSelector ) ) {
8709			opts = columnSelector;
8710			columnSelector = null;
8711		}
8712	
8713		// Cell selector
8714		if ( columnSelector === null || columnSelector === undefined ) {
8715			return this.iterator( 'table', function ( settings ) {
8716				return __cell_selector( settings, rowSelector, _selector_opts( opts ) );
8717			} );
8718		}
8719	
8720		// Row + column selector
8721		var columns = this.columns( columnSelector, opts );
8722		var rows = this.rows( rowSelector, opts );
8723		var a, i, ien, j, jen;
8724	
8725		var cells = this.iterator( 'table', function ( settings, idx ) {
8726			a = [];
8727	
8728			for ( i=0, ien=rows[idx].length ; i<ien ; i++ ) {
8729				for ( j=0, jen=columns[idx].length ; j<jen ; j++ ) {
8730					a.push( {
8731						row:    rows[idx][i],
8732						column: columns[idx][j]
8733					} );
8734				}
8735			}
8736	
8737			return a;
8738		}, 1 );
8739	
8740		$.extend( cells.selector, {
8741			cols: columnSelector,
8742			rows: rowSelector,
8743			opts: opts
8744		} );
8745	
8746		return cells;
8747	} );
8748	
8749	
8750	_api_registerPlural( 'cells().nodes()', 'cell().node()', function () {
8751		return this.iterator( 'cell', function ( settings, row, column ) {
8752			var data = settings.aoData[ row ];
8753	
8754			return data && data.anCells ?
8755				data.anCells[ column ] :
8756				undefined;
8757		}, 1 );
8758	} );
8759	
8760	
8761	_api_register( 'cells().data()', function () {
8762		return this.iterator( 'cell', function ( settings, row, column ) {
8763			return _fnGetCellData( settings, row, column );
8764		}, 1 );
8765	} );
8766	
8767	
8768	_api_registerPlural( 'cells().cache()', 'cell().cache()', function ( type ) {
8769		type = type === 'search' ? '_aFilterData' : '_aSortData';
8770	
8771		return this.iterator( 'cell', function ( settings, row, column ) {
8772			return settings.aoData[ row ][ type ][ column ];
8773		}, 1 );
8774	} );
8775	
8776	
8777	_api_registerPlural( 'cells().render()', 'cell().render()', function ( type ) {
8778		return this.iterator( 'cell', function ( settings, row, column ) {
8779			return _fnGetCellData( settings, row, column, type );
8780		}, 1 );
8781	} );
8782	
8783	
8784	_api_registerPlural( 'cells().indexes()', 'cell().index()', function () {
8785		return this.iterator( 'cell', function ( settings, row, column ) {
8786			return {
8787				row: row,
8788				column: column,
8789				columnVisible: _fnColumnIndexToVisible( settings, column )
8790			};
8791		}, 1 );
8792	} );
8793	
8794	
8795	_api_registerPlural( 'cells().invalidate()', 'cell().invalidate()', function ( src ) {
8796		return this.iterator( 'cell', function ( settings, row, column ) {
8797			_fnInvalidate( settings, row, src, column );
8798		} );
8799	} );
8800	
8801	
8802	
8803	_api_register( 'cell()', function ( rowSelector, columnSelector, opts ) {
8804		return _selector_first( this.cells( rowSelector, columnSelector, opts ) );
8805	} );
8806	
8807	
8808	_api_register( 'cell().data()', function ( data ) {
8809		var ctx = this.context;
8810		var cell = this[0];
8811	
8812		if ( data === undefined ) {
8813			// Get
8814			return ctx.length && cell.length ?
8815				_fnGetCellData( ctx[0], cell[0].row, cell[0].column ) :
8816				undefined;
8817		}
8818	
8819		// Set
8820		_fnSetCellData( ctx[0], cell[0].row, cell[0].column, data );
8821		_fnInvalidate( ctx[0], cell[0].row, 'data', cell[0].column );
8822	
8823		return this;
8824	} );
8825	
8826	
8827	
8828	/**
8829	 * Get current ordering (sorting) that has been applied to the table.
8830	 *
8831	 * @returns {array} 2D array containing the sorting information for the first
8832	 *   table in the current context. Each element in the parent array represents
8833	 *   a column being sorted upon (i.e. multi-sorting with two columns would have
8834	 *   2 inner arrays). The inner arrays may have 2 or 3 elements. The first is
8835	 *   the column index that the sorting condition applies to, the second is the
8836	 *   direction of the sort (`desc` or `asc`) and, optionally, the third is the
8837	 *   index of the sorting order from the `column.sorting` initialisation array.
8838	 *//**
8839	 * Set the ordering for the table.
8840	 *
8841	 * @param {integer} order Column index to sort upon.
8842	 * @param {string} direction Direction of the sort to be applied (`asc` or `desc`)
8843	 * @returns {DataTables.Api} this
8844	 *//**
8845	 * Set the ordering for the table.
8846	 *
8847	 * @param {array} order 1D array of sorting information to be applied.
8848	 * @param {array} [...] Optional additional sorting conditions
8849	 * @returns {DataTables.Api} this
8850	 *//**
8851	 * Set the ordering for the table.
8852	 *
8853	 * @param {array} order 2D array of sorting information to be applied.
8854	 * @returns {DataTables.Api} this
8855	 */
8856	_api_register( 'order()', function ( order, dir ) {
8857		var ctx = this.context;
8858	
8859		if ( order === undefined ) {
8860			// get
8861			return ctx.length !== 0 ?
8862				ctx[0].aaSorting :
8863				undefined;
8864		}
8865	
8866		// set
8867		if ( typeof order === 'number' ) {
8868			// Simple column / direction passed in
8869			order = [ [ order, dir ] ];
8870		}
8871		else if ( order.length && ! $.isArray( order[0] ) ) {
8872			// Arguments passed in (list of 1D arrays)
8873			order = Array.prototype.slice.call( arguments );
8874		}
8875		// otherwise a 2D array was passed in
8876	
8877		return this.iterator( 'table', function ( settings ) {
8878			settings.aaSorting = order.slice();
8879		} );
8880	} );
8881	
8882	
8883	/**
8884	 * Attach a sort listener to an element for a given column
8885	 *
8886	 * @param {node|jQuery|string} node Identifier for the element(s) to attach the
8887	 *   listener to. This can take the form of a single DOM node, a jQuery
8888	 *   collection of nodes or a jQuery selector which will identify the node(s).
8889	 * @param {integer} column the column that a click on this node will sort on
8890	 * @param {function} [callback] callback function when sort is run
8891	 * @returns {DataTables.Api} this
8892	 */
8893	_api_register( 'order.listener()', function ( node, column, callback ) {
8894		return this.iterator( 'table', function ( settings ) {
8895			_fnSortAttachListener( settings, node, column, callback );
8896		} );
8897	} );
8898	
8899	
8900	_api_register( 'order.fixed()', function ( set ) {
8901		if ( ! set ) {
8902			var ctx = this.context;
8903			var fixed = ctx.length ?
8904				ctx[0].aaSortingFixed :
8905				undefined;
8906	
8907			return $.isArray( fixed ) ?
8908				{ pre: fixed } :
8909				fixed;
8910		}
8911	
8912		return this.iterator( 'table', function ( settings ) {
8913			settings.aaSortingFixed = $.extend( true, {}, set );
8914		} );
8915	} );
8916	
8917	
8918	// Order by the selected column(s)
8919	_api_register( [
8920		'columns().order()',
8921		'column().order()'
8922	], function ( dir ) {
8923		var that = this;
8924	
8925		return this.iterator( 'table', function ( settings, i ) {
8926			var sort = [];
8927	
8928			$.each( that[i], function (j, col) {
8929				sort.push( [ col, dir ] );
8930			} );
8931	
8932			settings.aaSorting = sort;
8933		} );
8934	} );
8935	
8936	
8937	
8938	_api_register( 'search()', function ( input, regex, smart, caseInsen ) {
8939		var ctx = this.context;
8940	
8941		if ( input === undefined ) {
8942			// get
8943			return ctx.length !== 0 ?
8944				ctx[0].oPreviousSearch.sSearch :
8945				undefined;
8946		}
8947	
8948		// set
8949		return this.iterator( 'table', function ( settings ) {
8950			if ( ! settings.oFeatures.bFilter ) {
8951				return;
8952			}
8953	
8954			_fnFilterComplete( settings, $.extend( {}, settings.oPreviousSearch, {
8955				"sSearch": input+"",
8956				"bRegex":  regex === null ? false : regex,
8957				"bSmart":  smart === null ? true  : smart,
8958				"bCaseInsensitive": caseInsen === null ? true : caseInsen
8959			} ), 1 );
8960		} );
8961	} );
8962	
8963	
8964	_api_registerPlural(
8965		'columns().search()',
8966		'column().search()',
8967		function ( input, regex, smart, caseInsen ) {
8968			return this.iterator( 'column', function ( settings, column ) {
8969				var preSearch = settings.aoPreSearchCols;
8970	
8971				if ( input === undefined ) {
8972					// get
8973					return preSearch[ column ].sSearch;
8974				}
8975	
8976				// set
8977				if ( ! settings.oFeatures.bFilter ) {
8978					return;
8979				}
8980	
8981				$.extend( preSearch[ column ], {
8982					"sSearch": input+"",
8983					"bRegex":  regex === null ? false : regex,
8984					"bSmart":  smart === null ? true  : smart,
8985					"bCaseInsensitive": caseInsen === null ? true : caseInsen
8986				} );
8987	
8988				_fnFilterComplete( settings, settings.oPreviousSearch, 1 );
8989			} );
8990		}
8991	);
8992	
8993	/*
8994	 * State API methods
8995	 */
8996	
8997	_api_register( 'state()', function () {
8998		return this.context.length ?
8999			this.context[0].oSavedState :
9000			null;
9001	} );
9002	
9003	
9004	_api_register( 'state.clear()', function () {
9005		return this.iterator( 'table', function ( settings ) {
9006			// Save an empty object
9007			settings.fnStateSaveCallback.call( settings.oInstance, settings, {} );
9008		} );
9009	} );
9010	
9011	
9012	_api_register( 'state.loaded()', function () {
9013		return this.context.length ?
9014			this.context[0].oLoadedState :
9015			null;
9016	} );
9017	
9018	
9019	_api_register( 'state.save()', function () {
9020		return this.iterator( 'table', function ( settings ) {
9021			_fnSaveState( settings );
9022		} );
9023	} );
9024	
9025	
9026	
9027	/**
9028	 * Provide a common method for plug-ins to check the version of DataTables being
9029	 * used, in order to ensure compatibility.
9030	 *
9031	 *  @param {string} version Version string to check for, in the format "X.Y.Z".
9032	 *    Note that the formats "X" and "X.Y" are also acceptable.
9033	 *  @returns {boolean} true if this version of DataTables is greater or equal to
9034	 *    the required version, or false if this version of DataTales is not
9035	 *    suitable
9036	 *  @static
9037	 *  @dtopt API-Static
9038	 *
9039	 *  @example
9040	 *    alert( $.fn.dataTable.versionCheck( '1.9.0' ) );
9041	 */
9042	DataTable.versionCheck = DataTable.fnVersionCheck = function( version )
9043	{
9044		var aThis = DataTable.version.split('.');
9045		var aThat = version.split('.');
9046		var iThis, iThat;
9047	
9048		for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) {
9049			iThis = parseInt( aThis[i], 10 ) || 0;
9050			iThat = parseInt( aThat[i], 10 ) || 0;
9051	
9052			// Parts are the same, keep comparing
9053			if (iThis === iThat) {
9054				continue;
9055			}
9056	
9057			// Parts are different, return immediately
9058			return iThis > iThat;
9059		}
9060	
9061		return true;
9062	};
9063	
9064	
9065	/**
9066	 * Check if a `<table>` node is a DataTable table already or not.
9067	 *
9068	 *  @param {node|jquery|string} table Table node, jQuery object or jQuery
9069	 *      selector for the table to test. Note that if more than more than one
9070	 *      table is passed on, only the first will be checked
9071	 *  @returns {boolean} true the table given is a DataTable, or false otherwise
9072	 *  @static
9073	 *  @dtopt API-Static
9074	 *
9075	 *  @example
9076	 *    if ( ! $.fn.DataTable.isDataTable( '#example' ) ) {
9077	 *      $('#example').dataTable();
9078	 *    }
9079	 */
9080	DataTable.isDataTable = DataTable.fnIsDataTable = function ( table )
9081	{
9082		var t = $(table).get(0);
9083		var is = false;
9084	
9085		$.each( DataTable.settings, function (i, o) {
9086			var head = o.nScrollHead ? $('table', o.nScrollHead)[0] : null;
9087			var foot = o.nScrollFoot ? $('table', o.nScrollFoot)[0] : null;
9088	
9089			if ( o.nTable === t || head === t || foot === t ) {
9090				is = true;
9091			}
9092		} );
9093	
9094		return is;
9095	};
9096	
9097	
9098	/**
9099	 * Get all DataTable tables that have been initialised - optionally you can
9100	 * select to get only currently visible tables.
9101	 *
9102	 *  @param {boolean} [visible=false] Flag to indicate if you want all (default)
9103	 *    or visible tables only.
9104	 *  @returns {array} Array of `table` nodes (not DataTable instances) which are
9105	 *    DataTables
9106	 *  @static
9107	 *  @dtopt API-Static
9108	 *
9109	 *  @example
9110	 *    $.each( $.fn.dataTable.tables(true), function () {
9111	 *      $(table).DataTable().columns.adjust();
9112	 *    } );
9113	 */
9114	DataTable.tables = DataTable.fnTables = function ( visible )
9115	{
9116		var api = false;
9117	
9118		if ( $.isPlainObject( visible ) ) {
9119			api = visible.api;
9120			visible = visible.visible;
9121		}
9122	
9123		var a = $.map( DataTable.settings, function (o) {
9124			if ( !visible || (visible && $(o.nTable).is(':visible')) ) {
9125				return o.nTable;
9126			}
9127		} );
9128	
9129		return api ?
9130			new _Api( a ) :
9131			a;
9132	};
9133	
9134	
9135	/**
9136	 * Convert from camel case parameters to Hungarian notation. This is made public
9137	 * for the extensions to provide the same ability as DataTables core to accept
9138	 * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase
9139	 * parameters.
9140	 *
9141	 *  @param {object} src The model object which holds all parameters that can be
9142	 *    mapped.
9143	 *  @param {object} user The object to convert from camel case to Hungarian.
9144	 *  @param {boolean} force When set to `true`, properties which already have a
9145	 *    Hungarian value in the `user` object will be overwritten. Otherwise they
9146	 *    won't be.
9147	 */
9148	DataTable.camelToHungarian = _fnCamelToHungarian;
9149	
9150	
9151	
9152	/**
9153	 *
9154	 */
9155	_api_register( '$()', function ( selector, opts ) {
9156		var
9157			rows   = this.rows( opts ).nodes(), // Get all rows
9158			jqRows = $(rows);
9159	
9160		return $( [].concat(
9161			jqRows.filter( selector ).toArray(),
9162			jqRows.find( selector ).toArray()
9163		) );
9164	} );
9165	
9166	
9167	// jQuery functions to operate on the tables
9168	$.each( [ 'on', 'one', 'off' ], function (i, key) {
9169		_api_register( key+'()', function ( /* event, handler */ ) {
9170			var args = Array.prototype.slice.call(arguments);
9171	
9172			// Add the `dt` namespace automatically if it isn't already present
9173			if ( ! args[0].match(/\.dt\b/) ) {
9174				args[0] += '.dt';
9175			}
9176	
9177			var inst = $( this.tables().nodes() );
9178			inst[key].apply( inst, args );
9179			return this;
9180		} );
9181	} );
9182	
9183	
9184	_api_register( 'clear()', function () {
9185		return this.iterator( 'table', function ( settings ) {
9186			_fnClearTable( settings );
9187		} );
9188	} );
9189	
9190	
9191	_api_register( 'settings()', function () {
9192		return new _Api( this.context, this.context );
9193	} );
9194	
9195	
9196	_api_register( 'init()', function () {
9197		var ctx = this.context;
9198		return ctx.length ? ctx[0].oInit : null;
9199	} );
9200	
9201	
9202	_api_register( 'data()', function () {
9203		return this.iterator( 'table', function ( settings ) {
9204			return _pluck( settings.aoData, '_aData' );
9205		} ).flatten();
9206	} );
9207	
9208	
9209	_api_register( 'destroy()', function ( remove ) {
9210		remove = remove || false;
9211	
9212		return this.iterator( 'table', function ( settings ) {
9213			var orig      = settings.nTableWrapper.parentNode;
9214			var classes   = settings.oClasses;
9215			var table     = settings.nTable;
9216			var tbody     = settings.nTBody;
9217			var thead     = settings.nTHead;
9218			var tfoot     = settings.nTFoot;
9219			var jqTable   = $(table);
9220			var jqTbody   = $(tbody);
9221			var jqWrapper = $(settings.nTableWrapper);
9222			var rows      = $.map( settings.aoData, function (r) { return r.nTr; } );
9223			var i, ien;
9224	
9225			// Flag to note that the table is currently being destroyed - no action
9226			// should be taken
9227			settings.bDestroying = true;
9228	
9229			// Fire off the destroy callbacks for plug-ins etc
9230			_fnCallbackFire( settings, "aoDestroyCallback", "destroy", [settings] );
9231	
9232			// If not being removed from the document, make all columns visible
9233			if ( ! remove ) {
9234				new _Api( settings ).columns().visible( true );
9235			}
9236	
9237			// Blitz all `DT` namespaced events (these are internal events, the
9238			// lowercase, `dt` events are user subscribed and they are responsible
9239			// for removing them
9240			jqWrapper.unbind('.DT').find(':not(tbody *)').unbind('.DT');
9241			$(window).unbind('.DT-'+settings.sInstance);
9242	
9243			// When scrolling we had to break the table up - restore it
9244			if ( table != thead.parentNode ) {
9245				jqTable.children('thead').detach();
9246				jqTable.append( thead );
9247			}
9248	
9249			if ( tfoot && table != tfoot.parentNode ) {
9250				jqTable.children('tfoot').detach();
9251				jqTable.append( tfoot );
9252			}
9253	
9254			settings.aaSorting = [];
9255			settings.aaSortingFixed = [];
9256			_fnSortingClasses( settings );
9257	
9258			$( rows ).removeClass( settings.asStripeClasses.join(' ') );
9259	
9260			$('th, td', thead).removeClass( classes.sSortable+' '+
9261				classes.sSortableAsc+' '+classes.sSortableDesc+' '+classes.sSortableNone
9262			);
9263	
9264			if ( settings.bJUI ) {
9265				$('th span.'+classes.sSortIcon+ ', td span.'+classes.sSortIcon, thead).detach();
9266				$('th, td', thead).each( function () {
9267					var wrapper = $('div.'+classes.sSortJUIWrapper, this);
9268					$(this).append( wrapper.contents() );
9269					wrapper.detach();
9270				} );
9271			}
9272	
9273			// Add the TR elements back into the table in their original order
9274			jqTbody.children().detach();
9275			jqTbody.append( rows );
9276	
9277			// Remove the DataTables generated nodes, events and classes
9278			var removedMethod = remove ? 'remove' : 'detach';
9279			jqTable[ removedMethod ]();
9280			jqWrapper[ removedMethod ]();
9281	
9282			// If we need to reattach the table to the document
9283			if ( ! remove && orig ) {
9284				// insertBefore acts like appendChild if !arg[1]
9285				orig.insertBefore( table, settings.nTableReinsertBefore );
9286	
9287				// Restore the width of the original table - was read from the style property,
9288				// so we can restore directly to that
9289				jqTable
9290					.css( 'width', settings.sDestroyWidth )
9291					.removeClass( classes.sTable );
9292	
9293				// If the were originally stripe classes - then we add them back here.
9294				// Note this is not fool proof (for example if not all rows had stripe
9295				// classes - but it's a good effort without getting carried away
9296				ien = settings.asDestroyStripes.length;
9297	
9298				if ( ien ) {
9299					jqTbody.children().each( function (i) {
9300						$(this).addClass( settings.asDestroyStripes[i % ien] );
9301					} );
9302				}
9303			}
9304	
9305			/* Remove the settings object from the settings array */
9306			var idx = $.inArray( settings, DataTable.settings );
9307			if ( idx !== -1 ) {
9308				DataTable.settings.splice( idx, 1 );
9309			}
9310		} );
9311	} );
9312	
9313	
9314	// Add the `every()` method for rows, columns and cells in a compact form
9315	$.each( [ 'column', 'row', 'cell' ], function ( i, type ) {
9316		_api_register( type+'s().every()', function ( fn ) {
9317			var opts = this.selector.opts;
9318			var api = this;
9319	
9320			return this.iterator( type, function ( settings, arg1, arg2, arg3, arg4 ) {
9321				// Rows and columns:
9322				//  arg1 - index
9323				//  arg2 - table counter
9324				//  arg3 - loop counter
9325				//  arg4 - undefined
9326				// Cells:
9327				//  arg1 - row index
9328				//  arg2 - column index
9329				//  arg3 - table counter
9330				//  arg4 - loop counter
9331				fn.call(
9332					api[ type ](
9333						arg1,
9334						type==='cell' ? arg2 : opts,
9335						type==='cell' ? opts : undefined
9336					),
9337					arg1, arg2, arg3, arg4
9338				);
9339			} );
9340		} );
9341	} );
9342	
9343	
9344	// i18n method for extensions to be able to use the language object from the
9345	// DataTable
9346	_api_register( 'i18n()', function ( token, def, plural ) {
9347		var ctx = this.context[0];
9348		var resolved = _fnGetObjectDataFn( token )( ctx.oLanguage );
9349	
9350		if ( resolved === undefined ) {
9351			resolved = def;
9352		}
9353	
9354		if ( plural !== undefined && $.isPlainObject( resolved ) ) {
9355			resolved = resolved[ plural ] !== undefined ?
9356				resolved[ plural ] :
9357				resolved._;
9358		}
9359	
9360		return resolved.replace( '%d', plural ); // nb: plural might be undefined,
9361	} );
9362
9363	/**
9364	 * Version string for plug-ins to check compatibility. Allowed format is
9365	 * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used
9366	 * only for non-release builds. See http://semver.org/ for more information.
9367	 *  @member
9368	 *  @type string
9369	 *  @default Version number
9370	 */
9371	DataTable.version = "1.10.12";
9372
9373	/**
9374	 * Private data store, containing all of the settings objects that are
9375	 * created for the tables on a given page.
9376	 *
9377	 * Note that the `DataTable.settings` object is aliased to
9378	 * `jQuery.fn.dataTableExt` through which it may be accessed and
9379	 * manipulated, or `jQuery.fn.dataTable.settings`.
9380	 *  @member
9381	 *  @type array
9382	 *  @default []
9383	 *  @private
9384	 */
9385	DataTable.settings = [];
9386
9387	/**
9388	 * Object models container, for the various models that DataTables has
9389	 * available to it. These models define the objects that are used to hold
9390	 * the active state and configuration of the table.
9391	 *  @namespace
9392	 */
9393	DataTable.models = {};
9394	
9395	
9396	
9397	/**
9398	 * Template object for the way in which DataTables holds information about
9399	 * search information for the global filter and individual column filters.
9400	 *  @namespace
9401	 */
9402	DataTable.models.oSearch = {
9403		/**
9404		 * Flag to indicate if the filtering should be case insensitive or not
9405		 *  @type boolean
9406		 *  @default true
9407		 */
9408		"bCaseInsensitive": true,
9409	
9410		/**
9411		 * Applied search term
9412		 *  @type string
9413		 *  @default <i>Empty string</i>
9414		 */
9415		"sSearch": "",
9416	
9417		/**
9418		 * Flag to indicate if the search term should be interpreted as a
9419		 * regular expression (true) or not (false) and therefore and special
9420		 * regex characters escaped.
9421		 *  @type boolean
9422		 *  @default false
9423		 */
9424		"bRegex": false,
9425	
9426		/**
9427		 * Flag to indicate if DataTables is to use its smart filtering or not.
9428		 *  @type boolean
9429		 *  @default true
9430		 */
9431		"bSmart": true
9432	};
9433	
9434	
9435	
9436	
9437	/**
9438	 * Template object for the way in which DataTables holds information about
9439	 * each individual row. This is the object format used for the settings
9440	 * aoData array.
9441	 *  @namespace
9442	 */
9443	DataTable.models.oRow = {
9444		/**
9445		 * TR element for the row
9446		 *  @type node
9447		 *  @default null
9448		 */
9449		"nTr": null,
9450	
9451		/**
9452		 * Array of TD elements for each row. This is null until the row has been
9453		 * created.
9454		 *  @type array nodes
9455		 *  @default []
9456		 */
9457		"anCells": null,
9458	
9459		/**
9460		 * Data object from the original data source for the row. This is either
9461		 * an array if using the traditional form of DataTables, or an object if
9462		 * using mData options. The exact type will depend on the passed in
9463		 * data from the data source, or will be an array if using DOM a data
9464		 * source.
9465		 *  @type array|object
9466		 *  @default []
9467		 */
9468		"_aData": [],
9469	
9470		/**
9471		 * Sorting data cache - this array is ostensibly the same length as the
9472		 * number of columns (although each index is generated only as it is
9473		 * needed), and holds the data that is used for sorting each column in the
9474		 * row. We do this cache generation at the start of the sort in order that
9475		 * the formatting of the sort data need be done only once for each cell
9476		 * per sort. This array should not be read from or written to by anything
9477		 * other than the master sorting methods.
9478		 *  @type array
9479		 *  @default null
9480		 *  @private
9481		 */
9482		"_aSortData": null,
9483	
9484		/**
9485		 * Per cell filtering data cache. As per the sort data cache, used to
9486		 * increase the performance of the filtering in DataTables
9487		 *  @type array
9488		 *  @default null
9489		 *  @private
9490		 */
9491		"_aFilterData": null,
9492	
9493		/**
9494		 * Filtering data cache. This is the same as the cell filtering cache, but
9495		 * in this case a string rather than an array. This is easily computed with
9496		 * a join on `_aFilterData`, but is provided as a cache so the join isn't
9497		 * needed on every search (memory traded for performance)
9498		 *  @type array
9499		 *  @default null
9500		 *  @private
9501		 */
9502		"_sFilterRow": null,
9503	
9504		/**
9505		 * Cache of the class name that DataTables has applied to the row, so we
9506		 * can quickly look at this variable rather than needing to do a DOM check
9507		 * on className for the nTr property.
9508		 *  @type string
9509		 *  @default <i>Empty string</i>
9510		 *  @private
9511		 */
9512		"_sRowStripe": "",
9513	
9514		/**
9515		 * Denote if the original data source was from the DOM, or the data source
9516		 * object. This is used for invalidating data, so DataTables can
9517		 * automatically read data from the original source, unless uninstructed
9518		 * otherwise.
9519		 *  @type string
9520		 *  @default null
9521		 *  @private
9522		 */
9523		"src": null,
9524	
9525		/**
9526		 * Index in the aoData array. This saves an indexOf lookup when we have the
9527		 * object, but want to know the index
9528		 *  @type integer
9529		 *  @default -1
9530		 *  @private
9531		 */
9532		"idx": -1
9533	};
9534	
9535	
9536	/**
9537	 * Template object for the column information object in DataTables. This object
9538	 * is held in the settings aoColumns array and contains all the information that
9539	 * DataTables needs about each individual column.
9540	 *
9541	 * Note that this object is related to {@link DataTable.defaults.column}
9542	 * but this one is the internal data store for DataTables's cache of columns.
9543	 * It should NOT be manipulated outside of DataTables. Any configuration should
9544	 * be done through the initialisation options.
9545	 *  @namespace
9546	 */
9547	DataTable.models.oColumn = {
9548		/**
9549		 * Column index. This could be worked out on-the-fly with $.inArray, but it
9550		 * is faster to just hold it as a variable
9551		 *  @type integer
9552		 *  @default null
9553		 */
9554		"idx": null,
9555	
9556		/**
9557		 * A list of the columns that sorting should occur on when this column
9558		 * is sorted. That this property is an array allows multi-column sorting
9559		 * to be defined for a column (for example first name / last name columns
9560		 * would benefit from this). The values are integers pointing to the
9561		 * columns to be sorted on (typically it will be a single integer pointing
9562		 * at itself, but that doesn't need to be the case).
9563		 *  @type array
9564		 */
9565		"aDataSort": null,
9566	
9567		/**
9568		 * Define the sorting directions that are applied to the column, in sequence
9569		 * as the column is repeatedly sorted upon - i.e. the first value is used
9570		 * as the sorting direction when the column if first sorted (clicked on).
9571		 * Sort it again (click again) and it will move on to the next index.
9572		 * Repeat until loop.
9573		 *  @type array
9574		 */
9575		"asSorting": null,
9576	
9577		/**
9578		 * Flag to indicate if the column is searchable, and thus should be included
9579		 * in the filtering or not.
9580		 *  @type boolean
9581		 */
9582		"bSearchable": null,
9583	
9584		/**
9585		 * Flag to indicate if the column is sortable or not.
9586		 *  @type boolean
9587		 */
9588		"bSortable": null,
9589	
9590		/**
9591		 * Flag to indicate if the column is currently visible in the table or not
9592		 *  @type boolean
9593		 */
9594		"bVisible": null,
9595	
9596		/**
9597		 * Store for manual type assignment using the `column.type` option. This
9598		 * is held in store so we can manipulate the column's `sType` property.
9599		 *  @type string
9600		 *  @default null
9601		 *  @private
9602		 */
9603		"_sManualType": null,
9604	
9605		/**
9606		 * Flag to indicate if HTML5 data attributes should be used as the data
9607		 * source for filtering or sorting. True is either are.
9608		 *  @type boolean
9609		 *  @default false
9610		 *  @private
9611		 */
9612		"_bAttrSrc": false,
9613	
9614		/**
9615		 * Developer definable function that is called whenever a cell is created (Ajax source,
9616		 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
9617		 * allowing you to modify the DOM element (add background colour for example) when the
9618		 * element is available.
9619		 *  @type function
9620		 *  @param {element} nTd The TD node that has been created
9621		 *  @param {*} sData The Data for the cell
9622		 *  @param {array|object} oData The data for the whole row
9623		 *  @param {int} iRow The row index for the aoData data store
9624		 *  @default null
9625		 */
9626		"fnCreatedCell": null,
9627	
9628		/**
9629		 * Function to get data from a cell in a column. You should <b>never</b>
9630		 * access data directly through _aData internally in DataTables - always use
9631		 * the method attached to this property. It allows mData to function as
9632		 * required. This function is automatically assigned by the column
9633		 * initialisation method
9634		 *  @type function
9635		 *  @param {array|object} oData The data array/object for the array
9636		 *    (i.e. aoData[]._aData)
9637		 *  @param {string} sSpecific The specific data type you want to get -
9638		 *    'display', 'type' 'filter' 'sort'
9639		 *  @returns {*} The data for the cell from the given row's data
9640		 *  @default null
9641		 */
9642		"fnGetData": null,
9643	
9644		/**
9645		 * Function to set data for a cell in the column. You should <b>never</b>
9646		 * set the data directly to _aData internally in DataTables - always use
9647		 * this method. It allows mData to function as required. This function
9648		 * is automatically assigned by the column initialisation method
9649		 *  @type function
9650		 *  @param {array|object} oData The data array/object for the array
9651		 *    (i.e. aoData[]._aData)
9652		 *  @param {*} sValue Value to set
9653		 *  @default null
9654		 */
9655		"fnSetData": null,
9656	
9657		/**
9658		 * Property to read the value for the cells in the column from the data
9659		 * source array / object. If null, then the default content is used, if a
9660		 * function is given then the return from the function is used.
9661		 *  @type function|int|string|null
9662		 *  @default null
9663		 */
9664		"mData": null,
9665	
9666		/**
9667		 * Partner property to mData which is used (only when defined) to get
9668		 * the data - i.e. it is basically the same as mData, but without the
9669		 * 'set' option, and also the data fed to it is the result from mData.
9670		 * This is the rendering method to match the data method of mData.
9671		 *  @type function|int|string|null
9672		 *  @default null
9673		 */
9674		"mRender": null,
9675	
9676		/**
9677		 * Unique header TH/TD element for this column - this is what the sorting
9678		 * listener is attached to (if sorting is enabled.)
9679		 *  @type node
9680		 *  @default null
9681		 */
9682		"nTh": null,
9683	
9684		/**
9685		 * Unique footer TH/TD element for this column (if there is one). Not used
9686		 * in DataTables as such, but can be used for plug-ins to reference the
9687		 * footer for each column.
9688		 *  @type node
9689		 *  @default null
9690		 */
9691		"nTf": null,
9692	
9693		/**
9694		 * The class to apply to all TD elements in the table's TBODY for the column
9695		 *  @type string
9696		 *  @default null
9697		 */
9698		"sClass": null,
9699	
9700		/**
9701		 * When DataTables calculates the column widths to assign to each column,
9702		 * it finds the longest string in each column and then constructs a
9703		 * temporary table and reads the widths from that. The problem with this
9704		 * is that "mmm" is much wider then "iiii", but the latter is a longer
9705		 * string - thus the calculation can go wrong (doing it properly and putting
9706		 * it into an DOM object and measuring that is horribly(!) slow). Thus as
9707		 * a "work around" we provide this option. It will append its value to the
9708		 * text that is found to be the longest string for the column - i.e. padding.
9709		 *  @type string
9710		 */
9711		"sContentPadding": null,
9712	
9713		/**
9714		 * Allows a default value to be given for a column's data, and will be used
9715		 * whenever a null data source is encountered (this can be because mData
9716		 * is set to null, or because the data source itself is null).
9717		 *  @type string
9718		 *  @default null
9719		 */
9720		"sDefaultContent": null,
9721	
9722		/**
9723		 * Name for the column, allowing reference to the column by name as well as
9724		 * by index (needs a lookup to work by name).
9725		 *  @type string
9726		 */
9727		"sName": null,
9728	
9729		/**
9730		 * Custom sorting data type - defines which of the available plug-ins in
9731		 * afnSortData the custom sorting will use - if any is defined.
9732		 *  @type string
9733		 *  @default std
9734		 */
9735		"sSortDataType": 'std',
9736	
9737		/**
9738		 * Class to be applied to the header element when sorting on this column
9739		 *  @type string
9740		 *  @default null
9741		 */
9742		"sSortingClass": null,
9743	
9744		/**
9745		 * Class to be applied to the header element when sorting on this column -
9746		 * when jQuery UI theming is used.
9747		 *  @type string
9748		 *  @default null
9749		 */
9750		"sSortingClassJUI": null,
9751	
9752		/**
9753		 * Title of the column - what is seen in the TH element (nTh).
9754		 *  @type string
9755		 */
9756		"sTitle": null,
9757	
9758		/**
9759		 * Column sorting and filtering type
9760		 *  @type string
9761		 *  @default null
9762		 */
9763		"sType": null,
9764	
9765		/**
9766		 * Width of the column
9767		 *  @type string
9768		 *  @default null
9769		 */
9770		"sWidth": null,
9771	
9772		/**
9773		 * Width of the column when it was first "encountered"
9774		 *  @type string
9775		 *  @default null
9776		 */
9777		"sWidthOrig": null
9778	};
9779	
9780	
9781	/*
9782	 * Developer note: The properties of the object below are given in Hungarian
9783	 * notation, that was used as the interface for DataTables prior to v1.10, however
9784	 * from v1.10 onwards the primary interface is camel case. In order to avoid
9785	 * breaking backwards compatibility utterly with this change, the Hungarian
9786	 * version is still, internally the primary interface, but is is not documented
9787	 * - hence the @name tags in each doc comment. This allows a Javascript function
9788	 * to create a map from Hungarian notation to camel case (going the other direction
9789	 * would require each property to be listed, which would at around 3K to the size
9790	 * of DataTables, while this method is about a 0.5K hit.
9791	 *
9792	 * Ultimately this does pave the way for Hungarian notation to be dropped
9793	 * completely, but that is a massive amount of work and will break current
9794	 * installs (therefore is on-hold until v2).
9795	 */
9796	
9797	/**
9798	 * Initialisation options that can be given to DataTables at initialisation
9799	 * time.
9800	 *  @namespace
9801	 */
9802	DataTable.defaults = {
9803		/**
9804		 * An array of data to use for the table, passed in at initialisation which
9805		 * will be used in preference to any data which is already in the DOM. This is
9806		 * particularly useful for constructing tables purely in Javascript, for
9807		 * example with a custom Ajax call.
9808		 *  @type array
9809		 *  @default null
9810		 *
9811		 *  @dtopt Option
9812		 *  @name DataTable.defaults.data
9813		 *
9814		 *  @example
9815		 *    // Using a 2D array data source
9816		 *    $(document).ready( function () {
9817		 *      $('#example').dataTable( {
9818		 *        "data": [
9819		 *          ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
9820		 *          ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
9821		 *        ],
9822		 *        "columns": [
9823		 *          { "title": "Engine" },
9824		 *          { "title": "Browser" },
9825		 *          { "title": "Platform" },
9826		 *          { "title": "Version" },
9827		 *          { "title": "Grade" }
9828		 *        ]
9829		 *      } );
9830		 *    } );
9831		 *
9832		 *  @example
9833		 *    // Using an array of objects as a data source (`data`)
9834		 *    $(document).ready( function () {
9835		 *      $('#example').dataTable( {
9836		 *        "data": [
9837		 *          {
9838		 *            "engine":   "Trident",
9839		 *            "browser":  "Internet Explorer 4.0",
9840		 *            "platform": "Win 95+",
9841		 *            "version":  4,
9842		 *            "grade":    "X"
9843		 *          },
9844		 *          {
9845		 *            "engine":   "Trident",
9846		 *            "browser":  "Internet Explorer 5.0",
9847		 *            "platform": "Win 95+",
9848		 *            "version":  5,
9849		 *            "grade":    "C"
9850		 *          }
9851		 *        ],
9852		 *        "columns": [
9853		 *          { "title": "Engine",   "data": "engine" },
9854		 *          { "title": "Browser",  "data": "browser" },
9855		 *          { "title": "Platform", "data": "platform" },
9856		 *          { "title": "Version",  "data": "version" },
9857		 *          { "title": "Grade",    "data": "grade" }
9858		 *        ]
9859		 *      } );
9860		 *    } );
9861		 */
9862		"aaData": null,
9863	
9864	
9865		/**
9866		 * If ordering is enabled, then DataTables will perform a first pass sort on
9867		 * initialisation. You can define which column(s) the sort is performed
9868		 * upon, and the sorting direction, with this variable. The `sorting` array
9869		 * should contain an array for each column to be sorted initially containing
9870		 * the column's index and a direction string ('asc' or 'desc').
9871		 *  @type array
9872		 *  @default [[0,'asc']]
9873		 *
9874		 *  @dtopt Option
9875		 *  @name DataTable.defaults.order
9876		 *
9877		 *  @example
9878		 *    // Sort by 3rd column first, and then 4th column
9879		 *    $(document).ready( function() {
9880		 *      $('#example').dataTable( {
9881		 *        "order": [[2,'asc'], [3,'desc']]
9882		 *      } );
9883		 *    } );
9884		 *
9885		 *    // No initial sorting
9886		 *    $(document).ready( function() {
9887		 *      $('#example').dataTable( {
9888		 *        "order": []
9889		 *      } );
9890		 *    } );
9891		 */
9892		"aaSorting": [[0,'asc']],
9893	
9894	
9895		/**
9896		 * This parameter is basically identical to the `sorting` parameter, but
9897		 * cannot be overridden by user interaction with the table. What this means
9898		 * is that you could have a column (visible or hidden) which the sorting
9899		 * will always be forced on first - any sorting after that (from the user)
9900		 * will then be performed as required. This can be useful for grouping rows
9901		 * together.
9902		 *  @type array
9903		 *  @default null
9904		 *
9905		 *  @dtopt Option
9906		 *  @name DataTable.defaults.orderFixed
9907		 *
9908		 *  @example
9909		 *    $(document).ready( function() {
9910		 *      $('#example').dataTable( {
9911		 *        "orderFixed": [[0,'asc']]
9912		 *      } );
9913		 *    } )
9914		 */
9915		"aaSortingFixed": [],
9916	
9917	
9918		/**
9919		 * DataTables can be instructed to load data to display in the table from a
9920		 * Ajax source. This option defines how that Ajax call is made and where to.
9921		 *
9922		 * The `ajax` property has three different modes of operation, depending on
9923		 * how it is defined. These are:
9924		 *
9925		 * * `string` - Set the URL from where the data should be loaded from.
9926		 * * `object` - Define properties for `jQuery.ajax`.
9927		 * * `function` - Custom data get function
9928		 *
9929		 * `string`
9930		 * --------
9931		 *
9932		 * As a string, the `ajax` property simply defines the URL from which
9933		 * DataTables will load data.
9934		 *
9935		 * `object`
9936		 * --------
9937		 *
9938		 * As an object, the parameters in the object are passed to
9939		 * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control
9940		 * of the Ajax request. DataTables has a number of default parameters which
9941		 * you can override using this option. Please refer to the jQuery
9942		 * documentation for a full description of the options available, although
9943		 * the following parameters provide additional options in DataTables or
9944		 * require special consideration:
9945		 *
9946		 * * `data` - As with jQuery, `data` can be provided as an object, but it
9947		 *   can also be used as a function to manipulate the data DataTables sends
9948		 *   to the server. The function takes a single parameter, an object of
9949		 *   parameters with the values that DataTables has readied for sending. An
9950		 *   object may be returned which will be merged into the DataTables
9951		 *   defaults, or you can add the items to the object that was passed in and
9952		 *   not return anything from the function. This supersedes `fnServerParams`
9953		 *   from DataTables 1.9-.
9954		 *
9955		 * * `dataSrc` - By default DataTables will look for the property `data` (or
9956		 *   `aaData` for compatibility with DataTables 1.9-) when obtaining data
9957		 *   from an Ajax source or for server-side processing - this parameter
9958		 *   allows that property to be changed. You can use Javascript dotted
9959		 *   object notation to get a data source for multiple levels of nesting, or
9960		 *   it my be used as a function. As a function it takes a single parameter,
9961		 *   the JSON returned from the server, which can be manipulated as
9962		 *   required, with the returned value being that used by DataTables as the
9963		 *   data source for the table. This supersedes `sAjaxDataProp` from
9964		 *   DataTables 1.9-.
9965		 *
9966		 * * `success` - Should not be overridden it is used internally in
9967		 *   DataTables. To manipulate / transform the data returned by the server
9968		 *   use `ajax.dataSrc`, or use `ajax` as a function (see below).
9969		 *
9970		 * `function`
9971		 * ----------
9972		 *
9973		 * As a function, making the Ajax call is left up to yourself allowing
9974		 * complete control of the Ajax request. Indeed, if desired, a method other
9975		 * than Ajax could be used to obtain the required data, such as Web storage
9976		 * or an AIR database.
9977		 *
9978		 * The function is given four parameters and no return is required. The
9979		 * parameters are:
9980		 *
9981		 * 1. _object_ - Data to send to the server
9982		 * 2. _function_ - Callback function that must be executed when the required
9983		 *    data has been obtained. That data should be passed into the callback
9984		 *    as the only parameter
9985		 * 3. _object_ - DataTables settings object for the table
9986		 *
9987		 * Note that this supersedes `fnServerData` from DataTables 1.9-.
9988		 *
9989		 *  @type string|object|function
9990		 *  @default null
9991		 *
9992		 *  @dtopt Option
9993		 *  @name DataTable.defaults.ajax
9994		 *  @since 1.10.0
9995		 *
9996		 * @example
9997		 *   // Get JSON data from a file via Ajax.
9998		 *   // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default).
9999		 *   $('#example').dataTable( {
10000		 *     "ajax": "data.json"
10001		 *   } );
10002		 *
10003		 * @example
10004		 *   // Get JSON data from a file via Ajax, using `dataSrc` to change
10005		 *   // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`)
10006		 *   $('#example').dataTable( {
10007		 *     "ajax": {
10008		 *       "url": "data.json",
10009		 *       "dataSrc": "tableData"
10010		 *     }
10011		 *   } );
10012		 *
10013		 * @example
10014		 *   // Get JSON data from a file via Ajax, using `dataSrc` to read data
10015		 *   // from a plain array rather than an array in an object
10016		 *   $('#example').dataTable( {
10017		 *     "ajax": {
10018		 *       "url": "data.json",
10019		 *       "dataSrc": ""
10020		 *     }
10021		 *   } );
10022		 *
10023		 * @example
10024		 *   // Manipulate the data returned from the server - add a link to data
10025		 *   // (note this can, should, be done using `render` for the column - this
10026		 *   // is just a simple example of how the data can be manipulated).
10027		 *   $('#example').dataTable( {
10028		 *     "ajax": {
10029		 *       "url": "data.json",
10030		 *       "dataSrc": function ( json ) {
10031		 *         for ( var i=0, ien=json.length ; i<ien ; i++ ) {
10032		 *           json[i][0] = '<a href="/message/'+json[i][0]+'>View message</a>';
10033		 *         }
10034		 *         return json;
10035		 *       }
10036		 *     }
10037		 *   } );
10038		 *
10039		 * @example
10040		 *   // Add data to the request
10041		 *   $('#example').dataTable( {
10042		 *     "ajax": {
10043		 *       "url": "data.json",
10044		 *       "data": function ( d ) {
10045		 *         return {
10046		 *           "extra_search": $('#extra').val()
10047		 *         };
10048		 *       }
10049		 *     }
10050		 *   } );
10051		 *
10052		 * @example
10053		 *   // Send request as POST
10054		 *   $('#example').dataTable( {
10055		 *     "ajax": {
10056		 *       "url": "data.json",
10057		 *       "type": "POST"
10058		 *     }
10059		 *   } );
10060		 *
10061		 * @example
10062		 *   // Get the data from localStorage (could interface with a form for
10063		 *   // adding, editing and removing rows).
10064		 *   $('#example').dataTable( {
10065		 *     "ajax": function (data, callback, settings) {
10066		 *       callback(
10067		 *         JSON.parse( localStorage.getItem('dataTablesData') )
10068		 *       );
10069		 *     }
10070		 *   } );
10071		 */
10072		"ajax": null,
10073	
10074	
10075		/**
10076		 * This parameter allows you to readily specify the entries in the length drop
10077		 * down menu that DataTables shows when pagination is enabled. It can be
10078		 * either a 1D array of options which will be used for both the displayed
10079		 * option and the value, or a 2D array which will use the array in the first
10080		 * position as the value, and the array in the second position as the
10081		 * displayed options (useful for language strings such as 'All').
10082		 *
10083		 * Note that the `pageLength` property will be automatically set to the
10084		 * first value given in this array, unless `pageLength` is also provided.
10085		 *  @type array
10086		 *  @default [ 10, 25, 50, 100 ]
10087		 *
10088		 *  @dtopt Option
10089		 *  @name DataTable.defaults.lengthMenu
10090		 *
10091		 *  @example
10092		 *    $(document).ready( function() {
10093		 *      $('#example').dataTable( {
10094		 *        "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
10095		 *      } );
10096		 *    } );
10097		 */
10098		"aLengthMenu": [ 10, 25, 50, 100 ],
10099	
10100	
10101		/**
10102		 * The `columns` option in the initialisation parameter allows you to define
10103		 * details about the way individual columns behave. For a full list of
10104		 * column options that can be set, please see
10105		 * {@link DataTable.defaults.column}. Note that if you use `columns` to
10106		 * define your columns, you must have an entry in the array for every single
10107		 * column that you have in your table (these can be null if you don't which
10108		 * to specify any options).
10109		 *  @member
10110		 *
10111		 *  @name DataTable.defaults.column
10112		 */
10113		"aoColumns": null,
10114	
10115		/**
10116		 * Very similar to `columns`, `columnDefs` allows you to target a specific
10117		 * column, multiple columns, or all columns, using the `targets` property of
10118		 * each object in the array. This allows great flexibility when creating
10119		 * tables, as the `columnDefs` arrays can be of any length, targeting the
10120		 * columns you specifically want. `columnDefs` may use any of the column
10121		 * options available: {@link DataTable.defaults.column}, but it _must_
10122		 * have `targets` defined in each object in the array. Values in the `targets`
10123		 * array may be:
10124		 *   <ul>
10125		 *     <li>a string - class name will be matched on the TH for the column</li>
10126		 *     <li>0 or a positive integer - column index counting from the left</li>
10127		 *     <li>a negative integer - column index counting from the right</li>
10128		 *     <li>the string "_all" - all columns (i.e. assign a default)</li>
10129		 *   </ul>
10130		 *  @member
10131		 *
10132		 *  @name DataTable.defaults.columnDefs
10133		 */
10134		"aoColumnDefs": null,
10135	
10136	
10137		/**
10138		 * Basically the same as `search`, this parameter defines the individual column
10139		 * filtering state at initialisation time. The array must be of the same size
10140		 * as the number of columns, and each element be an object with the parameters
10141		 * `search` and `escapeRegex` (the latter is optional). 'null' is also
10142		 * accepted and the default will be used.
10143		 *  @type array
10144		 *  @default []
10145		 *
10146		 *  @dtopt Option
10147		 *  @name DataTable.defaults.searchCols
10148		 *
10149		 *  @example
10150		 *    $(document).ready( function() {
10151		 *      $('#example').dataTable( {
10152		 *        "searchCols": [
10153		 *          null,
10154		 *          { "search": "My filter" },
10155		 *          null,
10156		 *          { "search": "^[0-9]", "escapeRegex": false }
10157		 *        ]
10158		 *      } );
10159		 *    } )
10160		 */
10161		"aoSearchCols": [],
10162	
10163	
10164		/**
10165		 * An array of CSS classes that should be applied to displayed rows. This
10166		 * array may be of any length, and DataTables will apply each class
10167		 * sequentially, looping when required.
10168		 *  @type array
10169		 *  @default null <i>Will take the values determined by the `oClasses.stripe*`
10170		 *    options</i>
10171		 *
10172		 *  @dtopt Option
10173		 *  @name DataTable.defaults.stripeClasses
10174		 *
10175		 *  @example
10176		 *    $(document).ready( function() {
10177		 *      $('#example').dataTable( {
10178		 *        "stripeClasses": [ 'strip1', 'strip2', 'strip3' ]
10179		 *      } );
10180		 *    } )
10181		 */
10182		"asStripeClasses": null,
10183	
10184	
10185		/**
10186		 * Enable or disable automatic column width calculation. This can be disabled
10187		 * as an optimisation (it takes some time to calculate the widths) if the
10188		 * tables widths are passed in using `columns`.
10189		 *  @type boolean
10190		 *  @default true
10191		 *
10192		 *  @dtopt Features
10193		 *  @name DataTable.defaults.autoWidth
10194		 *
10195		 *  @example
10196		 *    $(document).ready( function () {
10197		 *      $('#example').dataTable( {
10198		 *        "autoWidth": false
10199		 *      } );
10200		 *    } );
10201		 */
10202		"bAutoWidth": true,
10203	
10204	
10205		/**
10206		 * Deferred rendering can provide DataTables with a huge speed boost when you
10207		 * are using an Ajax or JS data source for the table. This option, when set to
10208		 * true, will cause DataTables to defer the creation of the table elements for
10209		 * each row until they are needed for a draw - saving a significant amount of
10210		 * time.
10211		 *  @type boolean
10212		 *  @default false
10213		 *
10214		 *  @dtopt Features
10215		 *  @name DataTable.defaults.deferRender
10216		 *
10217		 *  @example
10218		 *    $(document).ready( function() {
10219		 *      $('#example').dataTable( {
10220		 *        "ajax": "sources/arrays.txt",
10221		 *        "deferRender": true
10222		 *      } );
10223		 *    } );
10224		 */
10225		"bDeferRender": false,
10226	
10227	
10228		/**
10229		 * Replace a DataTable which matches the given selector and replace it with
10230		 * one which has the properties of the new initialisation object passed. If no
10231		 * table matches the selector, then the new DataTable will be constructed as
10232		 * per normal.
10233		 *  @type boolean
10234		 *  @default false
10235		 *
10236		 *  @dtopt Options
10237		 *  @name DataTable.defaults.destroy
10238		 *
10239		 *  @example
10240		 *    $(document).ready( function() {
10241		 *      $('#example').dataTable( {
10242		 *        "srollY": "200px",
10243		 *        "paginate": false
10244		 *      } );
10245		 *
10246		 *      // Some time later....
10247		 *      $('#example').dataTable( {
10248		 *        "filter": false,
10249		 *        "destroy": true
10250		 *      } );
10251		 *    } );
10252		 */
10253		"bDestroy": false,
10254	
10255	
10256		/**
10257		 * Enable or disable filtering of data. Filtering in DataTables is "smart" in
10258		 * that it allows the end user to input multiple words (space separated) and
10259		 * will match a row containing those words, even if not in the order that was
10260		 * specified (this allow matching across multiple columns). Note that if you
10261		 * wish to use filtering in DataTables this must remain 'true' - to remove the
10262		 * default filtering input box and retain filtering abilities, please use
10263		 * {@link DataTable.defaults.dom}.
10264		 *  @type boolean
10265		 *  @default true
10266		 *
10267		 *  @dtopt Features
10268		 *  @name DataTable.defaults.searching
10269		 *
10270		 *  @example
10271		 *    $(document).ready( function () {
10272		 *      $('#example').dataTable( {
10273		 *        "searching": false
10274		 *      } );
10275		 *    } );
10276		 */
10277		"bFilter": true,
10278	
10279	
10280		/**
10281		 * Enable or disable the table information display. This shows information
10282		 * about the data that is currently visible on the page, including information
10283		 * about filtered data if that action is being performed.
10284		 *  @type boolean
10285		 *  @default true
10286		 *
10287		 *  @dtopt Features
10288		 *  @name DataTable.defaults.info
10289		 *
10290		 *  @example
10291		 *    $(document).ready( function () {
10292		 *      $('#example').dataTable( {
10293		 *        "info": false
10294		 *      } );
10295		 *    } );
10296		 */
10297		"bInfo": true,
10298	
10299	
10300		/**
10301		 * Enable jQuery UI ThemeRoller support (required as ThemeRoller requires some
10302		 * slightly different and additional mark-up from what DataTables has
10303		 * traditionally used).
10304		 *  @type boolean
10305		 *  @default false
10306		 *
10307		 *  @dtopt Features
10308		 *  @name DataTable.defaults.jQueryUI
10309		 *
10310		 *  @example
10311		 *    $(document).ready( function() {
10312		 *      $('#example').dataTable( {
10313		 *        "jQueryUI": true
10314		 *      } );
10315		 *    } );
10316		 */
10317		"bJQueryUI": false,
10318	
10319	
10320		/**
10321		 * Allows the end user to select the size of a formatted page from a select
10322		 * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`).
10323		 *  @type boolean
10324		 *  @default true
10325		 *
10326		 *  @dtopt Features
10327		 *  @name DataTable.defaults.lengthChange
10328		 *
10329		 *  @example
10330		 *    $(document).ready( function () {
10331		 *      $('#example').dataTable( {
10332		 *        "lengthChange": false
10333		 *      } );
10334		 *    } );
10335		 */
10336		"bLengthChange": true,
10337	
10338	
10339		/**
10340		 * Enable or disable pagination.
10341		 *  @type boolean
10342		 *  @default true
10343		 *
10344		 *  @dtopt Features
10345		 *  @name DataTable.defaults.paging
10346		 *
10347		 *  @example
10348		 *    $(document).ready( function () {
10349		 *      $('#example').dataTable( {
10350		 *        "paging": false
10351		 *      } );
10352		 *    } );
10353		 */
10354		"bPaginate": true,
10355	
10356	
10357		/**
10358		 * Enable or disable the display of a 'processing' indicator when the table is
10359		 * being processed (e.g. a sort). This is particularly useful for tables with
10360		 * large amounts of data where it can take a noticeable amount of time to sort
10361		 * the entries.
10362		 *  @type boolean
10363		 *  @default false
10364		 *
10365		 *  @dtopt Features
10366		 *  @name DataTable.defaults.processing
10367		 *
10368		 *  @example
10369		 *    $(document).ready( function () {
10370		 *      $('#example').dataTable( {
10371		 *        "processing": true
10372		 *      } );
10373		 *    } );
10374		 */
10375		"bProcessing": false,
10376	
10377	
10378		/**
10379		 * Retrieve the DataTables object for the given selector. Note that if the
10380		 * table has already been initialised, this parameter will cause DataTables
10381		 * to simply return the object that has already been set up - it will not take
10382		 * account of any changes you might have made to the initialisation object
10383		 * passed to DataTables (setting this parameter to true is an acknowledgement
10384		 * that you understand this). `destroy` can be used to reinitialise a table if
10385		 * you need.
10386		 *  @type boolean
10387		 *  @default false
10388		 *
10389		 *  @dtopt Options
10390		 *  @name DataTable.defaults.retrieve
10391		 *
10392		 *  @example
10393		 *    $(document).ready( function() {
10394		 *      initTable();
10395		 *      tableActions();
10396		 *    } );
10397		 *
10398		 *    function initTable ()
10399		 *    {
10400		 *      return $('#example').dataTable( {
10401		 *        "scrollY": "200px",
10402		 *        "paginate": false,
10403		 *        "retrieve": true
10404		 *      } );
10405		 *    }
10406		 *
10407		 *    function tableActions ()
10408		 *    {
10409		 *      var table = initTable();
10410		 *      // perform API operations with oTable
10411		 *    }
10412		 */
10413		"bRetrieve": false,
10414	
10415	
10416		/**
10417		 * When vertical (y) scrolling is enabled, DataTables will force the height of
10418		 * the table's viewport to the given height at all times (useful for layout).
10419		 * However, this can look odd when filtering data down to a small data set,
10420		 * and the footer is left "floating" further down. This parameter (when
10421		 * enabled) will cause DataTables to collapse the table's viewport down when
10422		 * the result set will fit within the given Y height.
10423		 *  @type boolean
10424		 *  @default false
10425		 *
10426		 *  @dtopt Options
10427		 *  @name DataTable.defaults.scrollCollapse
10428		 *
10429		 *  @example
10430		 *    $(document).ready( function() {
10431		 *      $('#example').dataTable( {
10432		 *        "scrollY": "200",
10433		 *        "scrollCollapse": true
10434		 *      } );
10435		 *    } );
10436		 */
10437		"bScrollCollapse": false,
10438	
10439	
10440		/**
10441		 * Configure DataTables to use server-side processing. Note that the
10442		 * `ajax` parameter must also be given in order to give DataTables a
10443		 * source to obtain the required data for each draw.
10444		 *  @type boolean
10445		 *  @default false
10446		 *
10447		 *  @dtopt Features
10448		 *  @dtopt Server-side
10449		 *  @name DataTable.defaults.serverSide
10450		 *
10451		 *  @example
10452		 *    $(document).ready( function () {
10453		 *      $('#example').dataTable( {
10454		 *        "serverSide": true,
10455		 *        "ajax": "xhr.php"
10456		 *      } );
10457		 *    } );
10458		 */
10459		"bServerSide": false,
10460	
10461	
10462		/**
10463		 * Enable or disable sorting of columns. Sorting of individual columns can be
10464		 * disabled by the `sortable` option for each column.
10465		 *  @type boolean
10466		 *  @default true
10467		 *
10468		 *  @dtopt Features
10469		 *  @name DataTable.defaults.ordering
10470		 *
10471		 *  @example
10472		 *    $(document).ready( function () {
10473		 *      $('#example').dataTable( {
10474		 *        "ordering": false
10475		 *      } );
10476		 *    } );
10477		 */
10478		"bSort": true,
10479	
10480	
10481		/**
10482		 * Enable or display DataTables' ability to sort multiple columns at the
10483		 * same time (activated by shift-click by the user).
10484		 *  @type boolean
10485		 *  @default true
10486		 *
10487		 *  @dtopt Options
10488		 *  @name DataTable.defaults.orderMulti
10489		 *
10490		 *  @example
10491		 *    // Disable multiple column sorting ability
10492		 *    $(document).ready( function () {
10493		 *      $('#example').dataTable( {
10494		 *        "orderMulti": false
10495		 *      } );
10496		 *    } );
10497		 */
10498		"bSortMulti": true,
10499	
10500	
10501		/**
10502		 * Allows control over whether DataTables should use the top (true) unique
10503		 * cell that is found for a single column, or the bottom (false - default).
10504		 * This is useful when using complex headers.
10505		 *  @type boolean
10506		 *  @default false
10507		 *
10508		 *  @dtopt Options
10509		 *  @name DataTable.defaults.orderCellsTop
10510		 *
10511		 *  @example
10512		 *    $(document).ready( function() {
10513		 *      $('#example').dataTable( {
10514		 *        "orderCellsTop": true
10515		 *      } );
10516		 *    } );
10517		 */
10518		"bSortCellsTop": false,
10519	
10520	
10521		/**
10522		 * Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and
10523		 * `sorting\_3` to the columns which are currently being sorted on. This is
10524		 * presented as a feature switch as it can increase processing time (while
10525		 * classes are removed and added) so for large data sets you might want to
10526		 * turn this off.
10527		 *  @type boolean
10528		 *  @default true
10529		 *
10530		 *  @dtopt Features
10531		 *  @name DataTable.defaults.orderClasses
10532		 *
10533		 *  @example
10534		 *    $(document).ready( function () {
10535		 *      $('#example').dataTable( {
10536		 *        "orderClasses": false
10537		 *      } );
10538		 *    } );
10539		 */
10540		"bSortClasses": true,
10541	
10542	
10543		/**
10544		 * Enable or disable state saving. When enabled HTML5 `localStorage` will be
10545		 * used to save table display information such as pagination information,
10546		 * display length, filtering and sorting. As such when the end user reloads
10547		 * the page the display display will match what thy had previously set up.
10548		 *
10549		 * Due to the use of `localStorage` the default state saving is not supported
10550		 * in IE6 or 7. If state saving is required in those browsers, use
10551		 * `stateSaveCallback` to provide a storage solution such as cookies.
10552		 *  @type boolean
10553		 *  @default false
10554		 *
10555		 *  @dtopt Features
10556		 *  @name DataTable.defaults.stateSave
10557		 *
10558		 *  @example
10559		 *    $(document).ready( function () {
10560		 *      $('#example').dataTable( {
10561		 *        "stateSave": true
10562		 *      } );
10563		 *    } );
10564		 */
10565		"bStateSave": false,
10566	
10567	
10568		/**
10569		 * This function is called when a TR element is created (and all TD child
10570		 * elements have been inserted), or registered if using a DOM source, allowing
10571		 * manipulation of the TR element (adding classes etc).
10572		 *  @type function
10573		 *  @param {node} row "TR" element for the current row
10574		 *  @param {array} data Raw data array for this row
10575		 *  @param {int} dataIndex The index of this row in the internal aoData array
10576		 *
10577		 *  @dtopt Callbacks
10578		 *  @name DataTable.defaults.createdRow
10579		 *
10580		 *  @example
10581		 *    $(document).ready( function() {
10582		 *      $('#example').dataTable( {
10583		 *        "createdRow": function( row, data, dataIndex ) {
10584		 *          // Bold the grade for all 'A' grade browsers
10585		 *          if ( data[4] == "A" )
10586		 *          {
10587		 *            $('td:eq(4)', row).html( '<b>A</b>' );
10588		 *          }
10589		 *        }
10590		 *      } );
10591		 *    } );
10592		 */
10593		"fnCreatedRow": null,
10594	
10595	
10596		/**
10597		 * This function is called on every 'draw' event, and allows you to
10598		 * dynamically modify any aspect you want about the created DOM.
10599		 *  @type function
10600		 *  @param {object} settings DataTables settings object
10601		 *
10602		 *  @dtopt Callbacks
10603		 *  @name DataTable.defaults.drawCallback
10604		 *
10605		 *  @example
10606		 *    $(document).ready( function() {
10607		 *      $('#example').dataTable( {
10608		 *        "drawCallback": function( settings ) {
10609		 *          alert( 'DataTables has redrawn the table' );
10610		 *        }
10611		 *      } );
10612		 *    } );
10613		 */
10614		"fnDrawCallback": null,
10615	
10616	
10617		/**
10618		 * Identical to fnHeaderCallback() but for the table footer this function
10619		 * allows you to modify the table footer on every 'draw' event.
10620		 *  @type function
10621		 *  @param {node} foot "TR" element for the footer
10622		 *  @param {array} data Full table data (as derived from the original HTML)
10623		 *  @param {int} start Index for the current display starting point in the
10624		 *    display array
10625		 *  @param {int} end Index for the current display ending point in the
10626		 *    display array
10627		 *  @param {array int} display Index array to translate the visual position
10628		 *    to the full data array
10629		 *
10630		 *  @dtopt Callbacks
10631		 *  @name DataTable.defaults.footerCallback
10632		 *
10633		 *  @example
10634		 *    $(document).ready( function() {
10635		 *      $('#example').dataTable( {
10636		 *        "footerCallback": function( tfoot, data, start, end, display ) {
10637		 *          tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start;
10638		 *        }
10639		 *      } );
10640		 *    } )
10641		 */
10642		"fnFooterCallback": null,
10643	
10644	
10645		/**
10646		 * When rendering large numbers in the information element for the table
10647		 * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
10648		 * to have a comma separator for the 'thousands' units (e.g. 1 million is
10649		 * rendered as "1,000,000") to help readability for the end user. This
10650		 * function will override the default method DataTables uses.
10651		 *  @type function
10652		 *  @member
10653		 *  @param {int} toFormat number to be formatted
10654		 *  @returns {string} formatted string for DataTables to show the number
10655		 *
10656		 *  @dtopt Callbacks
10657		 *  @name DataTable.defaults.formatNumber
10658		 *
10659		 *  @example
10660		 *    // Format a number using a single quote for the separator (note that
10661		 *    // this can also be done with the language.thousands option)
10662		 *    $(document).ready( function() {
10663		 *      $('#example').dataTable( {
10664		 *        "formatNumber": function ( toFormat ) {
10665		 *          return toFormat.toString().replace(
10666		 *            /\B(?=(\d{3})+(?!\d))/g, "'"
10667		 *          );
10668		 *        };
10669		 *      } );
10670		 *    } );
10671		 */
10672		"fnFormatNumber": function ( toFormat ) {
10673			return toFormat.toString().replace(
10674				/\B(?=(\d{3})+(?!\d))/g,
10675				this.oLanguage.sThousands
10676			);
10677		},
10678	
10679	
10680		/**
10681		 * This function is called on every 'draw' event, and allows you to
10682		 * dynamically modify the header row. This can be used to calculate and
10683		 * display useful information about the table.
10684		 *  @type function
10685		 *  @param {node} head "TR" element for the header
10686		 *  @param {array} data Full table data (as derived from the original HTML)
10687		 *  @param {int} start Index for the current display starting point in the
10688		 *    display array
10689		 *  @param {int} end Index for the current display ending point in the
10690		 *    display array
10691		 *  @param {array int} display Index array to translate the visual position
10692		 *    to the full data array
10693		 *
10694		 *  @dtopt Callbacks
10695		 *  @name DataTable.defaults.headerCallback
10696		 *
10697		 *  @example
10698		 *    $(document).ready( function() {
10699		 *      $('#example').dataTable( {
10700		 *        "fheaderCallback": function( head, data, start, end, display ) {
10701		 *          head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records";
10702		 *        }
10703		 *      } );
10704		 *    } )
10705		 */
10706		"fnHeaderCallback": null,
10707	
10708	
10709		/**
10710		 * The information element can be used to convey information about the current
10711		 * state of the table. Although the internationalisation options presented by
10712		 * DataTables are quite capable of dealing with most customisations, there may
10713		 * be times where you wish to customise the string further. This callback
10714		 * allows you to do exactly that.
10715		 *  @type function
10716		 *  @param {object} oSettings DataTables settings object
10717		 *  @param {int} start Starting position in data for the draw
10718		 *  @param {int} end End position in data for the draw
10719		 *  @param {int} max Total number of rows in the table (regardless of
10720		 *    filtering)
10721		 *  @param {int} total Total number of rows in the data set, after filtering
10722		 *  @param {string} pre The string that DataTables has formatted using it's
10723		 *    own rules
10724		 *  @returns {string} The string to be displayed in the information element.
10725		 *
10726		 *  @dtopt Callbacks
10727		 *  @name DataTable.defaults.infoCallback
10728		 *
10729		 *  @example
10730		 *    $('#example').dataTable( {
10731		 *      "infoCallback": function( settings, start, end, max, total, pre ) {
10732		 *        return start +" to "+ end;
10733		 *      }
10734		 *    } );
10735		 */
10736		"fnInfoCallback": null,
10737	
10738	
10739		/**
10740		 * Called when the table has been initialised. Normally DataTables will
10741		 * initialise sequentially and there will be no need for this function,
10742		 * however, this does not hold true when using external language information
10743		 * since that is obtained using an async XHR call.
10744		 *  @type function
10745		 *  @param {object} settings DataTables settings object
10746		 *  @param {object} json The JSON object request from the server - only
10747		 *    present if client-side Ajax sourced data is used
10748		 *
10749		 *  @dtopt Callbacks
10750		 *  @name DataTable.defaults.initComplete
10751		 *
10752		 *  @example
10753		 *    $(document).ready( function() {
10754		 *      $('#example').dataTable( {
10755		 *        "initComplete": function(settings, json) {
10756		 *          alert( 'DataTables has finished its initialisation.' );
10757		 *        }
10758		 *      } );
10759		 *    } )
10760		 */
10761		"fnInitComplete": null,
10762	
10763	
10764		/**
10765		 * Called at the very start of each table draw and can be used to cancel the
10766		 * draw by returning false, any other return (including undefined) results in
10767		 * the full draw occurring).
10768		 *  @type function
10769		 *  @param {object} settings DataTables settings object
10770		 *  @returns {boolean} False will cancel the draw, anything else (including no
10771		 *    return) will allow it to complete.
10772		 *
10773		 *  @dtopt Callbacks
10774		 *  @name DataTable.defaults.preDrawCallback
10775		 *
10776		 *  @example
10777		 *    $(document).ready( function() {
10778		 *      $('#example').dataTable( {
10779		 *        "preDrawCallback": function( settings ) {
10780		 *          if ( $('#test').val() == 1 ) {
10781		 *            return false;
10782		 *          }
10783		 *        }
10784		 *      } );
10785		 *    } );
10786		 */
10787		"fnPreDrawCallback": null,
10788	
10789	
10790		/**
10791		 * This function allows you to 'post process' each row after it have been
10792		 * generated for each table draw, but before it is rendered on screen. This
10793		 * function might be used for setting the row class name etc.
10794		 *  @type function
10795		 *  @param {node} row "TR" element for the current row
10796		 *  @param {array} data Raw data array for this row
10797		 *  @param {int} displayIndex The display index for the current table draw
10798		 *  @param {int} displayIndexFull The index of the data in the full list of
10799		 *    rows (after filtering)
10800		 *
10801		 *  @dtopt Callbacks
10802		 *  @name DataTable.defaults.rowCallback
10803		 *
10804		 *  @example
10805		 *    $(document).ready( function() {
10806		 *      $('#example').dataTable( {
10807		 *        "rowCallback": function( row, data, displayIndex, displayIndexFull ) {
10808		 *          // Bold the grade for all 'A' grade browsers
10809		 *          if ( data[4] == "A" ) {
10810		 *            $('td:eq(4)', row).html( '<b>A</b>' );
10811		 *          }
10812		 *        }
10813		 *      } );
10814		 *    } );
10815		 */
10816		"fnRowCallback": null,
10817	
10818	
10819		/**
10820		 * __Deprecated__ The functionality provided by this parameter has now been
10821		 * superseded by that provided through `ajax`, which should be used instead.
10822		 *
10823		 * This parameter allows you to override the default function which obtains
10824		 * the data from the server so something more suitable for your application.
10825		 * For example you could use POST data, or pull information from a Gears or
10826		 * AIR database.
10827		 *  @type function
10828		 *  @member
10829		 *  @param {string} source HTTP source to obtain the data from (`ajax`)
10830		 *  @param {array} data A key/value pair object containing the data to send
10831		 *    to the server
10832		 *  @param {function} callback to be called on completion of the data get
10833		 *    process that will draw the data on the page.
10834		 *  @param {object} settings DataTables settings object
10835		 *
10836		 *  @dtopt Callbacks
10837		 *  @dtopt Server-side
10838		 *  @name DataTable.defaults.serverData
10839		 *
10840		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
10841		 */
10842		"fnServerData": null,
10843	
10844	
10845		/**
10846		 * __Deprecated__ The functionality provided by this parameter has now been
10847		 * superseded by that provided through `ajax`, which should be used instead.
10848		 *
10849		 *  It is often useful to send extra data to the server when making an Ajax
10850		 * request - for example custom filtering information, and this callback
10851		 * function makes it trivial to send extra information to the server. The
10852		 * passed in parameter is the data set that has been constructed by
10853		 * DataTables, and you can add to this or modify it as you require.
10854		 *  @type function
10855		 *  @param {array} data Data array (array of objects which are name/value
10856		 *    pairs) that has been constructed by DataTables and will be sent to the
10857		 *    server. In the case of Ajax sourced data with server-side processing
10858		 *    this will be an empty array, for server-side processing there will be a
10859		 *    significant number of parameters!
10860		 *  @returns {undefined} Ensure that you modify the data array passed in,
10861		 *    as this is passed by reference.
10862		 *
10863		 *  @dtopt Callbacks
10864		 *  @dtopt Server-side
10865		 *  @name DataTable.defaults.serverParams
10866		 *
10867		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
10868		 */
10869		"fnServerParams": null,
10870	
10871	
10872		/**
10873		 * Load the table state. With this function you can define from where, and how, the
10874		 * state of a table is loaded. By default DataTables will load from `localStorage`
10875		 * but you might wish to use a server-side database or cookies.
10876		 *  @type function
10877		 *  @member
10878		 *  @param {object} settings DataTables settings object
10879		 *  @return {object} The DataTables state object to be loaded
10880		 *
10881		 *  @dtopt Callbacks
10882		 *  @name DataTable.defaults.stateLoadCallback
10883		 *
10884		 *  @example
10885		 *    $(document).ready( function() {
10886		 *      $('#example').dataTable( {
10887		 *        "stateSave": true,
10888		 *        "stateLoadCallback": function (settings) {
10889		 *          var o;
10890		 *
10891		 *          // Send an Ajax request to the server to get the data. Note that
10892		 *          // this is a synchronous request.
10893		 *          $.ajax( {
10894		 *            "url": "/state_load",
10895		 *            "async": false,
10896		 *            "dataType": "json",
10897		 *            "success": function (json) {
10898		 *              o = json;
10899		 *            }
10900		 *          } );
10901		 *
10902		 *          return o;
10903		 *        }
10904		 *      } );
10905		 *    } );
10906		 */
10907		"fnStateLoadCallback": function ( settings ) {
10908			try {
10909				return JSON.parse(
10910					(settings.iStateDuration === -1 ? sessionStorage : localStorage).getItem(
10911						'DataTables_'+settings.sInstance+'_'+location.pathname
10912					)
10913				);
10914			} catch (e) {}
10915		},
10916	
10917	
10918		/**
10919		 * Callback which allows modification of the saved state prior to loading that state.
10920		 * This callback is called when the table is loading state from the stored data, but
10921		 * prior to the settings object being modified by the saved state. Note that for
10922		 * plug-in authors, you should use the `stateLoadParams` event to load parameters for
10923		 * a plug-in.
10924		 *  @type function
10925		 *  @param {object} settings DataTables settings object
10926		 *  @param {object} data The state object that is to be loaded
10927		 *
10928		 *  @dtopt Callbacks
10929		 *  @name DataTable.defaults.stateLoadParams
10930		 *
10931		 *  @example
10932		 *    // Remove a saved filter, so filtering is never loaded
10933		 *    $(document).ready( function() {
10934		 *      $('#example').dataTable( {
10935		 *        "stateSave": true,
10936		 *        "stateLoadParams": function (settings, data) {
10937		 *          data.oSearch.sSearch = "";
10938		 *        }
10939		 *      } );
10940		 *    } );
10941		 *
10942		 *  @example
10943		 *    // Disallow state loading by returning false
10944		 *    $(document).ready( function() {
10945		 *      $('#example').dataTable( {
10946		 *        "stateSave": true,
10947		 *        "stateLoadParams": function (settings, data) {
10948		 *          return false;
10949		 *        }
10950		 *      } );
10951		 *    } );
10952		 */
10953		"fnStateLoadParams": null,
10954	
10955	
10956		/**
10957		 * Callback that is called when the state has been loaded from the state saving method
10958		 * and the DataTables settings object has been modified as a result of the loaded state.
10959		 *  @type function
10960		 *  @param {object} settings DataTables settings object
10961		 *  @param {object} data The state object that was loaded
10962		 *
10963		 *  @dtopt Callbacks
10964		 *  @name DataTable.defaults.stateLoaded
10965		 *
10966		 *  @example
10967		 *    // Show an alert with the filtering value that was saved
10968		 *    $(document).ready( function() {
10969		 *      $('#example').dataTable( {
10970		 *        "stateSave": true,
10971		 *        "stateLoaded": function (settings, data) {
10972		 *          alert( 'Saved filter was: '+data.oSearch.sSearch );
10973		 *        }
10974		 *      } );
10975		 *    } );
10976		 */
10977		"fnStateLoaded": null,
10978	
10979	
10980		/**
10981		 * Save the table state. This function allows you to define where and how the state
10982		 * information for the table is stored By default DataTables will use `localStorage`
10983		 * but you might wish to use a server-side database or cookies.
10984		 *  @type function
10985		 *  @member
10986		 *  @param {object} settings DataTables settings object
10987		 *  @param {object} data The state object to be saved
10988		 *
10989		 *  @dtopt Callbacks
10990		 *  @name DataTable.defaults.stateSaveCallback
10991		 *
10992		 *  @example
10993		 *    $(document).ready( function() {
10994		 *      $('#example').dataTable( {
10995		 *        "stateSave": true,
10996		 *        "stateSaveCallback": function (settings, data) {
10997		 *          // Send an Ajax request to the server with the state object
10998		 *          $.ajax( {
10999		 *            "url": "/state_save",
11000		 *            "data": data,
11001		 *            "dataType": "json",
11002		 *            "method": "POST"
11003		 *            "success": function () {}
11004		 *          } );
11005		 *        }
11006		 *      } );
11007		 *    } );
11008		 */
11009		"fnStateSaveCallback": function ( settings, data ) {
11010			try {
11011				(settings.iStateDuration === -1 ? sessionStorage : localStorage).setItem(
11012					'DataTables_'+settings.sInstance+'_'+location.pathname,
11013					JSON.stringify( data )
11014				);
11015			} catch (e) {}
11016		},
11017	
11018	
11019		/**
11020		 * Callback which allows modification of the state to be saved. Called when the table
11021		 * has changed state a new state save is required. This method allows modification of
11022		 * the state saving object prior to actually doing the save, including addition or
11023		 * other state properties or modification. Note that for plug-in authors, you should
11024		 * use the `stateSaveParams` event to save parameters for a plug-in.
11025		 *  @type function
11026		 *  @param {object} settings DataTables settings object
11027		 *  @param {object} data The state object to be saved
11028		 *
11029		 *  @dtopt Callbacks
11030		 *  @name DataTable.defaults.stateSaveParams
11031		 *
11032		 *  @example
11033		 *    // Remove a saved filter, so filtering is never saved
11034		 *    $(document).ready( function() {
11035		 *      $('#example').dataTable( {
11036		 *        "stateSave": true,
11037		 *        "stateSaveParams": function (settings, data) {
11038		 *          data.oSearch.sSearch = "";
11039		 *        }
11040		 *      } );
11041		 *    } );
11042		 */
11043		"fnStateSaveParams": null,
11044	
11045	
11046		/**
11047		 * Duration for which the saved state information is considered valid. After this period
11048		 * has elapsed the state will be returned to the default.
11049		 * Value is given in seconds.
11050		 *  @type int
11051		 *  @default 7200 <i>(2 hours)</i>
11052		 *
11053		 *  @dtopt Options
11054		 *  @name DataTable.defaults.stateDuration
11055		 *
11056		 *  @example
11057		 *    $(document).ready( function() {
11058		 *      $('#example').dataTable( {
11059		 *        "stateDuration": 60*60*24; // 1 day
11060		 *      } );
11061		 *    } )
11062		 */
11063		"iStateDuration": 7200,
11064	
11065	
11066		/**
11067		 * When enabled DataTables will not make a request to the server for the first
11068		 * page draw - rather it will use the data already on the page (no sorting etc
11069		 * will be applied to it), thus saving on an XHR at load time. `deferLoading`
11070		 * is used to indicate that deferred loading is required, but it is also used
11071		 * to tell DataTables how many records there are in the full table (allowing
11072		 * the information element and pagination to be displayed correctly). In the case
11073		 * where a filtering is applied to the table on initial load, this can be
11074		 * indicated by giving the parameter as an array, where the first element is
11075		 * the number of records available after filtering and the second element is the
11076		 * number of records without filtering (allowing the table information element
11077		 * to be shown correctly).
11078		 *  @type int | array
11079		 *  @default null
11080		 *
11081		 *  @dtopt Options
11082		 *  @name DataTable.defaults.deferLoading
11083		 *
11084		 *  @example
11085		 *    // 57 records available in the table, no filtering applied
11086		 *    $(document).ready( function() {
11087		 *      $('#example').dataTable( {
11088		 *        "serverSide": true,
11089		 *        "ajax": "scripts/server_processing.php",
11090		 *        "deferLoading": 57
11091		 *      } );
11092		 *    } );
11093		 *
11094		 *  @example
11095		 *    // 57 records after filtering, 100 without filtering (an initial filter applied)
11096		 *    $(document).ready( function() {
11097		 *      $('#example').dataTable( {
11098		 *        "serverSide": true,
11099		 *        "ajax": "scripts/server_processing.php",
11100		 *        "deferLoading": [ 57, 100 ],
11101		 *        "search": {
11102		 *          "search": "my_filter"
11103		 *        }
11104		 *      } );
11105		 *    } );
11106		 */
11107		"iDeferLoading": null,
11108	
11109	
11110		/**
11111		 * Number of rows to display on a single page when using pagination. If
11112		 * feature enabled (`lengthChange`) then the end user will be able to override
11113		 * this to a custom setting using a pop-up menu.
11114		 *  @type int
11115		 *  @default 10
11116		 *
11117		 *  @dtopt Options
11118		 *  @name DataTable.defaults.pageLength
11119		 *
11120		 *  @example
11121		 *    $(document).ready( function() {
11122		 *      $('#example').dataTable( {
11123		 *        "pageLength": 50
11124		 *      } );
11125		 *    } )
11126		 */
11127		"iDisplayLength": 10,
11128	
11129	
11130		/**
11131		 * Define the starting point for data display when using DataTables with
11132		 * pagination. Note that this parameter is the number of records, rather than
11133		 * the page number, so if you have 10 records per page and want to start on
11134		 * the third page, it should be "20".
11135		 *  @type int
11136		 *  @default 0
11137		 *
11138		 *  @dtopt Options
11139		 *  @name DataTable.defaults.displayStart
11140		 *
11141		 *  @example
11142		 *    $(document).ready( function() {
11143		 *      $('#example').dataTable( {
11144		 *        "displayStart": 20
11145		 *      } );
11146		 *    } )
11147		 */
11148		"iDisplayStart": 0,
11149	
11150	
11151		/**
11152		 * By default DataTables allows keyboard navigation of the table (sorting, paging,
11153		 * and filtering) by adding a `tabindex` attribute to the required elements. This
11154		 * allows you to tab through the controls and press the enter key to activate them.
11155		 * The tabindex is default 0, meaning that the tab follows the flow of the document.
11156		 * You can overrule this using this parameter if you wish. Use a value of -1 to
11157		 * disable built-in keyboard navigation.
11158		 *  @type int
11159		 *  @default 0
11160		 *
11161		 *  @dtopt Options
11162		 *  @name DataTable.defaults.tabIndex
11163		 *
11164		 *  @example
11165		 *    $(document).ready( function() {
11166		 *      $('#example').dataTable( {
11167		 *        "tabIndex": 1
11168		 *      } );
11169		 *    } );
11170		 */
11171		"iTabIndex": 0,
11172	
11173	
11174		/**
11175		 * Classes that DataTables assigns to the various components and features
11176		 * that it adds to the HTML table. This allows classes to be configured
11177		 * during initialisation in addition to through the static
11178		 * {@link DataTable.ext.oStdClasses} object).
11179		 *  @namespace
11180		 *  @name DataTable.defaults.classes
11181		 */
11182		"oClasses": {},
11183	
11184	
11185		/**
11186		 * All strings that DataTables uses in the user interface that it creates
11187		 * are defined in this object, allowing you to modified them individually or
11188		 * completely replace them all as required.
11189		 *  @namespace
11190		 *  @name DataTable.defaults.language
11191		 */
11192		"oLanguage": {
11193			/**
11194			 * Strings that are used for WAI-ARIA labels and controls only (these are not
11195			 * actually visible on the page, but will be read by screenreaders, and thus
11196			 * must be internationalised as well).
11197			 *  @namespace
11198			 *  @name DataTable.defaults.language.aria
11199			 */
11200			"oAria": {
11201				/**
11202				 * ARIA label that is added to the table headers when the column may be
11203				 * sorted ascending by activing the column (click or return when focused).
11204				 * Note that the column header is prefixed to this string.
11205				 *  @type string
11206				 *  @default : activate to sort column ascending
11207				 *
11208				 *  @dtopt Language
11209				 *  @name DataTable.defaults.language.aria.sortAscending
11210				 *
11211				 *  @example
11212				 *    $(document).ready( function() {
11213				 *      $('#example').dataTable( {
11214				 *        "language": {
11215				 *          "aria": {
11216				 *            "sortAscending": " - click/return to sort ascending"
11217				 *          }
11218				 *        }
11219				 *      } );
11220				 *    } );
11221				 */
11222				"sSortAscending": ": activate to sort column ascending",
11223	
11224				/**
11225				 * ARIA label that is added to the table headers when the column may be
11226				 * sorted descending by activing the column (click or return when focused).
11227				 * Note that the column header is prefixed to this string.
11228				 *  @type string
11229				 *  @default : activate to sort column ascending
11230				 *
11231				 *  @dtopt Language
11232				 *  @name DataTable.defaults.language.aria.sortDescending
11233				 *
11234				 *  @example
11235				 *    $(document).ready( function() {
11236				 *      $('#example').dataTable( {
11237				 *        "language": {
11238				 *          "aria": {
11239				 *            "sortDescending": " - click/return to sort descending"
11240				 *          }
11241				 *        }
11242				 *      } );
11243				 *    } );
11244				 */
11245				"sSortDescending": ": activate to sort column descending"
11246			},
11247	
11248			/**
11249			 * Pagination string used by DataTables for the built-in pagination
11250			 * control types.
11251			 *  @namespace
11252			 *  @name DataTable.defaults.language.paginate
11253			 */
11254			"oPaginate": {
11255				/**
11256				 * Text to use when using the 'full_numbers' type of pagination for the
11257				 * button to take the user to the first page.
11258				 *  @type string
11259				 *  @default First
11260				 *
11261				 *  @dtopt Language
11262				 *  @name DataTable.defaults.language.paginate.first
11263				 *
11264				 *  @example
11265				 *    $(document).ready( function() {
11266				 *      $('#example').dataTable( {
11267				 *        "language": {
11268				 *          "paginate": {
11269				 *            "first": "First page"
11270				 *          }
11271				 *        }
11272				 *      } );
11273				 *    } );
11274				 */
11275				"sFirst": "First",
11276	
11277	
11278				/**
11279				 * Text to use when using the 'full_numbers' type of pagination for the
11280				 * button to take the user to the last page.
11281				 *  @type string
11282				 *  @default Last
11283				 *
11284				 *  @dtopt Language
11285				 *  @name DataTable.defaults.language.paginate.last
11286				 *
11287				 *  @example
11288				 *    $(document).ready( function() {
11289				 *      $('#example').dataTable( {
11290				 *        "language": {
11291				 *          "paginate": {
11292				 *            "last": "Last page"
11293				 *          }
11294				 *        }
11295				 *      } );
11296				 *    } );
11297				 */
11298				"sLast": "Last",
11299	
11300	
11301				/**
11302				 * Text to use for the 'next' pagination button (to take the user to the
11303				 * next page).
11304				 *  @type string
11305				 *  @default Next
11306				 *
11307				 *  @dtopt Language
11308				 *  @name DataTable.defaults.language.paginate.next
11309				 *
11310				 *  @example
11311				 *    $(document).ready( function() {
11312				 *      $('#example').dataTable( {
11313				 *        "language": {
11314				 *          "paginate": {
11315				 *            "next": "Next page"
11316				 *          }
11317				 *        }
11318				 *      } );
11319				 *    } );
11320				 */
11321				"sNext": "Next",
11322	
11323	
11324				/**
11325				 * Text to use for the 'previous' pagination button (to take the user to
11326				 * the previous page).
11327				 *  @type string
11328				 *  @default Previous
11329				 *
11330				 *  @dtopt Language
11331				 *  @name DataTable.defaults.language.paginate.previous
11332				 *
11333				 *  @example
11334				 *    $(document).ready( function() {
11335				 *      $('#example').dataTable( {
11336				 *        "language": {
11337				 *          "paginate": {
11338				 *            "previous": "Previous page"
11339				 *          }
11340				 *        }
11341				 *      } );
11342				 *    } );
11343				 */
11344				"sPrevious": "Previous"
11345			},
11346	
11347			/**
11348			 * This string is shown in preference to `zeroRecords` when the table is
11349			 * empty of data (regardless of filtering). Note that this is an optional
11350			 * parameter - if it is not given, the value of `zeroRecords` will be used
11351			 * instead (either the default or given value).
11352			 *  @type string
11353			 *  @default No data available in table
11354			 *
11355			 *  @dtopt Language
11356			 *  @name DataTable.defaults.language.emptyTable
11357			 *
11358			 *  @example
11359			 *    $(document).ready( function() {
11360			 *      $('#example').dataTable( {
11361			 *        "language": {
11362			 *          "emptyTable": "No data available in table"
11363			 *        }
11364			 *      } );
11365			 *    } );
11366			 */
11367			"sEmptyTable": "No data available in table",
11368	
11369	
11370			/**
11371			 * This string gives information to the end user about the information
11372			 * that is current on display on the page. The following tokens can be
11373			 * used in the string and will be dynamically replaced as the table
11374			 * display updates. This tokens can be placed anywhere in the string, or
11375			 * removed as needed by the language requires:
11376			 *
11377			 * * `\_START\_` - Display index of the first record on the current page
11378			 * * `\_END\_` - Display index of the last record on the current page
11379			 * * `\_TOTAL\_` - Number of records in the table after filtering
11380			 * * `\_MAX\_` - Number of records in the table without filtering
11381			 * * `\_PAGE\_` - Current page number
11382			 * * `\_PAGES\_` - Total number of pages of data in the table
11383			 *
11384			 *  @type string
11385			 *  @default Showing _START_ to _END_ of _TOTAL_ entries
11386			 *
11387			 *  @dtopt Language
11388			 *  @name DataTable.defaults.language.info
11389			 *
11390			 *  @example
11391			 *    $(document).ready( function() {
11392			 *      $('#example').dataTable( {
11393			 *        "language": {
11394			 *          "info": "Showing page _PAGE_ of _PAGES_"
11395			 *        }
11396			 *      } );
11397			 *    } );
11398			 */
11399			"sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
11400	
11401	
11402			/**
11403			 * Display information string for when the table is empty. Typically the
11404			 * format of this string should match `info`.
11405			 *  @type string
11406			 *  @default Showing 0 to 0 of 0 entries
11407			 *
11408			 *  @dtopt Language
11409			 *  @name DataTable.defaults.language.infoEmpty
11410			 *
11411			 *  @example
11412			 *    $(document).ready( function() {
11413			 *      $('#example').dataTable( {
11414			 *        "language": {
11415			 *          "infoEmpty": "No entries to show"
11416			 *        }
11417			 *      } );
11418			 *    } );
11419			 */
11420			"sInfoEmpty": "Showing 0 to 0 of 0 entries",
11421	
11422	
11423			/**
11424			 * When a user filters the information in a table, this string is appended
11425			 * to the information (`info`) to give an idea of how strong the filtering
11426			 * is. The variable _MAX_ is dynamically updated.
11427			 *  @type string
11428			 *  @default (filtered from _MAX_ total entries)
11429			 *
11430			 *  @dtopt Language
11431			 *  @name DataTable.defaults.language.infoFiltered
11432			 *
11433			 *  @example
11434			 *    $(document).ready( function() {
11435			 *      $('#example').dataTable( {
11436			 *        "language": {
11437			 *          "infoFiltered": " - filtering from _MAX_ records"
11438			 *        }
11439			 *      } );
11440			 *    } );
11441			 */
11442			"sInfoFiltered": "(filtered from _MAX_ total entries)",
11443	
11444	
11445			/**
11446			 * If can be useful to append extra information to the info string at times,
11447			 * and this variable does exactly that. This information will be appended to
11448			 * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are
11449			 * being used) at all times.
11450			 *  @type string
11451			 *  @default <i>Empty string</i>
11452			 *
11453			 *  @dtopt Language
11454			 *  @name DataTable.defaults.language.infoPostFix
11455			 *
11456			 *  @example
11457			 *    $(document).ready( function() {
11458			 *      $('#example').dataTable( {
11459			 *        "language": {
11460			 *          "infoPostFix": "All records shown are derived from real information."
11461			 *        }
11462			 *      } );
11463			 *    } );
11464			 */
11465			"sInfoPostFix": "",
11466	
11467	
11468			/**
11469			 * This decimal place operator is a little different from the other
11470			 * language options since DataTables doesn't output floating point
11471			 * numbers, so it won't ever use this for display of a number. Rather,
11472			 * what this parameter does is modify the sort methods of the table so
11473			 * that numbers which are in a format which has a character other than
11474			 * a period (`.`) as a decimal place will be sorted numerically.
11475			 *
11476			 * Note that numbers with different decimal places cannot be shown in
11477			 * the same table and still be sortable, the table must be consistent.
11478			 * However, multiple different tables on the page can use different
11479			 * decimal place characters.
11480			 *  @type string
11481			 *  @default 
11482			 *
11483			 *  @dtopt Language
11484			 *  @name DataTable.defaults.language.decimal
11485			 *
11486			 *  @example
11487			 *    $(document).ready( function() {
11488			 *      $('#example').dataTable( {
11489			 *        "language": {
11490			 *          "decimal": ","
11491			 *          "thousands": "."
11492			 *        }
11493			 *      } );
11494			 *    } );
11495			 */
11496			"sDecimal": "",
11497	
11498	
11499			/**
11500			 * DataTables has a build in number formatter (`formatNumber`) which is
11501			 * used to format large numbers that are used in the table information.
11502			 * By default a comma is used, but this can be trivially changed to any
11503			 * character you wish with this parameter.
11504			 *  @type string
11505			 *  @default ,
11506			 *
11507			 *  @dtopt Language
11508			 *  @name DataTable.defaults.language.thousands
11509			 *
11510			 *  @example
11511			 *    $(document).ready( function() {
11512			 *      $('#example').dataTable( {
11513			 *        "language": {
11514			 *          "thousands": "'"
11515			 *        }
11516			 *      } );
11517			 *    } );
11518			 */
11519			"sThousands": ",",
11520	
11521	
11522			/**
11523			 * Detail the action that will be taken when the drop down menu for the
11524			 * pagination length option is changed. The '_MENU_' variable is replaced
11525			 * with a default select list of 10, 25, 50 and 100, and can be replaced
11526			 * with a custom select box if required.
11527			 *  @type string
11528			 *  @default Show _MENU_ entries
11529			 *
11530			 *  @dtopt Language
11531			 *  @name DataTable.defaults.language.lengthMenu
11532			 *
11533			 *  @example
11534			 *    // Language change only
11535			 *    $(document).ready( function() {
11536			 *      $('#example').dataTable( {
11537			 *        "language": {
11538			 *          "lengthMenu": "Display _MENU_ records"
11539			 *        }
11540			 *      } );
11541			 *    } );
11542			 *
11543			 *  @example
11544			 *    // Language and options change
11545			 *    $(document).ready( function() {
11546			 *      $('#example').dataTable( {
11547			 *        "language": {
11548			 *          "lengthMenu": 'Display <select>'+
11549			 *            '<option value="10">10</option>'+
11550			 *            '<option value="20">20</option>'+
11551			 *            '<option value="30">30</option>'+
11552			 *            '<option value="40">40</option>'+
11553			 *            '<option value="50">50</option>'+
11554			 *            '<option value="-1">All</option>'+
11555			 *            '</select> records'
11556			 *        }
11557			 *      } );
11558			 *    } );
11559			 */
11560			"sLengthMenu": "Show _MENU_ entries",
11561	
11562	
11563			/**
11564			 * When using Ajax sourced data and during the first draw when DataTables is
11565			 * gathering the data, this message is shown in an empty row in the table to
11566			 * indicate to the end user the the data is being loaded. Note that this
11567			 * parameter is not used when loading data by server-side processing, just
11568			 * Ajax sourced data with client-side processing.
11569			 *  @type string
11570			 *  @default Loading...
11571			 *
11572			 *  @dtopt Language
11573			 *  @name DataTable.defaults.language.loadingRecords
11574			 *
11575			 *  @example
11576			 *    $(document).ready( function() {
11577			 *      $('#example').dataTable( {
11578			 *        "language": {
11579			 *          "loadingRecords": "Please wait - loading..."
11580			 *        }
11581			 *      } );
11582			 *    } );
11583			 */
11584			"sLoadingRecords": "Loading...",
11585	
11586	
11587			/**
11588			 * Text which is displayed when the table is processing a user action
11589			 * (usually a sort command or similar).
11590			 *  @type string
11591			 *  @default Processing...
11592			 *
11593			 *  @dtopt Language
11594			 *  @name DataTable.defaults.language.processing
11595			 *
11596			 *  @example
11597			 *    $(document).ready( function() {
11598			 *      $('#example').dataTable( {
11599			 *        "language": {
11600			 *          "processing": "DataTables is currently busy"
11601			 *        }
11602			 *      } );
11603			 *    } );
11604			 */
11605			"sProcessing": "Processing...",
11606	
11607	
11608			/**
11609			 * Details the actions that will be taken when the user types into the
11610			 * filtering input text box. The variable "_INPUT_", if used in the string,
11611			 * is replaced with the HTML text box for the filtering input allowing
11612			 * control over where it appears in the string. If "_INPUT_" is not given
11613			 * then the input box is appended to the string automatically.
11614			 *  @type string
11615			 *  @default Search:
11616			 *
11617			 *  @dtopt Language
11618			 *  @name DataTable.defaults.language.search
11619			 *
11620			 *  @example
11621			 *    // Input text box will be appended at the end automatically
11622			 *    $(document).ready( function() {
11623			 *      $('#example').dataTable( {
11624			 *        "language": {
11625			 *          "search": "Filter records:"
11626			 *        }
11627			 *      } );
11628			 *    } );
11629			 *
11630			 *  @example
11631			 *    // Specify where the filter should appear
11632			 *    $(document).ready( function() {
11633			 *      $('#example').dataTable( {
11634			 *        "language": {
11635			 *          "search": "Apply filter _INPUT_ to table"
11636			 *        }
11637			 *      } );
11638			 *    } );
11639			 */
11640			"sSearch": "Search:",
11641	
11642	
11643			/**
11644			 * Assign a `placeholder` attribute to the search `input` element
11645			 *  @type string
11646			 *  @default 
11647			 *
11648			 *  @dtopt Language
11649			 *  @name DataTable.defaults.language.searchPlaceholder
11650			 */
11651			"sSearchPlaceholder": "",
11652	
11653	
11654			/**
11655			 * All of the language information can be stored in a file on the
11656			 * server-side, which DataTables will look up if this parameter is passed.
11657			 * It must store the URL of the language file, which is in a JSON format,
11658			 * and the object has the same properties as the oLanguage object in the
11659			 * initialiser object (i.e. the above parameters). Please refer to one of
11660			 * the example language files to see how this works in action.
11661			 *  @type string
11662			 *  @default <i>Empty string - i.e. disabled</i>
11663			 *
11664			 *  @dtopt Language
11665			 *  @name DataTable.defaults.language.url
11666			 *
11667			 *  @example
11668			 *    $(document).ready( function() {
11669			 *      $('#example').dataTable( {
11670			 *        "language": {
11671			 *          "url": "http://www.sprymedia.co.uk/dataTables/lang.txt"
11672			 *        }
11673			 *      } );
11674			 *    } );
11675			 */
11676			"sUrl": "",
11677	
11678	
11679			/**
11680			 * Text shown inside the table records when the is no information to be
11681			 * displayed after filtering. `emptyTable` is shown when there is simply no
11682			 * information in the table at all (regardless of filtering).
11683			 *  @type string
11684			 *  @default No matching records found
11685			 *
11686			 *  @dtopt Language
11687			 *  @name DataTable.defaults.language.zeroRecords
11688			 *
11689			 *  @example
11690			 *    $(document).ready( function() {
11691			 *      $('#example').dataTable( {
11692			 *        "language": {
11693			 *          "zeroRecords": "No records to display"
11694			 *        }
11695			 *      } );
11696			 *    } );
11697			 */
11698			"sZeroRecords": "No matching records found"
11699		},
11700	
11701	
11702		/**
11703		 * This parameter allows you to have define the global filtering state at
11704		 * initialisation time. As an object the `search` parameter must be
11705		 * defined, but all other parameters are optional. When `regex` is true,
11706		 * the search string will be treated as a regular expression, when false
11707		 * (default) it will be treated as a straight string. When `smart`
11708		 * DataTables will use it's smart filtering methods (to word match at
11709		 * any point in the data), when false this will not be done.
11710		 *  @namespace
11711		 *  @extends DataTable.models.oSearch
11712		 *
11713		 *  @dtopt Options
11714		 *  @name DataTable.defaults.search
11715		 *
11716		 *  @example
11717		 *    $(document).ready( function() {
11718		 *      $('#example').dataTable( {
11719		 *        "search": {"search": "Initial search"}
11720		 *      } );
11721		 *    } )
11722		 */
11723		"oSearch": $.extend( {}, DataTable.models.oSearch ),
11724	
11725	
11726		/**
11727		 * __Deprecated__ The functionality provided by this parameter has now been
11728		 * superseded by that provided through `ajax`, which should be used instead.
11729		 *
11730		 * By default DataTables will look for the property `data` (or `aaData` for
11731		 * compatibility with DataTables 1.9-) when obtaining data from an Ajax
11732		 * source or for server-side processing - this parameter allows that
11733		 * property to be changed. You can use Javascript dotted object notation to
11734		 * get a data source for multiple levels of nesting.
11735		 *  @type string
11736		 *  @default data
11737		 *
11738		 *  @dtopt Options
11739		 *  @dtopt Server-side
11740		 *  @name DataTable.defaults.ajaxDataProp
11741		 *
11742		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11743		 */
11744		"sAjaxDataProp": "data",
11745	
11746	
11747		/**
11748		 * __Deprecated__ The functionality provided by this parameter has now been
11749		 * superseded by that provided through `ajax`, which should be used instead.
11750		 *
11751		 * You can instruct DataTables to load data from an external
11752		 * source using this parameter (use aData if you want to pass data in you
11753		 * already have). Simply provide a url a JSON object can be obtained from.
11754		 *  @type string
11755		 *  @default null
11756		 *
11757		 *  @dtopt Options
11758		 *  @dtopt Server-side
11759		 *  @name DataTable.defaults.ajaxSource
11760		 *
11761		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11762		 */
11763		"sAjaxSource": null,
11764	
11765	
11766		/**
11767		 * This initialisation variable allows you to specify exactly where in the
11768		 * DOM you want DataTables to inject the various controls it adds to the page
11769		 * (for example you might want the pagination controls at the top of the
11770		 * table). DIV elements (with or without a custom class) can also be added to
11771		 * aid styling. The follow syntax is used:
11772		 *   <ul>
11773		 *     <li>The following options are allowed:
11774		 *       <ul>
11775		 *         <li>'l' - Length changing</li>
11776		 *         <li>'f' - Filtering input</li>
11777		 *         <li>'t' - The table!</li>
11778		 *         <li>'i' - Information</li>
11779		 *         <li>'p' - Pagination</li>
11780		 *         <li>'r' - pRocessing</li>
11781		 *       </ul>
11782		 *     </li>
11783		 *     <li>The following constants are allowed:
11784		 *       <ul>
11785		 *         <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>
11786		 *         <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>
11787		 *       </ul>
11788		 *     </li>
11789		 *     <li>The following syntax is expected:
11790		 *       <ul>
11791		 *         <li>'&lt;' and '&gt;' - div elements</li>
11792		 *         <li>'&lt;"class" and '&gt;' - div with a class</li>
11793		 *         <li>'&lt;"#id" and '&gt;' - div with an ID</li>
11794		 *       </ul>
11795		 *     </li>
11796		 *     <li>Examples:
11797		 *       <ul>
11798		 *         <li>'&lt;"wrapper"flipt&gt;'</li>
11799		 *         <li>'&lt;lf&lt;t&gt;ip&gt;'</li>
11800		 *       </ul>
11801		 *     </li>
11802		 *   </ul>
11803		 *  @type string
11804		 *  @default lfrtip <i>(when `jQueryUI` is false)</i> <b>or</b>
11805		 *    <"H"lfr>t<"F"ip> <i>(when `jQueryUI` is true)</i>
11806		 *
11807		 *  @dtopt Options
11808		 *  @name DataTable.defaults.dom
11809		 *
11810		 *  @example
11811		 *    $(document).ready( function() {
11812		 *      $('#example').dataTable( {
11813		 *        "dom": '&lt;"top"i&gt;rt&lt;"bottom"flp&gt;&lt;"clear"&gt;'
11814		 *      } );
11815		 *    } );
11816		 */
11817		"sDom": "lfrtip",
11818	
11819	
11820		/**
11821		 * Search delay option. This will throttle full table searches that use the
11822		 * DataTables provided search input element (it does not effect calls to
11823		 * `dt-api search()`, providing a delay before the search is made.
11824		 *  @type integer
11825		 *  @default 0
11826		 *
11827		 *  @dtopt Options
11828		 *  @name DataTable.defaults.searchDelay
11829		 *
11830		 *  @example
11831		 *    $(document).ready( function() {
11832		 *      $('#example').dataTable( {
11833		 *        "searchDelay": 200
11834		 *      } );
11835		 *    } )
11836		 */
11837		"searchDelay": null,
11838	
11839	
11840		/**
11841		 * DataTables features four different built-in options for the buttons to
11842		 * display for pagination control:
11843		 *
11844		 * * `simple` - 'Previous' and 'Next' buttons only
11845		 * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers
11846		 * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons
11847		 * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus
11848		 *   page numbers
11849		 *  
11850		 * Further methods can be added using {@link DataTable.ext.oPagination}.
11851		 *  @type string
11852		 *  @default simple_numbers
11853		 *
11854		 *  @dtopt Options
11855		 *  @name DataTable.defaults.pagingType
11856		 *
11857		 *  @example
11858		 *    $(document).ready( function() {
11859		 *      $('#example').dataTable( {
11860		 *        "pagingType": "full_numbers"
11861		 *      } );
11862		 *    } )
11863		 */
11864		"sPaginationType": "simple_numbers",
11865	
11866	
11867		/**
11868		 * Enable horizontal scrolling. When a table is too wide to fit into a
11869		 * certain layout, or you have a large number of columns in the table, you
11870		 * can enable x-scrolling to show the table in a viewport, which can be
11871		 * scrolled. This property can be `true` which will allow the table to
11872		 * scroll horizontally when needed, or any CSS unit, or a number (in which
11873		 * case it will be treated as a pixel measurement). Setting as simply `true`
11874		 * is recommended.
11875		 *  @type boolean|string
11876		 *  @default <i>blank string - i.e. disabled</i>
11877		 *
11878		 *  @dtopt Features
11879		 *  @name DataTable.defaults.scrollX
11880		 *
11881		 *  @example
11882		 *    $(document).ready( function() {
11883		 *      $('#example').dataTable( {
11884		 *        "scrollX": true,
11885		 *        "scrollCollapse": true
11886		 *      } );
11887		 *    } );
11888		 */
11889		"sScrollX": "",
11890	
11891	
11892		/**
11893		 * This property can be used to force a DataTable to use more width than it
11894		 * might otherwise do when x-scrolling is enabled. For example if you have a
11895		 * table which requires to be well spaced, this parameter is useful for
11896		 * "over-sizing" the table, and thus forcing scrolling. This property can by
11897		 * any CSS unit, or a number (in which case it will be treated as a pixel
11898		 * measurement).
11899		 *  @type string
11900		 *  @default <i>blank string - i.e. disabled</i>
11901		 *
11902		 *  @dtopt Options
11903		 *  @name DataTable.defaults.scrollXInner
11904		 *
11905		 *  @example
11906		 *    $(document).ready( function() {
11907		 *      $('#example').dataTable( {
11908		 *        "scrollX": "100%",
11909		 *        "scrollXInner": "110%"
11910		 *      } );
11911		 *    } );
11912		 */
11913		"sScrollXInner": "",
11914	
11915	
11916		/**
11917		 * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
11918		 * to the given height, and enable scrolling for any data which overflows the
11919		 * current viewport. This can be used as an alternative to paging to display
11920		 * a lot of data in a small area (although paging and scrolling can both be
11921		 * enabled at the same time). This property can be any CSS unit, or a number
11922		 * (in which case it will be treated as a pixel measurement).
11923		 *  @type string
11924		 *  @default <i>blank string - i.e. disabled</i>
11925		 *
11926		 *  @dtopt Features
11927		 *  @name DataTable.defaults.scrollY
11928		 *
11929		 *  @example
11930		 *    $(document).ready( function() {
11931		 *      $('#example').dataTable( {
11932		 *        "scrollY": "200px",
11933		 *        "paginate": false
11934		 *      } );
11935		 *    } );
11936		 */
11937		"sScrollY": "",
11938	
11939	
11940		/**
11941		 * __Deprecated__ The functionality provided by this parameter has now been
11942		 * superseded by that provided through `ajax`, which should be used instead.
11943		 *
11944		 * Set the HTTP method that is used to make the Ajax call for server-side
11945		 * processing or Ajax sourced data.
11946		 *  @type string
11947		 *  @default GET
11948		 *
11949		 *  @dtopt Options
11950		 *  @dtopt Server-side
11951		 *  @name DataTable.defaults.serverMethod
11952		 *
11953		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11954		 */
11955		"sServerMethod": "GET",
11956	
11957	
11958		/**
11959		 * DataTables makes use of renderers when displaying HTML elements for
11960		 * a table. These renderers can be added or modified by plug-ins to
11961		 * generate suitable mark-up for a site. For example the Bootstrap
11962		 * integration plug-in for DataTables uses a paging button renderer to
11963		 * display pagination buttons in the mark-up required by Bootstrap.
11964		 *
11965		 * For further information about the renderers available see
11966		 * DataTable.ext.renderer
11967		 *  @type string|object
11968		 *  @default null
11969		 *
11970		 *  @name DataTable.defaults.renderer
11971		 *
11972		 */
11973		"renderer": null,
11974	
11975	
11976		/**
11977		 * Set the data property name that DataTables should use to get a row's id
11978		 * to set as the `id` property in the node.
11979		 *  @type string
11980		 *  @default DT_RowId
11981		 *
11982		 *  @name DataTable.defaults.rowId
11983		 */
11984		"rowId": "DT_RowId"
11985	};
11986	
11987	_fnHungarianMap( DataTable.defaults );
11988	
11989	
11990	
11991	/*
11992	 * Developer note - See note in model.defaults.js about the use of Hungarian
11993	 * notation and camel case.
11994	 */
11995	
11996	/**
11997	 * Column options that can be given to DataTables at initialisation time.
11998	 *  @namespace
11999	 */
12000	DataTable.defaults.column = {
12001		/**
12002		 * Define which column(s) an order will occur on for this column. This
12003		 * allows a column's ordering to take multiple columns into account when
12004		 * doing a sort or use the data from a different column. For example first
12005		 * name / last name columns make sense to do a multi-column sort over the
12006		 * two columns.
12007		 *  @type array|int
12008		 *  @default null <i>Takes the value of the column index automatically</i>
12009		 *
12010		 *  @name DataTable.defaults.column.orderData
12011		 *  @dtopt Columns
12012		 *
12013		 *  @example
12014		 *    // Using `columnDefs`
12015		 *    $(document).ready( function() {
12016		 *      $('#example').dataTable( {
12017		 *        "columnDefs": [
12018		 *          { "orderData": [ 0, 1 ], "targets": [ 0 ] },
12019		 *          { "orderData": [ 1, 0 ], "targets": [ 1 ] },
12020		 *          { "orderData": 2, "targets": [ 2 ] }
12021		 *        ]
12022		 *      } );
12023		 *    } );
12024		 *
12025		 *  @example
12026		 *    // Using `columns`
12027		 *    $(document).ready( function() {
12028		 *      $('#example').dataTable( {
12029		 *        "columns": [
12030		 *          { "orderData": [ 0, 1 ] },
12031		 *          { "orderData": [ 1, 0 ] },
12032		 *          { "orderData": 2 },
12033		 *          null,
12034		 *          null
12035		 *        ]
12036		 *      } );
12037		 *    } );
12038		 */
12039		"aDataSort": null,
12040		"iDataSort": -1,
12041	
12042	
12043		/**
12044		 * You can control the default ordering direction, and even alter the
12045		 * behaviour of the sort handler (i.e. only allow ascending ordering etc)
12046		 * using this parameter.
12047		 *  @type array
12048		 *  @default [ 'asc', 'desc' ]
12049		 *
12050		 *  @name DataTable.defaults.column.orderSequence
12051		 *  @dtopt Columns
12052		 *
12053		 *  @example
12054		 *    // Using `columnDefs`
12055		 *    $(document).ready( function() {
12056		 *      $('#example').dataTable( {
12057		 *        "columnDefs": [
12058		 *          { "orderSequence": [ "asc" ], "targets": [ 1 ] },
12059		 *          { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] },
12060		 *          { "orderSequence": [ "desc" ], "targets": [ 3 ] }
12061		 *        ]
12062		 *      } );
12063		 *    } );
12064		 *
12065		 *  @example
12066		 *    // Using `columns`
12067		 *    $(document).ready( function() {
12068		 *      $('#example').dataTable( {
12069		 *        "columns": [
12070		 *          null,
12071		 *          { "orderSequence": [ "asc" ] },
12072		 *          { "orderSequence": [ "desc", "asc", "asc" ] },
12073		 *          { "orderSequence": [ "desc" ] },
12074		 *          null
12075		 *        ]
12076		 *      } );
12077		 *    } );
12078		 */
12079		"asSorting": [ 'asc', 'desc' ],
12080	
12081	
12082		/**
12083		 * Enable or disable filtering on the data in this column.
12084		 *  @type boolean
12085		 *  @default true
12086		 *
12087		 *  @name DataTable.defaults.column.searchable
12088		 *  @dtopt Columns
12089		 *
12090		 *  @example
12091		 *    // Using `columnDefs`
12092		 *    $(document).ready( function() {
12093		 *      $('#example').dataTable( {
12094		 *        "columnDefs": [
12095		 *          { "searchable": false, "targets": [ 0 ] }
12096		 *        ] } );
12097		 *    } );
12098		 *
12099		 *  @example
12100		 *    // Using `columns`
12101		 *    $(document).ready( function() {
12102		 *      $('#example').dataTable( {
12103		 *        "columns": [
12104		 *          { "searchable": false },
12105		 *          null,
12106		 *          null,
12107		 *          null,
12108		 *          null
12109		 *        ] } );
12110		 *    } );
12111		 */
12112		"bSearchable": true,
12113	
12114	
12115		/**
12116		 * Enable or disable ordering on this column.
12117		 *  @type boolean
12118		 *  @default true
12119		 *
12120		 *  @name DataTable.defaults.column.orderable
12121		 *  @dtopt Columns
12122		 *
12123		 *  @example
12124		 *    // Using `columnDefs`
12125		 *    $(document).ready( function() {
12126		 *      $('#example').dataTable( {
12127		 *        "columnDefs": [
12128		 *          { "orderable": false, "targets": [ 0 ] }
12129		 *        ] } );
12130		 *    } );
12131		 *
12132		 *  @example
12133		 *    // Using `columns`
12134		 *    $(document).ready( function() {
12135		 *      $('#example').dataTable( {
12136		 *        "columns": [
12137		 *          { "orderable": false },
12138		 *          null,
12139		 *          null,
12140		 *          null,
12141		 *          null
12142		 *        ] } );
12143		 *    } );
12144		 */
12145		"bSortable": true,
12146	
12147	
12148		/**
12149		 * Enable or disable the display of this column.
12150		 *  @type boolean
12151		 *  @default true
12152		 *
12153		 *  @name DataTable.defaults.column.visible
12154		 *  @dtopt Columns
12155		 *
12156		 *  @example
12157		 *    // Using `columnDefs`
12158		 *    $(document).ready( function() {
12159		 *      $('#example').dataTable( {
12160		 *        "columnDefs": [
12161		 *          { "visible": false, "targets": [ 0 ] }
12162		 *        ] } );
12163		 *    } );
12164		 *
12165		 *  @example
12166		 *    // Using `columns`
12167		 *    $(document).ready( function() {
12168		 *      $('#example').dataTable( {
12169		 *        "columns": [
12170		 *          { "visible": false },
12171		 *          null,
12172		 *          null,
12173		 *          null,
12174		 *          null
12175		 *        ] } );
12176		 *    } );
12177		 */
12178		"bVisible": true,
12179	
12180	
12181		/**
12182		 * Developer definable function that is called whenever a cell is created (Ajax source,
12183		 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
12184		 * allowing you to modify the DOM element (add background colour for example) when the
12185		 * element is available.
12186		 *  @type function
12187		 *  @param {element} td The TD node that has been created
12188		 *  @param {*} cellData The Data for the cell
12189		 *  @param {array|object} rowData The data for the whole row
12190		 *  @param {int} row The row index for the aoData data store
12191		 *  @param {int} col The column index for aoColumns
12192		 *
12193		 *  @name DataTable.defaults.column.createdCell
12194		 *  @dtopt Columns
12195		 *
12196		 *  @example
12197		 *    $(document).ready( function() {
12198		 *      $('#example').dataTable( {
12199		 *        "columnDefs": [ {
12200		 *          "targets": [3],
12201		 *          "createdCell": function (td, cellData, rowData, row, col) {
12202		 *            if ( cellData == "1.7" ) {
12203		 *              $(td).css('color', 'blue')
12204		 *            }
12205		 *          }
12206		 *        } ]
12207		 *      });
12208		 *    } );
12209		 */
12210		"fnCreatedCell": null,
12211	
12212	
12213		/**
12214		 * This parameter has been replaced by `data` in DataTables to ensure naming
12215		 * consistency. `dataProp` can still be used, as there is backwards
12216		 * compatibility in DataTables for this option, but it is strongly
12217		 * recommended that you use `data` in preference to `dataProp`.
12218		 *  @name DataTable.defaults.column.dataProp
12219		 */
12220	
12221	
12222		/**
12223		 * This property can be used to read data from any data source property,
12224		 * including deeply nested objects / properties. `data` can be given in a
12225		 * number of different ways which effect its behaviour:
12226		 *
12227		 * * `integer` - treated as an array index for the data source. This is the
12228		 *   default that DataTables uses (incrementally increased for each column).
12229		 * * `string` - read an object property from the data source. There are
12230		 *   three 'special' options that can be used in the string to alter how
12231		 *   DataTables reads the data from the source object:
12232		 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
12233		 *      Javascript to read from nested objects, so to can the options
12234		 *      specified in `data`. For example: `browser.version` or
12235		 *      `browser.name`. If your object parameter name contains a period, use
12236		 *      `\\` to escape it - i.e. `first\\.name`.
12237		 *    * `[]` - Array notation. DataTables can automatically combine data
12238		 *      from and array source, joining the data with the characters provided
12239		 *      between the two brackets. For example: `name[, ]` would provide a
12240		 *      comma-space separated list from the source array. If no characters
12241		 *      are provided between the brackets, the original array source is
12242		 *      returned.
12243		 *    * `()` - Function notation. Adding `()` to the end of a parameter will
12244		 *      execute a function of the name given. For example: `browser()` for a
12245		 *      simple function on the data source, `browser.version()` for a
12246		 *      function in a nested property or even `browser().version` to get an
12247		 *      object property if the function called returns an object. Note that
12248		 *      function notation is recommended for use in `render` rather than
12249		 *      `data` as it is much simpler to use as a renderer.
12250		 * * `null` - use the original data source for the row rather than plucking
12251		 *   data directly from it. This action has effects on two other
12252		 *   initialisation options:
12253		 *    * `defaultContent` - When null is given as the `data` option and
12254		 *      `defaultContent` is specified for the column, the value defined by
12255		 *      `defaultContent` will be used for the cell.
12256		 *    * `render` - When null is used for the `data` option and the `render`
12257		 *      option is specified for the column, the whole data source for the
12258		 *      row is used for the renderer.
12259		 * * `function` - the function given will be executed whenever DataTables
12260		 *   needs to set or get the data for a cell in the column. The function
12261		 *   takes three parameters:
12262		 *    * Parameters:
12263		 *      * `{array|object}` The data source for the row
12264		 *      * `{string}` The type call data requested - this will be 'set' when
12265		 *        setting data or 'filter', 'display', 'type', 'sort' or undefined
12266		 *        when gathering data. Note that when `undefined` is given for the
12267		 *        type DataTables expects to get the raw data for the object back<
12268		 *      * `{*}` Data to set when the second parameter is 'set'.
12269		 *    * Return:
12270		 *      * The return value from the function is not required when 'set' is
12271		 *        the type of call, but otherwise the return is what will be used
12272		 *        for the data requested.
12273		 *
12274		 * Note that `data` is a getter and setter option. If you just require
12275		 * formatting of data for output, you will likely want to use `render` which
12276		 * is simply a getter and thus simpler to use.
12277		 *
12278		 * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The
12279		 * name change reflects the flexibility of this property and is consistent
12280		 * with the naming of mRender. If 'mDataProp' is given, then it will still
12281		 * be used by DataTables, as it automatically maps the old name to the new
12282		 * if required.
12283		 *
12284		 *  @type string|int|function|null
12285		 *  @default null <i>Use automatically calculated column index</i>
12286		 *
12287		 *  @name DataTable.defaults.column.data
12288		 *  @dtopt Columns
12289		 *
12290		 *  @example
12291		 *    // Read table data from objects
12292		 *    // JSON structure for each row:
12293		 *    //   {
12294		 *    //      "engine": {value},
12295		 *    //      "browser": {value},
12296		 *    //      "platform": {value},
12297		 *    //      "version": {value},
12298		 *    //      "grade": {value}
12299		 *    //   }
12300		 *    $(document).ready( function() {
12301		 *      $('#example').dataTable( {
12302		 *        "ajaxSource": "sources/objects.txt",
12303		 *        "columns": [
12304		 *          { "data": "engine" },
12305		 *          { "data": "browser" },
12306		 *          { "data": "platform" },
12307		 *          { "data": "version" },
12308		 *          { "data": "grade" }
12309		 *        ]
12310		 *      } );
12311		 *    } );
12312		 *
12313		 *  @example
12314		 *    // Read information from deeply nested objects
12315		 *    // JSON structure for each row:
12316		 *    //   {
12317		 *    //      "engine": {value},
12318		 *    //      "browser": {value},
12319		 *    //      "platform": {
12320		 *    //         "inner": {value}
12321		 *    //      },
12322		 *    //      "details": [
12323		 *    //         {value}, {value}
12324		 *    //      ]
12325		 *    //   }
12326		 *    $(document).ready( function() {
12327		 *      $('#example').dataTable( {
12328		 *        "ajaxSource": "sources/deep.txt",
12329		 *        "columns": [
12330		 *          { "data": "engine" },
12331		 *          { "data": "browser" },
12332		 *          { "data": "platform.inner" },
12333		 *          { "data": "platform.details.0" },
12334		 *          { "data": "platform.details.1" }
12335		 *        ]
12336		 *      } );
12337		 *    } );
12338		 *
12339		 *  @example
12340		 *    // Using `data` as a function to provide different information for
12341		 *    // sorting, filtering and display. In this case, currency (price)
12342		 *    $(document).ready( function() {
12343		 *      $('#example').dataTable( {
12344		 *        "columnDefs": [ {
12345		 *          "targets": [ 0 ],
12346		 *          "data": function ( source, type, val ) {
12347		 *            if (type === 'set') {
12348		 *              source.price = val;
12349		 *              // Store the computed dislay and filter values for efficiency
12350		 *              source.price_display = val=="" ? "" : "$"+numberFormat(val);
12351		 *              source.price_filter  = val=="" ? "" : "$"+numberFormat(val)+" "+val;
12352		 *              return;
12353		 *            }
12354		 *            else if (type === 'display') {
12355		 *              return source.price_display;
12356		 *            }
12357		 *            else if (type === 'filter') {
12358		 *              return source.price_filter;
12359		 *            }
12360		 *            // 'sort', 'type' and undefined all just use the integer
12361		 *            return source.price;
12362		 *          }
12363		 *        } ]
12364		 *      } );
12365		 *    } );
12366		 *
12367		 *  @example
12368		 *    // Using default content
12369		 *    $(document).ready( function() {
12370		 *      $('#example').dataTable( {
12371		 *        "columnDefs": [ {
12372		 *          "targets": [ 0 ],
12373		 *          "data": null,
12374		 *          "defaultContent": "Click to edit"
12375		 *        } ]
12376		 *      } );
12377		 *    } );
12378		 *
12379		 *  @example
12380		 *    // Using array notation - outputting a list from an array
12381		 *    $(document).ready( function() {
12382		 *      $('#example').dataTable( {
12383		 *        "columnDefs": [ {
12384		 *          "targets": [ 0 ],
12385		 *          "data": "name[, ]"
12386		 *        } ]
12387		 *      } );
12388		 *    } );
12389		 *
12390		 */
12391		"mData": null,
12392	
12393	
12394		/**
12395		 * This property is the rendering partner to `data` and it is suggested that
12396		 * when you want to manipulate data for display (including filtering,
12397		 * sorting etc) without altering the underlying data for the table, use this
12398		 * property. `render` can be considered to be the the read only companion to
12399		 * `data` which is read / write (then as such more complex). Like `data`
12400		 * this option can be given in a number of different ways to effect its
12401		 * behaviour:
12402		 *
12403		 * * `integer` - treated as an array index for the data source. This is the
12404		 *   default that DataTables uses (incrementally increased for each column).
12405		 * * `string` - read an object property from the data source. There are
12406		 *   three 'special' options that can be used in the string to alter how
12407		 *   DataTables reads the data from the source object:
12408		 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
12409		 *      Javascript to read from nested objects, so to can the options
12410		 *      specified in `data`. For example: `browser.version` or
12411		 *      `browser.name`. If your object parameter name contains a period, use
12412		 *      `\\` to escape it - i.e. `first\\.name`.
12413		 *    * `[]` - Array notation. DataTables can automatically combine data
12414		 *      from and array source, joining the data with the characters provided
12415		 *      between the two brackets. For example: `name[, ]` would provide a
12416		 *      comma-space separated list from the source array. If no characters
12417		 *      are provided between the brackets, the original array source is
12418		 *      returned.
12419		 *    * `()` - Function notation. Adding `()` to the end of a parameter will
12420		 *      execute a function of the name given. For example: `browser()` for a
12421		 *      simple function on the data source, `browser.version()` for a
12422		 *      function in a nested property or even `browser().version` to get an
12423		 *      object property if the function called returns an object.
12424		 * * `object` - use different data for the different data types requested by
12425		 *   DataTables ('filter', 'display', 'type' or 'sort'). The property names
12426		 *   of the object is the data type the property refers to and the value can
12427		 *   defined using an integer, string or function using the same rules as
12428		 *   `render` normally does. Note that an `_` option _must_ be specified.
12429		 *   This is the default value to use if you haven't specified a value for
12430		 *   the data type requested by DataTables.
12431		 * * `function` - the function given will be executed whenever DataTables
12432		 *   needs to set or get the data for a cell in the column. The function
12433		 *   takes three parameters:
12434		 *    * Parameters:
12435		 *      * {array|object} The data source for the row (based on `data`)
12436		 *      * {string} The type call data requested - this will be 'filter',
12437		 *        'display', 'type' or 'sort'.
12438		 *      * {array|object} The full data source for the row (not based on
12439		 *        `data`)
12440		 *    * Return:
12441		 *      * The return value from the function is what will be used for the
12442		 *        data requested.
12443		 *
12444		 *  @type string|int|function|object|null
12445		 *  @default null Use the data source value.
12446		 *
12447		 *  @name DataTable.defaults.column.render
12448		 *  @dtopt Columns
12449		 *
12450		 *  @example
12451		 *    // Create a comma separated list from an array of objects
12452		 *    $(document).ready( function() {
12453		 *      $('#example').dataTable( {
12454		 *        "ajaxSource": "sources/deep.txt",
12455		 *        "columns": [
12456		 *          { "data": "engine" },
12457		 *          { "data": "browser" },
12458		 *          {
12459		 *            "data": "platform",
12460		 *            "render": "[, ].name"
12461		 *          }
12462		 *        ]
12463		 *      } );
12464		 *    } );
12465		 *
12466		 *  @example
12467		 *    // Execute a function to obtain data
12468		 *    $(document).ready( function() {
12469		 *      $('#example').dataTable( {
12470		 *        "columnDefs": [ {
12471		 *          "targets": [ 0 ],
12472		 *          "data": null, // Use the full data source object for the renderer's source
12473		 *          "render": "browserName()"
12474		 *        } ]
12475		 *      } );
12476		 *    } );
12477		 *
12478		 *  @example
12479		 *    // As an object, extracting different data for the different types
12480		 *    // This would be used with a data source such as:
12481		 *    //   { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" }
12482		 *    // Here the `phone` integer is used for sorting and type detection, while `phone_filter`
12483		 *    // (which has both forms) is used for filtering for if a user inputs either format, while
12484		 *    // the formatted phone number is the one that is shown in the table.
12485		 *    $(document).ready( function() {
12486		 *      $('#example').dataTable( {
12487		 *        "columnDefs": [ {
12488		 *          "targets": [ 0 ],
12489		 *          "data": null, // Use the full data source object for the renderer's source
12490		 *          "render": {
12491		 *            "_": "phone",
12492		 *            "filter": "phone_filter",
12493		 *            "display": "phone_display"
12494		 *          }
12495		 *        } ]
12496		 *      } );
12497		 *    } );
12498		 *
12499		 *  @example
12500		 *    // Use as a function to create a link from the data source
12501		 *    $(document).ready( function() {
12502		 *      $('#example').dataTable( {
12503		 *        "columnDefs": [ {
12504		 *          "targets": [ 0 ],
12505		 *          "data": "download_link",
12506		 *          "render": function ( data, type, full ) {
12507		 *            return '<a href="'+data+'">Download</a>';
12508		 *          }
12509		 *        } ]
12510		 *      } );
12511		 *    } );
12512		 */
12513		"mRender": null,
12514	
12515	
12516		/**
12517		 * Change the cell type created for the column - either TD cells or TH cells. This
12518		 * can be useful as TH cells have semantic meaning in the table body, allowing them
12519		 * to act as a header for a row (you may wish to add scope='row' to the TH elements).
12520		 *  @type string
12521		 *  @default td
12522		 *
12523		 *  @name DataTable.defaults.column.cellType
12524		 *  @dtopt Columns
12525		 *
12526		 *  @example
12527		 *    // Make the first column use TH cells
12528		 *    $(document).ready( function() {
12529		 *      $('#example').dataTable( {
12530		 *        "columnDefs": [ {
12531		 *          "targets": [ 0 ],
12532		 *          "cellType": "th"
12533		 *        } ]
12534		 *      } );
12535		 *    } );
12536		 */
12537		"sCellType": "td",
12538	
12539	
12540		/**
12541		 * Class to give to each cell in this column.
12542		 *  @type string
12543		 *  @default <i>Empty string</i>
12544		 *
12545		 *  @name DataTable.defaults.column.class
12546		 *  @dtopt Columns
12547		 *
12548		 *  @example
12549		 *    // Using `columnDefs`
12550		 *    $(document).ready( function() {
12551		 *      $('#example').dataTable( {
12552		 *        "columnDefs": [
12553		 *          { "class": "my_class", "targets": [ 0 ] }
12554		 *        ]
12555		 *      } );
12556		 *    } );
12557		 *
12558		 *  @example
12559		 *    // Using `columns`
12560		 *    $(document).ready( function() {
12561		 *      $('#example').dataTable( {
12562		 *        "columns": [
12563		 *          { "class": "my_class" },
12564		 *          null,
12565		 *          null,
12566		 *          null,
12567		 *          null
12568		 *        ]
12569		 *      } );
12570		 *    } );
12571		 */
12572		"sClass": "",
12573	
12574		/**
12575		 * When DataTables calculates the column widths to assign to each column,
12576		 * it finds the longest string in each column and then constructs a
12577		 * temporary table and reads the widths from that. The problem with this
12578		 * is that "mmm" is much wider then "iiii", but the latter is a longer
12579		 * string - thus the calculation can go wrong (doing it properly and putting
12580		 * it into an DOM object and measuring that is horribly(!) slow). Thus as
12581		 * a "work around" we provide this option. It will append its value to the
12582		 * text that is found to be the longest string for the column - i.e. padding.
12583		 * Generally you shouldn't need this!
12584		 *  @type string
12585		 *  @default <i>Empty string<i>
12586		 *
12587		 *  @name DataTable.defaults.column.contentPadding
12588		 *  @dtopt Columns
12589		 *
12590		 *  @example
12591		 *    // Using `columns`
12592		 *    $(document).ready( function() {
12593		 *      $('#example').dataTable( {
12594		 *        "columns": [
12595		 *          null,
12596		 *          null,
12597		 *          null,
12598		 *          {
12599		 *            "contentPadding": "mmm"
12600		 *          }
12601		 *        ]
12602		 *      } );
12603		 *    } );
12604		 */
12605		"sContentPadding": "",
12606	
12607	
12608		/**
12609		 * Allows a default value to be given for a column's data, and will be used
12610		 * whenever a null data source is encountered (this can be because `data`
12611		 * is set to null, or because the data source itself is null).
12612		 *  @type string
12613		 *  @default null
12614		 *
12615		 *  @name DataTable.defaults.column.defaultContent
12616		 *  @dtopt Columns
12617		 *
12618		 *  @example
12619		 *    // Using `columnDefs`
12620		 *    $(document).ready( function() {
12621		 *      $('#example').dataTable( {
12622		 *        "columnDefs": [
12623		 *          {
12624		 *            "data": null,
12625		 *            "defaultContent": "Edit",
12626		 *            "targets": [ -1 ]
12627		 *          }
12628		 *        ]
12629		 *      } );
12630		 *    } );
12631		 *
12632		 *  @example
12633		 *    // Using `columns`
12634		 *    $(document).ready( function() {
12635		 *      $('#example').dataTable( {
12636		 *        "columns": [
12637		 *          null,
12638		 *          null,
12639		 *          null,
12640		 *          {
12641		 *            "data": null,
12642		 *            "defaultContent": "Edit"
12643		 *          }
12644		 *        ]
12645		 *      } );
12646		 *    } );
12647		 */
12648		"sDefaultContent": null,
12649	
12650	
12651		/**
12652		 * This parameter is only used in DataTables' server-side processing. It can
12653		 * be exceptionally useful to know what columns are being displayed on the
12654		 * client side, and to map these to database fields. When defined, the names
12655		 * also allow DataTables to reorder information from the server if it comes
12656		 * back in an unexpected order (i.e. if you switch your columns around on the
12657		 * client-side, your server-side code does not also need updating).
12658		 *  @type string
12659		 *  @default <i>Empty string</i>
12660		 *
12661		 *  @name DataTable.defaults.column.name
12662		 *  @dtopt Columns
12663		 *
12664		 *  @example
12665		 *    // Using `columnDefs`
12666		 *    $(document).ready( function() {
12667		 *      $('#example').dataTable( {
12668		 *        "columnDefs": [
12669		 *          { "name": "engine", "targets": [ 0 ] },
12670		 *          { "name": "browser", "targets": [ 1 ] },
12671		 *          { "name": "platform", "targets": [ 2 ] },
12672		 *          { "name": "version", "targets": [ 3 ] },
12673		 *          { "name": "grade", "targets": [ 4 ] }
12674		 *        ]
12675		 *      } );
12676		 *    } );
12677		 *
12678		 *  @example
12679		 *    // Using `columns`
12680		 *    $(document).ready( function() {
12681		 *      $('#example').dataTable( {
12682		 *        "columns": [
12683		 *          { "name": "engine" },
12684		 *          { "name": "browser" },
12685		 *          { "name": "platform" },
12686		 *          { "name": "version" },
12687		 *          { "name": "grade" }
12688		 *        ]
12689		 *      } );
12690		 *    } );
12691		 */
12692		"sName": "",
12693	
12694	
12695		/**
12696		 * Defines a data source type for the ordering which can be used to read
12697		 * real-time information from the table (updating the internally cached
12698		 * version) prior to ordering. This allows ordering to occur on user
12699		 * editable elements such as form inputs.
12700		 *  @type string
12701		 *  @default std
12702		 *
12703		 *  @name DataTable.defaults.column.orderDataType
12704		 *  @dtopt Columns
12705		 *
12706		 *  @example
12707		 *    // Using `columnDefs`
12708		 *    $(document).ready( function() {
12709		 *      $('#example').dataTable( {
12710		 *        "columnDefs": [
12711		 *          { "orderDataType": "dom-text", "targets": [ 2, 3 ] },
12712		 *          { "type": "numeric", "targets": [ 3 ] },
12713		 *          { "orderDataType": "dom-select", "targets": [ 4 ] },
12714		 *          { "orderDataType": "dom-checkbox", "targets": [ 5 ] }
12715		 *        ]
12716		 *      } );
12717		 *    } );
12718		 *
12719		 *  @example
12720		 *    // Using `columns`
12721		 *    $(document).ready( function() {
12722		 *      $('#example').dataTable( {
12723		 *        "columns": [
12724		 *          null,
12725		 *          null,
12726		 *          { "orderDataType": "dom-text" },
12727		 *          { "orderDataType": "dom-text", "type": "numeric" },
12728		 *          { "orderDataType": "dom-select" },
12729		 *          { "orderDataType": "dom-checkbox" }
12730		 *        ]
12731		 *      } );
12732		 *    } );
12733		 */
12734		"sSortDataType": "std",
12735	
12736	
12737		/**
12738		 * The title of this column.
12739		 *  @type string
12740		 *  @default null <i>Derived from the 'TH' value for this column in the
12741		 *    original HTML table.</i>
12742		 *
12743		 *  @name DataTable.defaults.column.title
12744		 *  @dtopt Columns
12745		 *
12746		 *  @example
12747		 *    // Using `columnDefs`
12748		 *    $(document).ready( function() {
12749		 *      $('#example').dataTable( {
12750		 *        "columnDefs": [
12751		 *          { "title": "My column title", "targets": [ 0 ] }
12752		 *        ]
12753		 *      } );
12754		 *    } );
12755		 *
12756		 *  @example
12757		 *    // Using `columns`
12758		 *    $(document).ready( function() {
12759		 *      $('#example').dataTable( {
12760		 *        "columns": [
12761		 *          { "title": "My column title" },
12762		 *          null,
12763		 *          null,
12764		 *          null,
12765		 *          null
12766		 *        ]
12767		 *      } );
12768		 *    } );
12769		 */
12770		"sTitle": null,
12771	
12772	
12773		/**
12774		 * The type allows you to specify how the data for this column will be
12775		 * ordered. Four types (string, numeric, date and html (which will strip
12776		 * HTML tags before ordering)) are currently available. Note that only date
12777		 * formats understood by Javascript's Date() object will be accepted as type
12778		 * date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string',
12779		 * 'numeric', 'date' or 'html' (by default). Further types can be adding
12780		 * through plug-ins.
12781		 *  @type string
12782		 *  @default null <i>Auto-detected from raw data</i>
12783		 *
12784		 *  @name DataTable.defaults.column.type
12785		 *  @dtopt Columns
12786		 *
12787		 *  @example
12788		 *    // Using `columnDefs`
12789		 *    $(document).ready( function() {
12790		 *      $('#example').dataTable( {
12791		 *        "columnDefs": [
12792		 *          { "type": "html", "targets": [ 0 ] }
12793		 *        ]
12794		 *      } );
12795		 *    } );
12796		 *
12797		 *  @example
12798		 *    // Using `columns`
12799		 *    $(document).ready( function() {
12800		 *      $('#example').dataTable( {
12801		 *        "columns": [
12802		 *          { "type": "html" },
12803		 *          null,
12804		 *          null,
12805		 *          null,
12806		 *          null
12807		 *        ]
12808		 *      } );
12809		 *    } );
12810		 */
12811		"sType": null,
12812	
12813	
12814		/**
12815		 * Defining the width of the column, this parameter may take any CSS value
12816		 * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not
12817		 * been given a specific width through this interface ensuring that the table
12818		 * remains readable.
12819		 *  @type string
12820		 *  @default null <i>Automatic</i>
12821		 *
12822		 *  @name DataTable.defaults.column.width
12823		 *  @dtopt Columns
12824		 *
12825		 *  @example
12826		 *    // Using `columnDefs`
12827		 *    $(document).ready( function() {
12828		 *      $('#example').dataTable( {
12829		 *        "columnDefs": [
12830		 *          { "width": "20%", "targets": [ 0 ] }
12831		 *        ]
12832		 *      } );
12833		 *    } );
12834		 *
12835		 *  @example
12836		 *    // Using `columns`
12837		 *    $(document).ready( function() {
12838		 *      $('#example').dataTable( {
12839		 *        "columns": [
12840		 *          { "width": "20%" },
12841		 *          null,
12842		 *          null,
12843		 *          null,
12844		 *          null
12845		 *        ]
12846		 *      } );
12847		 *    } );
12848		 */
12849		"sWidth": null
12850	};
12851	
12852	_fnHungarianMap( DataTable.defaults.column );
12853	
12854	
12855	
12856	/**
12857	 * DataTables settings object - this holds all the information needed for a
12858	 * given table, including configuration, data and current application of the
12859	 * table options. DataTables does not have a single instance for each DataTable
12860	 * with the settings attached to that instance, but rather instances of the
12861	 * DataTable "class" are created on-the-fly as needed (typically by a
12862	 * $().dataTable() call) and the settings object is then applied to that
12863	 * instance.
12864	 *
12865	 * Note that this object is related to {@link DataTable.defaults} but this
12866	 * one is the internal data store for DataTables's cache of columns. It should
12867	 * NOT be manipulated outside of DataTables. Any configuration should be done
12868	 * through the initialisation options.
12869	 *  @namespace
12870	 *  @todo Really should attach the settings object to individual instances so we
12871	 *    don't need to create new instances on each $().dataTable() call (if the
12872	 *    table already exists). It would also save passing oSettings around and
12873	 *    into every single function. However, this is a very significant
12874	 *    architecture change for DataTables and will almost certainly break
12875	 *    backwards compatibility with older installations. This is something that
12876	 *    will be done in 2.0.
12877	 */
12878	DataTable.models.oSettings = {
12879		/**
12880		 * Primary features of DataTables and their enablement state.
12881		 *  @namespace
12882		 */
12883		"oFeatures": {
12884	
12885			/**
12886			 * Flag to say if DataTables should automatically try to calculate the
12887			 * optimum table and columns widths (true) or not (false).
12888			 * Note that this parameter will be set by the initialisation routine. To
12889			 * set a default use {@link DataTable.defaults}.
12890			 *  @type boolean
12891			 */
12892			"bAutoWidth": null,
12893	
12894			/**
12895			 * Delay the creation of TR and TD elements until they are actually
12896			 * needed by a driven page draw. This can give a significant speed
12897			 * increase for Ajax source and Javascript source data, but makes no
12898			 * difference at all fro DOM and server-side processing tables.
12899			 * Note that this parameter will be set by the initialisation routine. To
12900			 * set a default use {@link DataTable.defaults}.
12901			 *  @type boolean
12902			 */
12903			"bDeferRender": null,
12904	
12905			/**
12906			 * Enable filtering on the table or not. Note that if this is disabled
12907			 * then there is no filtering at all on the table, including fnFilter.
12908			 * To just remove the filtering input use sDom and remove the 'f' option.
12909			 * Note that this parameter will be set by the initialisation routine. To
12910			 * set a default use {@link DataTable.defaults}.
12911			 *  @type boolean
12912			 */
12913			"bFilter": null,
12914	
12915			/**
12916			 * Table information element (the 'Showing x of y records' div) enable
12917			 * flag.
12918			 * Note that this parameter will be set by the initialisation routine. To
12919			 * set a default use {@link DataTable.defaults}.
12920			 *  @type boolean
12921			 */
12922			"bInfo": null,
12923	
12924			/**
12925			 * Present a user control allowing the end user to change the page size
12926			 * when pagination is enabled.
12927			 * Note that this parameter will be set by the initialisation routine. To
12928			 * set a default use {@link DataTable.defaults}.
12929			 *  @type boolean
12930			 */
12931			"bLengthChange": null,
12932	
12933			/**
12934			 * Pagination enabled or not. Note that if this is disabled then length
12935			 * changing must also be disabled.
12936			 * Note that this parameter will be set by the initialisation routine. To
12937			 * set a default use {@link DataTable.defaults}.
12938			 *  @type boolean
12939			 */
12940			"bPaginate": null,
12941	
12942			/**
12943			 * Processing indicator enable flag whenever DataTables is enacting a
12944			 * user request - typically an Ajax request for server-side processing.
12945			 * Note that this parameter will be set by the initialisation routine. To
12946			 * set a default use {@link DataTable.defaults}.
12947			 *  @type boolean
12948			 */
12949			"bProcessing": null,
12950	
12951			/**
12952			 * Server-side processing enabled flag - when enabled DataTables will
12953			 * get all data from the server for every draw - there is no filtering,
12954			 * sorting or paging done on the client-side.
12955			 * Note that this parameter will be set by the initialisation routine. To
12956			 * set a default use {@link DataTable.defaults}.
12957			 *  @type boolean
12958			 */
12959			"bServerSide": null,
12960	
12961			/**
12962			 * Sorting enablement flag.
12963			 * Note that this parameter will be set by the initialisation routine. To
12964			 * set a default use {@link DataTable.defaults}.
12965			 *  @type boolean
12966			 */
12967			"bSort": null,
12968	
12969			/**
12970			 * Multi-column sorting
12971			 * Note that this parameter will be set by the initialisation routine. To
12972			 * set a default use {@link DataTable.defaults}.
12973			 *  @type boolean
12974			 */
12975			"bSortMulti": null,
12976	
12977			/**
12978			 * Apply a class to the columns which are being sorted to provide a
12979			 * visual highlight or not. This can slow things down when enabled since
12980			 * there is a lot of DOM interaction.
12981			 * Note that this parameter will be set by the initialisation routine. To
12982			 * set a default use {@link DataTable.defaults}.
12983			 *  @type boolean
12984			 */
12985			"bSortClasses": null,
12986	
12987			/**
12988			 * State saving enablement flag.
12989			 * Note that this parameter will be set by the initialisation routine. To
12990			 * set a default use {@link DataTable.defaults}.
12991			 *  @type boolean
12992			 */
12993			"bStateSave": null
12994		},
12995	
12996	
12997		/**
12998		 * Scrolling settings for a table.
12999		 *  @namespace
13000		 */
13001		"oScroll": {
13002			/**
13003			 * When the table is shorter in height than sScrollY, collapse the
13004			 * table container down to the height of the table (when true).
13005			 * Note that this parameter will be set by the initialisation routine. To
13006			 * set a default use {@link DataTable.defaults}.
13007			 *  @type boolean
13008			 */
13009			"bCollapse": null,
13010	
13011			/**
13012			 * Width of the scrollbar for the web-browser's platform. Calculated
13013			 * during table initialisation.
13014			 *  @type int
13015			 *  @default 0
13016			 */
13017			"iBarWidth": 0,
13018	
13019			/**
13020			 * Viewport width for horizontal scrolling. Horizontal scrolling is
13021			 * disabled if an empty string.
13022			 * Note that this parameter will be set by the initialisation routine. To
13023			 * set a default use {@link DataTable.defaults}.
13024			 *  @type string
13025			 */
13026			"sX": null,
13027	
13028			/**
13029			 * Width to expand the table to when using x-scrolling. Typically you
13030			 * should not need to use this.
13031			 * Note that this parameter will be set by the initialisation routine. To
13032			 * set a default use {@link DataTable.defaults}.
13033			 *  @type string
13034			 *  @deprecated
13035			 */
13036			"sXInner": null,
13037	
13038			/**
13039			 * Viewport height for vertical scrolling. Vertical scrolling is disabled
13040			 * if an empty string.
13041			 * Note that this parameter will be set by the initialisation routine. To
13042			 * set a default use {@link DataTable.defaults}.
13043			 *  @type string
13044			 */
13045			"sY": null
13046		},
13047	
13048		/**
13049		 * Language information for the table.
13050		 *  @namespace
13051		 *  @extends DataTable.defaults.oLanguage
13052		 */
13053		"oLanguage": {
13054			/**
13055			 * Information callback function. See
13056			 * {@link DataTable.defaults.fnInfoCallback}
13057			 *  @type function
13058			 *  @default null
13059			 */
13060			"fnInfoCallback": null
13061		},
13062	
13063		/**
13064		 * Browser support parameters
13065		 *  @namespace
13066		 */
13067		"oBrowser": {
13068			/**
13069			 * Indicate if the browser incorrectly calculates width:100% inside a
13070			 * scrolling element (IE6/7)
13071			 *  @type boolean
13072			 *  @default false
13073			 */
13074			"bScrollOversize": false,
13075	
13076			/**
13077			 * Determine if the vertical scrollbar is on the right or left of the
13078			 * scrolling container - needed for rtl language layout, although not
13079			 * all browsers move the scrollbar (Safari).
13080			 *  @type boolean
13081			 *  @default false
13082			 */
13083			"bScrollbarLeft": false,
13084	
13085			/**
13086			 * Flag for if `getBoundingClientRect` is fully supported or not
13087			 *  @type boolean
13088			 *  @default false
13089			 */
13090			"bBounding": false,
13091	
13092			/**
13093			 * Browser scrollbar width
13094			 *  @type integer
13095			 *  @default 0
13096			 */
13097			"barWidth": 0
13098		},
13099	
13100	
13101		"ajax": null,
13102	
13103	
13104		/**
13105		 * Array referencing the nodes which are used for the features. The
13106		 * parameters of this object match what is allowed by sDom - i.e.
13107		 *   <ul>
13108		 *     <li>'l' - Length changing</li>
13109		 *     <li>'f' - Filtering input</li>
13110		 *     <li>'t' - The table!</li>
13111		 *     <li>'i' - Information</li>
13112		 *     <li>'p' - Pagination</li>
13113		 *     <li>'r' - pRocessing</li>
13114		 *   </ul>
13115		 *  @type array
13116		 *  @default []
13117		 */
13118		"aanFeatures": [],
13119	
13120		/**
13121		 * Store data information - see {@link DataTable.models.oRow} for detailed
13122		 * information.
13123		 *  @type array
13124		 *  @default []
13125		 */
13126		"aoData": [],
13127	
13128		/**
13129		 * Array of indexes which are in the current display (after filtering etc)
13130		 *  @type array
13131		 *  @default []
13132		 */
13133		"aiDisplay": [],
13134	
13135		/**
13136		 * Array of indexes for display - no filtering
13137		 *  @type array
13138		 *  @default []
13139		 */
13140		"aiDisplayMaster": [],
13141	
13142		/**
13143		 * Map of row ids to data indexes
13144		 *  @type object
13145		 *  @default {}
13146		 */
13147		"aIds": {},
13148	
13149		/**
13150		 * Store information about each column that is in use
13151		 *  @type array
13152		 *  @default []
13153		 */
13154		"aoColumns": [],
13155	
13156		/**
13157		 * Store information about the table's header
13158		 *  @type array
13159		 *  @default []
13160		 */
13161		"aoHeader": [],
13162	
13163		/**
13164		 * Store information about the table's footer
13165		 *  @type array
13166		 *  @default []
13167		 */
13168		"aoFooter": [],
13169	
13170		/**
13171		 * Store the applied global search information in case we want to force a
13172		 * research or compare the old search to a new one.
13173		 * Note that this parameter will be set by the initialisation routine. To
13174		 * set a default use {@link DataTable.defaults}.
13175		 *  @namespace
13176		 *  @extends DataTable.models.oSearch
13177		 */
13178		"oPreviousSearch": {},
13179	
13180		/**
13181		 * Store the applied search for each column - see
13182		 * {@link DataTable.models.oSearch} for the format that is used for the
13183		 * filtering information for each column.
13184		 *  @type array
13185		 *  @default []
13186		 */
13187		"aoPreSearchCols": [],
13188	
13189		/**
13190		 * Sorting that is applied to the table. Note that the inner arrays are
13191		 * used in the following manner:
13192		 * <ul>
13193		 *   <li>Index 0 - column number</li>
13194		 *   <li>Index 1 - current sorting direction</li>
13195		 * </ul>
13196		 * Note that this parameter will be set by the initialisation routine. To
13197		 * set a default use {@link DataTable.defaults}.
13198		 *  @type array
13199		 *  @todo These inner arrays should really be objects
13200		 */
13201		"aaSorting": null,
13202	
13203		/**
13204		 * Sorting that is always applied to the table (i.e. prefixed in front of
13205		 * aaSorting).
13206		 * Note that this parameter will be set by the initialisation routine. To
13207		 * set a default use {@link DataTable.defaults}.
13208		 *  @type array
13209		 *  @default []
13210		 */
13211		"aaSortingFixed": [],
13212	
13213		/**
13214		 * Classes to use for the striping of a table.
13215		 * Note that this parameter will be set by the initialisation routine. To
13216		 * set a default use {@link DataTable.defaults}.
13217		 *  @type array
13218		 *  @default []
13219		 */
13220		"asStripeClasses": null,
13221	
13222		/**
13223		 * If restoring a table - we should restore its striping classes as well
13224		 *  @type array
13225		 *  @default []
13226		 */
13227		"asDestroyStripes": [],
13228	
13229		/**
13230		 * If restoring a table - we should restore its width
13231		 *  @type int
13232		 *  @default 0
13233		 */
13234		"sDestroyWidth": 0,
13235	
13236		/**
13237		 * Callback functions array for every time a row is inserted (i.e. on a draw).
13238		 *  @type array
13239		 *  @default []
13240		 */
13241		"aoRowCallback": [],
13242	
13243		/**
13244		 * Callback functions for the header on each draw.
13245		 *  @type array
13246		 *  @default []
13247		 */
13248		"aoHeaderCallback": [],
13249	
13250		/**
13251		 * Callback function for the footer on each draw.
13252		 *  @type array
13253		 *  @default []
13254		 */
13255		"aoFooterCallback": [],
13256	
13257		/**
13258		 * Array of callback functions for draw callback functions
13259		 *  @type array
13260		 *  @default []
13261		 */
13262		"aoDrawCallback": [],
13263	
13264		/**
13265		 * Array of callback functions for row created function
13266		 *  @type array
13267		 *  @default []
13268		 */
13269		"aoRowCreatedCallback": [],
13270	
13271		/**
13272		 * Callback functions for just before the table is redrawn. A return of
13273		 * false will be used to cancel the draw.
13274		 *  @type array
13275		 *  @default []
13276		 */
13277		"aoPreDrawCallback": [],
13278	
13279		/**
13280		 * Callback functions for when the table has been initialised.
13281		 *  @type array
13282		 *  @default []
13283		 */
13284		"aoInitComplete": [],
13285	
13286	
13287		/**
13288		 * Callbacks for modifying the settings to be stored for state saving, prior to
13289		 * saving state.
13290		 *  @type array
13291		 *  @default []
13292		 */
13293		"aoStateSaveParams": [],
13294	
13295		/**
13296		 * Callbacks for modifying the settings that have been stored for state saving
13297		 * prior to using the stored values to restore the state.
13298		 *  @type array
13299		 *  @default []
13300		 */
13301		"aoStateLoadParams": [],
13302	
13303		/**
13304		 * Callbacks for operating on the settings object once the saved state has been
13305		 * loaded
13306		 *  @type array
13307		 *  @default []
13308		 */
13309		"aoStateLoaded": [],
13310	
13311		/**
13312		 * Cache the table ID for quick access
13313		 *  @type string
13314		 *  @default <i>Empty string</i>
13315		 */
13316		"sTableId": "",
13317	
13318		/**
13319		 * The TABLE node for the main table
13320		 *  @type node
13321		 *  @default null
13322		 */
13323		"nTable": null,
13324	
13325		/**
13326		 * Permanent ref to the thead element
13327		 *  @type node
13328		 *  @default null
13329		 */
13330		"nTHead": null,
13331	
13332		/**
13333		 * Permanent ref to the tfoot element - if it exists
13334		 *  @type node
13335		 *  @default null
13336		 */
13337		"nTFoot": null,
13338	
13339		/**
13340		 * Permanent ref to the tbody element
13341		 *  @type node
13342		 *  @default null
13343		 */
13344		"nTBody": null,
13345	
13346		/**
13347		 * Cache the wrapper node (contains all DataTables controlled elements)
13348		 *  @type node
13349		 *  @default null
13350		 */
13351		"nTableWrapper": null,
13352	
13353		/**
13354		 * Indicate if when using server-side processing the loading of data
13355		 * should be deferred until the second draw.
13356		 * Note that this parameter will be set by the initialisation routine. To
13357		 * set a default use {@link DataTable.defaults}.
13358		 *  @type boolean
13359		 *  @default false
13360		 */
13361		"bDeferLoading": false,
13362	
13363		/**
13364		 * Indicate if all required information has been read in
13365		 *  @type boolean
13366		 *  @default false
13367		 */
13368		"bInitialised": false,
13369	
13370		/**
13371		 * Information about open rows. Each object in the array has the parameters
13372		 * 'nTr' and 'nParent'
13373		 *  @type array
13374		 *  @default []
13375		 */
13376		"aoOpenRows": [],
13377	
13378		/**
13379		 * Dictate the positioning of DataTables' control elements - see
13380		 * {@link DataTable.model.oInit.sDom}.
13381		 * Note that this parameter will be set by the initialisation routine. To
13382		 * set a default use {@link DataTable.defaults}.
13383		 *  @type string
13384		 *  @default null
13385		 */
13386		"sDom": null,
13387	
13388		/**
13389		 * Search delay (in mS)
13390		 *  @type integer
13391		 *  @default null
13392		 */
13393		"searchDelay": null,
13394	
13395		/**
13396		 * Which type of pagination should be used.
13397		 * Note that this parameter will be set by the initialisation routine. To
13398		 * set a default use {@link DataTable.defaults}.
13399		 *  @type string
13400		 *  @default two_button
13401		 */
13402		"sPaginationType": "two_button",
13403	
13404		/**
13405		 * The state duration (for `stateSave`) in seconds.
13406		 * Note that this parameter will be set by the initialisation routine. To
13407		 * set a default use {@link DataTable.defaults}.
13408		 *  @type int
13409		 *  @default 0
13410		 */
13411		"iStateDuration": 0,
13412	
13413		/**
13414		 * Array of callback functions for state saving. Each array element is an
13415		 * object with the following parameters:
13416		 *   <ul>
13417		 *     <li>function:fn - function to call. Takes two parameters, oSettings
13418		 *       and the JSON string to save that has been thus far created. Returns
13419		 *       a JSON string to be inserted into a json object
13420		 *       (i.e. '"param": [ 0, 1, 2]')</li>
13421		 *     <li>string:sName - name of callback</li>
13422		 *   </ul>
13423		 *  @type array
13424		 *  @default []
13425		 */
13426		"aoStateSave": [],
13427	
13428		/**
13429		 * Array of callback functions for state loading. Each array element is an
13430		 * object with the following parameters:
13431		 *   <ul>
13432		 *     <li>function:fn - function to call. Takes two parameters, oSettings
13433		 *       and the object stored. May return false to cancel state loading</li>
13434		 *     <li>string:sName - name of callback</li>
13435		 *   </ul>
13436		 *  @type array
13437		 *  @default []
13438		 */
13439		"aoStateLoad": [],
13440	
13441		/**
13442		 * State that was saved. Useful for back reference
13443		 *  @type object
13444		 *  @default null
13445		 */
13446		"oSavedState": null,
13447	
13448		/**
13449		 * State that was loaded. Useful for back reference
13450		 *  @type object
13451		 *  @default null
13452		 */
13453		"oLoadedState": null,
13454	
13455		/**
13456		 * Source url for AJAX data for the table.
13457		 * Note that this parameter will be set by the initialisation routine. To
13458		 * set a default use {@link DataTable.defaults}.
13459		 *  @type string
13460		 *  @default null
13461		 */
13462		"sAjaxSource": null,
13463	
13464		/**
13465		 * Property from a given object from which to read the table data from. This
13466		 * can be an empty string (when not server-side processing), in which case
13467		 * it is  assumed an an array is given directly.
13468		 * Note that this parameter will be set by the initialisation routine. To
13469		 * set a default use {@link DataTable.defaults}.
13470		 *  @type string
13471		 */
13472		"sAjaxDataProp": null,
13473	
13474		/**
13475		 * Note if draw should be blocked while getting data
13476		 *  @type boolean
13477		 *  @default true
13478		 */
13479		"bAjaxDataGet": true,
13480	
13481		/**
13482		 * The last jQuery XHR object that was used for server-side data gathering.
13483		 * This can be used for working with the XHR information in one of the
13484		 * callbacks
13485		 *  @type object
13486		 *  @default null
13487		 */
13488		"jqXHR": null,
13489	
13490		/**
13491		 * JSON returned from the server in the last Ajax request
13492		 *  @type object
13493		 *  @default undefined
13494		 */
13495		"json": undefined,
13496	
13497		/**
13498		 * Data submitted as part of the last Ajax request
13499		 *  @type object
13500		 *  @default undefined
13501		 */
13502		"oAjaxData": undefined,
13503	
13504		/**
13505		 * Function to get the server-side data.
13506		 * Note that this parameter will be set by the initialisation routine. To
13507		 * set a default use {@link DataTable.defaults}.
13508		 *  @type function
13509		 */
13510		"fnServerData": null,
13511	
13512		/**
13513		 * Functions which are called prior to sending an Ajax request so extra
13514		 * parameters can easily be sent to the server
13515		 *  @type array
13516		 *  @default []
13517		 */
13518		"aoServerParams": [],
13519	
13520		/**
13521		 * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
13522		 * required).
13523		 * Note that this parameter will be set by the initialisation routine. To
13524		 * set a default use {@link DataTable.defaults}.
13525		 *  @type string
13526		 */
13527		"sServerMethod": null,
13528	
13529		/**
13530		 * Format numbers for display.
13531		 * Note that this parameter will be set by the initialisation routine. To
13532		 * set a default use {@link DataTable.defaults}.
13533		 *  @type function
13534		 */
13535		"fnFormatNumber": null,
13536	
13537		/**
13538		 * List of options that can be used for the user selectable length menu.
13539		 * Note that this parameter will be set by the initialisation routine. To
13540		 * set a default use {@link DataTable.defaults}.
13541		 *  @type array
13542		 *  @default []
13543		 */
13544		"aLengthMenu": null,
13545	
13546		/**
13547		 * Counter for the draws that the table does. Also used as a tracker for
13548		 * server-side processing
13549		 *  @type int
13550		 *  @default 0
13551		 */
13552		"iDraw": 0,
13553	
13554		/**
13555		 * Indicate if a redraw is being done - useful for Ajax
13556		 *  @type boolean
13557		 *  @default false
13558		 */
13559		"bDrawing": false,
13560	
13561		/**
13562		 * Draw index (iDraw) of the last error when parsing the returned data
13563		 *  @type int
13564		 *  @default -1
13565		 */
13566		"iDrawError": -1,
13567	
13568		/**
13569		 * Paging display length
13570		 *  @type int
13571		 *  @default 10
13572		 */
13573		"_iDisplayLength": 10,
13574	
13575		/**
13576		 * Paging start point - aiDisplay index
13577		 *  @type int
13578		 *  @default 0
13579		 */
13580		"_iDisplayStart": 0,
13581	
13582		/**
13583		 * Server-side processing - number of records in the result set
13584		 * (i.e. before filtering), Use fnRecordsTotal rather than
13585		 * this property to get the value of the number of records, regardless of
13586		 * the server-side processing setting.
13587		 *  @type int
13588		 *  @default 0
13589		 *  @private
13590		 */
13591		"_iRecordsTotal": 0,
13592	
13593		/**
13594		 * Server-side processing - number of records in the current display set
13595		 * (i.e. after filtering). Use fnRecordsDisplay rather than
13596		 * this property to get the value of the number of records, regardless of
13597		 * the server-side processing setting.
13598		 *  @type boolean
13599		 *  @default 0
13600		 *  @private
13601		 */
13602		"_iRecordsDisplay": 0,
13603	
13604		/**
13605		 * Flag to indicate if jQuery UI marking and classes should be used.
13606		 * Note that this parameter will be set by the initialisation routine. To
13607		 * set a default use {@link DataTable.defaults}.
13608		 *  @type boolean
13609		 */
13610		"bJUI": null,
13611	
13612		/**
13613		 * The classes to use for the table
13614		 *  @type object
13615		 *  @default {}
13616		 */
13617		"oClasses": {},
13618	
13619		/**
13620		 * Flag attached to the settings object so you can check in the draw
13621		 * callback if filtering has been done in the draw. Deprecated in favour of
13622		 * events.
13623		 *  @type boolean
13624		 *  @default false
13625		 *  @deprecated
13626		 */
13627		"bFiltered": false,
13628	
13629		/**
13630		 * Flag attached to the settings object so you can check in the draw
13631		 * callback if sorting has been done in the draw. Deprecated in favour of
13632		 * events.
13633		 *  @type boolean
13634		 *  @default false
13635		 *  @deprecated
13636		 */
13637		"bSorted": false,
13638	
13639		/**
13640		 * Indicate that if multiple rows are in the header and there is more than
13641		 * one unique cell per column, if the top one (true) or bottom one (false)
13642		 * should be used for sorting / title by DataTables.
13643		 * Note that this parameter will be set by the initialisation routine. To
13644		 * set a default use {@link DataTable.defaults}.
13645		 *  @type boolean
13646		 */
13647		"bSortCellsTop": null,
13648	
13649		/**
13650		 * Initialisation object that is used for the table
13651		 *  @type object
13652		 *  @default null
13653		 */
13654		"oInit": null,
13655	
13656		/**
13657		 * Destroy callback functions - for plug-ins to attach themselves to the
13658		 * destroy so they can clean up markup and events.
13659		 *  @type array
13660		 *  @default []
13661		 */
13662		"aoDestroyCallback": [],
13663	
13664	
13665		/**
13666		 * Get the number of records in the current record set, before filtering
13667		 *  @type function
13668		 */
13669		"fnRecordsTotal": function ()
13670		{
13671			return _fnDataSource( this ) == 'ssp' ?
13672				this._iRecordsTotal * 1 :
13673				this.aiDisplayMaster.length;
13674		},
13675	
13676		/**
13677		 * Get the number of records in the current record set, after filtering
13678		 *  @type function
13679		 */
13680		"fnRecordsDisplay": function ()
13681		{
13682			return _fnDataSource( this ) == 'ssp' ?
13683				this._iRecordsDisplay * 1 :
13684				this.aiDisplay.length;
13685		},
13686	
13687		/**
13688		 * Get the display end point - aiDisplay index
13689		 *  @type function
13690		 */
13691		"fnDisplayEnd": function ()
13692		{
13693			var
13694				len      = this._iDisplayLength,
13695				start    = this._iDisplayStart,
13696				calc     = start + len,
13697				records  = this.aiDisplay.length,
13698				features = this.oFeatures,
13699				paginate = features.bPaginate;
13700	
13701			if ( features.bServerSide ) {
13702				return paginate === false || len === -1 ?
13703					start + records :
13704					Math.min( start+len, this._iRecordsDisplay );
13705			}
13706			else {
13707				return ! paginate || calc>records || len===-1 ?
13708					records :
13709					calc;
13710			}
13711		},
13712	
13713		/**
13714		 * The DataTables object for this table
13715		 *  @type object
13716		 *  @default null
13717		 */
13718		"oInstance": null,
13719	
13720		/**
13721		 * Unique identifier for each instance of the DataTables object. If there
13722		 * is an ID on the table node, then it takes that value, otherwise an
13723		 * incrementing internal counter is used.
13724		 *  @type string
13725		 *  @default null
13726		 */
13727		"sInstance": null,
13728	
13729		/**
13730		 * tabindex attribute value that is added to DataTables control elements, allowing
13731		 * keyboard navigation of the table and its controls.
13732		 */
13733		"iTabIndex": 0,
13734	
13735		/**
13736		 * DIV container for the footer scrolling table if scrolling
13737		 */
13738		"nScrollHead": null,
13739	
13740		/**
13741		 * DIV container for the footer scrolling table if scrolling
13742		 */
13743		"nScrollFoot": null,
13744	
13745		/**
13746		 * Last applied sort
13747		 *  @type array
13748		 *  @default []
13749		 */
13750		"aLastSort": [],
13751	
13752		/**
13753		 * Stored plug-in instances
13754		 *  @type object
13755		 *  @default {}
13756		 */
13757		"oPlugins": {},
13758	
13759		/**
13760		 * Function used to get a row's id from the row's data
13761		 *  @type function
13762		 *  @default null
13763		 */
13764		"rowIdFn": null,
13765	
13766		/**
13767		 * Data location where to store a row's id
13768		 *  @type string
13769		 *  @default null
13770		 */
13771		"rowId": null
13772	};
13773
13774	/**
13775	 * Extension object for DataTables that is used to provide all extension
13776	 * options.
13777	 *
13778	 * Note that the `DataTable.ext` object is available through
13779	 * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is
13780	 * also aliased to `jQuery.fn.dataTableExt` for historic reasons.
13781	 *  @namespace
13782	 *  @extends DataTable.models.ext
13783	 */
13784	
13785	
13786	/**
13787	 * DataTables extensions
13788	 * 
13789	 * This namespace acts as a collection area for plug-ins that can be used to
13790	 * extend DataTables capabilities. Indeed many of the build in methods
13791	 * use this method to provide their own capabilities (sorting methods for
13792	 * example).
13793	 *
13794	 * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy
13795	 * reasons
13796	 *
13797	 *  @namespace
13798	 */
13799	DataTable.ext = _ext = {
13800		/**
13801		 * Buttons. For use with the Buttons extension for DataTables. This is
13802		 * defined here so other extensions can define buttons regardless of load
13803		 * order. It is _not_ used by DataTables core.
13804		 *
13805		 *  @type object
13806		 *  @default {}
13807		 */
13808		buttons: {},
13809	
13810	
13811		/**
13812		 * Element class names
13813		 *
13814		 *  @type object
13815		 *  @default {}
13816		 */
13817		classes: {},
13818	
13819	
13820		/**
13821		 * DataTables build type (expanded by the download builder)
13822		 *
13823		 *  @type string
13824		 */
13825		builder: "-source-",
13826	
13827	
13828		/**
13829		 * Error reporting.
13830		 * 
13831		 * How should DataTables report an error. Can take the value 'alert',
13832		 * 'throw', 'none' or a function.
13833		 *
13834		 *  @type string|function
13835		 *  @default alert
13836		 */
13837		errMode: "alert",
13838	
13839	
13840		/**
13841		 * Feature plug-ins.
13842		 * 
13843		 * This is an array of objects which describe the feature plug-ins that are
13844		 * available to DataTables. These feature plug-ins are then available for
13845		 * use through the `dom` initialisation option.
13846		 * 
13847		 * Each feature plug-in is described by an object which must have the
13848		 * following properties:
13849		 * 
13850		 * * `fnInit` - function that is used to initialise the plug-in,
13851		 * * `cFeature` - a character so the feature can be enabled by the `dom`
13852		 *   instillation option. This is case sensitive.
13853		 *
13854		 * The `fnInit` function has the following input parameters:
13855		 *
13856		 * 1. `{object}` DataTables settings object: see
13857		 *    {@link DataTable.models.oSettings}
13858		 *
13859		 * And the following return is expected:
13860		 * 
13861		 * * {node|null} The element which contains your feature. Note that the
13862		 *   return may also be void if your plug-in does not require to inject any
13863		 *   DOM elements into DataTables control (`dom`) - for example this might
13864		 *   be useful when developing a plug-in which allows table control via
13865		 *   keyboard entry
13866		 *
13867		 *  @type array
13868		 *
13869		 *  @example
13870		 *    $.fn.dataTable.ext.features.push( {
13871		 *      "fnInit": function( oSettings ) {
13872		 *        return new TableTools( { "oDTSettings": oSettings } );
13873		 *      },
13874		 *      "cFeature": "T"
13875		 *    } );
13876		 */
13877		feature: [],
13878	
13879	
13880		/**
13881		 * Row searching.
13882		 * 
13883		 * This method of searching is complimentary to the default type based
13884		 * searching, and a lot more comprehensive as it allows you complete control
13885		 * over the searching logic. Each element in this array is a function
13886		 * (parameters described below) that is called for every row in the table,
13887		 * and your logic decides if it should be included in the searching data set
13888		 * or not.
13889		 *
13890		 * Searching functions have the following input parameters:
13891		 *
13892		 * 1. `{object}` DataTables settings object: see
13893		 *    {@link DataTable.models.oSettings}
13894		 * 2. `{array|object}` Data for the row to be processed (same as the
13895		 *    original format that was passed in as the data source, or an array
13896		 *    from a DOM data source
13897		 * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which
13898		 *    can be useful to retrieve the `TR` element if you need DOM interaction.
13899		 *
13900		 * And the following return is expected:
13901		 *
13902		 * * {boolean} Include the row in the searched result set (true) or not
13903		 *   (false)
13904		 *
13905		 * Note that as with the main search ability in DataTables, technically this
13906		 * is "filtering", since it is subtractive. However, for consistency in
13907		 * naming we call it searching here.
13908		 *
13909		 *  @type array
13910		 *  @default []
13911		 *
13912		 *  @example
13913		 *    // The following example shows custom search being applied to the
13914		 *    // fourth column (i.e. the data[3] index) based on two input values
13915		 *    // from the end-user, matching the data in a certain range.
13916		 *    $.fn.dataTable.ext.search.push(
13917		 *      function( settings, data, dataIndex ) {
13918		 *        var min = document.getElementById('min').value * 1;
13919		 *        var max = document.getElementById('max').value * 1;
13920		 *        var version = data[3] == "-" ? 0 : data[3]*1;
13921		 *
13922		 *        if ( min == "" && max == "" ) {
13923		 *          return true;
13924		 *        }
13925		 *        else if ( min == "" && version < max ) {
13926		 *          return true;
13927		 *        }
13928		 *        else if ( min < version && "" == max ) {
13929		 *          return true;
13930		 *        }
13931		 *        else if ( min < version && version < max ) {
13932		 *          return true;
13933		 *        }
13934		 *        return false;
13935		 *      }
13936		 *    );
13937		 */
13938		search: [],
13939	
13940	
13941		/**
13942		 * Selector extensions
13943		 *
13944		 * The `selector` option can be used to extend the options available for the
13945		 * selector modifier options (`selector-modifier` object data type) that
13946		 * each of the three built in selector types offer (row, column and cell +
13947		 * their plural counterparts). For example the Select extension uses this
13948		 * mechanism to provide an option to select only rows, columns and cells
13949		 * that have been marked as selected by the end user (`{selected: true}`),
13950		 * which can be used in conjunction with the existing built in selector
13951		 * options.
13952		 *
13953		 * Each property is an array to which functions can be pushed. The functions
13954		 * take three attributes:
13955		 *
13956		 * * Settings object for the host table
13957		 * * Options object (`selector-modifier` object type)
13958		 * * Array of selected item indexes
13959		 *
13960		 * The return is an array of the resulting item indexes after the custom
13961		 * selector has been applied.
13962		 *
13963		 *  @type object
13964		 */
13965		selector: {
13966			cell: [],
13967			column: [],
13968			row: []
13969		},
13970	
13971	
13972		/**
13973		 * Internal functions, exposed for used in plug-ins.
13974		 * 
13975		 * Please note that you should not need to use the internal methods for
13976		 * anything other than a plug-in (and even then, try to avoid if possible).
13977		 * The internal function may change between releases.
13978		 *
13979		 *  @type object
13980		 *  @default {}
13981		 */
13982		internal: {},
13983	
13984	
13985		/**
13986		 * Legacy configuration options. Enable and disable legacy options that
13987		 * are available in DataTables.
13988		 *
13989		 *  @type object
13990		 */
13991		legacy: {
13992			/**
13993			 * Enable / disable DataTables 1.9 compatible server-side processing
13994			 * requests
13995			 *
13996			 *  @type boolean
13997			 *  @default null
13998			 */
13999			ajax: null
14000		},
14001	
14002	
14003		/**
14004		 * Pagination plug-in methods.
14005		 * 
14006		 * Each entry in this object is a function and defines which buttons should
14007		 * be shown by the pagination rendering method that is used for the table:
14008		 * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the
14009		 * buttons are displayed in the document, while the functions here tell it
14010		 * what buttons to display. This is done by returning an array of button
14011		 * descriptions (what each button will do).
14012		 *
14013		 * Pagination types (the four built in options and any additional plug-in
14014		 * options defined here) can be used through the `paginationType`
14015		 * initialisation parameter.
14016		 *
14017		 * The functions defined take two parameters:
14018		 *
14019		 * 1. `{int} page` The current page index
14020		 * 2. `{int} pages` The number of pages in the table
14021		 *
14022		 * Each function is expected to return an array where each element of the
14023		 * array can be one of:
14024		 *
14025		 * * `first` - Jump to first page when activated
14026		 * * `last` - Jump to last page when activated
14027		 * * `previous` - Show previous page when activated
14028		 * * `next` - Show next page when activated
14029		 * * `{int}` - Show page of the index given
14030		 * * `{array}` - A nested array containing the above elements to add a
14031		 *   containing 'DIV' element (might be useful for styling).
14032		 *
14033		 * Note that DataTables v1.9- used this object slightly differently whereby
14034		 * an object with two functions would be defined for each plug-in. That
14035		 * ability is still supported by DataTables 1.10+ to provide backwards
14036		 * compatibility, but this option of use is now decremented and no longer
14037		 * documented in DataTables 1.10+.
14038		 *
14039		 *  @type object
14040		 *  @default {}
14041		 *
14042		 *  @example
14043		 *    // Show previous, next and current page buttons only
14044		 *    $.fn.dataTableExt.oPagination.current = function ( page, pages ) {
14045		 *      return [ 'previous', page, 'next' ];
14046		 *    };
14047		 */
14048		pager: {},
14049	
14050	
14051		renderer: {
14052			pageButton: {},
14053			header: {}
14054		},
14055	
14056	
14057		/**
14058		 * Ordering plug-ins - custom data source
14059		 * 
14060		 * The extension options for ordering of data available here is complimentary
14061		 * to the default type based ordering that DataTables typically uses. It
14062		 * allows much greater control over the the data that is being used to
14063		 * order a column, but is necessarily therefore more complex.
14064		 * 
14065		 * This type of ordering is useful if you want to do ordering based on data
14066		 * live from the DOM (for example the contents of an 'input' element) rather
14067		 * than just the static string that DataTables knows of.
14068		 * 
14069		 * The way these plug-ins work is that you create an array of the values you
14070		 * wish to be ordering for the column in question and then return that
14071		 * array. The data in the array much be in the index order of the rows in
14072		 * the table (not the currently ordering order!). Which order data gathering
14073		 * function is run here depends on the `dt-init columns.orderDataType`
14074		 * parameter that is used for the column (if any).
14075		 *
14076		 * The functions defined take two parameters:
14077		 *
14078		 * 1. `{object}` DataTables settings object: see
14079		 *    {@link DataTable.models.oSettings}
14080		 * 2. `{int}` Target column index
14081		 *
14082		 * Each function is expected to return an array:
14083		 *
14084		 * * `{array}` Data for the column to be ordering upon
14085		 *
14086		 *  @type array
14087		 *
14088		 *  @example
14089		 *    // Ordering using `input` node values
14090		 *    $.fn.dataTable.ext.order['dom-text'] = function  ( settings, col )
14091		 *    {
14092		 *      return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
14093		 *        return $('input', td).val();
14094		 *      } );
14095		 *    }
14096		 */
14097		order: {},
14098	
14099	
14100		/**
14101		 * Type based plug-ins.
14102		 *
14103		 * Each column in DataTables has a type assigned to it, either by automatic
14104		 * detection or by direct assignment using the `type` option for the column.
14105		 * The type of a column will effect how it is ordering and search (plug-ins
14106		 * can also make use of the column type if required).
14107		 *
14108		 * @namespace
14109		 */
14110		type: {
14111			/**
14112			 * Type detection functions.
14113			 *
14114			 * The functions defined in this object are used to automatically detect
14115			 * a column's type, making initialisation of DataTables super easy, even
14116			 * when complex data is in the table.
14117			 *
14118			 * The functions defined take two parameters:
14119			 *
14120		     *  1. `{*}` Data from the column cell to be analysed
14121		     *  2. `{settings}` DataTables settings object. This can be used to
14122		     *     perform context specific type detection - for example detection
14123		     *     based on language settings such as using a comma for a decimal
14124		     *     place. Generally speaking the options from the settings will not
14125		     *     be required
14126			 *
14127			 * Each function is expected to return:
14128			 *
14129			 * * `{string|null}` Data type detected, or null if unknown (and thus
14130			 *   pass it on to the other type detection functions.
14131			 *
14132			 *  @type array
14133			 *
14134			 *  @example
14135			 *    // Currency type detection plug-in:
14136			 *    $.fn.dataTable.ext.type.detect.push(
14137			 *      function ( data, settings ) {
14138			 *        // Check the numeric part
14139			 *        if ( ! $.isNumeric( data.substring(1) ) ) {
14140			 *          return null;
14141			 *        }
14142			 *
14143			 *        // Check prefixed by currency
14144			 *        if ( data.charAt(0) == '$' || data.charAt(0) == '&pound;' ) {
14145			 *          return 'currency';
14146			 *        }
14147			 *        return null;
14148			 *      }
14149			 *    );
14150			 */
14151			detect: [],
14152	
14153	
14154			/**
14155			 * Type based search formatting.
14156			 *
14157			 * The type based searching functions can be used to pre-format the
14158			 * data to be search on. For example, it can be used to strip HTML
14159			 * tags or to de-format telephone numbers for numeric only searching.
14160			 *
14161			 * Note that is a search is not defined for a column of a given type,
14162			 * no search formatting will be performed.
14163			 * 
14164			 * Pre-processing of searching data plug-ins - When you assign the sType
14165			 * for a column (or have it automatically detected for you by DataTables
14166			 * or a type detection plug-in), you will typically be using this for
14167			 * custom sorting, but it can also be used to provide custom searching
14168			 * by allowing you to pre-processing the data and returning the data in
14169			 * the format that should be searched upon. This is done by adding
14170			 * functions this object with a parameter name which matches the sType
14171			 * for that target column. This is the corollary of <i>afnSortData</i>
14172			 * for searching data.
14173			 *
14174			 * The functions defined take a single parameter:
14175			 *
14176		     *  1. `{*}` Data from the column cell to be prepared for searching
14177			 *
14178			 * Each function is expected to return:
14179			 *
14180			 * * `{string|null}` Formatted string that will be used for the searching.
14181			 *
14182			 *  @type object
14183			 *  @default {}
14184			 *
14185			 *  @example
14186			 *    $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) {
14187			 *      return d.replace(/\n/g," ").replace( /<.*?>/g, "" );
14188			 *    }
14189			 */
14190			search: {},
14191	
14192	
14193			/**
14194			 * Type based ordering.
14195			 *
14196			 * The column type tells DataTables what ordering to apply to the table
14197			 * when a column is sorted upon. The order for each type that is defined,
14198			 * is defined by the functions available in this object.
14199			 *
14200			 * Each ordering option can be described by three properties added to
14201			 * this object:
14202			 *
14203			 * * `{type}-pre` - Pre-formatting function
14204			 * * `{type}-asc` - Ascending order function
14205			 * * `{type}-desc` - Descending order function
14206			 *
14207			 * All three can be used together, only `{type}-pre` or only
14208			 * `{type}-asc` and `{type}-desc` together. It is generally recommended
14209			 * that only `{type}-pre` is used, as this provides the optimal
14210			 * implementation in terms of speed, although the others are provided
14211			 * for compatibility with existing Javascript sort functions.
14212			 *
14213			 * `{type}-pre`: Functions defined take a single parameter:
14214			 *
14215		     *  1. `{*}` Data from the column cell to be prepared for ordering
14216			 *
14217			 * And return:
14218			 *
14219			 * * `{*}` Data to be sorted upon
14220			 *
14221			 * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort
14222			 * functions, taking two parameters:
14223			 *
14224		     *  1. `{*}` Data to compare to the second parameter
14225		     *  2. `{*}` Data to compare to the first parameter
14226			 *
14227			 * And returning:
14228			 *
14229			 * * `{*}` Ordering match: <0 if first parameter should be sorted lower
14230			 *   than the second parameter, ===0 if the two parameters are equal and
14231			 *   >0 if the first parameter should be sorted height than the second
14232			 *   parameter.
14233			 * 
14234			 *  @type object
14235			 *  @default {}
14236			 *
14237			 *  @example
14238			 *    // Numeric ordering of formatted numbers with a pre-formatter
14239			 *    $.extend( $.fn.dataTable.ext.type.order, {
14240			 *      "string-pre": function(x) {
14241			 *        a = (a === "-" || a === "") ? 0 : a.replace( /[^\d\-\.]/g, "" );
14242			 *        return parseFloat( a );
14243			 *      }
14244			 *    } );
14245			 *
14246			 *  @example
14247			 *    // Case-sensitive string ordering, with no pre-formatting method
14248			 *    $.extend( $.fn.dataTable.ext.order, {
14249			 *      "string-case-asc": function(x,y) {
14250			 *        return ((x < y) ? -1 : ((x > y) ? 1 : 0));
14251			 *      },
14252			 *      "string-case-desc": function(x,y) {
14253			 *        return ((x < y) ? 1 : ((x > y) ? -1 : 0));
14254			 *      }
14255			 *    } );
14256			 */
14257			order: {}
14258		},
14259	
14260		/**
14261		 * Unique DataTables instance counter
14262		 *
14263		 * @type int
14264		 * @private
14265		 */
14266		_unique: 0,
14267	
14268	
14269		//
14270		// Depreciated
14271		// The following properties are retained for backwards compatiblity only.
14272		// The should not be used in new projects and will be removed in a future
14273		// version
14274		//
14275	
14276		/**
14277		 * Version check function.
14278		 *  @type function
14279		 *  @depreciated Since 1.10
14280		 */
14281		fnVersionCheck: DataTable.fnVersionCheck,
14282	
14283	
14284		/**
14285		 * Index for what 'this' index API functions should use
14286		 *  @type int
14287		 *  @deprecated Since v1.10
14288		 */
14289		iApiIndex: 0,
14290	
14291	
14292		/**
14293		 * jQuery UI class container
14294		 *  @type object
14295		 *  @deprecated Since v1.10
14296		 */
14297		oJUIClasses: {},
14298	
14299	
14300		/**
14301		 * Software version
14302		 *  @type string
14303		 *  @deprecated Since v1.10
14304		 */
14305		sVersion: DataTable.version
14306	};
14307	
14308	
14309	//
14310	// Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts
14311	//
14312	$.extend( _ext, {
14313		afnFiltering: _ext.search,
14314		aTypes:       _ext.type.detect,
14315		ofnSearch:    _ext.type.search,
14316		oSort:        _ext.type.order,
14317		afnSortData:  _ext.order,
14318		aoFeatures:   _ext.feature,
14319		oApi:         _ext.internal,
14320		oStdClasses:  _ext.classes,
14321		oPagination:  _ext.pager
14322	} );
14323	
14324	
14325	$.extend( DataTable.ext.classes, {
14326		"sTable": "dataTable",
14327		"sNoFooter": "no-footer",
14328	
14329		/* Paging buttons */
14330		"sPageButton": "paginate_button",
14331		"sPageButtonActive": "current",
14332		"sPageButtonDisabled": "disabled",
14333	
14334		/* Striping classes */
14335		"sStripeOdd": "odd",
14336		"sStripeEven": "even",
14337	
14338		/* Empty row */
14339		"sRowEmpty": "dataTables_empty",
14340	
14341		/* Features */
14342		"sWrapper": "dataTables_wrapper",
14343		"sFilter": "dataTables_filter",
14344		"sInfo": "dataTables_info",
14345		"sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
14346		"sLength": "dataTables_length",
14347		"sProcessing": "dataTables_processing",
14348	
14349		/* Sorting */
14350		"sSortAsc": "sorting_asc",
14351		"sSortDesc": "sorting_desc",
14352		"sSortable": "sorting", /* Sortable in both directions */
14353		"sSortableAsc": "sorting_asc_disabled",
14354		"sSortableDesc": "sorting_desc_disabled",
14355		"sSortableNone": "sorting_disabled",
14356		"sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
14357	
14358		/* Filtering */
14359		"sFilterInput": "",
14360	
14361		/* Page length */
14362		"sLengthSelect": "",
14363	
14364		/* Scrolling */
14365		"sScrollWrapper": "dataTables_scroll",
14366		"sScrollHead": "dataTables_scrollHead",
14367		"sScrollHeadInner": "dataTables_scrollHeadInner",
14368		"sScrollBody": "dataTables_scrollBody",
14369		"sScrollFoot": "dataTables_scrollFoot",
14370		"sScrollFootInner": "dataTables_scrollFootInner",
14371	
14372		/* Misc */
14373		"sHeaderTH": "",
14374		"sFooterTH": "",
14375	
14376		// Deprecated
14377		"sSortJUIAsc": "",
14378		"sSortJUIDesc": "",
14379		"sSortJUI": "",
14380		"sSortJUIAscAllowed": "",
14381		"sSortJUIDescAllowed": "",
14382		"sSortJUIWrapper": "",
14383		"sSortIcon": "",
14384		"sJUIHeader": "",
14385		"sJUIFooter": ""
14386	} );
14387	
14388	
14389	(function() {
14390	
14391	// Reused strings for better compression. Closure compiler appears to have a
14392	// weird edge case where it is trying to expand strings rather than use the
14393	// variable version. This results in about 200 bytes being added, for very
14394	// little preference benefit since it this run on script load only.
14395	var _empty = '';
14396	_empty = '';
14397	
14398	var _stateDefault = _empty + 'ui-state-default';
14399	var _sortIcon     = _empty + 'css_right ui-icon ui-icon-';
14400	var _headerFooter = _empty + 'fg-toolbar ui-toolbar ui-widget-header ui-helper-clearfix';
14401	
14402	$.extend( DataTable.ext.oJUIClasses, DataTable.ext.classes, {
14403		/* Full numbers paging buttons */
14404		"sPageButton":         "fg-button ui-button "+_stateDefault,
14405		"sPageButtonActive":   "ui-state-disabled",
14406		"sPageButtonDisabled": "ui-state-disabled",
14407	
14408		/* Features */
14409		"sPaging": "dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi "+
14410			"ui-buttonset-multi paging_", /* Note that the type is postfixed */
14411	
14412		/* Sorting */
14413		"sSortAsc":            _stateDefault+" sorting_asc",
14414		"sSortDesc":           _stateDefault+" sorting_desc",
14415		"sSortable":           _stateDefault+" sorting",
14416		"sSortableAsc":        _stateDefault+" sorting_asc_disabled",
14417		"sSortableDesc":       _stateDefault+" sorting_desc_disabled",
14418		"sSortableNone":       _stateDefault+" sorting_disabled",
14419		"sSortJUIAsc":         _sortIcon+"triangle-1-n",
14420		"sSortJUIDesc":        _sortIcon+"triangle-1-s",
14421		"sSortJUI":            _sortIcon+"carat-2-n-s",
14422		"sSortJUIAscAllowed":  _sortIcon+"carat-1-n",
14423		"sSortJUIDescAllowed": _sortIcon+"carat-1-s",
14424		"sSortJUIWrapper":     "DataTables_sort_wrapper",
14425		"sSortIcon":           "DataTables_sort_icon",
14426	
14427		/* Scrolling */
14428		"sScrollHead": "dataTables_scrollHead "+_stateDefault,
14429		"sScrollFoot": "dataTables_scrollFoot "+_stateDefault,
14430	
14431		/* Misc */
14432		"sHeaderTH":  _stateDefault,
14433		"sFooterTH":  _stateDefault,
14434		"sJUIHeader": _headerFooter+" ui-corner-tl ui-corner-tr",
14435		"sJUIFooter": _headerFooter+" ui-corner-bl ui-corner-br"
14436	} );
14437	
14438	}());
14439	
14440	
14441	
14442	var extPagination = DataTable.ext.pager;
14443	
14444	function _numbers ( page, pages ) {
14445		var
14446			numbers = [],
14447			buttons = extPagination.numbers_length,
14448			half = Math.floor( buttons / 2 ),
14449			i = 1;
14450	
14451		if ( pages <= buttons ) {
14452			numbers = _range( 0, pages );
14453		}
14454		else if ( page <= half ) {
14455			numbers = _range( 0, buttons-2 );
14456			numbers.push( 'ellipsis' );
14457			numbers.push( pages-1 );
14458		}
14459		else if ( page >= pages - 1 - half ) {
14460			numbers = _range( pages-(buttons-2), pages );
14461			numbers.splice( 0, 0, 'ellipsis' ); // no unshift in ie6
14462			numbers.splice( 0, 0, 0 );
14463		}
14464		else {
14465			numbers = _range( page-half+2, page+half-1 );
14466			numbers.push( 'ellipsis' );
14467			numbers.push( pages-1 );
14468			numbers.splice( 0, 0, 'ellipsis' );
14469			numbers.splice( 0, 0, 0 );
14470		}
14471	
14472		numbers.DT_el = 'span';
14473		return numbers;
14474	}
14475	
14476	
14477	$.extend( extPagination, {
14478		simple: function ( page, pages ) {
14479			return [ 'previous', 'next' ];
14480		},
14481	
14482		full: function ( page, pages ) {
14483			return [  'first', 'previous', 'next', 'last' ];
14484		},
14485	
14486		numbers: function ( page, pages ) {
14487			return [ _numbers(page, pages) ];
14488		},
14489	
14490		simple_numbers: function ( page, pages ) {
14491			return [ 'previous', _numbers(page, pages), 'next' ];
14492		},
14493	
14494		full_numbers: function ( page, pages ) {
14495			return [ 'first', 'previous', _numbers(page, pages), 'next', 'last' ];
14496		},
14497	
14498		// For testing and plug-ins to use
14499		_numbers: _numbers,
14500	
14501		// Number of number buttons (including ellipsis) to show. _Must be odd!_
14502		numbers_length: 7
14503	} );
14504	
14505	
14506	$.extend( true, DataTable.ext.renderer, {
14507		pageButton: {
14508			_: function ( settings, host, idx, buttons, page, pages ) {
14509				var classes = settings.oClasses;
14510				var lang = settings.oLanguage.oPaginate;
14511				var aria = settings.oLanguage.oAria.paginate || {};
14512				var btnDisplay, btnClass, counter=0;
14513	
14514				var attach = function( container, buttons ) {
14515					var i, ien, node, button;
14516					var clickHandler = function ( e ) {
14517						_fnPageChange( settings, e.data.action, true );
14518					};
14519	
14520					for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
14521						button = buttons[i];
14522	
14523						if ( $.isArray( button ) ) {
14524							var inner = $( '<'+(button.DT_el || 'div')+'/>' )
14525								.appendTo( container );
14526							attach( inner, button );
14527						}
14528						else {
14529							btnDisplay = null;
14530							btnClass = '';
14531	
14532							switch ( button ) {
14533								case 'ellipsis':
14534									container.append('<span class="ellipsis">&#x2026;</span>');
14535									break;
14536	
14537								case 'first':
14538									btnDisplay = lang.sFirst;
14539									btnClass = button + (page > 0 ?
14540										'' : ' '+classes.sPageButtonDisabled);
14541									break;
14542	
14543								case 'previous':
14544									btnDisplay = lang.sPrevious;
14545									btnClass = button + (page > 0 ?
14546										'' : ' '+classes.sPageButtonDisabled);
14547									break;
14548	
14549								case 'next':
14550									btnDisplay = lang.sNext;
14551									btnClass = button + (page < pages-1 ?
14552										'' : ' '+classes.sPageButtonDisabled);
14553									break;
14554	
14555								case 'last':
14556									btnDisplay = lang.sLast;
14557									btnClass = button + (page < pages-1 ?
14558										'' : ' '+classes.sPageButtonDisabled);
14559									break;
14560	
14561								default:
14562									btnDisplay = button + 1;
14563									btnClass = page === button ?
14564										classes.sPageButtonActive : '';
14565									break;
14566							}
14567	
14568							if ( btnDisplay !== null ) {
14569								node = $('<a>', {
14570										'class': classes.sPageButton+' '+btnClass,
14571										'aria-controls': settings.sTableId,
14572										'aria-label': aria[ button ],
14573										'data-dt-idx': counter,
14574										'tabindex': settings.iTabIndex,
14575										'id': idx === 0 && typeof button === 'string' ?
14576											settings.sTableId +'_'+ button :
14577											null
14578									} )
14579									.html( btnDisplay )
14580									.appendTo( container );
14581	
14582								_fnBindAction(
14583									node, {action: button}, clickHandler
14584								);
14585	
14586								counter++;
14587							}
14588						}
14589					}
14590				};
14591	
14592				// IE9 throws an 'unknown error' if document.activeElement is used
14593				// inside an iframe or frame. Try / catch the error. Not good for
14594				// accessibility, but neither are frames.
14595				var activeEl;
14596	
14597				try {
14598					// Because this approach is destroying and recreating the paging
14599					// elements, focus is lost on the select button which is bad for
14600					// accessibility. So we want to restore focus once the draw has
14601					// completed
14602					activeEl = $(host).find(document.activeElement).data('dt-idx');
14603				}
14604				catch (e) {}
14605	
14606				attach( $(host).empty(), buttons );
14607	
14608				if ( activeEl ) {
14609					$(host).find( '[data-dt-idx='+activeEl+']' ).focus();
14610				}
14611			}
14612		}
14613	} );
14614	
14615	
14616	
14617	// Built in type detection. See model.ext.aTypes for information about
14618	// what is required from this methods.
14619	$.extend( DataTable.ext.type.detect, [
14620		// Plain numbers - first since V8 detects some plain numbers as dates
14621		// e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...).
14622		function ( d, settings )
14623		{
14624			var decimal = settings.oLanguage.sDecimal;
14625			return _isNumber( d, decimal ) ? 'num'+decimal : null;
14626		},
14627	
14628		// Dates (only those recognised by the browser's Date.parse)
14629		function ( d, settings )
14630		{
14631			// V8 will remove any unknown characters at the start and end of the
14632			// expression, leading to false matches such as `$245.12` or `10%` being
14633			// a valid date. See forum thread 18941 for detail.
14634			if ( d && !(d instanceof Date) && ( ! _re_date_start.test(d) || ! _re_date_end.test(d) ) ) {
14635				return null;
14636			}
14637			var parsed = Date.parse(d);
14638			return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null;
14639		},
14640	
14641		// Formatted numbers
14642		function ( d, settings )
14643		{
14644			var decimal = settings.oLanguage.sDecimal;
14645			return _isNumber( d, decimal, true ) ? 'num-fmt'+decimal : null;
14646		},
14647	
14648		// HTML numeric
14649		function ( d, settings )
14650		{
14651			var decimal = settings.oLanguage.sDecimal;
14652			return _htmlNumeric( d, decimal ) ? 'html-num'+decimal : null;
14653		},
14654	
14655		// HTML numeric, formatted
14656		function ( d, settings )
14657		{
14658			var decimal = settings.oLanguage.sDecimal;
14659			return _htmlNumeric( d, decimal, true ) ? 'html-num-fmt'+decimal : null;
14660		},
14661	
14662		// HTML (this is strict checking - there must be html)
14663		function ( d, settings )
14664		{
14665			return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ?
14666				'html' : null;
14667		}
14668	] );
14669	
14670	
14671	
14672	// Filter formatting functions. See model.ext.ofnSearch for information about
14673	// what is required from these methods.
14674	// 
14675	// Note that additional search methods are added for the html numbers and
14676	// html formatted numbers by `_addNumericSort()` when we know what the decimal
14677	// place is
14678	
14679	
14680	$.extend( DataTable.ext.type.search, {
14681		html: function ( data ) {
14682			return _empty(data) ?
14683				data :
14684				typeof data === 'string' ?
14685					data
14686						.replace( _re_new_lines, " " )
14687						.replace( _re_html, "" ) :
14688					'';
14689		},
14690	
14691		string: function ( data ) {
14692			return _empty(data) ?
14693				data :
14694				typeof data === 'string' ?
14695					data.replace( _re_new_lines, " " ) :
14696					data;
14697		}
14698	} );
14699	
14700	
14701	
14702	var __numericReplace = function ( d, decimalPlace, re1, re2 ) {
14703		if ( d !== 0 && (!d || d === '-') ) {
14704			return -Infinity;
14705		}
14706	
14707		// If a decimal place other than `.` is used, it needs to be given to the
14708		// function so we can detect it and replace with a `.` which is the only
14709		// decimal place Javascript recognises - it is not locale aware.
14710		if ( decimalPlace ) {
14711			d = _numToDecimal( d, decimalPlace );
14712		}
14713	
14714		if ( d.replace ) {
14715			if ( re1 ) {
14716				d = d.replace( re1, '' );
14717			}
14718	
14719			if ( re2 ) {
14720				d = d.replace( re2, '' );
14721			}
14722		}
14723	
14724		return d * 1;
14725	};
14726	
14727	
14728	// Add the numeric 'deformatting' functions for sorting and search. This is done
14729	// in a function to provide an easy ability for the language options to add
14730	// additional methods if a non-period decimal place is used.
14731	function _addNumericSort ( decimalPlace ) {
14732		$.each(
14733			{
14734				// Plain numbers
14735				"num": function ( d ) {
14736					return __numericReplace( d, decimalPlace );
14737				},
14738	
14739				// Formatted numbers
14740				"num-fmt": function ( d ) {
14741					return __numericReplace( d, decimalPlace, _re_formatted_numeric );
14742				},
14743	
14744				// HTML numeric
14745				"html-num": function ( d ) {
14746					return __numericReplace( d, decimalPlace, _re_html );
14747				},
14748	
14749				// HTML numeric, formatted
14750				"html-num-fmt": function ( d ) {
14751					return __numericReplace( d, decimalPlace, _re_html, _re_formatted_numeric );
14752				}
14753			},
14754			function ( key, fn ) {
14755				// Add the ordering method
14756				_ext.type.order[ key+decimalPlace+'-pre' ] = fn;
14757	
14758				// For HTML types add a search formatter that will strip the HTML
14759				if ( key.match(/^html\-/) ) {
14760					_ext.type.search[ key+decimalPlace ] = _ext.type.search.html;
14761				}
14762			}
14763		);
14764	}
14765	
14766	
14767	// Default sort methods
14768	$.extend( _ext.type.order, {
14769		// Dates
14770		"date-pre": function ( d ) {
14771			return Date.parse( d ) || 0;
14772		},
14773	
14774		// html
14775		"html-pre": function ( a ) {
14776			return _empty(a) ?
14777				'' :
14778				a.replace ?
14779					a.replace( /<.*?>/g, "" ).toLowerCase() :
14780					a+'';
14781		},
14782	
14783		// string
14784		"string-pre": function ( a ) {
14785			// This is a little complex, but faster than always calling toString,
14786			// http://jsperf.com/tostring-v-check
14787			return _empty(a) ?
14788				'' :
14789				typeof a === 'string' ?
14790					a.toLowerCase() :
14791					! a.toString ?
14792						'' :
14793						a.toString();
14794		},
14795	
14796		// string-asc and -desc are retained only for compatibility with the old
14797		// sort methods
14798		"string-asc": function ( x, y ) {
14799			return ((x < y) ? -1 : ((x > y) ? 1 : 0));
14800		},
14801	
14802		"string-desc": function ( x, y ) {
14803			return ((x < y) ? 1 : ((x > y) ? -1 : 0));
14804		}
14805	} );
14806	
14807	
14808	// Numeric sorting types - order doesn't matter here
14809	_addNumericSort( '' );
14810	
14811	
14812	$.extend( true, DataTable.ext.renderer, {
14813		header: {
14814			_: function ( settings, cell, column, classes ) {
14815				// No additional mark-up required
14816				// Attach a sort listener to update on sort - note that using the
14817				// `DT` namespace will allow the event to be removed automatically
14818				// on destroy, while the `dt` namespaced event is the one we are
14819				// listening for
14820				$(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
14821					if ( settings !== ctx ) { // need to check this this is the host
14822						return;               // table, not a nested one
14823					}
14824	
14825					var colIdx = column.idx;
14826	
14827					cell
14828						.removeClass(
14829							column.sSortingClass +' '+
14830							classes.sSortAsc +' '+
14831							classes.sSortDesc
14832						)
14833						.addClass( columns[ colIdx ] == 'asc' ?
14834							classes.sSortAsc : columns[ colIdx ] == 'desc' ?
14835								classes.sSortDesc :
14836								column.sSortingClass
14837						);
14838				} );
14839			},
14840	
14841			jqueryui: function ( settings, cell, column, classes ) {
14842				$('<div/>')
14843					.addClass( classes.sSortJUIWrapper )
14844					.append( cell.contents() )
14845					.append( $('<span/>')
14846						.addClass( classes.sSortIcon+' '+column.sSortingClassJUI )
14847					)
14848					.appendTo( cell );
14849	
14850				// Attach a sort listener to update on sort
14851				$(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
14852					if ( settings !== ctx ) {
14853						return;
14854					}
14855	
14856					var colIdx = column.idx;
14857	
14858					cell
14859						.removeClass( classes.sSortAsc +" "+classes.sSortDesc )
14860						.addClass( columns[ colIdx ] == 'asc' ?
14861							classes.sSortAsc : columns[ colIdx ] == 'desc' ?
14862								classes.sSortDesc :
14863								column.sSortingClass
14864						);
14865	
14866					cell
14867						.find( 'span.'+classes.sSortIcon )
14868						.removeClass(
14869							classes.sSortJUIAsc +" "+
14870							classes.sSortJUIDesc +" "+
14871							classes.sSortJUI +" "+
14872							classes.sSortJUIAscAllowed +" "+
14873							classes.sSortJUIDescAllowed
14874						)
14875						.addClass( columns[ colIdx ] == 'asc' ?
14876							classes.sSortJUIAsc : columns[ colIdx ] == 'desc' ?
14877								classes.sSortJUIDesc :
14878								column.sSortingClassJUI
14879						);
14880				} );
14881			}
14882		}
14883	} );
14884	
14885	/*
14886	 * Public helper functions. These aren't used internally by DataTables, or
14887	 * called by any of the options passed into DataTables, but they can be used
14888	 * externally by developers working with DataTables. They are helper functions
14889	 * to make working with DataTables a little bit easier.
14890	 */
14891	
14892	var __htmlEscapeEntities = function ( d ) {
14893		return typeof d === 'string' ?
14894			d.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;') :
14895			d;
14896	};
14897	
14898	/**
14899	 * Helpers for `columns.render`.
14900	 *
14901	 * The options defined here can be used with the `columns.render` initialisation
14902	 * option to provide a display renderer. The following functions are defined:
14903	 *
14904	 * * `number` - Will format numeric data (defined by `columns.data`) for
14905	 *   display, retaining the original unformatted data for sorting and filtering.
14906	 *   It takes 5 parameters:
14907	 *   * `string` - Thousands grouping separator
14908	 *   * `string` - Decimal point indicator
14909	 *   * `integer` - Number of decimal points to show
14910	 *   * `string` (optional) - Prefix.
14911	 *   * `string` (optional) - Postfix (/suffix).
14912	 * * `text` - Escape HTML to help prevent XSS attacks. It has no optional
14913	 *   parameters.
14914	 *
14915	 * @example
14916	 *   // Column definition using the number renderer
14917	 *   {
14918	 *     data: "salary",
14919	 *     render: $.fn.dataTable.render.number( '\'', '.', 0, '$' )
14920	 *   }
14921	 *
14922	 * @namespace
14923	 */
14924	DataTable.render = {
14925		number: function ( thousands, decimal, precision, prefix, postfix ) {
14926			return {
14927				display: function ( d ) {
14928					if ( typeof d !== 'number' && typeof d !== 'string' ) {
14929						return d;
14930					}
14931	
14932					var negative = d < 0 ? '-' : '';
14933					var flo = parseFloat( d );
14934	
14935					// If NaN then there isn't much formatting that we can do - just
14936					// return immediately, escaping any HTML (this was supposed to
14937					// be a number after all)
14938					if ( isNaN( flo ) ) {
14939						return __htmlEscapeEntities( d );
14940					}
14941	
14942					d = Math.abs( flo );
14943	
14944					var intPart = parseInt( d, 10 );
14945					var floatPart = precision ?
14946						decimal+(d - intPart).toFixed( precision ).substring( 2 ):
14947						'';
14948	
14949					return negative + (prefix||'') +
14950						intPart.toString().replace(
14951							/\B(?=(\d{3})+(?!\d))/g, thousands
14952						) +
14953						floatPart +
14954						(postfix||'');
14955				}
14956			};
14957		},
14958	
14959		text: function () {
14960			return {
14961				display: __htmlEscapeEntities
14962			};
14963		}
14964	};
14965	
14966	
14967	/*
14968	 * This is really a good bit rubbish this method of exposing the internal methods
14969	 * publicly... - To be fixed in 2.0 using methods on the prototype
14970	 */
14971	
14972	
14973	/**
14974	 * Create a wrapper function for exporting an internal functions to an external API.
14975	 *  @param {string} fn API function name
14976	 *  @returns {function} wrapped function
14977	 *  @memberof DataTable#internal
14978	 */
14979	function _fnExternApiFunc (fn)
14980	{
14981		return function() {
14982			var args = [_fnSettingsFromNode( this[DataTable.ext.iApiIndex] )].concat(
14983				Array.prototype.slice.call(arguments)
14984			);
14985			return DataTable.ext.internal[fn].apply( this, args );
14986		};
14987	}
14988	
14989	
14990	/**
14991	 * Reference to internal functions for use by plug-in developers. Note that
14992	 * these methods are references to internal functions and are considered to be
14993	 * private. If you use these methods, be aware that they are liable to change
14994	 * between versions.
14995	 *  @namespace
14996	 */
14997	$.extend( DataTable.ext.internal, {
14998		_fnExternApiFunc: _fnExternApiFunc,
14999		_fnBuildAjax: _fnBuildAjax,
15000		_fnAjaxUpdate: _fnAjaxUpdate,
15001		_fnAjaxParameters: _fnAjaxParameters,
15002		_fnAjaxUpdateDraw: _fnAjaxUpdateDraw,
15003		_fnAjaxDataSrc: _fnAjaxDataSrc,
15004		_fnAddColumn: _fnAddColumn,
15005		_fnColumnOptions: _fnColumnOptions,
15006		_fnAdjustColumnSizing: _fnAdjustColumnSizing,
15007		_fnVisibleToColumnIndex: _fnVisibleToColumnIndex,
15008		_fnColumnIndexToVisible: _fnColumnIndexToVisible,
15009		_fnVisbleColumns: _fnVisbleColumns,
15010		_fnGetColumns: _fnGetColumns,
15011		_fnColumnTypes: _fnColumnTypes,
15012		_fnApplyColumnDefs: _fnApplyColumnDefs,
15013		_fnHungarianMap: _fnHungarianMap,
15014		_fnCamelToHungarian: _fnCamelToHungarian,
15015		_fnLanguageCompat: _fnLanguageCompat,
15016		_fnBrowserDetect: _fnBrowserDetect,
15017		_fnAddData: _fnAddData,
15018		_fnAddTr: _fnAddTr,
15019		_fnNodeToDataIndex: _fnNodeToDataIndex,
15020		_fnNodeToColumnIndex: _fnNodeToColumnIndex,
15021		_fnGetCellData: _fnGetCellData,
15022		_fnSetCellData: _fnSetCellData,
15023		_fnSplitObjNotation: _fnSplitObjNotation,
15024		_fnGetObjectDataFn: _fnGetObjectDataFn,
15025		_fnSetObjectDataFn: _fnSetObjectDataFn,
15026		_fnGetDataMaster: _fnGetDataMaster,
15027		_fnClearTable: _fnClearTable,
15028		_fnDeleteIndex: _fnDeleteIndex,
15029		_fnInvalidate: _fnInvalidate,
15030		_fnGetRowElements: _fnGetRowElements,
15031		_fnCreateTr: _fnCreateTr,
15032		_fnBuildHead: _fnBuildHead,
15033		_fnDrawHead: _fnDrawHead,
15034		_fnDraw: _fnDraw,
15035		_fnReDraw: _fnReDraw,
15036		_fnAddOptionsHtml: _fnAddOptionsHtml,
15037		_fnDetectHeader: _fnDetectHeader,
15038		_fnGetUniqueThs: _fnGetUniqueThs,
15039		_fnFeatureHtmlFilter: _fnFeatureHtmlFilter,
15040		_fnFilterComplete: _fnFilterComplete,
15041		_fnFilterCustom: _fnFilterCustom,
15042		_fnFilterColumn: _fnFilterColumn,
15043		_fnFilter: _fnFilter,
15044		_fnFilterCreateSearch: _fnFilterCreateSearch,
15045		_fnEscapeRegex: _fnEscapeRegex,
15046		_fnFilterData: _fnFilterData,
15047		_fnFeatureHtmlInfo: _fnFeatureHtmlInfo,
15048		_fnUpdateInfo: _fnUpdateInfo,
15049		_fnInfoMacros: _fnInfoMacros,
15050		_fnInitialise: _fnInitialise,
15051		_fnInitComplete: _fnInitComplete,
15052		_fnLengthChange: _fnLengthChange,
15053		_fnFeatureHtmlLength: _fnFeatureHtmlLength,
15054		_fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate,
15055		_fnPageChange: _fnPageChange,
15056		_fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing,
15057		_fnProcessingDisplay: _fnProcessingDisplay,
15058		_fnFeatureHtmlTable: _fnFeatureHtmlTable,
15059		_fnScrollDraw: _fnScrollDraw,
15060		_fnApplyToChildren: _fnApplyToChildren,
15061		_fnCalculateColumnWidths: _fnCalculateColumnWidths,
15062		_fnThrottle: _fnThrottle,
15063		_fnConvertToWidth: _fnConvertToWidth,
15064		_fnGetWidestNode: _fnGetWidestNode,
15065		_fnGetMaxLenString: _fnGetMaxLenString,
15066		_fnStringToCss: _fnStringToCss,
15067		_fnSortFlatten: _fnSortFlatten,
15068		_fnSort: _fnSort,
15069		_fnSortAria: _fnSortAria,
15070		_fnSortListener: _fnSortListener,
15071		_fnSortAttachListener: _fnSortAttachListener,
15072		_fnSortingClasses: _fnSortingClasses,
15073		_fnSortData: _fnSortData,
15074		_fnSaveState: _fnSaveState,
15075		_fnLoadState: _fnLoadState,
15076		_fnSettingsFromNode: _fnSettingsFromNode,
15077		_fnLog: _fnLog,
15078		_fnMap: _fnMap,
15079		_fnBindAction: _fnBindAction,
15080		_fnCallbackReg: _fnCallbackReg,
15081		_fnCallbackFire: _fnCallbackFire,
15082		_fnLengthOverflow: _fnLengthOverflow,
15083		_fnRenderer: _fnRenderer,
15084		_fnDataSource: _fnDataSource,
15085		_fnRowAttributes: _fnRowAttributes,
15086		_fnCalculateEnd: function () {} // Used by a lot of plug-ins, but redundant
15087		                                // in 1.10, so this dead-end function is
15088		                                // added to prevent errors
15089	} );
15090	
15091
15092	// jQuery access
15093	$.fn.dataTable = DataTable;
15094
15095	// Provide access to the host jQuery object (circular reference)
15096	DataTable.$ = $;
15097
15098	// Legacy aliases
15099	$.fn.dataTableSettings = DataTable.settings;
15100	$.fn.dataTableExt = DataTable.ext;
15101
15102	// With a capital `D` we return a DataTables API instance rather than a
15103	// jQuery object
15104	$.fn.DataTable = function ( opts ) {
15105		return $(this).dataTable( opts ).api();
15106	};
15107
15108	// All properties that are available to $.fn.dataTable should also be
15109	// available on $.fn.DataTable
15110	$.each( DataTable, function ( prop, val ) {
15111		$.fn.DataTable[ prop ] = val;
15112	} );
15113
15114
15115	// Information about events fired by DataTables - for documentation.
15116	/**
15117	 * Draw event, fired whenever the table is redrawn on the page, at the same
15118	 * point as fnDrawCallback. This may be useful for binding events or
15119	 * performing calculations when the table is altered at all.
15120	 *  @name DataTable#draw.dt
15121	 *  @event
15122	 *  @param {event} e jQuery event object
15123	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15124	 */
15125
15126	/**
15127	 * Search event, fired when the searching applied to the table (using the
15128	 * built-in global search, or column filters) is altered.
15129	 *  @name DataTable#search.dt
15130	 *  @event
15131	 *  @param {event} e jQuery event object
15132	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15133	 */
15134
15135	/**
15136	 * Page change event, fired when the paging of the table is altered.
15137	 *  @name DataTable#page.dt
15138	 *  @event
15139	 *  @param {event} e jQuery event object
15140	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15141	 */
15142
15143	/**
15144	 * Order event, fired when the ordering applied to the table is altered.
15145	 *  @name DataTable#order.dt
15146	 *  @event
15147	 *  @param {event} e jQuery event object
15148	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15149	 */
15150
15151	/**
15152	 * DataTables initialisation complete event, fired when the table is fully
15153	 * drawn, including Ajax data loaded, if Ajax data is required.
15154	 *  @name DataTable#init.dt
15155	 *  @event
15156	 *  @param {event} e jQuery event object
15157	 *  @param {object} oSettings DataTables settings object
15158	 *  @param {object} json The JSON object request from the server - only
15159	 *    present if client-side Ajax sourced data is used</li></ol>
15160	 */
15161
15162	/**
15163	 * State save event, fired when the table has changed state a new state save
15164	 * is required. This event allows modification of the state saving object
15165	 * prior to actually doing the save, including addition or other state
15166	 * properties (for plug-ins) or modification of a DataTables core property.
15167	 *  @name DataTable#stateSaveParams.dt
15168	 *  @event
15169	 *  @param {event} e jQuery event object
15170	 *  @param {object} oSettings DataTables settings object
15171	 *  @param {object} json The state information to be saved
15172	 */
15173
15174	/**
15175	 * State load event, fired when the table is loading state from the stored
15176	 * data, but prior to the settings object being modified by the saved state
15177	 * - allowing modification of the saved state is required or loading of
15178	 * state for a plug-in.
15179	 *  @name DataTable#stateLoadParams.dt
15180	 *  @event
15181	 *  @param {event} e jQuery event object
15182	 *  @param {object} oSettings DataTables settings object
15183	 *  @param {object} json The saved state information
15184	 */
15185
15186	/**
15187	 * State loaded event, fired when state has been loaded from stored data and
15188	 * the settings object has been modified by the loaded data.
15189	 *  @name DataTable#stateLoaded.dt
15190	 *  @event
15191	 *  @param {event} e jQuery event object
15192	 *  @param {object} oSettings DataTables settings object
15193	 *  @param {object} json The saved state information
15194	 */
15195
15196	/**
15197	 * Processing event, fired when DataTables is doing some kind of processing
15198	 * (be it, order, searcg or anything else). It can be used to indicate to
15199	 * the end user that there is something happening, or that something has
15200	 * finished.
15201	 *  @name DataTable#processing.dt
15202	 *  @event
15203	 *  @param {event} e jQuery event object
15204	 *  @param {object} oSettings DataTables settings object
15205	 *  @param {boolean} bShow Flag for if DataTables is doing processing or not
15206	 */
15207
15208	/**
15209	 * Ajax (XHR) event, fired whenever an Ajax request is completed from a
15210	 * request to made to the server for new data. This event is called before
15211	 * DataTables processed the returned data, so it can also be used to pre-
15212	 * process the data returned from the server, if needed.
15213	 *
15214	 * Note that this trigger is called in `fnServerData`, if you override
15215	 * `fnServerData` and which to use this event, you need to trigger it in you
15216	 * success function.
15217	 *  @name DataTable#xhr.dt
15218	 *  @event
15219	 *  @param {event} e jQuery event object
15220	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15221	 *  @param {object} json JSON returned from the server
15222	 *
15223	 *  @example
15224	 *     // Use a custom property returned from the server in another DOM element
15225	 *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
15226	 *       $('#status').html( json.status );
15227	 *     } );
15228	 *
15229	 *  @example
15230	 *     // Pre-process the data returned from the server
15231	 *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
15232	 *       for ( var i=0, ien=json.aaData.length ; i<ien ; i++ ) {
15233	 *         json.aaData[i].sum = json.aaData[i].one + json.aaData[i].two;
15234	 *       }
15235	 *       // Note no return - manipulate the data directly in the JSON object.
15236	 *     } );
15237	 */
15238
15239	/**
15240	 * Destroy event, fired when the DataTable is destroyed by calling fnDestroy
15241	 * or passing the bDestroy:true parameter in the initialisation object. This
15242	 * can be used to remove bound events, added DOM nodes, etc.
15243	 *  @name DataTable#destroy.dt
15244	 *  @event
15245	 *  @param {event} e jQuery event object
15246	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15247	 */
15248
15249	/**
15250	 * Page length change event, fired when number of records to show on each
15251	 * page (the length) is changed.
15252	 *  @name DataTable#length.dt
15253	 *  @event
15254	 *  @param {event} e jQuery event object
15255	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15256	 *  @param {integer} len New length
15257	 */
15258
15259	/**
15260	 * Column sizing has changed.
15261	 *  @name DataTable#column-sizing.dt
15262	 *  @event
15263	 *  @param {event} e jQuery event object
15264	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15265	 */
15266
15267	/**
15268	 * Column visibility has changed.
15269	 *  @name DataTable#column-visibility.dt
15270	 *  @event
15271	 *  @param {event} e jQuery event object
15272	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15273	 *  @param {int} column Column index
15274	 *  @param {bool} vis `false` if column now hidden, or `true` if visible
15275	 */
15276
15277	return $.fn.dataTable;
15278}));

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.