PageSourceSearch

https://alumni.fondationcultureetdiversite.org/global/vendor/datat…/datatables/media/js/jquery.dataTables.js

js fondationcultureetdiversite.org collected 2026-09-28 11:06:55 UTC 449,246 bytes, 15,354 lines download raw bytes

1/*! DataTables 1.10.21
2 * ©2008-2020 SpryMedia Ltd - datatables.net/license
3 */
4
5/**
6 * @summary     DataTables
7 * @description Paginate, search and order HTML tables
8 * @version     1.10.21
9 * @file        jquery.dataTables.js
10 * @author      SpryMedia Ltd
11 * @contact     www.datatables.net
12 * @copyright   Copyright 2008-2020 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	{
vendor: 6,636 bytes, lines 95-254
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 = 
254$.isArray(data) && ( $
vendor: 18,409 bytes, lines 254-850
254.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).on('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		
vendor: 57,821 bytes, lines 851-2871
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() ), true );
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 (
913					s.nTable == this ||
914					(s.nTHead && s.nTHead.parentNode == this) ||
915					(s.nTFoot && s.nTFoot.parentNode == this)
916				) {
917					var bRetrieve = oInit.bRetrieve !== undefined ? oInit.bRetrieve : defaults.bRetrieve;
918					var bDestroy = oInit.bDestroy !== undefined ? oInit.bDestroy : defaults.bDestroy;
919			
920					if ( emptyInit || bRetrieve )
921					{
922						return s.oInstance;
923					}
924					else if ( bDestroy )
925					{
926						s.oInstance.fnDestroy();
927						break;
928					}
929					else
930					{
931						_fnLog( s, 0, 'Cannot reinitialise DataTable', 3 );
932						return;
933					}
934				}
935			
936				/* If the element we are initialising has the same ID as a table which was previously
937				 * initialised, but the table nodes don't match (from before) then we destroy the old
938				 * instance by simply deleting it. This is under the assumption that the table has been
939				 * destroyed by other methods. Anyone using non-id selectors will need to do this manually
940				 */
941				if ( s.sTableId == this.id )
942				{
943					allSettings.splice( i, 1 );
944					break;
945				}
946			}
947			
948			/* Ensure the table has an ID - required for accessibility */
949			if ( sId === null || sId === "" )
950			{
951				sId = "DataTables_Table_"+(DataTable.ext._unique++);
952				this.id = sId;
953			}
954			
955			/* Create the settings object for this table and set some of the default parameters */
956			var oSettings = $.extend( true, {}, DataTable.models.oSettings, {
957				"sDestroyWidth": $this[0].style.width,
958				"sInstance":     sId,
959				"sTableId":      sId
960			} );
961			oSettings.nTable = this;
962			oSettings.oApi   = _that.internal;
963			oSettings.oInit  = oInit;
964			
965			allSettings.push( oSettings );
966			
967			// Need to add the instance after the instance after the settings object has been added
968			// to the settings array, so we can self reference the table instance if more than one
969			oSettings.oInstance = (_that.length===1) ? _that : $this.dataTable();
970			
971			// Backwards compatibility, before we apply all the defaults
972			_fnCompatOpts( oInit );
973			_fnLanguageCompat( oInit.oLanguage );
974			
975			// If the length menu is given, but the init display length is not, use the length menu
976			if ( oInit.aLengthMenu && ! oInit.iDisplayLength )
977			{
978				oInit.iDisplayLength = $.isArray( oInit.aLengthMenu[0] ) ?
979					oInit.aLengthMenu[0][0] : oInit.aLengthMenu[0];
980			}
981			
982			// Apply the defaults and init options to make a single init object will all
983			// options defined from defaults and instance options.
984			oInit = _fnExtend( $.extend( true, {}, defaults ), oInit );
985			
986			
987			// Map the initialisation options onto the settings object
988			_fnMap( oSettings.oFeatures, oInit, [
989				"bPaginate",
990				"bLengthChange",
991				"bFilter",
992				"bSort",
993				"bSortMulti",
994				"bInfo",
995				"bProcessing",
996				"bAutoWidth",
997				"bSortClasses",
998				"bServerSide",
999				"bDeferRender"
1000			] );
1001			_fnMap( oSettings, oInit, [
1002				"asStripeClasses",
1003				"ajax",
1004				"fnServerData",
1005				"fnFormatNumber",
1006				"sServerMethod",
1007				"aaSorting",
1008				"aaSortingFixed",
1009				"aLengthMenu",
1010				"sPaginationType",
1011				"sAjaxSource",
1012				"sAjaxDataProp",
1013				"iStateDuration",
1014				"sDom",
1015				"bSortCellsTop",
1016				"iTabIndex",
1017				"fnStateLoadCallback",
1018				"fnStateSaveCallback",
1019				"renderer",
1020				"searchDelay",
1021				"rowId",
1022				[ "iCookieDuration", "iStateDuration" ], // backwards compat
1023				[ "oSearch", "oPreviousSearch" ],
1024				[ "aoSearchCols", "aoPreSearchCols" ],
1025				[ "iDisplayLength", "_iDisplayLength" ]
1026			] );
1027			_fnMap( oSettings.oScroll, oInit, [
1028				[ "sScrollX", "sX" ],
1029				[ "sScrollXInner", "sXInner" ],
1030				[ "sScrollY", "sY" ],
1031				[ "bScrollCollapse", "bCollapse" ]
1032			] );
1033			_fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" );
1034			
1035			/* Callback functions which are array driven */
1036			_fnCallbackReg( oSettings, 'aoDrawCallback',       oInit.fnDrawCallback,      'user' );
1037			_fnCallbackReg( oSettings, 'aoServerParams',       oInit.fnServerParams,      'user' );
1038			_fnCallbackReg( oSettings, 'aoStateSaveParams',    oInit.fnStateSaveParams,   'user' );
1039			_fnCallbackReg( oSettings, 'aoStateLoadParams',    oInit.fnStateLoadParams,   'user' );
1040			_fnCallbackReg( oSettings, 'aoStateLoaded',        oInit.fnStateLoaded,       'user' );
1041			_fnCallbackReg( oSettings, 'aoRowCallback',        oInit.fnRowCallback,       'user' );
1042			_fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow,        'user' );
1043			_fnCallbackReg( oSettings, 'aoHeaderCallback',     oInit.fnHeaderCallback,    'user' );
1044			_fnCallbackReg( oSettings, 'aoFooterCallback',     oInit.fnFooterCallback,    'user' );
1045			_fnCallbackReg( oSettings, 'aoInitComplete',       oInit.fnInitComplete,      'user' );
1046			_fnCallbackReg( oSettings, 'aoPreDrawCallback',    oInit.fnPreDrawCallback,   'user' );
1047			
1048			oSettings.rowIdFn = _fnGetObjectDataFn( oInit.rowId );
1049			
1050			/* Browser support detection */
1051			_fnBrowserDetect( oSettings );
1052			
1053			var oClasses = oSettings.oClasses;
1054			
1055			$.extend( oClasses, DataTable.ext.classes, oInit.oClasses );
1056			$this.addClass( oClasses.sTable );
1057			
1058			
1059			if ( oSettings.iInitDisplayStart === undefined )
1060			{
1061				/* Display start point, taking into account the save saving */
1062				oSettings.iInitDisplayStart = oInit.iDisplayStart;
1063				oSettings._iDisplayStart = oInit.iDisplayStart;
1064			}
1065			
1066			if ( oInit.iDeferLoading !== null )
1067			{
1068				oSettings.bDeferLoading = true;
1069				var tmp = $.isArray( oInit.iDeferLoading );
1070				oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading;
1071				oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading;
1072			}
1073			
1074			/* Language definitions */
1075			var oLanguage = oSettings.oLanguage;
1076			$.extend( true, oLanguage, oInit.oLanguage );
1077			
1078			if ( oLanguage.sUrl )
1079			{
1080				/* Get the language definitions from a file - because this Ajax call makes the language
1081				 * get async to the remainder of this function we use bInitHandedOff to indicate that
1082				 * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor
1083				 */
1084				$.ajax( {
1085					dataType: 'json',
1086					url: oLanguage.sUrl,
1087					success: function ( json ) {
1088						_fnLanguageCompat( json );
1089						_fnCamelToHungarian( defaults.oLanguage, json );
1090						$.extend( true, oLanguage, json );
1091						_fnInitialise( oSettings );
1092					},
1093					error: function () {
1094						// Error occurred loading language file, continue on as best we can
1095						_fnInitialise( oSettings );
1096					}
1097				} );
1098				bInitHandedOff = true;
1099			}
1100			
1101			/*
1102			 * Stripes
1103			 */
1104			if ( oInit.asStripeClasses === null )
1105			{
1106				oSettings.asStripeClasses =[
1107					oClasses.sStripeOdd,
1108					oClasses.sStripeEven
1109				];
1110			}
1111			
1112			/* Remove row stripe classes if they are already on the table row */
1113			var stripeClasses = oSettings.asStripeClasses;
1114			var rowOne = $this.children('tbody').find('tr').eq(0);
1115			if ( $.inArray( true, $.map( stripeClasses, function(el, i) {
1116				return rowOne.hasClass(el);
1117			} ) ) !== -1 ) {
1118				$('tbody tr', this).removeClass( stripeClasses.join(' ') );
1119				oSettings.asDestroyStripes = stripeClasses.slice();
1120			}
1121			
1122			/*
1123			 * Columns
1124			 * See if we should load columns automatically or use defined ones
1125			 */
1126			var anThs = [];
1127			var aoColumnsInit;
1128			var nThead = this.getElementsByTagName('thead');
1129			if ( nThead.length !== 0 )
1130			{
1131				_fnDetectHeader( oSettings.aoHeader, nThead[0] );
1132				anThs = _fnGetUniqueThs( oSettings );
1133			}
1134			
1135			/* If not given a column array, generate one with nulls */
1136			if ( oInit.aoColumns === null )
1137			{
1138				aoColumnsInit = [];
1139				for ( i=0, iLen=anThs.length ; i<iLen ; i++ )
1140				{
1141					aoColumnsInit.push( null );
1142				}
1143			}
1144			else
1145			{
1146				aoColumnsInit = oInit.aoColumns;
1147			}
1148			
1149			/* Add the columns */
1150			for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ )
1151			{
1152				_fnAddColumn( oSettings, anThs ? anThs[i] : null );
1153			}
1154			
1155			/* Apply the column definitions */
1156			_fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) {
1157				_fnColumnOptions( oSettings, iCol, oDef );
1158			} );
1159			
1160			/* HTML5 attribute detection - build an mData object automatically if the
1161			 * attributes are found
1162			 */
1163			if ( rowOne.length ) {
1164				var a = function ( cell, name ) {
1165					return cell.getAttribute( 'data-'+name ) !== null ? name : null;
1166				};
1167			
1168				$( rowOne[0] ).children('th, td').each( function (i, cell) {
1169					var col = oSettings.aoColumns[i];
1170			
1171					if ( col.mData === i ) {
1172						var sort = a( cell, 'sort' ) || a( cell, 'order' );
1173						var filter = a( cell, 'filter' ) || a( cell, 'search' );
1174			
1175						if ( sort !== null || filter !== null ) {
1176							col.mData = {
1177								_:      i+'.display',
1178								sort:   sort !== null   ? i+'.@data-'+sort   : undefined,
1179								type:   sort !== null   ? i+'.@data-'+sort   : undefined,
1180								filter: filter !== null ? i+'.@data-'+filter : undefined
1181							};
1182			
1183							_fnColumnOptions( oSettings, i );
1184						}
1185					}
1186				} );
1187			}
1188			
1189			var features = oSettings.oFeatures;
1190			var loadedInit = function () {
1191				/*
1192				 * Sorting
1193				 * @todo For modularisation (1.11) this needs to do into a sort start up handler
1194				 */
1195			
1196				// If aaSorting is not defined, then we use the first indicator in asSorting
1197				// in case that has been altered, so the default sort reflects that option
1198				if ( oInit.aaSorting === undefined ) {
1199					var sorting = oSettings.aaSorting;
1200					for ( i=0, iLen=sorting.length ; i<iLen ; i++ ) {
1201						sorting[i][1] = oSettings.aoColumns[ i ].asSorting[0];
1202					}
1203				}
1204			
1205				/* Do a first pass on the sorting classes (allows any size changes to be taken into
1206				 * account, and also will apply sorting disabled classes if disabled
1207				 */
1208				_fnSortingClasses( oSettings );
1209			
1210				if ( features.bSort ) {
1211					_fnCallbackReg( oSettings, 'aoDrawCallback', function () {
1212						if ( oSettings.bSorted ) {
1213							var aSort = _fnSortFlatten( oSettings );
1214							var sortedColumns = {};
1215			
1216							$.each( aSort, function (i, val) {
1217								sortedColumns[ val.src ] = val.dir;
1218							} );
1219			
1220							_fnCallbackFire( oSettings, null, 'order', [oSettings, aSort, sortedColumns] );
1221							_fnSortAria( oSettings );
1222						}
1223					} );
1224				}
1225			
1226				_fnCallbackReg( oSettings, 'aoDrawCallback', function () {
1227					if ( oSettings.bSorted || _fnDataSource( oSettings ) === 'ssp' || features.bDeferRender ) {
1228						_fnSortingClasses( oSettings );
1229					}
1230				}, 'sc' );
1231			
1232			
1233				/*
1234				 * Final init
1235				 * Cache the header, body and footer as required, creating them if needed
1236				 */
1237			
1238				// Work around for Webkit bug 83867 - store the caption-side before removing from doc
1239				var captions = $this.children('caption').each( function () {
1240					this._captionSide = $(this).css('caption-side');
1241				} );
1242			
1243				var thead = $this.children('thead');
1244				if ( thead.length === 0 ) {
1245					thead = $('<thead/>').appendTo($this);
1246				}
1247				oSettings.nTHead = thead[0];
1248			
1249				var tbody = $this.children('tbody');
1250				if ( tbody.length === 0 ) {
1251					tbody = $('<tbody/>').appendTo($this);
1252				}
1253				oSettings.nTBody = tbody[0];
1254			
1255				var tfoot = $this.children('tfoot');
1256				if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") ) {
1257					// If we are a scrolling table, and no footer has been given, then we need to create
1258					// a tfoot element for the caption element to be appended to
1259					tfoot = $('<tfoot/>').appendTo($this);
1260				}
1261			
1262				if ( tfoot.length === 0 || tfoot.children().length === 0 ) {
1263					$this.addClass( oClasses.sNoFooter );
1264				}
1265				else if ( tfoot.length > 0 ) {
1266					oSettings.nTFoot = tfoot[0];
1267					_fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );
1268				}
1269			
1270				/* Check if there is data passing into the constructor */
1271				if ( oInit.aaData ) {
1272					for ( i=0 ; i<oInit.aaData.length ; i++ ) {
1273						_fnAddData( oSettings, oInit.aaData[ i ] );
1274					}
1275				}
1276				else if ( oSettings.bDeferLoading || _fnDataSource( oSettings ) == 'dom' ) {
1277					/* Grab the data from the page - only do this when deferred loading or no Ajax
1278					 * source since there is no point in reading the DOM data if we are then going
1279					 * to replace it with Ajax data
1280					 */
1281					_fnAddTr( oSettings, $(oSettings.nTBody).children('tr') );
1282				}
1283			
1284				/* Copy the data index array */
1285				oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
1286			
1287				/* Initialisation complete - table can be drawn */
1288				oSettings.bInitialised = true;
1289			
1290				/* Check if we need to initialise the table (it might not have been handed off to the
1291				 * language processor)
1292				 */
1293				if ( bInitHandedOff === false ) {
1294					_fnInitialise( oSettings );
1295				}
1296			};
1297			
1298			/* Must be done after everything which can be overridden by the state saving! */
1299			if ( oInit.bStateSave )
1300			{
1301				features.bStateSave = true;
1302				_fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' );
1303				_fnLoadState( oSettings, oInit, loadedInit );
1304			}
1305			else {
1306				loadedInit();
1307			}
1308			
1309		} );
1310		_that = null;
1311		return this;
1312	};
1313
1314	
1315	/*
1316	 * It is useful to have variables which are scoped locally so only the
1317	 * DataTables functions can access them and they don't leak into global space.
1318	 * At the same time these functions are often useful over multiple files in the
1319	 * core and API, so we list, or at least document, all variables which are used
1320	 * by DataTables as private variables here. This also ensures that there is no
1321	 * clashing of variable names and that they can easily referenced for reuse.
1322	 */
1323	
1324	
1325	// Defined else where
1326	//  _selector_run
1327	//  _selector_opts
1328	//  _selector_first
1329	//  _selector_row_indexes
1330	
1331	var _ext; // DataTable.ext
1332	var _Api; // DataTable.Api
1333	var _api_register; // DataTable.Api.register
1334	var _api_registerPlural; // DataTable.Api.registerPlural
1335	
1336	var _re_dic = {};
1337	var _re_new_lines = /[\r\n\u2028]/g;
1338	var _re_html = /<.*?>/g;
1339	
1340	// This is not strict ISO8601 - Date.parse() is quite lax, although
1341	// implementations differ between browsers.
1342	var _re_date = /^\d{2,4}[\.\/\-]\d{1,2}[\.\/\-]\d{1,2}([T ]{1}\d{1,2}[:\.]\d{2}([\.:]\d{2})?)?$/;
1343	
1344	// Escape regular expression special characters
1345	var _re_escape_regex = new RegExp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' );
1346	
1347	// http://en.wikipedia.org/wiki/Foreign_exchange_market
1348	// - \u20BD - Russian ruble.
1349	// - \u20a9 - South Korean Won
1350	// - \u20BA - Turkish Lira
1351	// - \u20B9 - Indian Rupee
1352	// - R - Brazil (R$) and South Africa
1353	// - fr - Swiss Franc
1354	// - kr - Swedish krona, Norwegian krone and Danish krone
1355	// - \u2009 is thin space and \u202F is narrow no-break space, both used in many
1356	// - Ƀ - Bitcoin
1357	// - Ξ - Ethereum
1358	//   standards as thousands separators.
1359	var _re_formatted_numeric = /[',$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfkɃΞ]/gi;
1360	
1361	
1362	var _empty = function ( d ) {
1363		return !d || d === true || d === '-' ? true : false;
1364	};
1365	
1366	
1367	var _intVal = function ( s ) {
1368		var integer = parseInt( s, 10 );
1369		return !isNaN(integer) && isFinite(s) ? integer : null;
1370	};
1371	
1372	// Convert from a formatted number with characters other than `.` as the
1373	// decimal place, to a Javascript number
1374	var _numToDecimal = function ( num, decimalPoint ) {
1375		// Cache created regular expressions for speed as this function is called often
1376		if ( ! _re_dic[ decimalPoint ] ) {
1377			_re_dic[ decimalPoint ] = new RegExp( _fnEscapeRegex( decimalPoint ), 'g' );
1378		}
1379		return typeof num === 'string' && decimalPoint !== '.' ?
1380			num.replace( /\./g, '' ).replace( _re_dic[ decimalPoint ], '.' ) :
1381			num;
1382	};
1383	
1384	
1385	var _isNumber = function ( d, decimalPoint, formatted ) {
1386		var strType = typeof d === 'string';
1387	
1388		// If empty return immediately so there must be a number if it is a
1389		// formatted string (this stops the string "k", or "kr", etc being detected
1390		// as a formatted number for currency
1391		if ( _empty( d ) ) {
1392			return true;
1393		}
1394	
1395		if ( decimalPoint && strType ) {
1396			d = _numToDecimal( d, decimalPoint );
1397		}
1398	
1399		if ( formatted && strType ) {
1400			d = d.replace( _re_formatted_numeric, '' );
1401		}
1402	
1403		return !isNaN( parseFloat(d) ) && isFinite( d );
1404	};
1405	
1406	
1407	// A string without HTML in it can be considered to be HTML still
1408	var _isHtml = function ( d ) {
1409		return _empty( d ) || typeof d === 'string';
1410	};
1411	
1412	
1413	var _htmlNumeric = function ( d, decimalPoint, formatted ) {
1414		if ( _empty( d ) ) {
1415			return true;
1416		}
1417	
1418		var html = _isHtml( d );
1419		return ! html ?
1420			null :
1421			_isNumber( _stripHtml( d ), decimalPoint, formatted ) ?
1422				true :
1423				null;
1424	};
1425	
1426	
1427	var _pluck = function ( a, prop, prop2 ) {
1428		var out = [];
1429		var i=0, ien=a.length;
1430	
1431		// Could have the test in the loop for slightly smaller code, but speed
1432		// is essential here
1433		if ( prop2 !== undefined ) {
1434			for ( ; i<ien ; i++ ) {
1435				if ( a[i] && a[i][ prop ] ) {
1436					out.push( a[i][ prop ][ prop2 ] );
1437				}
1438			}
1439		}
1440		else {
1441			for ( ; i<ien ; i++ ) {
1442				if ( a[i] ) {
1443					out.push( a[i][ prop ] );
1444				}
1445			}
1446		}
1447	
1448		return out;
1449	};
1450	
1451	
1452	// Basically the same as _pluck, but rather than looping over `a` we use `order`
1453	// as the indexes to pick from `a`
1454	var _pluck_order = function ( a, order, prop, prop2 )
1455	{
1456		var out = [];
1457		var i=0, ien=order.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[ order[i] ][ prop ] ) {
1464					out.push( a[ order[i] ][ prop ][ prop2 ] );
1465				}
1466			}
1467		}
1468		else {
1469			for ( ; i<ien ; i++ ) {
1470				out.push( a[ order[i] ][ prop ] );
1471			}
1472		}
1473	
1474		return out;
1475	};
1476	
1477	
1478	var _range = function ( len, start )
1479	{
1480		var out = [];
1481		var end;
1482	
1483		if ( start === undefined ) {
1484			start = 0;
1485			end = len;
1486		}
1487		else {
1488			end = start;
1489			start = len;
1490		}
1491	
1492		for ( var i=start ; i<end ; i++ ) {
1493			out.push( i );
1494		}
1495	
1496		return out;
1497	};
1498	
1499	
1500	var _removeEmpty = function ( a )
1501	{
1502		var out = [];
1503	
1504		for ( var i=0, ien=a.length ; i<ien ; i++ ) {
1505			if ( a[i] ) { // careful - will remove all falsy values!
1506				out.push( a[i] );
1507			}
1508		}
1509	
1510		return out;
1511	};
1512	
1513	
1514	var _stripHtml = function ( d ) {
1515		return d.replace( _re_html, '' );
1516	};
1517	
1518	
1519	/**
1520	 * Determine if all values in the array are unique. This means we can short
1521	 * cut the _unique method at the cost of a single loop. A sorted array is used
1522	 * to easily check the values.
1523	 *
1524	 * @param  {array} src Source array
1525	 * @return {boolean} true if all unique, false otherwise
1526	 * @ignore
1527	 */
1528	var _areAllUnique = function ( src ) {
1529		if ( src.length < 2 ) {
1530			return true;
1531		}
1532	
1533		var sorted = src.slice().sort();
1534		var last = sorted[0];
1535	
1536		for ( var i=1, ien=sorted.length ; i<ien ; i++ ) {
1537			if ( sorted[i] === last ) {
1538				return false;
1539			}
1540	
1541			last = sorted[i];
1542		}
1543	
1544		return true;
1545	};
1546	
1547	
1548	/**
1549	 * Find the unique elements in a source array.
1550	 *
1551	 * @param  {array} src Source array
1552	 * @return {array} Array of unique items
1553	 * @ignore
1554	 */
1555	var _unique = function ( src )
1556	{
1557		if ( _areAllUnique( src ) ) {
1558			return src.slice();
1559		}
1560	
1561		// A faster unique method is to use object keys to identify used values,
1562		// but this doesn't work with arrays or objects, which we must also
1563		// consider. See jsperf.com/compare-array-unique-versions/4 for more
1564		// information.
1565		var
1566			out = [],
1567			val,
1568			i, ien=src.length,
1569			j, k=0;
1570	
1571		again: for ( i=0 ; i<ien ; i++ ) {
1572			val = src[i];
1573	
1574			for ( j=0 ; j<k ; j++ ) {
1575				if ( out[j] === val ) {
1576					continue again;
1577				}
1578			}
1579	
1580			out.push( val );
1581			k++;
1582		}
1583	
1584		return out;
1585	};
1586	
1587	
1588	/**
1589	 * DataTables utility methods
1590	 * 
1591	 * This namespace provides helper methods that DataTables uses internally to
1592	 * create a DataTable, but which are not exclusively used only for DataTables.
1593	 * These methods can be used by extension authors to save the duplication of
1594	 * code.
1595	 *
1596	 *  @namespace
1597	 */
1598	DataTable.util = {
1599		/**
1600		 * Throttle the calls to a function. Arguments and context are maintained
1601		 * for the throttled function.
1602		 *
1603		 * @param {function} fn Function to be called
1604		 * @param {integer} freq Call frequency in mS
1605		 * @return {function} Wrapped function
1606		 */
1607		throttle: function ( fn, freq ) {
1608			var
1609				frequency = freq !== undefined ? freq : 200,
1610				last,
1611				timer;
1612	
1613			return function () {
1614				var
1615					that = this,
1616					now  = +new Date(),
1617					args = arguments;
1618	
1619				if ( last && now < last + frequency ) {
1620					clearTimeout( timer );
1621	
1622					timer = setTimeout( function () {
1623						last = undefined;
1624						fn.apply( that, args );
1625					}, frequency );
1626				}
1627				else {
1628					last = now;
1629					fn.apply( that, args );
1630				}
1631			};
1632		},
1633	
1634	
1635		/**
1636		 * Escape a string such that it can be used in a regular expression
1637		 *
1638		 *  @param {string} val string to escape
1639		 *  @returns {string} escaped string
1640		 */
1641		escapeRegex: function ( val ) {
1642			return val.replace( _re_escape_regex, '\\$1' );
1643		}
1644	};
1645	
1646	
1647	
1648	/**
1649	 * Create a mapping object that allows camel case parameters to be looked up
1650	 * for their Hungarian counterparts. The mapping is stored in a private
1651	 * parameter called `_hungarianMap` which can be accessed on the source object.
1652	 *  @param {object} o
1653	 *  @memberof DataTable#oApi
1654	 */
1655	function _fnHungarianMap ( o )
1656	{
1657		var
1658			hungarian = 'a aa ai ao as b fn i m o s ',
1659			match,
1660			newKey,
1661			map = {};
1662	
1663		$.each( o, function (key, val) {
1664			match = key.match(/^([^A-Z]+?)([A-Z])/);
1665	
1666			if ( match && hungarian.indexOf(match[1]+' ') !== -1 )
1667			{
1668				newKey = key.replace( match[0], match[2].toLowerCase() );
1669				map[ newKey ] = key;
1670	
1671				if ( match[1] === 'o' )
1672				{
1673					_fnHungarianMap( o[key] );
1674				}
1675			}
1676		} );
1677	
1678		o._hungarianMap = map;
1679	}
1680	
1681	
1682	/**
1683	 * Convert from camel case parameters to Hungarian, based on a Hungarian map
1684	 * created by _fnHungarianMap.
1685	 *  @param {object} src The model object which holds all parameters that can be
1686	 *    mapped.
1687	 *  @param {object} user The object to convert from camel case to Hungarian.
1688	 *  @param {boolean} force When set to `true`, properties which already have a
1689	 *    Hungarian value in the `user` object will be overwritten. Otherwise they
1690	 *    won't be.
1691	 *  @memberof DataTable#oApi
1692	 */
1693	function _fnCamelToHungarian ( src, user, force )
1694	{
1695		if ( ! src._hungarianMap ) {
1696			_fnHungarianMap( src );
1697		}
1698	
1699		var hungarianKey;
1700	
1701		$.each( user, function (key, val) {
1702			hungarianKey = src._hungarianMap[ key ];
1703	
1704			if ( hungarianKey !== undefined && (force || user[hungarianKey] === undefined) )
1705			{
1706				// For objects, we need to buzz down into the object to copy parameters
1707				if ( hungarianKey.charAt(0) === 'o' )
1708				{
1709					// Copy the camelCase options over to the hungarian
1710					if ( ! user[ hungarianKey ] ) {
1711						user[ hungarianKey ] = {};
1712					}
1713					$.extend( true, user[hungarianKey], user[key] );
1714	
1715					_fnCamelToHungarian( src[hungarianKey], user[hungarianKey], force );
1716				}
1717				else {
1718					user[hungarianKey] = user[ key ];
1719				}
1720			}
1721		} );
1722	}
1723	
1724	
1725	/**
1726	 * Language compatibility - when certain options are given, and others aren't, we
1727	 * need to duplicate the values over, in order to provide backwards compatibility
1728	 * with older language files.
1729	 *  @param {object} oSettings dataTables settings object
1730	 *  @memberof DataTable#oApi
1731	 */
1732	function _fnLanguageCompat( lang )
1733	{
1734		// Note the use of the Hungarian notation for the parameters in this method as
1735		// this is called after the mapping of camelCase to Hungarian
1736		var defaults = DataTable.defaults.oLanguage;
1737	
1738		// Default mapping
1739		var defaultDecimal = defaults.sDecimal;
1740		if ( defaultDecimal ) {
1741			_addNumericSort( defaultDecimal );
1742		}
1743	
1744		if ( lang ) {
1745			var zeroRecords = lang.sZeroRecords;
1746	
1747			// Backwards compatibility - if there is no sEmptyTable given, then use the same as
1748			// sZeroRecords - assuming that is given.
1749			if ( ! lang.sEmptyTable && zeroRecords &&
1750				defaults.sEmptyTable === "No data available in table" )
1751			{
1752				_fnMap( lang, lang, 'sZeroRecords', 'sEmptyTable' );
1753			}
1754	
1755			// Likewise with loading records
1756			if ( ! lang.sLoadingRecords && zeroRecords &&
1757				defaults.sLoadingRecords === "Loading..." )
1758			{
1759				_fnMap( lang, lang, 'sZeroRecords', 'sLoadingRecords' );
1760			}
1761	
1762			// Old parameter name of the thousands separator mapped onto the new
1763			if ( lang.sInfoThousands ) {
1764				lang.sThousands = lang.sInfoThousands;
1765			}
1766	
1767			var decimal = lang.sDecimal;
1768			if ( decimal && defaultDecimal !== decimal ) {
1769				_addNumericSort( decimal );
1770			}
1771		}
1772	}
1773	
1774	
1775	/**
1776	 * Map one parameter onto another
1777	 *  @param {object} o Object to map
1778	 *  @param {*} knew The new parameter name
1779	 *  @param {*} old The old parameter name
1780	 */
1781	var _fnCompatMap = function ( o, knew, old ) {
1782		if ( o[ knew ] !== undefined ) {
1783			o[ old ] = o[ knew ];
1784		}
1785	};
1786	
1787	
1788	/**
1789	 * Provide backwards compatibility for the main DT options. Note that the new
1790	 * options are mapped onto the old parameters, so this is an external interface
1791	 * change only.
1792	 *  @param {object} init Object to map
1793	 */
1794	function _fnCompatOpts ( init )
1795	{
1796		_fnCompatMap( init, 'ordering',      'bSort' );
1797		_fnCompatMap( init, 'orderMulti',    'bSortMulti' );
1798		_fnCompatMap( init, 'orderClasses',  'bSortClasses' );
1799		_fnCompatMap( init, 'orderCellsTop', 'bSortCellsTop' );
1800		_fnCompatMap( init, 'order',         'aaSorting' );
1801		_fnCompatMap( init, 'orderFixed',    'aaSortingFixed' );
1802		_fnCompatMap( init, 'paging',        'bPaginate' );
1803		_fnCompatMap( init, 'pagingType',    'sPaginationType' );
1804		_fnCompatMap( init, 'pageLength',    'iDisplayLength' );
1805		_fnCompatMap( init, 'searching',     'bFilter' );
1806	
1807		// Boolean initialisation of x-scrolling
1808		if ( typeof init.sScrollX === 'boolean' ) {
1809			init.sScrollX = init.sScrollX ? '100%' : '';
1810		}
1811		if ( typeof init.scrollX === 'boolean' ) {
1812			init.scrollX = init.scrollX ? '100%' : '';
1813		}
1814	
1815		// Column search objects are in an array, so it needs to be converted
1816		// element by element
1817		var searchCols = init.aoSearchCols;
1818	
1819		if ( searchCols ) {
1820			for ( var i=0, ien=searchCols.length ; i<ien ; i++ ) {
1821				if ( searchCols[i] ) {
1822					_fnCamelToHungarian( DataTable.models.oSearch, searchCols[i] );
1823				}
1824			}
1825		}
1826	}
1827	
1828	
1829	/**
1830	 * Provide backwards compatibility for column options. Note that the new options
1831	 * are mapped onto the old parameters, so this is an external interface change
1832	 * only.
1833	 *  @param {object} init Object to map
1834	 */
1835	function _fnCompatCols ( init )
1836	{
1837		_fnCompatMap( init, 'orderable',     'bSortable' );
1838		_fnCompatMap( init, 'orderData',     'aDataSort' );
1839		_fnCompatMap( init, 'orderSequence', 'asSorting' );
1840		_fnCompatMap( init, 'orderDataType', 'sortDataType' );
1841	
1842		// orderData can be given as an integer
1843		var dataSort = init.aDataSort;
1844		if ( typeof dataSort === 'number' && ! $.isArray( dataSort ) ) {
1845			init.aDataSort = [ dataSort ];
1846		}
1847	}
1848	
1849	
1850	/**
1851	 * Browser feature detection for capabilities, quirks
1852	 *  @param {object} settings dataTables settings object
1853	 *  @memberof DataTable#oApi
1854	 */
1855	function _fnBrowserDetect( settings )
1856	{
1857		// We don't need to do this every time DataTables is constructed, the values
1858		// calculated are specific to the browser and OS configuration which we
1859		// don't expect to change between initialisations
1860		if ( ! DataTable.__browser ) {
1861			var browser = {};
1862			DataTable.__browser = browser;
1863	
1864			// Scrolling feature / quirks detection
1865			var n = $('<div/>')
1866				.css( {
1867					position: 'fixed',
1868					top: 0,
1869					left: $(window).scrollLeft()*-1, // allow for scrolling
1870					height: 1,
1871					width: 1,
1872					overflow: 'hidden'
1873				} )
1874				.append(
1875					$('<div/>')
1876						.css( {
1877							position: 'absolute',
1878							top: 1,
1879							left: 1,
1880							width: 100,
1881							overflow: 'scroll'
1882						} )
1883						.append(
1884							$('<div/>')
1885								.css( {
1886									width: '100%',
1887									height: 10
1888								} )
1889						)
1890				)
1891				.appendTo( 'body' );
1892	
1893			var outer = n.children();
1894			var inner = outer.children();
1895	
1896			// Numbers below, in order, are:
1897			// inner.offsetWidth, inner.clientWidth, outer.offsetWidth, outer.clientWidth
1898			//
1899			// IE6 XP:                           100 100 100  83
1900			// IE7 Vista:                        100 100 100  83
1901			// IE 8+ Windows:                     83  83 100  83
1902			// Evergreen Windows:                 83  83 100  83
1903			// Evergreen Mac with scrollbars:     85  85 100  85
1904			// Evergreen Mac without scrollbars: 100 100 100 100
1905	
1906			// Get scrollbar width
1907			browser.barWidth = outer[0].offsetWidth - outer[0].clientWidth;
1908	
1909			// IE6/7 will oversize a width 100% element inside a scrolling element, to
1910			// include the width of the scrollbar, while other browsers ensure the inner
1911			// element is contained without forcing scrolling
1912			browser.bScrollOversize = inner[0].offsetWidth === 100 && outer[0].clientWidth !== 100;
1913	
1914			// In rtl text layout, some browsers (most, but not all) will place the
1915			// scrollbar on the left, rather than the right.
1916			browser.bScrollbarLeft = Math.round( inner.offset().left ) !== 1;
1917	
1918			// IE8- don't provide height and width for getBoundingClientRect
1919			browser.bBounding = n[0].getBoundingClientRect().width ? true : false;
1920	
1921			n.remove();
1922		}
1923	
1924		$.extend( settings.oBrowser, DataTable.__browser );
1925		settings.oScroll.iBarWidth = DataTable.__browser.barWidth;
1926	}
1927	
1928	
1929	/**
1930	 * Array.prototype reduce[Right] method, used for browsers which don't support
1931	 * JS 1.6. Done this way to reduce code size, since we iterate either way
1932	 *  @param {object} settings dataTables settings object
1933	 *  @memberof DataTable#oApi
1934	 */
1935	function _fnReduce ( that, fn, init, start, end, inc )
1936	{
1937		var
1938			i = start,
1939			value,
1940			isSet = false;
1941	
1942		if ( init !== undefined ) {
1943			value = init;
1944			isSet = true;
1945		}
1946	
1947		while ( i !== end ) {
1948			if ( ! that.hasOwnProperty(i) ) {
1949				continue;
1950			}
1951	
1952			value = isSet ?
1953				fn( value, that[i], i, that ) :
1954				that[i];
1955	
1956			isSet = true;
1957			i += inc;
1958		}
1959	
1960		return value;
1961	}
1962	
1963	/**
1964	 * Add a column to the list used for the table with default values
1965	 *  @param {object} oSettings dataTables settings object
1966	 *  @param {node} nTh The th element for this column
1967	 *  @memberof DataTable#oApi
1968	 */
1969	function _fnAddColumn( oSettings, nTh )
1970	{
1971		// Add column to aoColumns array
1972		var oDefaults = DataTable.defaults.column;
1973		var iCol = oSettings.aoColumns.length;
1974		var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {
1975			"nTh": nTh ? nTh : document.createElement('th'),
1976			"sTitle":    oDefaults.sTitle    ? oDefaults.sTitle    : nTh ? nTh.innerHTML : '',
1977			"aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],
1978			"mData": oDefaults.mData ? oDefaults.mData : iCol,
1979			idx: iCol
1980		} );
1981		oSettings.aoColumns.push( oCol );
1982	
1983		// Add search object for column specific search. Note that the `searchCols[ iCol ]`
1984		// passed into extend can be undefined. This allows the user to give a default
1985		// with only some of the parameters defined, and also not give a default
1986		var searchCols = oSettings.aoPreSearchCols;
1987		searchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] );
1988	
1989		// Use the default column options function to initialise classes etc
1990		_fnColumnOptions( oSettings, iCol, $(nTh).data() );
1991	}
1992	
1993	
1994	/**
1995	 * Apply options for a column
1996	 *  @param {object} oSettings dataTables settings object
1997	 *  @param {int} iCol column index to consider
1998	 *  @param {object} oOptions object with sType, bVisible and bSearchable etc
1999	 *  @memberof DataTable#oApi
2000	 */
2001	function _fnColumnOptions( oSettings, iCol, oOptions )
2002	{
2003		var oCol = oSettings.aoColumns[ iCol ];
2004		var oClasses = oSettings.oClasses;
2005		var th = $(oCol.nTh);
2006	
2007		// Try to get width information from the DOM. We can't get it from CSS
2008		// as we'd need to parse the CSS stylesheet. `width` option can override
2009		if ( ! oCol.sWidthOrig ) {
2010			// Width attribute
2011			oCol.sWidthOrig = th.attr('width') || null;
2012	
2013			// Style attribute
2014			var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/);
2015			if ( t ) {
2016				oCol.sWidthOrig = t[1];
2017			}
2018		}
2019	
2020		/* User specified column options */
2021		if ( oOptions !== undefined && oOptions !== null )
2022		{
2023			// Backwards compatibility
2024			_fnCompatCols( oOptions );
2025	
2026			// Map camel case parameters to their Hungarian counterparts
2027			_fnCamelToHungarian( DataTable.defaults.column, oOptions, true );
2028	
2029			/* Backwards compatibility for mDataProp */
2030			if ( oOptions.mDataProp !== undefined && !oOptions.mData )
2031			{
2032				oOptions.mData = oOptions.mDataProp;
2033			}
2034	
2035			if ( oOptions.sType )
2036			{
2037				oCol._sManualType = oOptions.sType;
2038			}
2039	
2040			// `class` is a reserved word in Javascript, so we need to provide
2041			// the ability to use a valid name for the camel case input
2042			if ( oOptions.className && ! oOptions.sClass )
2043			{
2044				oOptions.sClass = oOptions.className;
2045			}
2046			if ( oOptions.sClass ) {
2047				th.addClass( oOptions.sClass );
2048			}
2049	
2050			$.extend( oCol, oOptions );
2051			_fnMap( oCol, oOptions, "sWidth", "sWidthOrig" );
2052	
2053			/* iDataSort to be applied (backwards compatibility), but aDataSort will take
2054			 * priority if defined
2055			 */
2056			if ( oOptions.iDataSort !== undefined )
2057			{
2058				oCol.aDataSort = [ oOptions.iDataSort ];
2059			}
2060			_fnMap( oCol, oOptions, "aDataSort" );
2061		}
2062	
2063		/* Cache the data get and set functions for speed */
2064		var mDataSrc = oCol.mData;
2065		var mData = _fnGetObjectDataFn( mDataSrc );
2066		var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null;
2067	
2068		var attrTest = function( src ) {
2069			return typeof src === 'string' && src.indexOf('@') !== -1;
2070		};
2071		oCol._bAttrSrc = $.isPlainObject( mDataSrc ) && (
2072			attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter)
2073		);
2074		oCol._setter = null;
2075	
2076		oCol.fnGetData = function (rowData, type, meta) {
2077			var innerData = mData( rowData, type, undefined, meta );
2078	
2079			return mRender && type ?
2080				mRender( innerData, type, rowData, meta ) :
2081				innerData;
2082		};
2083		oCol.fnSetData = function ( rowData, val, meta ) {
2084			return _fnSetObjectDataFn( mDataSrc )( rowData, val, meta );
2085		};
2086	
2087		// Indicate if DataTables should read DOM data as an object or array
2088		// Used in _fnGetRowElements
2089		if ( typeof mDataSrc !== 'number' ) {
2090			oSettings._rowReadObject = true;
2091		}
2092	
2093		/* Feature sorting overrides column specific when off */
2094		if ( !oSettings.oFeatures.bSort )
2095		{
2096			oCol.bSortable = false;
2097			th.addClass( oClasses.sSortableNone ); // Have to add class here as order event isn't called
2098		}
2099	
2100		/* Check that the class assignment is correct for sorting */
2101		var bAsc = $.inArray('asc', oCol.asSorting) !== -1;
2102		var bDesc = $.inArray('desc', oCol.asSorting) !== -1;
2103		if ( !oCol.bSortable || (!bAsc && !bDesc) )
2104		{
2105			oCol.sSortingClass = oClasses.sSortableNone;
2106			oCol.sSortingClassJUI = "";
2107		}
2108		else if ( bAsc && !bDesc )
2109		{
2110			oCol.sSortingClass = oClasses.sSortableAsc;
2111			oCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed;
2112		}
2113		else if ( !bAsc && bDesc )
2114		{
2115			oCol.sSortingClass = oClasses.sSortableDesc;
2116			oCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed;
2117		}
2118		else
2119		{
2120			oCol.sSortingClass = oClasses.sSortable;
2121			oCol.sSortingClassJUI = oClasses.sSortJUI;
2122		}
2123	}
2124	
2125	
2126	/**
2127	 * Adjust the table column widths for new data. Note: you would probably want to
2128	 * do a redraw after calling this function!
2129	 *  @param {object} settings dataTables settings object
2130	 *  @memberof DataTable#oApi
2131	 */
2132	function _fnAdjustColumnSizing ( settings )
2133	{
2134		/* Not interested in doing column width calculation if auto-width is disabled */
2135		if ( settings.oFeatures.bAutoWidth !== false )
2136		{
2137			var columns = settings.aoColumns;
2138	
2139			_fnCalculateColumnWidths( settings );
2140			for ( var i=0 , iLen=columns.length ; i<iLen ; i++ )
2141			{
2142				columns[i].nTh.style.width = columns[i].sWidth;
2143			}
2144		}
2145	
2146		var scroll = settings.oScroll;
2147		if ( scroll.sY !== '' || scroll.sX !== '')
2148		{
2149			_fnScrollDraw( settings );
2150		}
2151	
2152		_fnCallbackFire( settings, null, 'column-sizing', [settings] );
2153	}
2154	
2155	
2156	/**
2157	 * Covert the index of a visible column to the index in the data array (take account
2158	 * of hidden columns)
2159	 *  @param {object} oSettings dataTables settings object
2160	 *  @param {int} iMatch Visible column index to lookup
2161	 *  @returns {int} i the data index
2162	 *  @memberof DataTable#oApi
2163	 */
2164	function _fnVisibleToColumnIndex( oSettings, iMatch )
2165	{
2166		var aiVis = _fnGetColumns( oSettings, 'bVisible' );
2167	
2168		return typeof aiVis[iMatch] === 'number' ?
2169			aiVis[iMatch] :
2170			null;
2171	}
2172	
2173	
2174	/**
2175	 * Covert the index of an index in the data array and convert it to the visible
2176	 *   column index (take account of hidden columns)
2177	 *  @param {int} iMatch Column index to lookup
2178	 *  @param {object} oSettings dataTables settings object
2179	 *  @returns {int} i the data index
2180	 *  @memberof DataTable#oApi
2181	 */
2182	function _fnColumnIndexToVisible( oSettings, iMatch )
2183	{
2184		var aiVis = _fnGetColumns( oSettings, 'bVisible' );
2185		var iPos = $.inArray( iMatch, aiVis );
2186	
2187		return iPos !== -1 ? iPos : null;
2188	}
2189	
2190	
2191	/**
2192	 * Get the number of visible columns
2193	 *  @param {object} oSettings dataTables settings object
2194	 *  @returns {int} i the number of visible columns
2195	 *  @memberof DataTable#oApi
2196	 */
2197	function _fnVisbleColumns( oSettings )
2198	{
2199		var vis = 0;
2200	
2201		// No reduce in IE8, use a loop for now
2202		$.each( oSettings.aoColumns, function ( i, col ) {
2203			if ( col.bVisible && $(col.nTh).css('display') !== 'none' ) {
2204				vis++;
2205			}
2206		} );
2207	
2208		return vis;
2209	}
2210	
2211	
2212	/**
2213	 * Get an array of column indexes that match a given property
2214	 *  @param {object} oSettings dataTables settings object
2215	 *  @param {string} sParam Parameter in aoColumns to look for - typically
2216	 *    bVisible or bSearchable
2217	 *  @returns {array} Array of indexes with matched properties
2218	 *  @memberof DataTable#oApi
2219	 */
2220	function _fnGetColumns( oSettings, sParam )
2221	{
2222		var a = [];
2223	
2224		$.map( oSettings.aoColumns, function(val, i) {
2225			if ( val[sParam] ) {
2226				a.push( i );
2227			}
2228		} );
2229	
2230		return a;
2231	}
2232	
2233	
2234	/**
2235	 * Calculate the 'type' of a column
2236	 *  @param {object} settings dataTables settings object
2237	 *  @memberof DataTable#oApi
2238	 */
2239	function _fnColumnTypes ( settings )
2240	{
2241		var columns = settings.aoColumns;
2242		var data = settings.aoData;
2243		var types = DataTable.ext.type.detect;
2244		var i, ien, j, jen, k, ken;
2245		var col, cell, detectedType, cache;
2246	
2247		// For each column, spin over the 
2248		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
2249			col = columns[i];
2250			cache = [];
2251	
2252			if ( ! col.sType && col._sManualType ) {
2253				col.sType = col._sManualType;
2254			}
2255			else if ( ! col.sType ) {
2256				for ( j=0, jen=types.length ; j<jen ; j++ ) {
2257					for ( k=0, ken=data.length ; k<ken ; k++ ) {
2258						// Use a cache array so we only need to get the type data
2259						// from the formatter once (when using multiple detectors)
2260						if ( cache[k] === undefined ) {
2261							cache[k] = _fnGetCellData( settings, k, i, 'type' );
2262						}
2263	
2264						detectedType = types[j]( cache[k], settings );
2265	
2266						// If null, then this type can't apply to this column, so
2267						// rather than testing all cells, break out. There is an
2268						// exception for the last type which is `html`. We need to
2269						// scan all rows since it is possible to mix string and HTML
2270						// types
2271						if ( ! detectedType && j !== types.length-1 ) {
2272							break;
2273						}
2274	
2275						// Only a single match is needed for html type since it is
2276						// bottom of the pile and very similar to string
2277						if ( detectedType === 'html' ) {
2278							break;
2279						}
2280					}
2281	
2282					// Type is valid for all data points in the column - use this
2283					// type
2284					if ( detectedType ) {
2285						col.sType = detectedType;
2286						break;
2287					}
2288				}
2289	
2290				// Fall back - if no type was detected, always use string
2291				if ( ! col.sType ) {
2292					col.sType = 'string';
2293				}
2294			}
2295		}
2296	}
2297	
2298	
2299	/**
2300	 * Take the column definitions and static columns arrays and calculate how
2301	 * they relate to column indexes. The callback function will then apply the
2302	 * definition found for a column to a suitable configuration object.
2303	 *  @param {object} oSettings dataTables settings object
2304	 *  @param {array} aoColDefs The aoColumnDefs array that is to be applied
2305	 *  @param {array} aoCols The aoColumns array that defines columns individually
2306	 *  @param {function} fn Callback function - takes two parameters, the calculated
2307	 *    column index and the definition for that column.
2308	 *  @memberof DataTable#oApi
2309	 */
2310	function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )
2311	{
2312		var i, iLen, j, jLen, k, kLen, def;
2313		var columns = oSettings.aoColumns;
2314	
2315		// Column definitions with aTargets
2316		if ( aoColDefs )
2317		{
2318			/* Loop over the definitions array - loop in reverse so first instance has priority */
2319			for ( i=aoColDefs.length-1 ; i>=0 ; i-- )
2320			{
2321				def = aoColDefs[i];
2322	
2323				/* Each definition can target multiple columns, as it is an array */
2324				var aTargets = def.targets !== undefined ?
2325					def.targets :
2326					def.aTargets;
2327	
2328				if ( ! $.isArray( aTargets ) )
2329				{
2330					aTargets = [ aTargets ];
2331				}
2332	
2333				for ( j=0, jLen=aTargets.length ; j<jLen ; j++ )
2334				{
2335					if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 )
2336					{
2337						/* Add columns that we don't yet know about */
2338						while( columns.length <= aTargets[j] )
2339						{
2340							_fnAddColumn( oSettings );
2341						}
2342	
2343						/* Integer, basic index */
2344						fn( aTargets[j], def );
2345					}
2346					else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 )
2347					{
2348						/* Negative integer, right to left column counting */
2349						fn( columns.length+aTargets[j], def );
2350					}
2351					else if ( typeof aTargets[j] === 'string' )
2352					{
2353						/* Class name matching on TH element */
2354						for ( k=0, kLen=columns.length ; k<kLen ; k++ )
2355						{
2356							if ( aTargets[j] == "_all" ||
2357							     $(columns[k].nTh).hasClass( aTargets[j] ) )
2358							{
2359								fn( k, def );
2360							}
2361						}
2362					}
2363				}
2364			}
2365		}
2366	
2367		// Statically defined columns array
2368		if ( aoCols )
2369		{
2370			for ( i=0, iLen=aoCols.length ; i<iLen ; i++ )
2371			{
2372				fn( i, aoCols[i] );
2373			}
2374		}
2375	}
2376	
2377	/**
2378	 * Add a data array to the table, creating DOM node etc. This is the parallel to
2379	 * _fnGatherData, but for adding rows from a Javascript source, rather than a
2380	 * DOM source.
2381	 *  @param {object} oSettings dataTables settings object
2382	 *  @param {array} aData data array to be added
2383	 *  @param {node} [nTr] TR element to add to the table - optional. If not given,
2384	 *    DataTables will create a row automatically
2385	 *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
2386	 *    if nTr is.
2387	 *  @returns {int} >=0 if successful (index of new aoData entry), -1 if failed
2388	 *  @memberof DataTable#oApi
2389	 */
2390	function _fnAddData ( oSettings, aDataIn, nTr, anTds )
2391	{
2392		/* Create the object for storing information about this new row */
2393		var iRow = oSettings.aoData.length;
2394		var oData = $.extend( true, {}, DataTable.models.oRow, {
2395			src: nTr ? 'dom' : 'data',
2396			idx: iRow
2397		} );
2398	
2399		oData._aData = aDataIn;
2400		oSettings.aoData.push( oData );
2401	
2402		/* Create the cells */
2403		var nTd, sThisType;
2404		var columns = oSettings.aoColumns;
2405	
2406		// Invalidate the column types as the new data needs to be revalidated
2407		for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
2408		{
2409			columns[i].sType = null;
2410		}
2411	
2412		/* Add to the display array */
2413		oSettings.aiDisplayMaster.push( iRow );
2414	
2415		var id = oSettings.rowIdFn( aDataIn );
2416		if ( id !== undefined ) {
2417			oSettings.aIds[ id ] = oData;
2418		}
2419	
2420		/* Create the DOM information, or register it if already present */
2421		if ( nTr || ! oSettings.oFeatures.bDeferRender )
2422		{
2423			_fnCreateTr( oSettings, iRow, nTr, anTds );
2424		}
2425	
2426		return iRow;
2427	}
2428	
2429	
2430	/**
2431	 * Add one or more TR elements to the table. Generally we'd expect to
2432	 * use this for reading data from a DOM sourced table, but it could be
2433	 * used for an TR element. Note that if a TR is given, it is used (i.e.
2434	 * it is not cloned).
2435	 *  @param {object} settings dataTables settings object
2436	 *  @param {array|node|jQuery} trs The TR element(s) to add to the table
2437	 *  @returns {array} Array of indexes for the added rows
2438	 *  @memberof DataTable#oApi
2439	 */
2440	function _fnAddTr( settings, trs )
2441	{
2442		var row;
2443	
2444		// Allow an individual node to be passed in
2445		if ( ! (trs instanceof $) ) {
2446			trs = $(trs);
2447		}
2448	
2449		return trs.map( function (i, el) {
2450			row = _fnGetRowElements( settings, el );
2451			return _fnAddData( settings, row.data, el, row.cells );
2452		} );
2453	}
2454	
2455	
2456	/**
2457	 * Take a TR element and convert it to an index in aoData
2458	 *  @param {object} oSettings dataTables settings object
2459	 *  @param {node} n the TR element to find
2460	 *  @returns {int} index if the node is found, null if not
2461	 *  @memberof DataTable#oApi
2462	 */
2463	function _fnNodeToDataIndex( oSettings, n )
2464	{
2465		return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null;
2466	}
2467	
2468	
2469	/**
2470	 * Take a TD element and convert it into a column data index (not the visible index)
2471	 *  @param {object} oSettings dataTables settings object
2472	 *  @param {int} iRow The row number the TD/TH can be found in
2473	 *  @param {node} n The TD/TH element to find
2474	 *  @returns {int} index if the node is found, -1 if not
2475	 *  @memberof DataTable#oApi
2476	 */
2477	function _fnNodeToColumnIndex( oSettings, iRow, n )
2478	{
2479		return $.inArray( n, oSettings.aoData[ iRow ].anCells );
2480	}
2481	
2482	
2483	/**
2484	 * Get the data for a given cell from the internal cache, taking into account data mapping
2485	 *  @param {object} settings dataTables settings object
2486	 *  @param {int} rowIdx aoData row id
2487	 *  @param {int} colIdx Column index
2488	 *  @param {string} type data get type ('display', 'type' 'filter' 'sort')
2489	 *  @returns {*} Cell data
2490	 *  @memberof DataTable#oApi
2491	 */
2492	function _fnGetCellData( settings, rowIdx, colIdx, type )
2493	{
2494		var draw           = settings.iDraw;
2495		var col            = settings.aoColumns[colIdx];
2496		var rowData        = settings.aoData[rowIdx]._aData;
2497		var defaultContent = col.sDefaultContent;
2498		var cellData       = col.fnGetData( rowData, type, {
2499			settings: settings,
2500			row:      rowIdx,
2501			col:      colIdx
2502		} );
2503	
2504		if ( cellData === undefined ) {
2505			if ( settings.iDrawError != draw && defaultContent === null ) {
2506				_fnLog( settings, 0, "Requested unknown parameter "+
2507					(typeof col.mData=='function' ? '{function}' : "'"+col.mData+"'")+
2508					" for row "+rowIdx+", column "+colIdx, 4 );
2509				settings.iDrawError = draw;
2510			}
2511			return defaultContent;
2512		}
2513	
2514		// When the data source is null and a specific data type is requested (i.e.
2515		// not the original data), we can use default column data
2516		if ( (cellData === rowData || cellData === null) && defaultContent !== null && type !== undefined ) {
2517			cellData = defaultContent;
2518		}
2519		else if ( typeof cellData === 'function' ) {
2520			// If the data source is a function, then we run it and use the return,
2521			// executing in the scope of the data object (for instances)
2522			return cellData.call( rowData );
2523		}
2524	
2525		if ( cellData === null && type == 'display' ) {
2526			return '';
2527		}
2528		return cellData;
2529	}
2530	
2531	
2532	/**
2533	 * Set the value for a specific cell, into the internal data cache
2534	 *  @param {object} settings dataTables settings object
2535	 *  @param {int} rowIdx aoData row id
2536	 *  @param {int} colIdx Column index
2537	 *  @param {*} val Value to set
2538	 *  @memberof DataTable#oApi
2539	 */
2540	function _fnSetCellData( settings, rowIdx, colIdx, val )
2541	{
2542		var col     = settings.aoColumns[colIdx];
2543		var rowData = settings.aoData[rowIdx]._aData;
2544	
2545		col.fnSetData( rowData, val, {
2546			settings: settings,
2547			row:      rowIdx,
2548			col:      colIdx
2549		}  );
2550	}
2551	
2552	
2553	// Private variable that is used to match action syntax in the data property object
2554	var __reArray = /\[.*?\]$/;
2555	var __reFn = /\(\)$/;
2556	
2557	/**
2558	 * Split string on periods, taking into account escaped periods
2559	 * @param  {string} str String to split
2560	 * @return {array} Split string
2561	 */
2562	function _fnSplitObjNotation( str )
2563	{
2564		return $.map( str.match(/(\\.|[^\.])+/g) || [''], function ( s ) {
2565			return s.replace(/\\\./g, '.');
2566		} );
2567	}
2568	
2569	
2570	/**
2571	 * Return a function that can be used to get data from a source object, taking
2572	 * into account the ability to use nested objects as a source
2573	 *  @param {string|int|function} mSource The data source for the object
2574	 *  @returns {function} Data get function
2575	 *  @memberof DataTable#oApi
2576	 */
2577	function _fnGetObjectDataFn( mSource )
2578	{
2579		if ( $.isPlainObject( mSource ) )
2580		{
2581			/* Build an object of get functions, and wrap them in a single call */
2582			var o = {};
2583			$.each( mSource, function (key, val) {
2584				if ( val ) {
2585					o[key] = _fnGetObjectDataFn( val );
2586				}
2587			} );
2588	
2589			return function (data, type, row, meta) {
2590				var t = o[type] || o._;
2591				return t !== undefined ?
2592					t(data, type, row, meta) :
2593					data;
2594			};
2595		}
2596		else if ( mSource === null )
2597		{
2598			/* Give an empty string for rendering / sorting etc */
2599			return function (data) { // type, row and meta also passed, but not used
2600				return data;
2601			};
2602		}
2603		else if ( typeof mSource === 'function' )
2604		{
2605			return function (data, type, row, meta) {
2606				return mSource( data, type, row, meta );
2607			};
2608		}
2609		else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
2610			      mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
2611		{
2612			/* If there is a . in the source string then the data source is in a
2613			 * nested object so we loop over the data for each level to get the next
2614			 * level down. On each loop we test for undefined, and if found immediately
2615			 * return. This allows entire objects to be missing and sDefaultContent to
2616			 * be used if defined, rather than throwing an error
2617			 */
2618			var fetchData = function (data, type, src) {
2619				var arrayNotation, funcNotation, out, innerSrc;
2620	
2621				if ( src !== "" )
2622				{
2623					var a = _fnSplitObjNotation( src );
2624	
2625					for ( var i=0, iLen=a.length ; i<iLen ; i++ )
2626					{
2627						// Check if we are dealing with special notation
2628						arrayNotation = a[i].match(__reArray);
2629						funcNotation = a[i].match(__reFn);
2630	
2631						if ( arrayNotation )
2632						{
2633							// Array notation
2634							a[i] = a[i].replace(__reArray, '');
2635	
2636							// Condition allows simply [] to be passed in
2637							if ( a[i] !== "" ) {
2638								data = data[ a[i] ];
2639							}
2640							out = [];
2641	
2642							// Get the remainder of the nested object to get
2643							a.splice( 0, i+1 );
2644							innerSrc = a.join('.');
2645	
2646							// Traverse each entry in the array getting the properties requested
2647							if ( $.isArray( data ) ) {
2648								for ( var j=0, jLen=data.length ; j<jLen ; j++ ) {
2649									out.push( fetchData( data[j], type, innerSrc ) );
2650								}
2651							}
2652	
2653							// If a string is given in between the array notation indicators, that
2654							// is used to join the strings together, otherwise an array is returned
2655							var join = arrayNotation[0].substring(1, arrayNotation[0].length-1);
2656							data = (join==="") ? out : out.join(join);
2657	
2658							// The inner call to fetchData has already traversed through the remainder
2659							// of the source requested, so we exit from the loop
2660							break;
2661						}
2662						else if ( funcNotation )
2663						{
2664							// Function call
2665							a[i] = a[i].replace(__reFn, '');
2666							data = data[ a[i] ]();
2667							continue;
2668						}
2669	
2670						if ( data === null || data[ a[i] ] === undefined )
2671						{
2672							return undefined;
2673						}
2674						data = data[ a[i] ];
2675					}
2676				}
2677	
2678				return data;
2679			};
2680	
2681			return function (data, type) { // row and meta also passed, but not used
2682				return fetchData( data, type, mSource );
2683			};
2684		}
2685		else
2686		{
2687			/* Array or flat object mapping */
2688			return function (data, type) { // row and meta also passed, but not used
2689				return data[mSource];
2690			};
2691		}
2692	}
2693	
2694	
2695	/**
2696	 * Return a function that can be used to set data from a source object, taking
2697	 * into account the ability to use nested objects as a source
2698	 *  @param {string|int|function} mSource The data source for the object
2699	 *  @returns {function} Data set function
2700	 *  @memberof DataTable#oApi
2701	 */
2702	function _fnSetObjectDataFn( mSource )
2703	{
2704		if ( $.isPlainObject( mSource ) )
2705		{
2706			/* Unlike get, only the underscore (global) option is used for for
2707			 * setting data since we don't know the type here. This is why an object
2708			 * option is not documented for `mData` (which is read/write), but it is
2709			 * for `mRender` which is read only.
2710			 */
2711			return _fnSetObjectDataFn( mSource._ );
2712		}
2713		else if ( mSource === null )
2714		{
2715			/* Nothing to do when the data source is null */
2716			return function () {};
2717		}
2718		else if ( typeof mSource === 'function' )
2719		{
2720			return function (data, val, meta) {
2721				mSource( data, 'set', val, meta );
2722			};
2723		}
2724		else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
2725			      mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
2726		{
2727			/* Like the get, we need to get data from a nested object */
2728			var setData = function (data, val, src) {
2729				var a = _fnSplitObjNotation( src ), b;
2730				var aLast = a[a.length-1];
2731				var arrayNotation, funcNotation, o, innerSrc;
2732	
2733				for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ )
2734				{
2735					// Check if we are dealing with an array notation request
2736					arrayNotation = a[i].match(__reArray);
2737					funcNotation = a[i].match(__reFn);
2738	
2739					if ( arrayNotation )
2740					{
2741						a[i] = a[i].replace(__reArray, '');
2742						data[ a[i] ] = [];
2743	
2744						// Get the remainder of the nested object to set so we can recurse
2745						b = a.slice();
2746						b.splice( 0, i+1 );
2747						innerSrc = b.join('.');
2748	
2749						// Traverse each entry in the array setting the properties requested
2750						if ( $.isArray( val ) )
2751						{
2752							for ( var j=0, jLen=val.length ; j<jLen ; j++ )
2753							{
2754								o = {};
2755								setData( o, val[j], innerSrc );
2756								data[ a[i] ].push( o );
2757							}
2758						}
2759						else
2760						{
2761							// We've been asked to save data to an array, but it
2762							// isn't array data to be saved. Best that can be done
2763							// is to just save the value.
2764							data[ a[i] ] = val;
2765						}
2766	
2767						// The inner call to setData has already traversed through the remainder
2768						// of the source and has set the data, thus we can exit here
2769						return;
2770					}
2771					else if ( funcNotation )
2772					{
2773						// Function call
2774						a[i] = a[i].replace(__reFn, '');
2775						data = data[ a[i] ]( val );
2776					}
2777	
2778					// If the nested object doesn't currently exist - since we are
2779					// trying to set the value - create it
2780					if ( data[ a[i] ] === null || data[ a[i] ] === undefined )
2781					{
2782						data[ a[i] ] = {};
2783					}
2784					data = data[ a[i] ];
2785				}
2786	
2787				// Last item in the input - i.e, the actual set
2788				if ( aLast.match(__reFn ) )
2789				{
2790					// Function call
2791					data = data[ aLast.replace(__reFn, '') ]( val );
2792				}
2793				else
2794				{
2795					// If array notation is used, we just want to strip it and use the property name
2796					// and assign the value. If it isn't used, then we get the result we want anyway
2797					data[ aLast.replace(__reArray, '') ] = val;
2798				}
2799			};
2800	
2801			return function (data, val) { // meta is also passed in, but not used
2802				return setData( data, val, mSource );
2803			};
2804		}
2805		else
2806		{
2807			/* Array or flat object mapping */
2808			return function (data, val) { // meta is also passed in, but not used
2809				data[mSource] = val;
2810			};
2811		}
2812	}
2813	
2814	
2815	/**
2816	 * Return an array with the full table data
2817	 *  @param {object} oSettings dataTables settings object
2818	 *  @returns array {array} aData Master data array
2819	 *  @memberof DataTable#oApi
2820	 */
2821	function _fnGetDataMaster ( settings )
2822	{
2823		return _pluck( settings.aoData, '_aData' );
2824	}
2825	
2826	
2827	/**
2828	 * Nuke the table
2829	 *  @param {object} oSettings dataTables settings object
2830	 *  @memberof DataTable#oApi
2831	 */
2832	function _fnClearTable( settings )
2833	{
2834		settings.aoData.length = 0;
2835		settings.aiDisplayMaster.length = 0;
2836		settings.aiDisplay.length = 0;
2837		settings.aIds = {};
2838	}
2839	
2840	
2841	 /**
2842	 * Take an array of integers (index array) and remove a target integer (value - not
2843	 * the key!)
2844	 *  @param {array} a Index array to target
2845	 *  @param {int} iTarget value to find
2846	 *  @memberof DataTable#oApi
2847	 */
2848	function _fnDeleteIndex( a, iTarget, splice )
2849	{
2850		var iTargetIndex = -1;
2851	
2852		for ( var i=0, iLen=a.length ; i<iLen ; i++ )
2853		{
2854			if ( a[i] == iTarget )
2855			{
2856				iTargetIndex = i;
2857			}
2858			else if ( a[i] > iTarget )
2859			{
2860				a[i]--;
2861			}
2862		}
2863	
2864		if ( iTargetIndex != -1 && splice === undefined )
2865		{
2866			a.splice( iTargetIndex, 1 );
2867		}
2868	}
2869	
2870	
2871	/**
2872	 * Mark cached data as invalid such that a re-read of the data will occur when
2873	 * the cached data is next requested. Also update from the data source object.
2874	 *
2875	 * @param {object} settings DataTables settings object
2876	 * @param {int}    rowIdx   Row index to invalidate
2877	 * @param {string} [src]    Source to invalidate from: undefined, 'auto', 'dom'
2878	 *     or 'data'
2879	 * @param {int}    [colIdx] Column index to invalidate. If undefined the whole
2880	 *     row will be invalidated
2881	 * @memberof DataTable#oApi
2882	 *
2883	 * @todo For the modularisation of v1.11 this will need to become a callback, so
2884	 *   the sort and filter methods can subscribe to it. That will required
2885	 *   initialisation options for sorting, which is why it is not already baked in
2886	 */
2887	function _fnInvalidate( settings, rowIdx, src, colIdx )
2888	{
2889		var row = settings.aoData[ rowIdx ];
2890		var i, ien;
2891		var cellWrite = function ( cell, col ) {
2892			// This is very frustrating, but in IE if you just write directly
2893			// to innerHTML, and elements that are overwritten are GC'ed,
2894			// even if there is a reference to them elsewhere
2895			while ( cell.childNodes.length ) {
2896				cell.removeChild( cell.firstChild );
2897			}
2898	
2899			cell.innerHTML = _fnGetCellData( settings, rowIdx, col, 'display' );
2900		};
2901	
2902		// Are we reading last data from DOM or the data object?
2903		if ( src === 'dom' || ((! src || src === 'auto') && row.src === 'dom') ) {
2904			// Read the data from the DOM
2905			row._aData = _fnGetRowElements(
2906					settings, row, colIdx, colIdx === undefined ? undefined : row._aData
2907				)
2908				.data;
2909		}
2910		else {
2911			// Reading from data object, update the DOM
2912			var cells = row.anCells;
2913	
2914			if ( cells ) {
2915				if ( colIdx !== undefined ) {
2916					cellWrite( cells[colIdx], colIdx );
2917				}
2918				else {
2919					for ( i=0, ien=cells.length ; i<ien ; i++ ) {
2920						cellWrite( cells[i], i );
2921					}
2922				}
2923			}
2924		}
2925	
2926		// For both row and cell invalidation, the cached data for sorting and
2927		// filtering is nulled out
2928		row._aSortData = null;
2929		row._aFilterData = null;
2930	
2931		// Invalidate the type for a specific column (if given) or all columns since
2932		// the data might have changed
2933		var cols = settings.aoColumns;
2934		if ( colIdx !== undefined ) {
2935			cols[ colIdx ].sType = null;
2936		}
2937		else {
2938			for ( i=0, ien=cols.length ; i<ien ; i++ ) {
2939				cols[i].sType = null;
2940			}
2941	
2942			// Update DataTables special `DT_*` attributes for the row
2943			_fnRowAttributes( settings, row );
2944		}
2945	}
2946	
2947	
2948	/**
2949	 * Build a data source object from an HTML row, reading the contents of the
2950	 * cells that are in the row.
2951	 *
2952	 * @param {object} settings DataTables settings object
2953	 * @param {node|object} TR element from which to read data or existing row
2954	 *   object from which to re-read the data from the cells
2955	 * @param {int} [colIdx] Optional column index
2956	 * @param {array|object} [d] Data source object. If `colIdx` is given then this
2957	 *   parameter should also be given and will be used to write the data into.
2958	 *   Only the column in question will be written
2959	 * @returns {object} Object with two parameters: `data` the data read, in
2960	 *   document order, and `cells` and array of nodes (they can be useful to the
2961	 *   caller, so rather than needing a second traversal to get them, just return
2962	 *   them from here).
2963	 * @memberof DataTable#oApi
2964	 */
2965	function _fnGetRowElements( settings, row, colIdx, d )
2966	{
2967		var
2968			tds = [],
2969			td = row.firstChild,
2970			name, col, o, i=0, contents,
2971			columns = settings.aoColumns,
2972			objectRead = settings._rowReadObject;
2973	
2974		// Allow the data object to be passed in, or construct
2975		d = d !== undefined ?
2976			d :
2977			objectRead ?
2978				{} :
2979				[];
2980	
2981		var attr = function ( str, td  ) {
2982			if ( typeof str === 'string' ) {
2983				var idx = str.indexOf('@');
2984	
2985				if ( idx !== -1 ) {
2986					var attr = str.substring( idx+1 );
2987					var setter = _fnSetObjectDataFn( str );
2988					setter( d, td.getAttribute( attr ) );
2989				}
2990			}
2991		};
2992	
2993		// Read data from a cell and store into the data object
2994		var cellProcess = function ( cell ) {
2995			if ( colIdx === undefined || colIdx === i ) {
2996				col = columns[i];
2997				contents = $.trim(cell.innerHTML);
2998	
2999				if ( col && col._bAttrSrc ) {
3000					var setter = _fnSetObjectDataFn( col.mData._ );
3001					setter( d, contents );
3002	
3003					attr( col.mData.sort, cell );
3004					attr( col.mData.type, cell );
3005					attr( col.mData.filter, cell );
3006				}
3007				else {
3008					// Depending on the `data` option for the columns the data can
3009					// be read to either an object or an array.
vendor: 11,053 bytes, lines 3010-3433
3010					if ( objectRead ) {
3011						if ( ! col._setter ) {
3012							// Cache the setter function
3013							col._setter = _fnSetObjectDataFn( col.mData );
3014						}
3015						col._setter( d, contents );
3016					}
3017					else {
3018						d[i] = contents;
3019					}
3020				}
3021			}
3022	
3023			i++;
3024		};
3025	
3026		if ( td ) {
3027			// `tr` element was passed in
3028			while ( td ) {
3029				name = td.nodeName.toUpperCase();
3030	
3031				if ( name == "TD" || name == "TH" ) {
3032					cellProcess( td );
3033					tds.push( td );
3034				}
3035	
3036				td = td.nextSibling;
3037			}
3038		}
3039		else {
3040			// Existing row object passed in
3041			tds = row.anCells;
3042	
3043			for ( var j=0, jen=tds.length ; j<jen ; j++ ) {
3044				cellProcess( tds[j] );
3045			}
3046		}
3047	
3048		// Read the ID from the DOM if present
3049		var rowNode = row.firstChild ? row : row.nTr;
3050	
3051		if ( rowNode ) {
3052			var id = rowNode.getAttribute( 'id' );
3053	
3054			if ( id ) {
3055				_fnSetObjectDataFn( settings.rowId )( d, id );
3056			}
3057		}
3058	
3059		return {
3060			data: d,
3061			cells: tds
3062		};
3063	}
3064	/**
3065	 * Create a new TR element (and it's TD children) for a row
3066	 *  @param {object} oSettings dataTables settings object
3067	 *  @param {int} iRow Row to consider
3068	 *  @param {node} [nTrIn] TR element to add to the table - optional. If not given,
3069	 *    DataTables will create a row automatically
3070	 *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
3071	 *    if nTr is.
3072	 *  @memberof DataTable#oApi
3073	 */
3074	function _fnCreateTr ( oSettings, iRow, nTrIn, anTds )
3075	{
3076		var
3077			row = oSettings.aoData[iRow],
3078			rowData = row._aData,
3079			cells = [],
3080			nTr, nTd, oCol,
3081			i, iLen, create;
3082	
3083		if ( row.nTr === null )
3084		{
3085			nTr = nTrIn || document.createElement('tr');
3086	
3087			row.nTr = nTr;
3088			row.anCells = cells;
3089	
3090			/* Use a private property on the node to allow reserve mapping from the node
3091			 * to the aoData array for fast look up
3092			 */
3093			nTr._DT_RowIndex = iRow;
3094	
3095			/* Special parameters can be given by the data source to be used on the row */
3096			_fnRowAttributes( oSettings, row );
3097	
3098			/* Process each column */
3099			for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
3100			{
3101				oCol = oSettings.aoColumns[i];
3102				create = nTrIn ? false : true;
3103	
3104				nTd = create ? document.createElement( oCol.sCellType ) : anTds[i];
3105				nTd._DT_CellIndex = {
3106					row: iRow,
3107					column: i
3108				};
3109				
3110				cells.push( nTd );
3111	
3112				// Need to create the HTML if new, or if a rendering function is defined
3113				if ( create || ((!nTrIn || oCol.mRender || oCol.mData !== i) &&
3114					 (!$.isPlainObject(oCol.mData) || oCol.mData._ !== i+'.display')
3115				)) {
3116					nTd.innerHTML = _fnGetCellData( oSettings, iRow, i, 'display' );
3117				}
3118	
3119				/* Add user defined class */
3120				if ( oCol.sClass )
3121				{
3122					nTd.className += ' '+oCol.sClass;
3123				}
3124	
3125				// Visibility - add or remove as required
3126				if ( oCol.bVisible && ! nTrIn )
3127				{
3128					nTr.appendChild( nTd );
3129				}
3130				else if ( ! oCol.bVisible && nTrIn )
3131				{
3132					nTd.parentNode.removeChild( nTd );
3133				}
3134	
3135				if ( oCol.fnCreatedCell )
3136				{
3137					oCol.fnCreatedCell.call( oSettings.oInstance,
3138						nTd, _fnGetCellData( oSettings, iRow, i ), rowData, iRow, i
3139					);
3140				}
3141			}
3142	
3143			_fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow, cells] );
3144		}
3145	
3146		// Remove once webkit bug 131819 and Chromium bug 365619 have been resolved
3147		// and deployed
3148		row.nTr.setAttribute( 'role', 'row' );
3149	}
3150	
3151	
3152	/**
3153	 * Add attributes to a row based on the special `DT_*` parameters in a data
3154	 * source object.
3155	 *  @param {object} settings DataTables settings object
3156	 *  @param {object} DataTables row object for the row to be modified
3157	 *  @memberof DataTable#oApi
3158	 */
3159	function _fnRowAttributes( settings, row )
3160	{
3161		var tr = row.nTr;
3162		var data = row._aData;
3163	
3164		if ( tr ) {
3165			var id = settings.rowIdFn( data );
3166	
3167			if ( id ) {
3168				tr.id = id;
3169			}
3170	
3171			if ( data.DT_RowClass ) {
3172				// Remove any classes added by DT_RowClass before
3173				var a = data.DT_RowClass.split(' ');
3174				row.__rowc = row.__rowc ?
3175					_unique( row.__rowc.concat( a ) ) :
3176					a;
3177	
3178				$(tr)
3179					.removeClass( row.__rowc.join(' ') )
3180					.addClass( data.DT_RowClass );
3181			}
3182	
3183			if ( data.DT_RowAttr ) {
3184				$(tr).attr( data.DT_RowAttr );
3185			}
3186	
3187			if ( data.DT_RowData ) {
3188				$(tr).data( data.DT_RowData );
3189			}
3190		}
3191	}
3192	
3193	
3194	/**
3195	 * Create the HTML header for the table
3196	 *  @param {object} oSettings dataTables settings object
3197	 *  @memberof DataTable#oApi
3198	 */
3199	function _fnBuildHead( oSettings )
3200	{
3201		var i, ien, cell, row, column;
3202		var thead = oSettings.nTHead;
3203		var tfoot = oSettings.nTFoot;
3204		var createHeader = $('th, td', thead).length === 0;
3205		var classes = oSettings.oClasses;
3206		var columns = oSettings.aoColumns;
3207	
3208		if ( createHeader ) {
3209			row = $('<tr/>').appendTo( thead );
3210		}
3211	
3212		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
3213			column = columns[i];
3214			cell = $( column.nTh ).addClass( column.sClass );
3215	
3216			if ( createHeader ) {
3217				cell.appendTo( row );
3218			}
3219	
3220			// 1.11 move into sorting
3221			if ( oSettings.oFeatures.bSort ) {
3222				cell.addClass( column.sSortingClass );
3223	
3224				if ( column.bSortable !== false ) {
3225					cell
3226						.attr( 'tabindex', oSettings.iTabIndex )
3227						.attr( 'aria-controls', oSettings.sTableId );
3228	
3229					_fnSortAttachListener( oSettings, column.nTh, i );
3230				}
3231			}
3232	
3233			if ( column.sTitle != cell[0].innerHTML ) {
3234				cell.html( column.sTitle );
3235			}
3236	
3237			_fnRenderer( oSettings, 'header' )(
3238				oSettings, cell, column, classes
3239			);
3240		}
3241	
3242		if ( createHeader ) {
3243			_fnDetectHeader( oSettings.aoHeader, thead );
3244		}
3245		
3246		/* ARIA role for the rows */
3247	 	$(thead).find('>tr').attr('role', 'row');
3248	
3249		/* Deal with the footer - add classes if required */
3250		$(thead).find('>tr>th, >tr>td').addClass( classes.sHeaderTH );
3251		$(tfoot).find('>tr>th, >tr>td').addClass( classes.sFooterTH );
3252	
3253		// Cache the footer cells. Note that we only take the cells from the first
3254		// row in the footer. If there is more than one row the user wants to
3255		// interact with, they need to use the table().foot() method. Note also this
3256		// allows cells to be used for multiple columns using colspan
3257		if ( tfoot !== null ) {
3258			var cells = oSettings.aoFooter[0];
3259	
3260			for ( i=0, ien=cells.length ; i<ien ; i++ ) {
3261				column = columns[i];
3262				column.nTf = cells[i].cell;
3263	
3264				if ( column.sClass ) {
3265					$(column.nTf).addClass( column.sClass );
3266				}
3267			}
3268		}
3269	}
3270	
3271	
3272	/**
3273	 * Draw the header (or footer) element based on the column visibility states. The
3274	 * methodology here is to use the layout array from _fnDetectHeader, modified for
3275	 * the instantaneous column visibility, to construct the new layout. The grid is
3276	 * traversed over cell at a time in a rows x columns grid fashion, although each
3277	 * cell insert can cover multiple elements in the grid - which is tracks using the
3278	 * aApplied array. Cell inserts in the grid will only occur where there isn't
3279	 * already a cell in that position.
3280	 *  @param {object} oSettings dataTables settings object
3281	 *  @param array {objects} aoSource Layout array from _fnDetectHeader
3282	 *  @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,
3283	 *  @memberof DataTable#oApi
3284	 */
3285	function _fnDrawHead( oSettings, aoSource, bIncludeHidden )
3286	{
3287		var i, iLen, j, jLen, k, kLen, n, nLocalTr;
3288		var aoLocal = [];
3289		var aApplied = [];
3290		var iColumns = oSettings.aoColumns.length;
3291		var iRowspan, iColspan;
3292	
3293		if ( ! aoSource )
3294		{
3295			return;
3296		}
3297	
3298		if (  bIncludeHidden === undefined )
3299		{
3300			bIncludeHidden = false;
3301		}
3302	
3303		/* Make a copy of the master layout array, but without the visible columns in it */
3304		for ( i=0, iLen=aoSource.length ; i<iLen ; i++ )
3305		{
3306			aoLocal[i] = aoSource[i].slice();
3307			aoLocal[i].nTr = aoSource[i].nTr;
3308	
3309			/* Remove any columns which are currently hidden */
3310			for ( j=iColumns-1 ; j>=0 ; j-- )
3311			{
3312				if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden )
3313				{
3314					aoLocal[i].splice( j, 1 );
3315				}
3316			}
3317	
3318			/* Prep the applied array - it needs an element for each row */
3319			aApplied.push( [] );
3320		}
3321	
3322		for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ )
3323		{
3324			nLocalTr = aoLocal[i].nTr;
3325	
3326			/* All cells are going to be replaced, so empty out the row */
3327			if ( nLocalTr )
3328			{
3329				while( (n = nLocalTr.firstChild) )
3330				{
3331					nLocalTr.removeChild( n );
3332				}
3333			}
3334	
3335			for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ )
3336			{
3337				iRowspan = 1;
3338				iColspan = 1;
3339	
3340				/* Check to see if there is already a cell (row/colspan) covering our target
3341				 * insert point. If there is, then there is nothing to do.
3342				 */
3343				if ( aApplied[i][j] === undefined )
3344				{
3345					nLocalTr.appendChild( aoLocal[i][j].cell );
3346					aApplied[i][j] = 1;
3347	
3348					/* Expand the cell to cover as many rows as needed */
3349					while ( aoLocal[i+iRowspan] !== undefined &&
3350					        aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell )
3351					{
3352						aApplied[i+iRowspan][j] = 1;
3353						iRowspan++;
3354					}
3355	
3356					/* Expand the cell to cover as many columns as needed */
3357					while ( aoLocal[i][j+iColspan] !== undefined &&
3358					        aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell )
3359					{
3360						/* Must update the applied array over the rows for the columns */
3361						for ( k=0 ; k<iRowspan ; k++ )
3362						{
3363							aApplied[i+k][j+iColspan] = 1;
3364						}
3365						iColspan++;
3366					}
3367	
3368					/* Do the actual expansion in the DOM */
3369					$(aoLocal[i][j].cell)
3370						.attr('rowspan', iRowspan)
3371						.attr('colspan', iColspan);
3372				}
3373			}
3374		}
3375	}
3376	
3377	
3378	/**
3379	 * Insert the required TR nodes into the table for display
3380	 *  @param {object} oSettings dataTables settings object
3381	 *  @memberof DataTable#oApi
3382	 */
3383	function _fnDraw( oSettings )
3384	{
3385		/* Provide a pre-callback function which can be used to cancel the draw is false is returned */
3386		var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] );
3387		if ( $.inArray( false, aPreDraw ) !== -1 )
3388		{
3389			_fnProcessingDisplay( oSettings, false );
3390			return;
3391		}
3392	
3393		var i, iLen, n;
3394		var anRows = [];
3395		var iRowCount = 0;
3396		var asStripeClasses = oSettings.asStripeClasses;
3397		var iStripes = asStripeClasses.length;
3398		var iOpenRows = oSettings.aoOpenRows.length;
3399		var oLang = oSettings.oLanguage;
3400		var iInitDisplayStart = oSettings.iInitDisplayStart;
3401		var bServerSide = _fnDataSource( oSettings ) == 'ssp';
3402		var aiDisplay = oSettings.aiDisplay;
3403	
3404		oSettings.bDrawing = true;
3405	
3406		/* Check and see if we have an initial draw position from state saving */
3407		if ( iInitDisplayStart !== undefined && iInitDisplayStart !== -1 )
3408		{
3409			oSettings._iDisplayStart = bServerSide ?
3410				iInitDisplayStart :
3411				iInitDisplayStart >= oSettings.fnRecordsDisplay() ?
3412					0 :
3413					iInitDisplayStart;
3414	
3415			oSettings.iInitDisplayStart = -1;
3416		}
3417	
3418		var iDisplayStart = oSettings._iDisplayStart;
3419		var iDisplayEnd = oSettings.fnDisplayEnd();
3420	
3421		/* Server-side processing draw intercept */
3422		if ( oSettings.bDeferLoading )
3423		{
3424			oSettings.bDeferLoading = false;
3425			oSettings.iDraw++;
3426			_fnProcessingDisplay( oSettings, false );
3427		}
3428		else if ( !bServerSide )
3429		{
3430			oSettings.iDraw++;
3431		}
3432		else if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) )
3433		{
vendor: 10,503 bytes, lines 3433-3822
3433
3434			return;
3435		}
3436	
3437		if ( aiDisplay.length !== 0 )
3438		{
3439			var iStart = bServerSide ? 0 : iDisplayStart;
3440			var iEnd = bServerSide ? oSettings.aoData.length : iDisplayEnd;
3441	
3442			for ( var j=iStart ; j<iEnd ; j++ )
3443			{
3444				var iDataIndex = aiDisplay[j];
3445				var aoData = oSettings.aoData[ iDataIndex ];
3446				if ( aoData.nTr === null )
3447				{
3448					_fnCreateTr( oSettings, iDataIndex );
3449				}
3450	
3451				var nRow = aoData.nTr;
3452	
3453				/* Remove the old striping classes and then add the new one */
3454				if ( iStripes !== 0 )
3455				{
3456					var sStripe = asStripeClasses[ iRowCount % iStripes ];
3457					if ( aoData._sRowStripe != sStripe )
3458					{
3459						$(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe );
3460						aoData._sRowStripe = sStripe;
3461					}
3462				}
3463	
3464				// Row callback functions - might want to manipulate the row
3465				// iRowCount and j are not currently documented. Are they at all
3466				// useful?
3467				_fnCallbackFire( oSettings, 'aoRowCallback', null,
3468					[nRow, aoData._aData, iRowCount, j, iDataIndex] );
3469	
3470				anRows.push( nRow );
3471				iRowCount++;
3472			}
3473		}
3474		else
3475		{
3476			/* Table is empty - create a row with an empty message in it */
3477			var sZero = oLang.sZeroRecords;
3478			if ( oSettings.iDraw == 1 &&  _fnDataSource( oSettings ) == 'ajax' )
3479			{
3480				sZero = oLang.sLoadingRecords;
3481			}
3482			else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 )
3483			{
3484				sZero = oLang.sEmptyTable;
3485			}
3486	
3487			anRows[ 0 ] = $( '<tr/>', { 'class': iStripes ? asStripeClasses[0] : '' } )
3488				.append( $('<td />', {
3489					'valign':  'top',
3490					'colSpan': _fnVisbleColumns( oSettings ),
3491					'class':   oSettings.oClasses.sRowEmpty
3492				} ).html( sZero ) )[0];
3493		}
3494	
3495		/* Header and footer callbacks */
3496		_fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0],
3497			_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
3498	
3499		_fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0],
3500			_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
3501	
3502		var body = $(oSettings.nTBody);
3503	
3504		body.children().detach();
3505		body.append( $(anRows) );
3506	
3507		/* Call all required callback functions for the end of a draw */
3508		_fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] );
3509	
3510		/* Draw is complete, sorting and filtering must be as well */
3511		oSettings.bSorted = false;
3512		oSettings.bFiltered = false;
3513		oSettings.bDrawing = false;
3514	}
3515	
3516	
3517	/**
3518	 * Redraw the table - taking account of the various features which are enabled
3519	 *  @param {object} oSettings dataTables settings object
3520	 *  @param {boolean} [holdPosition] Keep the current paging position. By default
3521	 *    the paging is reset to the first page
3522	 *  @memberof DataTable#oApi
3523	 */
3524	function _fnReDraw( settings, holdPosition )
3525	{
3526		var
3527			features = settings.oFeatures,
3528			sort     = features.bSort,
3529			filter   = features.bFilter;
3530	
3531		if ( sort ) {
3532			_fnSort( settings );
3533		}
3534	
3535		if ( filter ) {
3536			_fnFilterComplete( settings, settings.oPreviousSearch );
3537		}
3538		else {
3539			// No filtering, so we want to just use the display master
3540			settings.aiDisplay = settings.aiDisplayMaster.slice();
3541		}
3542	
3543		if ( holdPosition !== true ) {
3544			settings._iDisplayStart = 0;
3545		}
3546	
3547		// Let any modules know about the draw hold position state (used by
3548		// scrolling internally)
3549		settings._drawHold = holdPosition;
3550	
3551		_fnDraw( settings );
3552	
3553		settings._drawHold = false;
3554	}
3555	
3556	
3557	/**
3558	 * Add the options to the page HTML for the table
3559	 *  @param {object} oSettings dataTables settings object
3560	 *  @memberof DataTable#oApi
3561	 */
3562	function _fnAddOptionsHtml ( oSettings )
3563	{
3564		var classes = oSettings.oClasses;
3565		var table = $(oSettings.nTable);
3566		var holding = $('<div/>').insertBefore( table ); // Holding element for speed
3567		var features = oSettings.oFeatures;
3568	
3569		// All DataTables are wrapped in a div
3570		var insert = $('<div/>', {
3571			id:      oSettings.sTableId+'_wrapper',
3572			'class': classes.sWrapper + (oSettings.nTFoot ? '' : ' '+classes.sNoFooter)
3573		} );
3574	
3575		oSettings.nHolding = holding[0];
3576		oSettings.nTableWrapper = insert[0];
3577		oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;
3578	
3579		/* Loop over the user set positioning and place the elements as needed */
3580		var aDom = oSettings.sDom.split('');
3581		var featureNode, cOption, nNewNode, cNext, sAttr, j;
3582		for ( var i=0 ; i<aDom.length ; i++ )
3583		{
3584			featureNode = null;
3585			cOption = aDom[i];
3586	
3587			if ( cOption == '<' )
3588			{
3589				/* New container div */
3590				nNewNode = $('<div/>')[0];
3591	
3592				/* Check to see if we should append an id and/or a class name to the container */
3593				cNext = aDom[i+1];
3594				if ( cNext == "'" || cNext == '"' )
3595				{
3596					sAttr = "";
3597					j = 2;
3598					while ( aDom[i+j] != cNext )
3599					{
3600						sAttr += aDom[i+j];
3601						j++;
3602					}
3603	
3604					/* Replace jQuery UI constants @todo depreciated */
3605					if ( sAttr == "H" )
3606					{
3607						sAttr = classes.sJUIHeader;
3608					}
3609					else if ( sAttr == "F" )
3610					{
3611						sAttr = classes.sJUIFooter;
3612					}
3613	
3614					/* The attribute can be in the format of "#id.class", "#id" or "class" This logic
3615					 * breaks the string into parts and applies them as needed
3616					 */
3617					if ( sAttr.indexOf('.') != -1 )
3618					{
3619						var aSplit = sAttr.split('.');
3620						nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);
3621						nNewNode.className = aSplit[1];
3622					}
3623					else if ( sAttr.charAt(0) == "#" )
3624					{
3625						nNewNode.id = sAttr.substr(1, sAttr.length-1);
3626					}
3627					else
3628					{
3629						nNewNode.className = sAttr;
3630					}
3631	
3632					i += j; /* Move along the position array */
3633				}
3634	
3635				insert.append( nNewNode );
3636				insert = $(nNewNode);
3637			}
3638			else if ( cOption == '>' )
3639			{
3640				/* End container div */
3641				insert = insert.parent();
3642			}
3643			// @todo Move options into their own plugins?
3644			else if ( cOption == 'l' && features.bPaginate && features.bLengthChange )
3645			{
3646				/* Length */
3647				featureNode = _fnFeatureHtmlLength( oSettings );
3648			}
3649			else if ( cOption == 'f' && features.bFilter )
3650			{
3651				/* Filter */
3652				featureNode = _fnFeatureHtmlFilter( oSettings );
3653			}
3654			else if ( cOption == 'r' && features.bProcessing )
3655			{
3656				/* pRocessing */
3657				featureNode = _fnFeatureHtmlProcessing( oSettings );
3658			}
3659			else if ( cOption == 't' )
3660			{
3661				/* Table */
3662				featureNode = _fnFeatureHtmlTable( oSettings );
3663			}
3664			else if ( cOption ==  'i' && features.bInfo )
3665			{
3666				/* Info */
3667				featureNode = _fnFeatureHtmlInfo( oSettings );
3668			}
3669			else if ( cOption == 'p' && features.bPaginate )
3670			{
3671				/* Pagination */
3672				featureNode = _fnFeatureHtmlPaginate( oSettings );
3673			}
3674			else if ( DataTable.ext.feature.length !== 0 )
3675			{
3676				/* Plug-in features */
3677				var aoFeatures = DataTable.ext.feature;
3678				for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )
3679				{
3680					if ( cOption == aoFeatures[k].cFeature )
3681					{
3682						featureNode = aoFeatures[k].fnInit( oSettings );
3683						break;
3684					}
3685				}
3686			}
3687	
3688			/* Add to the 2D features array */
3689			if ( featureNode )
3690			{
3691				var aanFeatures = oSettings.aanFeatures;
3692	
3693				if ( ! aanFeatures[cOption] )
3694				{
3695					aanFeatures[cOption] = [];
3696				}
3697	
3698				aanFeatures[cOption].push( featureNode );
3699				insert.append( featureNode );
3700			}
3701		}
3702	
3703		/* Built our DOM structure - replace the holding div with what we want */
3704		holding.replaceWith( insert );
3705		oSettings.nHolding = null;
3706	}
3707	
3708	
3709	/**
3710	 * Use the DOM source to create up an array of header cells. The idea here is to
3711	 * create a layout grid (array) of rows x columns, which contains a reference
3712	 * to the cell that that point in the grid (regardless of col/rowspan), such that
3713	 * any column / row could be removed and the new grid constructed
3714	 *  @param array {object} aLayout Array to store the calculated layout in
3715	 *  @param {node} nThead The header/footer element for the table
3716	 *  @memberof DataTable#oApi
3717	 */
3718	function _fnDetectHeader ( aLayout, nThead )
3719	{
3720		var nTrs = $(nThead).children('tr');
3721		var nTr, nCell;
3722		var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan;
3723		var bUnique;
3724		var fnShiftCol = function ( a, i, j ) {
3725			var k = a[i];
3726	                while ( k[j] ) {
3727				j++;
3728			}
3729			return j;
3730		};
3731	
3732		aLayout.splice( 0, aLayout.length );
3733	
3734		/* We know how many rows there are in the layout - so prep it */
3735		for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
3736		{
3737			aLayout.push( [] );
3738		}
3739	
3740		/* Calculate a layout array */
3741		for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
3742		{
3743			nTr = nTrs[i];
3744			iColumn = 0;
3745	
3746			/* For every cell in the row... */
3747			nCell = nTr.firstChild;
3748			while ( nCell ) {
3749				if ( nCell.nodeName.toUpperCase() == "TD" ||
3750				     nCell.nodeName.toUpperCase() == "TH" )
3751				{
3752					/* Get the col and rowspan attributes from the DOM and sanitise them */
3753					iColspan = nCell.getAttribute('colspan') * 1;
3754					iRowspan = nCell.getAttribute('rowspan') * 1;
3755					iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan;
3756					iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan;
3757	
3758					/* There might be colspan cells already in this row, so shift our target
3759					 * accordingly
3760					 */
3761					iColShifted = fnShiftCol( aLayout, i, iColumn );
3762	
3763					/* Cache calculation for unique columns */
3764					bUnique = iColspan === 1 ? true : false;
3765	
3766					/* If there is col / rowspan, copy the information into the layout grid */
3767					for ( l=0 ; l<iColspan ; l++ )
3768					{
3769						for ( k=0 ; k<iRowspan ; k++ )
3770						{
3771							aLayout[i+k][iColShifted+l] = {
3772								"cell": nCell,
3773								"unique": bUnique
3774							};
3775							aLayout[i+k].nTr = nTr;
3776						}
3777					}
3778				}
3779				nCell = nCell.nextSibling;
3780			}
3781		}
3782	}
3783	
3784	
3785	/**
3786	 * Get an array of unique th elements, one for each column
3787	 *  @param {object} oSettings dataTables settings object
3788	 *  @param {node} nHeader automatically detect the layout from this node - optional
3789	 *  @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional
3790	 *  @returns array {node} aReturn list of unique th's
3791	 *  @memberof DataTable#oApi
3792	 */
3793	function _fnGetUniqueThs ( oSettings, nHeader, aLayout )
3794	{
3795		var aReturn = [];
3796		if ( !aLayout )
3797		{
3798			aLayout = oSettings.aoHeader;
3799			if ( nHeader )
3800			{
3801				aLayout = [];
3802				_fnDetectHeader( aLayout, nHeader );
3803			}
3804		}
3805	
3806		for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ )
3807		{
3808			for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ )
3809			{
3810				if ( aLayout[i][j].unique &&
3811					 (!aReturn[j] || !oSettings.bSortCellsTop) )
3812				{
3813					aReturn[j] = aLayout[i][j].cell;
3814				}
3815			}
3816		}
3817	
3818		return aReturn;
3819	}
3820	
3821	/**
3822	 * 
vendor: 34,951 bytes, lines 3822-5053
3822Create an Ajax call based on the table's settings, taking into account that
3823	 * parameters can have multiple forms, and backwards compatibility.
3824	 *
3825	 * @param {object} oSettings dataTables settings object
3826	 * @param {array} data Data to send to the server, required by
3827	 *     DataTables - may be augmented by developer callbacks
3828	 * @param {function} fn Callback function to run when data is obtained
3829	 */
3830	function _fnBuildAjax( oSettings, data, fn )
3831	{
3832		// Compatibility with 1.9-, allow fnServerData and event to manipulate
3833		_fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [data] );
3834	
3835		// Convert to object based for 1.10+ if using the old array scheme which can
3836		// come from server-side processing or serverParams
3837		if ( data && $.isArray(data) ) {
3838			var tmp = {};
3839			var rbracket = /(.*?)\[\]$/;
3840	
3841			$.each( data, function (key, val) {
3842				var match = val.name.match(rbracket);
3843	
3844				if ( match ) {
3845					// Support for arrays
3846					var name = match[0];
3847	
3848					if ( ! tmp[ name ] ) {
3849						tmp[ name ] = [];
3850					}
3851					tmp[ name ].push( val.value );
3852				}
3853				else {
3854					tmp[val.name] = val.value;
3855				}
3856			} );
3857			data = tmp;
3858		}
3859	
3860		var ajaxData;
3861		var ajax = oSettings.ajax;
3862		var instance = oSettings.oInstance;
3863		var callback = function ( json ) {
3864			_fnCallbackFire( oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR] );
3865			fn( json );
3866		};
3867	
3868		if ( $.isPlainObject( ajax ) && ajax.data )
3869		{
3870			ajaxData = ajax.data;
3871	
3872			var newData = typeof ajaxData === 'function' ?
3873				ajaxData( data, oSettings ) :  // fn can manipulate data or return
3874				ajaxData;                      // an object object or array to merge
3875	
3876			// If the function returned something, use that alone
3877			data = typeof ajaxData === 'function' && newData ?
3878				newData :
3879				$.extend( true, data, newData );
3880	
3881			// Remove the data property as we've resolved it already and don't want
3882			// jQuery to do it again (it is restored at the end of the function)
3883			delete ajax.data;
3884		}
3885	
3886		var baseAjax = {
3887			"data": data,
3888			"success": function (json) {
3889				var error = json.error || json.sError;
3890				if ( error ) {
3891					_fnLog( oSettings, 0, error );
3892				}
3893	
3894				oSettings.json = json;
3895				callback( json );
3896			},
3897			"dataType": "json",
3898			"cache": false,
3899			"type": oSettings.sServerMethod,
3900			"error": function (xhr, error, thrown) {
3901				var ret = _fnCallbackFire( oSettings, null, 'xhr', [oSettings, null, oSettings.jqXHR] );
3902	
3903				if ( $.inArray( true, ret ) === -1 ) {
3904					if ( error == "parsererror" ) {
3905						_fnLog( oSettings, 0, 'Invalid JSON response', 1 );
3906					}
3907					else if ( xhr.readyState === 4 ) {
3908						_fnLog( oSettings, 0, 'Ajax error', 7 );
3909					}
3910				}
3911	
3912				_fnProcessingDisplay( oSettings, false );
3913			}
3914		};
3915	
3916		// Store the data submitted for the API
3917		oSettings.oAjaxData = data;
3918	
3919		// Allow plug-ins and external processes to modify the data
3920		_fnCallbackFire( oSettings, null, 'preXhr', [oSettings, data] );
3921	
3922		if ( oSettings.fnServerData )
3923		{
3924			// DataTables 1.9- compatibility
3925			oSettings.fnServerData.call( instance,
3926				oSettings.sAjaxSource,
3927				$.map( data, function (val, key) { // Need to convert back to 1.9 trad format
3928					return { name: key, value: val };
3929				} ),
3930				callback,
3931				oSettings
3932			);
3933		}
3934		else if ( oSettings.sAjaxSource || typeof ajax === 'string' )
3935		{
3936			// DataTables 1.9- compatibility
3937			oSettings.jqXHR = $.ajax( $.extend( baseAjax, {
3938				url: ajax || oSettings.sAjaxSource
3939			} ) );
3940		}
3941		else if ( typeof ajax === 'function' )
3942		{
3943			// Is a function - let the caller define what needs to be done
3944			oSettings.jqXHR = ajax.call( instance, data, callback, oSettings );
3945		}
3946		else
3947		{
3948			// Object to extend the base settings
3949			oSettings.jqXHR = $.ajax( $.extend( baseAjax, ajax ) );
3950	
3951			// Restore for next time around
3952			ajax.data = ajaxData;
3953		}
3954	}
3955	
3956	
3957	/**
3958	 * Update the table using an Ajax call
3959	 *  @param {object} settings dataTables settings object
3960	 *  @returns {boolean} Block the table drawing or not
3961	 *  @memberof DataTable#oApi
3962	 */
3963	function _fnAjaxUpdate( settings )
3964	{
3965		if ( settings.bAjaxDataGet ) {
3966			settings.iDraw++;
3967			_fnProcessingDisplay( settings, true );
3968	
3969			_fnBuildAjax(
3970				settings,
3971				_fnAjaxParameters( settings ),
3972				function(json) {
3973					_fnAjaxUpdateDraw( settings, json );
3974				}
3975			);
3976	
3977			return false;
3978		}
3979		return true;
3980	}
3981	
3982	
3983	/**
3984	 * Build up the parameters in an object needed for a server-side processing
3985	 * request. Note that this is basically done twice, is different ways - a modern
3986	 * method which is used by default in DataTables 1.10 which uses objects and
3987	 * arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if
3988	 * the sAjaxSource option is used in the initialisation, or the legacyAjax
3989	 * option is set.
3990	 *  @param {object} oSettings dataTables settings object
3991	 *  @returns {bool} block the table drawing or not
3992	 *  @memberof DataTable#oApi
3993	 */
3994	function _fnAjaxParameters( settings )
3995	{
3996		var
3997			columns = settings.aoColumns,
3998			columnCount = columns.length,
3999			features = settings.oFeatures,
4000			preSearch = settings.oPreviousSearch,
4001			preColSearch = settings.aoPreSearchCols,
4002			i, data = [], dataProp, column, columnSearch,
4003			sort = _fnSortFlatten( settings ),
4004			displayStart = settings._iDisplayStart,
4005			displayLength = features.bPaginate !== false ?
4006				settings._iDisplayLength :
4007				-1;
4008	
4009		var param = function ( name, value ) {
4010			data.push( { 'name': name, 'value': value } );
4011		};
4012	
4013		// DataTables 1.9- compatible method
4014		param( 'sEcho',          settings.iDraw );
4015		param( 'iColumns',       columnCount );
4016		param( 'sColumns',       _pluck( columns, 'sName' ).join(',') );
4017		param( 'iDisplayStart',  displayStart );
4018		param( 'iDisplayLength', displayLength );
4019	
4020		// DataTables 1.10+ method
4021		var d = {
4022			draw:    settings.iDraw,
4023			columns: [],
4024			order:   [],
4025			start:   displayStart,
4026			length:  displayLength,
4027			search:  {
4028				value: preSearch.sSearch,
4029				regex: preSearch.bRegex
4030			}
4031		};
4032	
4033		for ( i=0 ; i<columnCount ; i++ ) {
4034			column = columns[i];
4035			columnSearch = preColSearch[i];
4036			dataProp = typeof column.mData=="function" ? 'function' : column.mData ;
4037	
4038			d.columns.push( {
4039				data:       dataProp,
4040				name:       column.sName,
4041				searchable: column.bSearchable,
4042				orderable:  column.bSortable,
4043				search:     {
4044					value: columnSearch.sSearch,
4045					regex: columnSearch.bRegex
4046				}
4047			} );
4048	
4049			param( "mDataProp_"+i, dataProp );
4050	
4051			if ( features.bFilter ) {
4052				param( 'sSearch_'+i,     columnSearch.sSearch );
4053				param( 'bRegex_'+i,      columnSearch.bRegex );
4054				param( 'bSearchable_'+i, column.bSearchable );
4055			}
4056	
4057			if ( features.bSort ) {
4058				param( 'bSortable_'+i, column.bSortable );
4059			}
4060		}
4061	
4062		if ( features.bFilter ) {
4063			param( 'sSearch', preSearch.sSearch );
4064			param( 'bRegex', preSearch.bRegex );
4065		}
4066	
4067		if ( features.bSort ) {
4068			$.each( sort, function ( i, val ) {
4069				d.order.push( { column: val.col, dir: val.dir } );
4070	
4071				param( 'iSortCol_'+i, val.col );
4072				param( 'sSortDir_'+i, val.dir );
4073			} );
4074	
4075			param( 'iSortingCols', sort.length );
4076		}
4077	
4078		// If the legacy.ajax parameter is null, then we automatically decide which
4079		// form to use, based on sAjaxSource
4080		var legacy = DataTable.ext.legacy.ajax;
4081		if ( legacy === null ) {
4082			return settings.sAjaxSource ? data : d;
4083		}
4084	
4085		// Otherwise, if legacy has been specified then we use that to decide on the
4086		// form
4087		return legacy ? data : d;
4088	}
4089	
4090	
4091	/**
4092	 * Data the data from the server (nuking the old) and redraw the table
4093	 *  @param {object} oSettings dataTables settings object
4094	 *  @param {object} json json data return from the server.
4095	 *  @param {string} json.sEcho Tracking flag for DataTables to match requests
4096	 *  @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering
4097	 *  @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering
4098	 *  @param {array} json.aaData The data to display on this page
4099	 *  @param {string} [json.sColumns] Column ordering (sName, comma separated)
4100	 *  @memberof DataTable#oApi
4101	 */
4102	function _fnAjaxUpdateDraw ( settings, json )
4103	{
4104		// v1.10 uses camelCase variables, while 1.9 uses Hungarian notation.
4105		// Support both
4106		var compat = function ( old, modern ) {
4107			return json[old] !== undefined ? json[old] : json[modern];
4108		};
4109	
4110		var data = _fnAjaxDataSrc( settings, json );
4111		var draw            = compat( 'sEcho',                'draw' );
4112		var recordsTotal    = compat( 'iTotalRecords',        'recordsTotal' );
4113		var recordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' );
4114	
4115		if ( draw !== undefined ) {
4116			// Protect against out of sequence returns
4117			if ( draw*1 < settings.iDraw ) {
4118				return;
4119			}
4120			settings.iDraw = draw * 1;
4121		}
4122	
4123		_fnClearTable( settings );
4124		settings._iRecordsTotal   = parseInt(recordsTotal, 10);
4125		settings._iRecordsDisplay = parseInt(recordsFiltered, 10);
4126	
4127		for ( var i=0, ien=data.length ; i<ien ; i++ ) {
4128			_fnAddData( settings, data[i] );
4129		}
4130		settings.aiDisplay = settings.aiDisplayMaster.slice();
4131	
4132		settings.bAjaxDataGet = false;
4133		_fnDraw( settings );
4134	
4135		if ( ! settings._bInitComplete ) {
4136			_fnInitComplete( settings, json );
4137		}
4138	
4139		settings.bAjaxDataGet = true;
4140		_fnProcessingDisplay( settings, false );
4141	}
4142	
4143	
4144	/**
4145	 * Get the data from the JSON data source to use for drawing a table. Using
4146	 * `_fnGetObjectDataFn` allows the data to be sourced from a property of the
4147	 * source object, or from a processing function.
4148	 *  @param {object} oSettings dataTables settings object
4149	 *  @param  {object} json Data source object / array from the server
4150	 *  @return {array} Array of data to use
4151	 */
4152	function _fnAjaxDataSrc ( oSettings, json )
4153	{
4154		var dataSrc = $.isPlainObject( oSettings.ajax ) && oSettings.ajax.dataSrc !== undefined ?
4155			oSettings.ajax.dataSrc :
4156			oSettings.sAjaxDataProp; // Compatibility with 1.9-.
4157	
4158		// Compatibility with 1.9-. In order to read from aaData, check if the
4159		// default has been changed, if not, check for aaData
4160		if ( dataSrc === 'data' ) {
4161			return json.aaData || json[dataSrc];
4162		}
4163	
4164		return dataSrc !== "" ?
4165			_fnGetObjectDataFn( dataSrc )( json ) :
4166			json;
4167	}
4168	
4169	/**
4170	 * Generate the node required for filtering text
4171	 *  @returns {node} Filter control element
4172	 *  @param {object} oSettings dataTables settings object
4173	 *  @memberof DataTable#oApi
4174	 */
4175	function _fnFeatureHtmlFilter ( settings )
4176	{
4177		var classes = settings.oClasses;
4178		var tableId = settings.sTableId;
4179		var language = settings.oLanguage;
4180		var previousSearch = settings.oPreviousSearch;
4181		var features = settings.aanFeatures;
4182		var input = '<input type="search" class="'+classes.sFilterInput+'"/>';
4183	
4184		var str = language.sSearch;
4185		str = str.match(/_INPUT_/) ?
4186			str.replace('_INPUT_', input) :
4187			str+input;
4188	
4189		var filter = $('<div/>', {
4190				'id': ! features.f ? tableId+'_filter' : null,
4191				'class': classes.sFilter
4192			} )
4193			.append( $('<label/>' ).append( str ) );
4194	
4195		var searchFn = function() {
4196			/* Update all other filter input elements for the new display */
4197			var n = features.f;
4198			var val = !this.value ? "" : this.value; // mental IE8 fix :-(
4199	
4200			/* Now do the filter */
4201			if ( val != previousSearch.sSearch ) {
4202				_fnFilterComplete( settings, {
4203					"sSearch": val,
4204					"bRegex": previousSearch.bRegex,
4205					"bSmart": previousSearch.bSmart ,
4206					"bCaseInsensitive": previousSearch.bCaseInsensitive
4207				} );
4208	
4209				// Need to redraw, without resorting
4210				settings._iDisplayStart = 0;
4211				_fnDraw( settings );
4212			}
4213		};
4214	
4215		var searchDelay = settings.searchDelay !== null ?
4216			settings.searchDelay :
4217			_fnDataSource( settings ) === 'ssp' ?
4218				400 :
4219				0;
4220	
4221		var jqFilter = $('input', filter)
4222			.val( previousSearch.sSearch )
4223			.attr( 'placeholder', language.sSearchPlaceholder )
4224			.on(
4225				'keyup.DT search.DT input.DT paste.DT cut.DT',
4226				searchDelay ?
4227					_fnThrottle( searchFn, searchDelay ) :
4228					searchFn
4229			)
4230			.on( 'mouseup', function(e) {
4231				// Edge fix! Edge 17 does not trigger anything other than mouse events when clicking
4232				// on the clear icon (Edge bug 17584515). This is safe in other browsers as `searchFn`
4233				// checks the value to see if it has changed. In other browsers it won't have.
4234				setTimeout( function () {
4235					searchFn.call(jqFilter[0]);
4236				}, 10);
4237			} )
4238			.on( 'keypress.DT', function(e) {
4239				/* Prevent form submission */
4240				if ( e.keyCode == 13 ) {
4241					return false;
4242				}
4243			} )
4244			.attr('aria-controls', tableId);
4245	
4246		// Update the input elements whenever the table is filtered
4247		$(settings.nTable).on( 'search.dt.DT', function ( ev, s ) {
4248			if ( settings === s ) {
4249				// IE9 throws an 'unknown error' if document.activeElement is used
4250				// inside an iframe or frame...
4251				try {
4252					if ( jqFilter[0] !== document.activeElement ) {
4253						jqFilter.val( previousSearch.sSearch );
4254					}
4255				}
4256				catch ( e ) {}
4257			}
4258		} );
4259	
4260		return filter[0];
4261	}
4262	
4263	
4264	/**
4265	 * Filter the table using both the global filter and column based filtering
4266	 *  @param {object} oSettings dataTables settings object
4267	 *  @param {object} oSearch search information
4268	 *  @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)
4269	 *  @memberof DataTable#oApi
4270	 */
4271	function _fnFilterComplete ( oSettings, oInput, iForce )
4272	{
4273		var oPrevSearch = oSettings.oPreviousSearch;
4274		var aoPrevSearch = oSettings.aoPreSearchCols;
4275		var fnSaveFilter = function ( oFilter ) {
4276			/* Save the filtering values */
4277			oPrevSearch.sSearch = oFilter.sSearch;
4278			oPrevSearch.bRegex = oFilter.bRegex;
4279			oPrevSearch.bSmart = oFilter.bSmart;
4280			oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive;
4281		};
4282		var fnRegex = function ( o ) {
4283			// Backwards compatibility with the bEscapeRegex option
4284			return o.bEscapeRegex !== undefined ? !o.bEscapeRegex : o.bRegex;
4285		};
4286	
4287		// Resolve any column types that are unknown due to addition or invalidation
4288		// @todo As per sort - can this be moved into an event handler?
4289		_fnColumnTypes( oSettings );
4290	
4291		/* In server-side processing all filtering is done by the server, so no point hanging around here */
4292		if ( _fnDataSource( oSettings ) != 'ssp' )
4293		{
4294			/* Global filter */
4295			_fnFilter( oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive );
4296			fnSaveFilter( oInput );
4297	
4298			/* Now do the individual column filter */
4299			for ( var i=0 ; i<aoPrevSearch.length ; i++ )
4300			{
4301				_fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, fnRegex(aoPrevSearch[i]),
4302					aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive );
4303			}
4304	
4305			/* Custom filtering */
4306			_fnFilterCustom( oSettings );
4307		}
4308		else
4309		{
4310			fnSaveFilter( oInput );
4311		}
4312	
4313		/* Tell the draw function we have been filtering */
4314		oSettings.bFiltered = true;
4315		_fnCallbackFire( oSettings, null, 'search', [oSettings] );
4316	}
4317	
4318	
4319	/**
4320	 * Apply custom filtering functions
4321	 *  @param {object} oSettings dataTables settings object
4322	 *  @memberof DataTable#oApi
4323	 */
4324	function _fnFilterCustom( settings )
4325	{
4326		var filters = DataTable.ext.search;
4327		var displayRows = settings.aiDisplay;
4328		var row, rowIdx;
4329	
4330		for ( var i=0, ien=filters.length ; i<ien ; i++ ) {
4331			var rows = [];
4332	
4333			// Loop over each row and see if it should be included
4334			for ( var j=0, jen=displayRows.length ; j<jen ; j++ ) {
4335				rowIdx = displayRows[ j ];
4336				row = settings.aoData[ rowIdx ];
4337	
4338				if ( filters[i]( settings, row._aFilterData, rowIdx, row._aData, j ) ) {
4339					rows.push( rowIdx );
4340				}
4341			}
4342	
4343			// So the array reference doesn't break set the results into the
4344			// existing array
4345			displayRows.length = 0;
4346			$.merge( displayRows, rows );
4347		}
4348	}
4349	
4350	
4351	/**
4352	 * Filter the table on a per-column basis
4353	 *  @param {object} oSettings dataTables settings object
4354	 *  @param {string} sInput string to filter on
4355	 *  @param {int} iColumn column to filter
4356	 *  @param {bool} bRegex treat search string as a regular expression or not
4357	 *  @param {bool} bSmart use smart filtering or not
4358	 *  @param {bool} bCaseInsensitive Do case insenstive matching or not
4359	 *  @memberof DataTable#oApi
4360	 */
4361	function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, caseInsensitive )
4362	{
4363		if ( searchStr === '' ) {
4364			return;
4365		}
4366	
4367		var data;
4368		var out = [];
4369		var display = settings.aiDisplay;
4370		var rpSearch = _fnFilterCreateSearch( searchStr, regex, smart, caseInsensitive );
4371	
4372		for ( var i=0 ; i<display.length ; i++ ) {
4373			data = settings.aoData[ display[i] ]._aFilterData[ colIdx ];
4374	
4375			if ( rpSearch.test( data ) ) {
4376				out.push( display[i] );
4377			}
4378		}
4379	
4380		settings.aiDisplay = out;
4381	}
4382	
4383	
4384	/**
4385	 * Filter the data table based on user input and draw the table
4386	 *  @param {object} settings dataTables settings object
4387	 *  @param {string} input string to filter on
4388	 *  @param {int} force optional - force a research of the master array (1) or not (undefined or 0)
4389	 *  @param {bool} regex treat as a regular expression or not
4390	 *  @param {bool} smart perform smart filtering or not
4391	 *  @param {bool} caseInsensitive Do case insenstive matching or not
4392	 *  @memberof DataTable#oApi
4393	 */
4394	function _fnFilter( settings, input, force, regex, smart, caseInsensitive )
4395	{
4396		var rpSearch = _fnFilterCreateSearch( input, regex, smart, caseInsensitive );
4397		var prevSearch = settings.oPreviousSearch.sSearch;
4398		var displayMaster = settings.aiDisplayMaster;
4399		var display, invalidated, i;
4400		var filtered = [];
4401	
4402		// Need to take account of custom filtering functions - always filter
4403		if ( DataTable.ext.search.length !== 0 ) {
4404			force = true;
4405		}
4406	
4407		// Check if any of the rows were invalidated
4408		invalidated = _fnFilterData( settings );
4409	
4410		// If the input is blank - we just want the full data set
4411		if ( input.length <= 0 ) {
4412			settings.aiDisplay = displayMaster.slice();
4413		}
4414		else {
4415			// New search - start from the master array
4416			if ( invalidated ||
4417				 force ||
4418				 regex ||
4419				 prevSearch.length > input.length ||
4420				 input.indexOf(prevSearch) !== 0 ||
4421				 settings.bSorted // On resort, the display master needs to be
4422				                  // re-filtered since indexes will have changed
4423			) {
4424				settings.aiDisplay = displayMaster.slice();
4425			}
4426	
4427			// Search the display array
4428			display = settings.aiDisplay;
4429	
4430			for ( i=0 ; i<display.length ; i++ ) {
4431				if ( rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) {
4432					filtered.push( display[i] );
4433				}
4434			}
4435	
4436			settings.aiDisplay = filtered;
4437		}
4438	}
4439	
4440	
4441	/**
4442	 * Build a regular expression object suitable for searching a table
4443	 *  @param {string} sSearch string to search for
4444	 *  @param {bool} bRegex treat as a regular expression or not
4445	 *  @param {bool} bSmart perform smart filtering or not
4446	 *  @param {bool} bCaseInsensitive Do case insensitive matching or not
4447	 *  @returns {RegExp} constructed object
4448	 *  @memberof DataTable#oApi
4449	 */
4450	function _fnFilterCreateSearch( search, regex, smart, caseInsensitive )
4451	{
4452		search = regex ?
4453			search :
4454			_fnEscapeRegex( search );
4455		
4456		if ( smart ) {
4457			/* For smart filtering we want to allow the search to work regardless of
4458			 * word order. We also want double quoted text to be preserved, so word
4459			 * order is important - a la google. So this is what we want to
4460			 * generate:
4461			 * 
4462			 * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$
4463			 */
4464			var a = $.map( search.match( /"[^"]+"|[^ ]+/g ) || [''], function ( word ) {
4465				if ( word.charAt(0) === '"' ) {
4466					var m = word.match( /^"(.*)"$/ );
4467					word = m ? m[1] : word;
4468				}
4469	
4470				return word.replace('"', '');
4471			} );
4472	
4473			search = '^(?=.*?'+a.join( ')(?=.*?' )+').*$';
4474		}
4475	
4476		return new RegExp( search, caseInsensitive ? 'i' : '' );
4477	}
4478	
4479	
4480	/**
4481	 * Escape a string such that it can be used in a regular expression
4482	 *  @param {string} sVal string to escape
4483	 *  @returns {string} escaped string
4484	 *  @memberof DataTable#oApi
4485	 */
4486	var _fnEscapeRegex = DataTable.util.escapeRegex;
4487	
4488	var __filter_div = $('<div>')[0];
4489	var __filter_div_textContent = __filter_div.textContent !== undefined;
4490	
4491	// Update the filtering data for each row if needed (by invalidation or first run)
4492	function _fnFilterData ( settings )
4493	{
4494		var columns = settings.aoColumns;
4495		var column;
4496		var i, j, ien, jen, filterData, cellData, row;
4497		var fomatters = DataTable.ext.type.search;
4498		var wasInvalidated = false;
4499	
4500		for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
4501			row = settings.aoData[i];
4502	
4503			if ( ! row._aFilterData ) {
4504				filterData = [];
4505	
4506				for ( j=0, jen=columns.length ; j<jen ; j++ ) {
4507					column = columns[j];
4508	
4509					if ( column.bSearchable ) {
4510						cellData = _fnGetCellData( settings, i, j, 'filter' );
4511	
4512						if ( fomatters[ column.sType ] ) {
4513							cellData = fomatters[ column.sType ]( cellData );
4514						}
4515	
4516						// Search in DataTables 1.10 is string based. In 1.11 this
4517						// should be altered to also allow strict type checking.
4518						if ( cellData === null ) {
4519							cellData = '';
4520						}
4521	
4522						if ( typeof cellData !== 'string' && cellData.toString ) {
4523							cellData = cellData.toString();
4524						}
4525					}
4526					else {
4527						cellData = '';
4528					}
4529	
4530					// If it looks like there is an HTML entity in the string,
4531					// attempt to decode it so sorting works as expected. Note that
4532					// we could use a single line of jQuery to do this, but the DOM
4533					// method used here is much faster http://jsperf.com/html-decode
4534					if ( cellData.indexOf && cellData.indexOf('&') !== -1 ) {
4535						__filter_div.innerHTML = cellData;
4536						cellData = __filter_div_textContent ?
4537							__filter_div.textContent :
4538							__filter_div.innerText;
4539					}
4540	
4541					if ( cellData.replace ) {
4542						cellData = cellData.replace(/[\r\n\u2028]/g, '');
4543					}
4544	
4545					filterData.push( cellData );
4546				}
4547	
4548				row._aFilterData = filterData;
4549				row._sFilterRow = filterData.join('  ');
4550				wasInvalidated = true;
4551			}
4552		}
4553	
4554		return wasInvalidated;
4555	}
4556	
4557	
4558	/**
4559	 * Convert from the internal Hungarian notation to camelCase for external
4560	 * interaction
4561	 *  @param {object} obj Object to convert
4562	 *  @returns {object} Inverted object
4563	 *  @memberof DataTable#oApi
4564	 */
4565	function _fnSearchToCamel ( obj )
4566	{
4567		return {
4568			search:          obj.sSearch,
4569			smart:           obj.bSmart,
4570			regex:           obj.bRegex,
4571			caseInsensitive: obj.bCaseInsensitive
4572		};
4573	}
4574	
4575	
4576	
4577	/**
4578	 * Convert from camelCase notation to the internal Hungarian. We could use the
4579	 * Hungarian convert function here, but this is cleaner
4580	 *  @param {object} obj Object to convert
4581	 *  @returns {object} Inverted object
4582	 *  @memberof DataTable#oApi
4583	 */
4584	function _fnSearchToHung ( obj )
4585	{
4586		return {
4587			sSearch:          obj.search,
4588			bSmart:           obj.smart,
4589			bRegex:           obj.regex,
4590			bCaseInsensitive: obj.caseInsensitive
4591		};
4592	}
4593	
4594	/**
4595	 * Generate the node required for the info display
4596	 *  @param {object} oSettings dataTables settings object
4597	 *  @returns {node} Information element
4598	 *  @memberof DataTable#oApi
4599	 */
4600	function _fnFeatureHtmlInfo ( settings )
4601	{
4602		var
4603			tid = settings.sTableId,
4604			nodes = settings.aanFeatures.i,
4605			n = $('<div/>', {
4606				'class': settings.oClasses.sInfo,
4607				'id': ! nodes ? tid+'_info' : null
4608			} );
4609	
4610		if ( ! nodes ) {
4611			// Update display on each draw
4612			settings.aoDrawCallback.push( {
4613				"fn": _fnUpdateInfo,
4614				"sName": "information"
4615			} );
4616	
4617			n
4618				.attr( 'role', 'status' )
4619				.attr( 'aria-live', 'polite' );
4620	
4621			// Table is described by our info div
4622			$(settings.nTable).attr( 'aria-describedby', tid+'_info' );
4623		}
4624	
4625		return n[0];
4626	}
4627	
4628	
4629	/**
4630	 * Update the information elements in the display
4631	 *  @param {object} settings dataTables settings object
4632	 *  @memberof DataTable#oApi
4633	 */
4634	function _fnUpdateInfo ( settings )
4635	{
4636		/* Show information about the table */
4637		var nodes = settings.aanFeatures.i;
4638		if ( nodes.length === 0 ) {
4639			return;
4640		}
4641	
4642		var
4643			lang  = settings.oLanguage,
4644			start = settings._iDisplayStart+1,
4645			end   = settings.fnDisplayEnd(),
4646			max   = settings.fnRecordsTotal(),
4647			total = settings.fnRecordsDisplay(),
4648			out   = total ?
4649				lang.sInfo :
4650				lang.sInfoEmpty;
4651	
4652		if ( total !== max ) {
4653			/* Record set after filtering */
4654			out += ' ' + lang.sInfoFiltered;
4655		}
4656	
4657		// Convert the macros
4658		out += lang.sInfoPostFix;
4659		out = _fnInfoMacros( settings, out );
4660	
4661		var callback = lang.fnInfoCallback;
4662		if ( callback !== null ) {
4663			out = callback.call( settings.oInstance,
4664				settings, start, end, max, total, out
4665			);
4666		}
4667	
4668		$(nodes).html( out );
4669	}
4670	
4671	
4672	function _fnInfoMacros ( settings, str )
4673	{
4674		// When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
4675		// internally
4676		var
4677			formatter  = settings.fnFormatNumber,
4678			start      = settings._iDisplayStart+1,
4679			len        = settings._iDisplayLength,
4680			vis        = settings.fnRecordsDisplay(),
4681			all        = len === -1;
4682	
4683		return str.
4684			replace(/_START_/g, formatter.call( settings, start ) ).
4685			replace(/_END_/g,   formatter.call( settings, settings.fnDisplayEnd() ) ).
4686			replace(/_MAX_/g,   formatter.call( settings, settings.fnRecordsTotal() ) ).
4687			replace(/_TOTAL_/g, formatter.call( settings, vis ) ).
4688			replace(/_PAGE_/g,  formatter.call( settings, all ? 1 : Math.ceil( start / len ) ) ).
4689			replace(/_PAGES_/g, formatter.call( settings, all ? 1 : Math.ceil( vis / len ) ) );
4690	}
4691	
4692	
4693	
4694	/**
4695	 * Draw the table for the first time, adding all required features
4696	 *  @param {object} settings dataTables settings object
4697	 *  @memberof DataTable#oApi
4698	 */
4699	function _fnInitialise ( settings )
4700	{
4701		var i, iLen, iAjaxStart=settings.iInitDisplayStart;
4702		var columns = settings.aoColumns, column;
4703		var features = settings.oFeatures;
4704		var deferLoading = settings.bDeferLoading; // value modified by the draw
4705	
4706		/* Ensure that the table data is fully initialised */
4707		if ( ! settings.bInitialised ) {
4708			setTimeout( function(){ _fnInitialise( settings ); }, 200 );
4709			return;
4710		}
4711	
4712		/* Show the display HTML options */
4713		_fnAddOptionsHtml( settings );
4714	
4715		/* Build and draw the header / footer for the table */
4716		_fnBuildHead( settings );
4717		_fnDrawHead( settings, settings.aoHeader );
4718		_fnDrawHead( settings, settings.aoFooter );
4719	
4720		/* Okay to show that something is going on now */
4721		_fnProcessingDisplay( settings, true );
4722	
4723		/* Calculate sizes for columns */
4724		if ( features.bAutoWidth ) {
4725			_fnCalculateColumnWidths( settings );
4726		}
4727	
4728		for ( i=0, iLen=columns.length ; i<iLen ; i++ ) {
4729			column = columns[i];
4730	
4731			if ( column.sWidth ) {
4732				column.nTh.style.width = _fnStringToCss( column.sWidth );
4733			}
4734		}
4735	
4736		_fnCallbackFire( settings, null, 'preInit', [settings] );
4737	
4738		// If there is default sorting required - let's do it. The sort function
4739		// will do the drawing for us. Otherwise we draw the table regardless of the
4740		// Ajax source - this allows the table to look initialised for Ajax sourcing
4741		// data (show 'loading' message possibly)
4742		_fnReDraw( settings );
4743	
4744		// Server-side processing init complete is done by _fnAjaxUpdateDraw
4745		var dataSrc = _fnDataSource( settings );
4746		if ( dataSrc != 'ssp' || deferLoading ) {
4747			// if there is an ajax source load the data
4748			if ( dataSrc == 'ajax' ) {
4749				_fnBuildAjax( settings, [], function(json) {
4750					var aData = _fnAjaxDataSrc( settings, json );
4751	
4752					// Got the data - add it to the table
4753					for ( i=0 ; i<aData.length ; i++ ) {
4754						_fnAddData( settings, aData[i] );
4755					}
4756	
4757					// Reset the init display for cookie saving. We've already done
4758					// a filter, and therefore cleared it before. So we need to make
4759					// it appear 'fresh'
4760					settings.iInitDisplayStart = iAjaxStart;
4761	
4762					_fnReDraw( settings );
4763	
4764					_fnProcessingDisplay( settings, false );
4765					_fnInitComplete( settings, json );
4766				}, settings );
4767			}
4768			else {
4769				_fnProcessingDisplay( settings, false );
4770				_fnInitComplete( settings );
4771			}
4772		}
4773	}
4774	
4775	
4776	/**
4777	 * Draw the table for the first time, adding all required features
4778	 *  @param {object} oSettings dataTables settings object
4779	 *  @param {object} [json] JSON from the server that completed the table, if using Ajax source
4780	 *    with client-side processing (optional)
4781	 *  @memberof DataTable#oApi
4782	 */
4783	function _fnInitComplete ( settings, json )
4784	{
4785		settings._bInitComplete = true;
4786	
4787		// When data was added after the initialisation (data or Ajax) we need to
4788		// calculate the column sizing
4789		if ( json || settings.oInit.aaData ) {
4790			_fnAdjustColumnSizing( settings );
4791		}
4792	
4793		_fnCallbackFire( settings, null, 'plugin-init', [settings, json] );
4794		_fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] );
4795	}
4796	
4797	
4798	function _fnLengthChange ( settings, val )
4799	{
4800		var len = parseInt( val, 10 );
4801		settings._iDisplayLength = len;
4802	
4803		_fnLengthOverflow( settings );
4804	
4805		// Fire length change event
4806		_fnCallbackFire( settings, null, 'length', [settings, len] );
4807	}
4808	
4809	
4810	/**
4811	 * Generate the node required for user display length changing
4812	 *  @param {object} settings dataTables settings object
4813	 *  @returns {node} Display length feature node
4814	 *  @memberof DataTable#oApi
4815	 */
4816	function _fnFeatureHtmlLength ( settings )
4817	{
4818		var
4819			classes  = settings.oClasses,
4820			tableId  = settings.sTableId,
4821			menu     = settings.aLengthMenu,
4822			d2       = $.isArray( menu[0] ),
4823			lengths  = d2 ? menu[0] : menu,
4824			language = d2 ? menu[1] : menu;
4825	
4826		var select = $('<select/>', {
4827			'name':          tableId+'_length',
4828			'aria-controls': tableId,
4829			'class':         classes.sLengthSelect
4830		} );
4831	
4832		for ( var i=0, ien=lengths.length ; i<ien ; i++ ) {
4833			select[0][ i ] = new Option(
4834				typeof language[i] === 'number' ?
4835					settings.fnFormatNumber( language[i] ) :
4836					language[i],
4837				lengths[i]
4838			);
4839		}
4840	
4841		var div = $('<div><label/></div>').addClass( classes.sLength );
4842		if ( ! settings.aanFeatures.l ) {
4843			div[0].id = tableId+'_length';
4844		}
4845	
4846		div.children().append(
4847			settings.oLanguage.sLengthMenu.replace( '_MENU_', select[0].outerHTML )
4848		);
4849	
4850		// Can't use `select` variable as user might provide their own and the
4851		// reference is broken by the use of outerHTML
4852		$('select', div)
4853			.val( settings._iDisplayLength )
4854			.on( 'change.DT', function(e) {
4855				_fnLengthChange( settings, $(this).val() );
4856				_fnDraw( settings );
4857			} );
4858	
4859		// Update node value whenever anything changes the table's length
4860		$(settings.nTable).on( 'length.dt.DT', function (e, s, len) {
4861			if ( settings === s ) {
4862				$('select', div).val( len );
4863			}
4864		} );
4865	
4866		return div[0];
4867	}
4868	
4869	
4870	
4871	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
4872	 * Note that most of the paging logic is done in
4873	 * DataTable.ext.pager
4874	 */
4875	
4876	/**
4877	 * Generate the node required for default pagination
4878	 *  @param {object} oSettings dataTables settings object
4879	 *  @returns {node} Pagination feature node
4880	 *  @memberof DataTable#oApi
4881	 */
4882	function _fnFeatureHtmlPaginate ( settings )
4883	{
4884		var
4885			type   = settings.sPaginationType,
4886			plugin = DataTable.ext.pager[ type ],
4887			modern = typeof plugin === 'function',
4888			redraw = function( settings ) {
4889				_fnDraw( settings );
4890			},
4891			node = $('<div/>').addClass( settings.oClasses.sPaging + type )[0],
4892			features = settings.aanFeatures;
4893	
4894		if ( ! modern ) {
4895			plugin.fnInit( settings, node, redraw );
4896		}
4897	
4898		/* Add a draw callback for the pagination on first instance, to update the paging display */
4899		if ( ! features.p )
4900		{
4901			node.id = settings.sTableId+'_paginate';
4902	
4903			settings.aoDrawCallback.push( {
4904				"fn": function( settings ) {
4905					if ( modern ) {
4906						var
4907							start      = settings._iDisplayStart,
4908							len        = settings._iDisplayLength,
4909							visRecords = settings.fnRecordsDisplay(),
4910							all        = len === -1,
4911							page = all ? 0 : Math.ceil( start / len ),
4912							pages = all ? 1 : Math.ceil( visRecords / len ),
4913							buttons = plugin(page, pages),
4914							i, ien;
4915	
4916						for ( i=0, ien=features.p.length ; i<ien ; i++ ) {
4917							_fnRenderer( settings, 'pageButton' )(
4918								settings, features.p[i], i, buttons, page, pages
4919							);
4920						}
4921					}
4922					else {
4923						plugin.fnUpdate( settings, redraw );
4924					}
4925				},
4926				"sName": "pagination"
4927			} );
4928		}
4929	
4930		return node;
4931	}
4932	
4933	
4934	/**
4935	 * Alter the display settings to change the page
4936	 *  @param {object} settings DataTables settings object
4937	 *  @param {string|int} action Paging action to take: "first", "previous",
4938	 *    "next" or "last" or page number to jump to (integer)
4939	 *  @param [bool] redraw Automatically draw the update or not
4940	 *  @returns {bool} true page has changed, false - no change
4941	 *  @memberof DataTable#oApi
4942	 */
4943	function _fnPageChange ( settings, action, redraw )
4944	{
4945		var
4946			start     = settings._iDisplayStart,
4947			len       = settings._iDisplayLength,
4948			records   = settings.fnRecordsDisplay();
4949	
4950		if ( records === 0 || len === -1 )
4951		{
4952			start = 0;
4953		}
4954		else if ( typeof action === "number" )
4955		{
4956			start = action * len;
4957	
4958			if ( start > records )
4959			{
4960				start = 0;
4961			}
4962		}
4963		else if ( action == "first" )
4964		{
4965			start = 0;
4966		}
4967		else if ( action == "previous" )
4968		{
4969			start = len >= 0 ?
4970				start - len :
4971				0;
4972	
4973			if ( start < 0 )
4974			{
4975			  start = 0;
4976			}
4977		}
4978		else if ( action == "next" )
4979		{
4980			if ( start + len < records )
4981			{
4982				start += len;
4983			}
4984		}
4985		else if ( action == "last" )
4986		{
4987			start = Math.floor( (records-1) / len) * len;
4988		}
4989		else
4990		{
4991			_fnLog( settings, 0, "Unknown paging action: "+action, 5 );
4992		}
4993	
4994		var changed = settings._iDisplayStart !== start;
4995		settings._iDisplayStart = start;
4996	
4997		if ( changed ) {
4998			_fnCallbackFire( settings, null, 'page', [settings] );
4999	
5000			if ( redraw ) {
5001				_fnDraw( settings );
5002			}
5003		}
5004	
5005		return changed;
5006	}
5007	
5008	
5009	
5010	/**
5011	 * Generate the node required for the processing node
5012	 *  @param {object} settings dataTables settings object
5013	 *  @returns {node} Processing element
5014	 *  @memberof DataTable#oApi
5015	 */
5016	function _fnFeatureHtmlProcessing ( settings )
5017	{
5018		return $('<div/>', {
5019				'id': ! settings.aanFeatures.r ? settings.sTableId+'_processing' : null,
5020				'class': settings.oClasses.sProcessing
5021			} )
5022			.html( settings.oLanguage.sProcessing )
5023			.insertBefore( settings.nTable )[0];
5024	}
5025	
5026	
5027	/**
5028	 * Display or hide the processing indicator
5029	 *  @param {object} settings dataTables settings object
5030	 *  @param {bool} show Show the processing indicator (true) or not (false)
5031	 *  @memberof DataTable#oApi
5032	 */
5033	function _fnProcessingDisplay ( settings, show )
5034	{
5035		if ( settings.oFeatures.bProcessing ) {
5036			$(settings.aanFeatures.r).css( 'display', show ? 'block' : 'none' );
5037		}
5038	
5039		_fnCallbackFire( settings, null, 'processing', [settings, show] );
5040	}
5041	
5042	/**
5043	 * Add any control elements for the table - specifically scrolling
5044	 *  @param {object} settings dataTables settings object
5045	 *  @returns {node} Node to add to the DOM
5046	 *  @memberof DataTable#oApi
5047	 */
5048	function _fnFeatureHtmlTable ( settings )
5049	{
5050		var table = $(settings.nTable);
5051	
5052		// Add the ARIA grid role to the table
5053		table.attr( 'role', 'grid' 
vendor: 6,387 bytes, lines 5053-5275
5053);
5054	
5055		// Scrolling from here on in
5056		var scroll = settings.oScroll;
5057	
5058		if ( scroll.sX === '' && scroll.sY === '' ) {
5059			return settings.nTable;
5060		}
5061	
5062		var scrollX = scroll.sX;
5063		var scrollY = scroll.sY;
5064		var classes = settings.oClasses;
5065		var caption = table.children('caption');
5066		var captionSide = caption.length ? caption[0]._captionSide : null;
5067		var headerClone = $( table[0].cloneNode(false) );
5068		var footerClone = $( table[0].cloneNode(false) );
5069		var footer = table.children('tfoot');
5070		var _div = '<div/>';
5071		var size = function ( s ) {
5072			return !s ? null : _fnStringToCss( s );
5073		};
5074	
5075		if ( ! footer.length ) {
5076			footer = null;
5077		}
5078	
5079		/*
5080		 * The HTML structure that we want to generate in this function is:
5081		 *  div - scroller
5082		 *    div - scroll head
5083		 *      div - scroll head inner
5084		 *        table - scroll head table
5085		 *          thead - thead
5086		 *    div - scroll body
5087		 *      table - table (master table)
5088		 *        thead - thead clone for sizing
5089		 *        tbody - tbody
5090		 *    div - scroll foot
5091		 *      div - scroll foot inner
5092		 *        table - scroll foot table
5093		 *          tfoot - tfoot
5094		 */
5095		var scroller = $( _div, { 'class': classes.sScrollWrapper } )
5096			.append(
5097				$(_div, { 'class': classes.sScrollHead } )
5098					.css( {
5099						overflow: 'hidden',
5100						position: 'relative',
5101						border: 0,
5102						width: scrollX ? size(scrollX) : '100%'
5103					} )
5104					.append(
5105						$(_div, { 'class': classes.sScrollHeadInner } )
5106							.css( {
5107								'box-sizing': 'content-box',
5108								width: scroll.sXInner || '100%'
5109							} )
5110							.append(
5111								headerClone
5112									.removeAttr('id')
5113									.css( 'margin-left', 0 )
5114									.append( captionSide === 'top' ? caption : null )
5115									.append(
5116										table.children('thead')
5117									)
5118							)
5119					)
5120			)
5121			.append(
5122				$(_div, { 'class': classes.sScrollBody } )
5123					.css( {
5124						position: 'relative',
5125						overflow: 'auto',
5126						width: size( scrollX )
5127					} )
5128					.append( table )
5129			);
5130	
5131		if ( footer ) {
5132			scroller.append(
5133				$(_div, { 'class': classes.sScrollFoot } )
5134					.css( {
5135						overflow: 'hidden',
5136						border: 0,
5137						width: scrollX ? size(scrollX) : '100%'
5138					} )
5139					.append(
5140						$(_div, { 'class': classes.sScrollFootInner } )
5141							.append(
5142								footerClone
5143									.removeAttr('id')
5144									.css( 'margin-left', 0 )
5145									.append( captionSide === 'bottom' ? caption : null )
5146									.append(
5147										table.children('tfoot')
5148									)
5149							)
5150					)
5151			);
5152		}
5153	
5154		var children = scroller.children();
5155		var scrollHead = children[0];
5156		var scrollBody = children[1];
5157		var scrollFoot = footer ? children[2] : null;
5158	
5159		// When the body is scrolled, then we also want to scroll the headers
5160		if ( scrollX ) {
5161			$(scrollBody).on( 'scroll.DT', function (e) {
5162				var scrollLeft = this.scrollLeft;
5163	
5164				scrollHead.scrollLeft = scrollLeft;
5165	
5166				if ( footer ) {
5167					scrollFoot.scrollLeft = scrollLeft;
5168				}
5169			} );
5170		}
5171	
5172		$(scrollBody).css('max-height', scrollY);
5173		if (! scroll.bCollapse) {
5174			$(scrollBody).css('height', scrollY);
5175		}
5176	
5177		settings.nScrollHead = scrollHead;
5178		settings.nScrollBody = scrollBody;
5179		settings.nScrollFoot = scrollFoot;
5180	
5181		// On redraw - align columns
5182		settings.aoDrawCallback.push( {
5183			"fn": _fnScrollDraw,
5184			"sName": "scrolling"
5185		} );
5186	
5187		return scroller[0];
5188	}
5189	
5190	
5191	
5192	/**
5193	 * Update the header, footer and body tables for resizing - i.e. column
5194	 * alignment.
5195	 *
5196	 * Welcome to the most horrible function DataTables. The process that this
5197	 * function follows is basically:
5198	 *   1. Re-create the table inside the scrolling div
5199	 *   2. Take live measurements from the DOM
5200	 *   3. Apply the measurements to align the columns
5201	 *   4. Clean up
5202	 *
5203	 *  @param {object} settings dataTables settings object
5204	 *  @memberof DataTable#oApi
5205	 */
5206	function _fnScrollDraw ( settings )
5207	{
5208		// Given that this is such a monster function, a lot of variables are use
5209		// to try and keep the minimised size as small as possible
5210		var
5211			scroll         = settings.oScroll,
5212			scrollX        = scroll.sX,
5213			scrollXInner   = scroll.sXInner,
5214			scrollY        = scroll.sY,
5215			barWidth       = scroll.iBarWidth,
5216			divHeader      = $(settings.nScrollHead),
5217			divHeaderStyle = divHeader[0].style,
5218			divHeaderInner = divHeader.children('div'),
5219			divHeaderInnerStyle = divHeaderInner[0].style,
5220			divHeaderTable = divHeaderInner.children('table'),
5221			divBodyEl      = settings.nScrollBody,
5222			divBody        = $(divBodyEl),
5223			divBodyStyle   = divBodyEl.style,
5224			divFooter      = $(settings.nScrollFoot),
5225			divFooterInner = divFooter.children('div'),
5226			divFooterTable = divFooterInner.children('table'),
5227			header         = $(settings.nTHead),
5228			table          = $(settings.nTable),
5229			tableEl        = table[0],
5230			tableStyle     = tableEl.style,
5231			footer         = settings.nTFoot ? $(settings.nTFoot) : null,
5232			browser        = settings.oBrowser,
5233			ie67           = browser.bScrollOversize,
5234			dtHeaderCells  = _pluck( settings.aoColumns, 'nTh' ),
5235			headerTrgEls, footerTrgEls,
5236			headerSrcEls, footerSrcEls,
5237			headerCopy, footerCopy,
5238			headerWidths=[], footerWidths=[],
5239			headerContent=[], footerContent=[],
5240			idx, correction, sanityWidth,
5241			zeroOut = function(nSizer) {
5242				var style = nSizer.style;
5243				style.paddingTop = "0";
5244				style.paddingBottom = "0";
5245				style.borderTopWidth = "0";
5246				style.borderBottomWidth = "0";
5247				style.height = 0;
5248			};
5249	
5250		// If the scrollbar visibility has changed from the last draw, we need to
5251		// adjust the column sizes as the table width will have changed to account
5252		// for the scrollbar
5253		var scrollBarVis = divBodyEl.scrollHeight > divBodyEl.clientHeight;
5254		
5255		if ( settings.scrollBarVis !== scrollBarVis && settings.scrollBarVis !== undefined ) {
5256			settings.scrollBarVis = scrollBarVis;
5257			_fnAdjustColumnSizing( settings );
5258			return; // adjust column sizing will call this function again
5259		}
5260		else {
5261			settings.scrollBarVis = scrollBarVis;
5262		}
5263	
5264		/*
5265		 * 1. Re-create the table inside the scrolling div
5266		 */
5267	
5268		// Remove the old minimised thead and tfoot elements in the inner table
5269		table.children('thead, tfoot').remove();
5270	
5271		if ( footer ) {
5272			footerCopy = footer.clone().prependTo( table );
5273			footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized
5274			footerSrcEls = footerCopy.find('tr');
5275		
vendor: 4,185 bytes, lines 5275-5402
5275}
5276	
5277		// Clone the current header and footer elements and then place it into the inner table
5278		headerCopy = header.clone().prependTo( table );
5279		headerTrgEls = header.find('tr'); // original header is in its own table
5280		headerSrcEls = headerCopy.find('tr');
5281		headerCopy.find('th, td').removeAttr('tabindex');
5282	
5283	
5284		/*
5285		 * 2. Take live measurements from the DOM - do not alter the DOM itself!
5286		 */
5287	
5288		// Remove old sizing and apply the calculated column widths
5289		// Get the unique column headers in the newly created (cloned) header. We want to apply the
5290		// calculated sizes to this header
5291		if ( ! scrollX )
5292		{
5293			divBodyStyle.width = '100%';
5294			divHeader[0].style.width = '100%';
5295		}
5296	
5297		$.each( _fnGetUniqueThs( settings, headerCopy ), function ( i, el ) {
5298			idx = _fnVisibleToColumnIndex( settings, i );
5299			el.style.width = settings.aoColumns[idx].sWidth;
5300		} );
5301	
5302		if ( footer ) {
5303			_fnApplyToChildren( function(n) {
5304				n.style.width = "";
5305			}, footerSrcEls );
5306		}
5307	
5308		// Size the table as a whole
5309		sanityWidth = table.outerWidth();
5310		if ( scrollX === "" ) {
5311			// No x scrolling
5312			tableStyle.width = "100%";
5313	
5314			// IE7 will make the width of the table when 100% include the scrollbar
5315			// - which is shouldn't. When there is a scrollbar we need to take this
5316			// into account.
5317			if ( ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight ||
5318				divBody.css('overflow-y') == "scroll")
5319			) {
5320				tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth);
5321			}
5322	
5323			// Recalculate the sanity width
5324			sanityWidth = table.outerWidth();
5325		}
5326		else if ( scrollXInner !== "" ) {
5327			// legacy x scroll inner has been given - use it
5328			tableStyle.width = _fnStringToCss(scrollXInner);
5329	
5330			// Recalculate the sanity width
5331			sanityWidth = table.outerWidth();
5332		}
5333	
5334		// Hidden header should have zero height, so remove padding and borders. Then
5335		// set the width based on the real headers
5336	
5337		// Apply all styles in one pass
5338		_fnApplyToChildren( zeroOut, headerSrcEls );
5339	
5340		// Read all widths in next pass
5341		_fnApplyToChildren( function(nSizer) {
5342			headerContent.push( nSizer.innerHTML );
5343			headerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
5344		}, headerSrcEls );
5345	
5346		// Apply all widths in final pass
5347		_fnApplyToChildren( function(nToSize, i) {
5348			// Only apply widths to the DataTables detected header cells - this
5349			// prevents complex headers from having contradictory sizes applied
5350			if ( $.inArray( nToSize, dtHeaderCells ) !== -1 ) {
5351				nToSize.style.width = headerWidths[i];
5352			}
5353		}, headerTrgEls );
5354	
5355		$(headerSrcEls).height(0);
5356	
5357		/* Same again with the footer if we have one */
5358		if ( footer )
5359		{
5360			_fnApplyToChildren( zeroOut, footerSrcEls );
5361	
5362			_fnApplyToChildren( function(nSizer) {
5363				footerContent.push( nSizer.innerHTML );
5364				footerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
5365			}, footerSrcEls );
5366	
5367			_fnApplyToChildren( function(nToSize, i) {
5368				nToSize.style.width = footerWidths[i];
5369			}, footerTrgEls );
5370	
5371			$(footerSrcEls).height(0);
5372		}
5373	
5374	
5375		/*
5376		 * 3. Apply the measurements
5377		 */
5378	
5379		// "Hide" the header and footer that we used for the sizing. We need to keep
5380		// the content of the cell so that the width applied to the header and body
5381		// both match, but we want to hide it completely. We want to also fix their
5382		// width to what they currently are
5383		_fnApplyToChildren( function(nSizer, i) {
5384			nSizer.innerHTML = '<div class="dataTables_sizing">'+headerContent[i]+'</div>';
5385			nSizer.childNodes[0].style.height = "0";
5386			nSizer.childNodes[0].style.overflow = "hidden";
5387			nSizer.style.width = headerWidths[i];
5388		}, headerSrcEls );
5389	
5390		if ( footer )
5391		{
5392			_fnApplyToChildren( function(nSizer, i) {
5393				nSizer.innerHTML = '<div class="dataTables_sizing">'+footerContent[i]+'</div>';
5394				nSizer.childNodes[0].style.height = "0";
5395				nSizer.childNodes[0].style.overflow = "hidden";
5396				nSizer.style.width = footerWidths[i];
5397			}, footerSrcEls );
5398		}
5399	
5400		// Sanity check that the table is of a sensible width. If not then we are going to get
5401		// misalignment - try to prevent this by not allowing the table to shrink below its min width
5402		if ( table.outerWidth() < sanityWidth
vendor: 14,111 bytes, lines 5402-5868
5402 )
5403		{
5404			// The min width depends upon if we have a vertical scrollbar visible or not */
5405			correction = ((divBodyEl.scrollHeight > divBodyEl.offsetHeight ||
5406				divBody.css('overflow-y') == "scroll")) ?
5407					sanityWidth+barWidth :
5408					sanityWidth;
5409	
5410			// IE6/7 are a law unto themselves...
5411			if ( ie67 && (divBodyEl.scrollHeight >
5412				divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll")
5413			) {
5414				tableStyle.width = _fnStringToCss( correction-barWidth );
5415			}
5416	
5417			// And give the user a warning that we've stopped the table getting too small
5418			if ( scrollX === "" || scrollXInner !== "" ) {
5419				_fnLog( settings, 1, 'Possible column misalignment', 6 );
5420			}
5421		}
5422		else
5423		{
5424			correction = '100%';
5425		}
5426	
5427		// Apply to the container elements
5428		divBodyStyle.width = _fnStringToCss( correction );
5429		divHeaderStyle.width = _fnStringToCss( correction );
5430	
5431		if ( footer ) {
5432			settings.nScrollFoot.style.width = _fnStringToCss( correction );
5433		}
5434	
5435	
5436		/*
5437		 * 4. Clean up
5438		 */
5439		if ( ! scrollY ) {
5440			/* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
5441			 * the scrollbar height from the visible display, rather than adding it on. We need to
5442			 * set the height in order to sort this. Don't want to do it in any other browsers.
5443			 */
5444			if ( ie67 ) {
5445				divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+barWidth );
5446			}
5447		}
5448	
5449		/* Finally set the width's of the header and footer tables */
5450		var iOuterWidth = table.outerWidth();
5451		divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth );
5452		divHeaderInnerStyle.width = _fnStringToCss( iOuterWidth );
5453	
5454		// Figure out if there are scrollbar present - if so then we need a the header and footer to
5455		// provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
5456		var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll";
5457		var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' );
5458		divHeaderInnerStyle[ padding ] = bScrolling ? barWidth+"px" : "0px";
5459	
5460		if ( footer ) {
5461			divFooterTable[0].style.width = _fnStringToCss( iOuterWidth );
5462			divFooterInner[0].style.width = _fnStringToCss( iOuterWidth );
5463			divFooterInner[0].style[padding] = bScrolling ? barWidth+"px" : "0px";
5464		}
5465	
5466		// Correct DOM ordering for colgroup - comes before the thead
5467		table.children('colgroup').insertBefore( table.children('thead') );
5468	
5469		/* Adjust the position of the header in case we loose the y-scrollbar */
5470		divBody.trigger('scroll');
5471	
5472		// If sorting or filtering has occurred, jump the scrolling back to the top
5473		// only if we aren't holding the position
5474		if ( (settings.bSorted || settings.bFiltered) && ! settings._drawHold ) {
5475			divBodyEl.scrollTop = 0;
5476		}
5477	}
5478	
5479	
5480	
5481	/**
5482	 * Apply a given function to the display child nodes of an element array (typically
5483	 * TD children of TR rows
5484	 *  @param {function} fn Method to apply to the objects
5485	 *  @param array {nodes} an1 List of elements to look through for display children
5486	 *  @param array {nodes} an2 Another list (identical structure to the first) - optional
5487	 *  @memberof DataTable#oApi
5488	 */
5489	function _fnApplyToChildren( fn, an1, an2 )
5490	{
5491		var index=0, i=0, iLen=an1.length;
5492		var nNode1, nNode2;
5493	
5494		while ( i < iLen ) {
5495			nNode1 = an1[i].firstChild;
5496			nNode2 = an2 ? an2[i].firstChild : null;
5497	
5498			while ( nNode1 ) {
5499				if ( nNode1.nodeType === 1 ) {
5500					if ( an2 ) {
5501						fn( nNode1, nNode2, index );
5502					}
5503					else {
5504						fn( nNode1, index );
5505					}
5506	
5507					index++;
5508				}
5509	
5510				nNode1 = nNode1.nextSibling;
5511				nNode2 = an2 ? nNode2.nextSibling : null;
5512			}
5513	
5514			i++;
5515		}
5516	}
5517	
5518	
5519	
5520	var __re_html_remove = /<.*?>/g;
5521	
5522	
5523	/**
5524	 * Calculate the width of columns for the table
5525	 *  @param {object} oSettings dataTables settings object
5526	 *  @memberof DataTable#oApi
5527	 */
5528	function _fnCalculateColumnWidths ( oSettings )
5529	{
5530		var
5531			table = oSettings.nTable,
5532			columns = oSettings.aoColumns,
5533			scroll = oSettings.oScroll,
5534			scrollY = scroll.sY,
5535			scrollX = scroll.sX,
5536			scrollXInner = scroll.sXInner,
5537			columnCount = columns.length,
5538			visibleColumns = _fnGetColumns( oSettings, 'bVisible' ),
5539			headerCells = $('th', oSettings.nTHead),
5540			tableWidthAttr = table.getAttribute('width'), // from DOM element
5541			tableContainer = table.parentNode,
5542			userInputs = false,
5543			i, column, columnIdx, width, outerWidth,
5544			browser = oSettings.oBrowser,
5545			ie67 = browser.bScrollOversize;
5546	
5547		var styleWidth = table.style.width;
5548		if ( styleWidth && styleWidth.indexOf('%') !== -1 ) {
5549			tableWidthAttr = styleWidth;
5550		}
5551	
5552		/* Convert any user input sizes into pixel sizes */
5553		for ( i=0 ; i<visibleColumns.length ; i++ ) {
5554			column = columns[ visibleColumns[i] ];
5555	
5556			if ( column.sWidth !== null ) {
5557				column.sWidth = _fnConvertToWidth( column.sWidthOrig, tableContainer );
5558	
5559				userInputs = true;
5560			}
5561		}
5562	
5563		/* If the number of columns in the DOM equals the number that we have to
5564		 * process in DataTables, then we can use the offsets that are created by
5565		 * the web- browser. No custom sizes can be set in order for this to happen,
5566		 * nor scrolling used
5567		 */
5568		if ( ie67 || ! userInputs && ! scrollX && ! scrollY &&
5569		     columnCount == _fnVisbleColumns( oSettings ) &&
5570		     columnCount == headerCells.length
5571		) {
5572			for ( i=0 ; i<columnCount ; i++ ) {
5573				var colIdx = _fnVisibleToColumnIndex( oSettings, i );
5574	
5575				if ( colIdx !== null ) {
5576					columns[ colIdx ].sWidth = _fnStringToCss( headerCells.eq(i).width() );
5577				}
5578			}
5579		}
5580		else
5581		{
5582			// Otherwise construct a single row, worst case, table with the widest
5583			// node in the data, assign any user defined widths, then insert it into
5584			// the DOM and allow the browser to do all the hard work of calculating
5585			// table widths
5586			var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table
5587				.css( 'visibility', 'hidden' )
5588				.removeAttr( 'id' );
5589	
5590			// Clean up the table body
5591			tmpTable.find('tbody tr').remove();
5592			var tr = $('<tr/>').appendTo( tmpTable.find('tbody') );
5593	
5594			// Clone the table header and footer - we can't use the header / footer
5595			// from the cloned table, since if scrolling is active, the table's
5596			// real header and footer are contained in different table tags
5597			tmpTable.find('thead, tfoot').remove();
5598			tmpTable
5599				.append( $(oSettings.nTHead).clone() )
5600				.append( $(oSettings.nTFoot).clone() );
5601	
5602			// Remove any assigned widths from the footer (from scrolling)
5603			tmpTable.find('tfoot th, tfoot td').css('width', '');
5604	
5605			// Apply custom sizing to the cloned header
5606			headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] );
5607	
5608			for ( i=0 ; i<visibleColumns.length ; i++ ) {
5609				column = columns[ visibleColumns[i] ];
5610	
5611				headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ?
5612					_fnStringToCss( column.sWidthOrig ) :
5613					'';
5614	
5615				// For scrollX we need to force the column width otherwise the
5616				// browser will collapse it. If this width is smaller than the
5617				// width the column requires, then it will have no effect
5618				if ( column.sWidthOrig && scrollX ) {
5619					$( headerCells[i] ).append( $('<div/>').css( {
5620						width: column.sWidthOrig,
5621						margin: 0,
5622						padding: 0,
5623						border: 0,
5624						height: 1
5625					} ) );
5626				}
5627			}
5628	
5629			// Find the widest cell for each column and put it into the table
5630			if ( oSettings.aoData.length ) {
5631				for ( i=0 ; i<visibleColumns.length ; i++ ) {
5632					columnIdx = visibleColumns[i];
5633					column = columns[ columnIdx ];
5634	
5635					$( _fnGetWidestNode( oSettings, columnIdx ) )
5636						.clone( false )
5637						.append( column.sContentPadding )
5638						.appendTo( tr );
5639				}
5640			}
5641	
5642			// Tidy the temporary table - remove name attributes so there aren't
5643			// duplicated in the dom (radio elements for example)
5644			$('[name]', tmpTable).removeAttr('name');
5645	
5646			// Table has been built, attach to the document so we can work with it.
5647			// A holding element is used, positioned at the top of the container
5648			// with minimal height, so it has no effect on if the container scrolls
5649			// or not. Otherwise it might trigger scrolling when it actually isn't
5650			// needed
5651			var holder = $('<div/>').css( scrollX || scrollY ?
5652					{
5653						position: 'absolute',
5654						top: 0,
5655						left: 0,
5656						height: 1,
5657						right: 0,
5658						overflow: 'hidden'
5659					} :
5660					{}
5661				)
5662				.append( tmpTable )
5663				.appendTo( tableContainer );
5664	
5665			// When scrolling (X or Y) we want to set the width of the table as 
5666			// appropriate. However, when not scrolling leave the table width as it
5667			// is. This results in slightly different, but I think correct behaviour
5668			if ( scrollX && scrollXInner ) {
5669				tmpTable.width( scrollXInner );
5670			}
5671			else if ( scrollX ) {
5672				tmpTable.css( 'width', 'auto' );
5673				tmpTable.removeAttr('width');
5674	
5675				// If there is no width attribute or style, then allow the table to
5676				// collapse
5677				if ( tmpTable.width() < tableContainer.clientWidth && tableWidthAttr ) {
5678					tmpTable.width( tableContainer.clientWidth );
5679				}
5680			}
5681			else if ( scrollY ) {
5682				tmpTable.width( tableContainer.clientWidth );
5683			}
5684			else if ( tableWidthAttr ) {
5685				tmpTable.width( tableWidthAttr );
5686			}
5687	
5688			// Get the width of each column in the constructed table - we need to
5689			// know the inner width (so it can be assigned to the other table's
5690			// cells) and the outer width so we can calculate the full width of the
5691			// table. This is safe since DataTables requires a unique cell for each
5692			// column, but if ever a header can span multiple columns, this will
5693			// need to be modified.
5694			var total = 0;
5695			for ( i=0 ; i<visibleColumns.length ; i++ ) {
5696				var cell = $(headerCells[i]);
5697				var border = cell.outerWidth() - cell.width();
5698	
5699				// Use getBounding... where possible (not IE8-) because it can give
5700				// sub-pixel accuracy, which we then want to round up!
5701				var bounding = browser.bBounding ?
5702					Math.ceil( headerCells[i].getBoundingClientRect().width ) :
5703					cell.outerWidth();
5704	
5705				// Total is tracked to remove any sub-pixel errors as the outerWidth
5706				// of the table might not equal the total given here (IE!).
5707				total += bounding;
5708	
5709				// Width for each column to use
5710				columns[ visibleColumns[i] ].sWidth = _fnStringToCss( bounding - border );
5711			}
5712	
5713			table.style.width = _fnStringToCss( total );
5714	
5715			// Finished with the table - ditch it
5716			holder.remove();
5717		}
5718	
5719		// If there is a width attr, we want to attach an event listener which
5720		// allows the table sizing to automatically adjust when the window is
5721		// resized. Use the width attr rather than CSS, since we can't know if the
5722		// CSS is a relative value or absolute - DOM read is always px.
5723		if ( tableWidthAttr ) {
5724			table.style.width = _fnStringToCss( tableWidthAttr );
5725		}
5726	
5727		if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) {
5728			var bindResize = function () {
5729				$(window).on('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {
5730					_fnAdjustColumnSizing( oSettings );
5731				} ) );
5732			};
5733	
5734			// IE6/7 will crash if we bind a resize event handler on page load.
5735			// To be removed in 1.11 which drops IE6/7 support
5736			if ( ie67 ) {
5737				setTimeout( bindResize, 1000 );
5738			}
5739			else {
5740				bindResize();
5741			}
5742	
5743			oSettings._reszEvt = true;
5744		}
5745	}
5746	
5747	
5748	/**
5749	 * Throttle the calls to a function. Arguments and context are maintained for
5750	 * the throttled function
5751	 *  @param {function} fn Function to be called
5752	 *  @param {int} [freq=200] call frequency in mS
5753	 *  @returns {function} wrapped function
5754	 *  @memberof DataTable#oApi
5755	 */
5756	var _fnThrottle = DataTable.util.throttle;
5757	
5758	
5759	/**
5760	 * Convert a CSS unit width to pixels (e.g. 2em)
5761	 *  @param {string} width width to be converted
5762	 *  @param {node} parent parent to get the with for (required for relative widths) - optional
5763	 *  @returns {int} width in pixels
5764	 *  @memberof DataTable#oApi
5765	 */
5766	function _fnConvertToWidth ( width, parent )
5767	{
5768		if ( ! width ) {
5769			return 0;
5770		}
5771	
5772		var n = $('<div/>')
5773			.css( 'width', _fnStringToCss( width ) )
5774			.appendTo( parent || document.body );
5775	
5776		var val = n[0].offsetWidth;
5777		n.remove();
5778	
5779		return val;
5780	}
5781	
5782	
5783	/**
5784	 * Get the widest node
5785	 *  @param {object} settings dataTables settings object
5786	 *  @param {int} colIdx column of interest
5787	 *  @returns {node} widest table node
5788	 *  @memberof DataTable#oApi
5789	 */
5790	function _fnGetWidestNode( settings, colIdx )
5791	{
5792		var idx = _fnGetMaxLenString( settings, colIdx );
5793		if ( idx < 0 ) {
5794			return null;
5795		}
5796	
5797		var data = settings.aoData[ idx ];
5798		return ! data.nTr ? // Might not have been created when deferred rendering
5799			$('<td/>').html( _fnGetCellData( settings, idx, colIdx, 'display' ) )[0] :
5800			data.anCells[ colIdx ];
5801	}
5802	
5803	
5804	/**
5805	 * Get the maximum strlen for each data column
5806	 *  @param {object} settings dataTables settings object
5807	 *  @param {int} colIdx column of interest
5808	 *  @returns {string} max string length for each column
5809	 *  @memberof DataTable#oApi
5810	 */
5811	function _fnGetMaxLenString( settings, colIdx )
5812	{
5813		var s, max=-1, maxIdx = -1;
5814	
5815		for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
5816			s = _fnGetCellData( settings, i, colIdx, 'display' )+'';
5817			s = s.replace( __re_html_remove, '' );
5818			s = s.replace( /&nbsp;/g, ' ' );
5819	
5820			if ( s.length > max ) {
5821				max = s.length;
5822				maxIdx = i;
5823			}
5824		}
5825	
5826		return maxIdx;
5827	}
5828	
5829	
5830	/**
5831	 * Append a CSS unit (only if required) to a string
5832	 *  @param {string} value to css-ify
5833	 *  @returns {string} value with css unit
5834	 *  @memberof DataTable#oApi
5835	 */
5836	function _fnStringToCss( s )
5837	{
5838		if ( s === null ) {
5839			return '0px';
5840		}
5841	
5842		if ( typeof s == 'number' ) {
5843			return s < 0 ?
5844				'0px' :
5845				s+'px';
5846		}
5847	
5848		// Check it has a unit character already
5849		return s.match(/\d$/) ?
5850			s+'px' :
5851			s;
5852	}
5853	
5854	
5855	
5856	function _fnSortFlatten ( settings )
5857	{
5858		var
5859			i, iLen, k, kLen,
5860			aSort = [],
5861			aiOrig = [],
5862			aoColumns = settings.aoColumns,
5863			aDataSort, iCol, sType, srcCol,
5864			fixed = settings.aaSortingFixed,
5865			fixedObj = $.isPlainObject( fixed ),
5866			nestedSort = [],
5867			add = function ( a ) {
5868				if ( a.length && ! 
vendor: 38,761 bytes, lines 5868-7358
5868$.isArray( a[0] ) ) {
5869					// 1D array
5870					nestedSort.push( a );
5871				}
5872				else {
5873					// 2D array
5874					$.merge( nestedSort, a );
5875				}
5876			};
5877	
5878		// Build the sort array, with pre-fix and post-fix options if they have been
5879		// specified
5880		if ( $.isArray( fixed ) ) {
5881			add( fixed );
5882		}
5883	
5884		if ( fixedObj && fixed.pre ) {
5885			add( fixed.pre );
5886		}
5887	
5888		add( settings.aaSorting );
5889	
5890		if (fixedObj && fixed.post ) {
5891			add( fixed.post );
5892		}
5893	
5894		for ( i=0 ; i<nestedSort.length ; i++ )
5895		{
5896			srcCol = nestedSort[i][0];
5897			aDataSort = aoColumns[ srcCol ].aDataSort;
5898	
5899			for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ )
5900			{
5901				iCol = aDataSort[k];
5902				sType = aoColumns[ iCol ].sType || 'string';
5903	
5904				if ( nestedSort[i]._idx === undefined ) {
5905					nestedSort[i]._idx = $.inArray( nestedSort[i][1], aoColumns[iCol].asSorting );
5906				}
5907	
5908				aSort.push( {
5909					src:       srcCol,
5910					col:       iCol,
5911					dir:       nestedSort[i][1],
5912					index:     nestedSort[i]._idx,
5913					type:      sType,
5914					formatter: DataTable.ext.type.order[ sType+"-pre" ]
5915				} );
5916			}
5917		}
5918	
5919		return aSort;
5920	}
5921	
5922	/**
5923	 * Change the order of the table
5924	 *  @param {object} oSettings dataTables settings object
5925	 *  @memberof DataTable#oApi
5926	 *  @todo This really needs split up!
5927	 */
5928	function _fnSort ( oSettings )
5929	{
5930		var
5931			i, ien, iLen, j, jLen, k, kLen,
5932			sDataType, nTh,
5933			aiOrig = [],
5934			oExtSort = DataTable.ext.type.order,
5935			aoData = oSettings.aoData,
5936			aoColumns = oSettings.aoColumns,
5937			aDataSort, data, iCol, sType, oSort,
5938			formatters = 0,
5939			sortCol,
5940			displayMaster = oSettings.aiDisplayMaster,
5941			aSort;
5942	
5943		// Resolve any column types that are unknown due to addition or invalidation
5944		// @todo Can this be moved into a 'data-ready' handler which is called when
5945		//   data is going to be used in the table?
5946		_fnColumnTypes( oSettings );
5947	
5948		aSort = _fnSortFlatten( oSettings );
5949	
5950		for ( i=0, ien=aSort.length ; i<ien ; i++ ) {
5951			sortCol = aSort[i];
5952	
5953			// Track if we can use the fast sort algorithm
5954			if ( sortCol.formatter ) {
5955				formatters++;
5956			}
5957	
5958			// Load the data needed for the sort, for each cell
5959			_fnSortData( oSettings, sortCol.col );
5960		}
5961	
5962		/* No sorting required if server-side or no sorting array */
5963		if ( _fnDataSource( oSettings ) != 'ssp' && aSort.length !== 0 )
5964		{
5965			// Create a value - key array of the current row positions such that we can use their
5966			// current position during the sort, if values match, in order to perform stable sorting
5967			for ( i=0, iLen=displayMaster.length ; i<iLen ; i++ ) {
5968				aiOrig[ displayMaster[i] ] = i;
5969			}
5970	
5971			/* Do the sort - here we want multi-column sorting based on a given data source (column)
5972			 * and sorting function (from oSort) in a certain direction. It's reasonably complex to
5973			 * follow on it's own, but this is what we want (example two column sorting):
5974			 *  fnLocalSorting = function(a,b){
5975			 *    var iTest;
5976			 *    iTest = oSort['string-asc']('data11', 'data12');
5977			 *      if (iTest !== 0)
5978			 *        return iTest;
5979			 *    iTest = oSort['numeric-desc']('data21', 'data22');
5980			 *    if (iTest !== 0)
5981			 *      return iTest;
5982			 *    return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
5983			 *  }
5984			 * Basically we have a test for each sorting column, if the data in that column is equal,
5985			 * test the next column. If all columns match, then we use a numeric sort on the row
5986			 * positions in the original data array to provide a stable sort.
5987			 *
5988			 * Note - I know it seems excessive to have two sorting methods, but the first is around
5989			 * 15% faster, so the second is only maintained for backwards compatibility with sorting
5990			 * methods which do not have a pre-sort formatting function.
5991			 */
5992			if ( formatters === aSort.length ) {
5993				// All sort types have formatting functions
5994				displayMaster.sort( function ( a, b ) {
5995					var
5996						x, y, k, test, sort,
5997						len=aSort.length,
5998						dataA = aoData[a]._aSortData,
5999						dataB = aoData[b]._aSortData;
6000	
6001					for ( k=0 ; k<len ; k++ ) {
6002						sort = aSort[k];
6003	
6004						x = dataA[ sort.col ];
6005						y = dataB[ sort.col ];
6006	
6007						test = x<y ? -1 : x>y ? 1 : 0;
6008						if ( test !== 0 ) {
6009							return sort.dir === 'asc' ? test : -test;
6010						}
6011					}
6012	
6013					x = aiOrig[a];
6014					y = aiOrig[b];
6015					return x<y ? -1 : x>y ? 1 : 0;
6016				} );
6017			}
6018			else {
6019				// Depreciated - remove in 1.11 (providing a plug-in option)
6020				// Not all sort types have formatting methods, so we have to call their sorting
6021				// methods.
6022				displayMaster.sort( function ( a, b ) {
6023					var
6024						x, y, k, l, test, sort, fn,
6025						len=aSort.length,
6026						dataA = aoData[a]._aSortData,
6027						dataB = aoData[b]._aSortData;
6028	
6029					for ( k=0 ; k<len ; k++ ) {
6030						sort = aSort[k];
6031	
6032						x = dataA[ sort.col ];
6033						y = dataB[ sort.col ];
6034	
6035						fn = oExtSort[ sort.type+"-"+sort.dir ] || oExtSort[ "string-"+sort.dir ];
6036						test = fn( x, y );
6037						if ( test !== 0 ) {
6038							return test;
6039						}
6040					}
6041	
6042					x = aiOrig[a];
6043					y = aiOrig[b];
6044					return x<y ? -1 : x>y ? 1 : 0;
6045				} );
6046			}
6047		}
6048	
6049		/* Tell the draw function that we have sorted the data */
6050		oSettings.bSorted = true;
6051	}
6052	
6053	
6054	function _fnSortAria ( settings )
6055	{
6056		var label;
6057		var nextSort;
6058		var columns = settings.aoColumns;
6059		var aSort = _fnSortFlatten( settings );
6060		var oAria = settings.oLanguage.oAria;
6061	
6062		// ARIA attributes - need to loop all columns, to update all (removing old
6063		// attributes as needed)
6064		for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
6065		{
6066			var col = columns[i];
6067			var asSorting = col.asSorting;
6068			var sTitle = col.sTitle.replace( /<.*?>/g, "" );
6069			var th = col.nTh;
6070	
6071			// IE7 is throwing an error when setting these properties with jQuery's
6072			// attr() and removeAttr() methods...
6073			th.removeAttribute('aria-sort');
6074	
6075			/* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
6076			if ( col.bSortable ) {
6077				if ( aSort.length > 0 && aSort[0].col == i ) {
6078					th.setAttribute('aria-sort', aSort[0].dir=="asc" ? "ascending" : "descending" );
6079					nextSort = asSorting[ aSort[0].index+1 ] || asSorting[0];
6080				}
6081				else {
6082					nextSort = asSorting[0];
6083				}
6084	
6085				label = sTitle + ( nextSort === "asc" ?
6086					oAria.sSortAscending :
6087					oAria.sSortDescending
6088				);
6089			}
6090			else {
6091				label = sTitle;
6092			}
6093	
6094			th.setAttribute('aria-label', label);
6095		}
6096	}
6097	
6098	
6099	/**
6100	 * Function to run on user sort request
6101	 *  @param {object} settings dataTables settings object
6102	 *  @param {node} attachTo node to attach the handler to
6103	 *  @param {int} colIdx column sorting index
6104	 *  @param {boolean} [append=false] Append the requested sort to the existing
6105	 *    sort if true (i.e. multi-column sort)
6106	 *  @param {function} [callback] callback function
6107	 *  @memberof DataTable#oApi
6108	 */
6109	function _fnSortListener ( settings, colIdx, append, callback )
6110	{
6111		var col = settings.aoColumns[ colIdx ];
6112		var sorting = settings.aaSorting;
6113		var asSorting = col.asSorting;
6114		var nextSortIdx;
6115		var next = function ( a, overflow ) {
6116			var idx = a._idx;
6117			if ( idx === undefined ) {
6118				idx = $.inArray( a[1], asSorting );
6119			}
6120	
6121			return idx+1 < asSorting.length ?
6122				idx+1 :
6123				overflow ?
6124					null :
6125					0;
6126		};
6127	
6128		// Convert to 2D array if needed
6129		if ( typeof sorting[0] === 'number' ) {
6130			sorting = settings.aaSorting = [ sorting ];
6131		}
6132	
6133		// If appending the sort then we are multi-column sorting
6134		if ( append && settings.oFeatures.bSortMulti ) {
6135			// Are we already doing some kind of sort on this column?
6136			var sortIdx = $.inArray( colIdx, _pluck(sorting, '0') );
6137	
6138			if ( sortIdx !== -1 ) {
6139				// Yes, modify the sort
6140				nextSortIdx = next( sorting[sortIdx], true );
6141	
6142				if ( nextSortIdx === null && sorting.length === 1 ) {
6143					nextSortIdx = 0; // can't remove sorting completely
6144				}
6145	
6146				if ( nextSortIdx === null ) {
6147					sorting.splice( sortIdx, 1 );
6148				}
6149				else {
6150					sorting[sortIdx][1] = asSorting[ nextSortIdx ];
6151					sorting[sortIdx]._idx = nextSortIdx;
6152				}
6153			}
6154			else {
6155				// No sort on this column yet
6156				sorting.push( [ colIdx, asSorting[0], 0 ] );
6157				sorting[sorting.length-1]._idx = 0;
6158			}
6159		}
6160		else if ( sorting.length && sorting[0][0] == colIdx ) {
6161			// Single column - already sorting on this column, modify the sort
6162			nextSortIdx = next( sorting[0] );
6163	
6164			sorting.length = 1;
6165			sorting[0][1] = asSorting[ nextSortIdx ];
6166			sorting[0]._idx = nextSortIdx;
6167		}
6168		else {
6169			// Single column - sort only on this column
6170			sorting.length = 0;
6171			sorting.push( [ colIdx, asSorting[0] ] );
6172			sorting[0]._idx = 0;
6173		}
6174	
6175		// Run the sort by calling a full redraw
6176		_fnReDraw( settings );
6177	
6178		// callback used for async user interaction
6179		if ( typeof callback == 'function' ) {
6180			callback( settings );
6181		}
6182	}
6183	
6184	
6185	/**
6186	 * Attach a sort handler (click) to a node
6187	 *  @param {object} settings dataTables settings object
6188	 *  @param {node} attachTo node to attach the handler to
6189	 *  @param {int} colIdx column sorting index
6190	 *  @param {function} [callback] callback function
6191	 *  @memberof DataTable#oApi
6192	 */
6193	function _fnSortAttachListener ( settings, attachTo, colIdx, callback )
6194	{
6195		var col = settings.aoColumns[ colIdx ];
6196	
6197		_fnBindAction( attachTo, {}, function (e) {
6198			/* If the column is not sortable - don't to anything */
6199			if ( col.bSortable === false ) {
6200				return;
6201			}
6202	
6203			// If processing is enabled use a timeout to allow the processing
6204			// display to be shown - otherwise to it synchronously
6205			if ( settings.oFeatures.bProcessing ) {
6206				_fnProcessingDisplay( settings, true );
6207	
6208				setTimeout( function() {
6209					_fnSortListener( settings, colIdx, e.shiftKey, callback );
6210	
6211					// In server-side processing, the draw callback will remove the
6212					// processing display
6213					if ( _fnDataSource( settings ) !== 'ssp' ) {
6214						_fnProcessingDisplay( settings, false );
6215					}
6216				}, 0 );
6217			}
6218			else {
6219				_fnSortListener( settings, colIdx, e.shiftKey, callback );
6220			}
6221		} );
6222	}
6223	
6224	
6225	/**
6226	 * Set the sorting classes on table's body, Note: it is safe to call this function
6227	 * when bSort and bSortClasses are false
6228	 *  @param {object} oSettings dataTables settings object
6229	 *  @memberof DataTable#oApi
6230	 */
6231	function _fnSortingClasses( settings )
6232	{
6233		var oldSort = settings.aLastSort;
6234		var sortClass = settings.oClasses.sSortColumn;
6235		var sort = _fnSortFlatten( settings );
6236		var features = settings.oFeatures;
6237		var i, ien, colIdx;
6238	
6239		if ( features.bSort && features.bSortClasses ) {
6240			// Remove old sorting classes
6241			for ( i=0, ien=oldSort.length ; i<ien ; i++ ) {
6242				colIdx = oldSort[i].src;
6243	
6244				// Remove column sorting
6245				$( _pluck( settings.aoData, 'anCells', colIdx ) )
6246					.removeClass( sortClass + (i<2 ? i+1 : 3) );
6247			}
6248	
6249			// Add new column sorting
6250			for ( i=0, ien=sort.length ; i<ien ; i++ ) {
6251				colIdx = sort[i].src;
6252	
6253				$( _pluck( settings.aoData, 'anCells', colIdx ) )
6254					.addClass( sortClass + (i<2 ? i+1 : 3) );
6255			}
6256		}
6257	
6258		settings.aLastSort = sort;
6259	}
6260	
6261	
6262	// Get the data to sort a column, be it from cache, fresh (populating the
6263	// cache), or from a sort formatter
6264	function _fnSortData( settings, idx )
6265	{
6266		// Custom sorting function - provided by the sort data type
6267		var column = settings.aoColumns[ idx ];
6268		var customSort = DataTable.ext.order[ column.sSortDataType ];
6269		var customData;
6270	
6271		if ( customSort ) {
6272			customData = customSort.call( settings.oInstance, settings, idx,
6273				_fnColumnIndexToVisible( settings, idx )
6274			);
6275		}
6276	
6277		// Use / populate cache
6278		var row, cellData;
6279		var formatter = DataTable.ext.type.order[ column.sType+"-pre" ];
6280	
6281		for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
6282			row = settings.aoData[i];
6283	
6284			if ( ! row._aSortData ) {
6285				row._aSortData = [];
6286			}
6287	
6288			if ( ! row._aSortData[idx] || customSort ) {
6289				cellData = customSort ?
6290					customData[i] : // If there was a custom sort function, use data from there
6291					_fnGetCellData( settings, i, idx, 'sort' );
6292	
6293				row._aSortData[ idx ] = formatter ?
6294					formatter( cellData ) :
6295					cellData;
6296			}
6297		}
6298	}
6299	
6300	
6301	
6302	/**
6303	 * Save the state of a table
6304	 *  @param {object} oSettings dataTables settings object
6305	 *  @memberof DataTable#oApi
6306	 */
6307	function _fnSaveState ( settings )
6308	{
6309		if ( !settings.oFeatures.bStateSave || settings.bDestroying )
6310		{
6311			return;
6312		}
6313	
6314		/* Store the interesting variables */
6315		var state = {
6316			time:    +new Date(),
6317			start:   settings._iDisplayStart,
6318			length:  settings._iDisplayLength,
6319			order:   $.extend( true, [], settings.aaSorting ),
6320			search:  _fnSearchToCamel( settings.oPreviousSearch ),
6321			columns: $.map( settings.aoColumns, function ( col, i ) {
6322				return {
6323					visible: col.bVisible,
6324					search: _fnSearchToCamel( settings.aoPreSearchCols[i] )
6325				};
6326			} )
6327		};
6328	
6329		_fnCallbackFire( settings, "aoStateSaveParams", 'stateSaveParams', [settings, state] );
6330	
6331		settings.oSavedState = state;
6332		settings.fnStateSaveCallback.call( settings.oInstance, settings, state );
6333	}
6334	
6335	
6336	/**
6337	 * Attempt to load a saved table state
6338	 *  @param {object} oSettings dataTables settings object
6339	 *  @param {object} oInit DataTables init object so we can override settings
6340	 *  @param {function} callback Callback to execute when the state has been loaded
6341	 *  @memberof DataTable#oApi
6342	 */
6343	function _fnLoadState ( settings, oInit, callback )
6344	{
6345		var i, ien;
6346		var columns = settings.aoColumns;
6347		var loaded = function ( s ) {
6348			if ( ! s || ! s.time ) {
6349				callback();
6350				return;
6351			}
6352	
6353			// Allow custom and plug-in manipulation functions to alter the saved data set and
6354			// cancelling of loading by returning false
6355			var abStateLoad = _fnCallbackFire( settings, 'aoStateLoadParams', 'stateLoadParams', [settings, s] );
6356			if ( $.inArray( false, abStateLoad ) !== -1 ) {
6357				callback();
6358				return;
6359			}
6360	
6361			// Reject old data
6362			var duration = settings.iStateDuration;
6363			if ( duration > 0 && s.time < +new Date() - (duration*1000) ) {
6364				callback();
6365				return;
6366			}
6367	
6368			// Number of columns have changed - all bets are off, no restore of settings
6369			if ( s.columns && columns.length !== s.columns.length ) {
6370				callback();
6371				return;
6372			}
6373	
6374			// Store the saved state so it might be accessed at any time
6375			settings.oLoadedState = $.extend( true, {}, s );
6376	
6377			// Restore key features - todo - for 1.11 this needs to be done by
6378			// subscribed events
6379			if ( s.start !== undefined ) {
6380				settings._iDisplayStart    = s.start;
6381				settings.iInitDisplayStart = s.start;
6382			}
6383			if ( s.length !== undefined ) {
6384				settings._iDisplayLength   = s.length;
6385			}
6386	
6387			// Order
6388			if ( s.order !== undefined ) {
6389				settings.aaSorting = [];
6390				$.each( s.order, function ( i, col ) {
6391					settings.aaSorting.push( col[0] >= columns.length ?
6392						[ 0, col[1] ] :
6393						col
6394					);
6395				} );
6396			}
6397	
6398			// Search
6399			if ( s.search !== undefined ) {
6400				$.extend( settings.oPreviousSearch, _fnSearchToHung( s.search ) );
6401			}
6402	
6403			// Columns
6404			//
6405			if ( s.columns ) {
6406				for ( i=0, ien=s.columns.length ; i<ien ; i++ ) {
6407					var col = s.columns[i];
6408	
6409					// Visibility
6410					if ( col.visible !== undefined ) {
6411						columns[i].bVisible = col.visible;
6412					}
6413	
6414					// Search
6415					if ( col.search !== undefined ) {
6416						$.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) );
6417					}
6418				}
6419			}
6420	
6421			_fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, s] );
6422			callback();
6423		};
6424	
6425		if ( ! settings.oFeatures.bStateSave ) {
6426			callback();
6427			return;
6428		}
6429	
6430		var state = settings.fnStateLoadCallback.call( settings.oInstance, settings, loaded );
6431	
6432		if ( state !== undefined ) {
6433			loaded( state );
6434		}
6435		// otherwise, wait for the loaded callback to be executed
6436	}
6437	
6438	
6439	/**
6440	 * Return the settings object for a particular table
6441	 *  @param {node} table table we are using as a dataTable
6442	 *  @returns {object} Settings object - or null if not found
6443	 *  @memberof DataTable#oApi
6444	 */
6445	function _fnSettingsFromNode ( table )
6446	{
6447		var settings = DataTable.settings;
6448		var idx = $.inArray( table, _pluck( settings, 'nTable' ) );
6449	
6450		return idx !== -1 ?
6451			settings[ idx ] :
6452			null;
6453	}
6454	
6455	
6456	/**
6457	 * Log an error message
6458	 *  @param {object} settings dataTables settings object
6459	 *  @param {int} level log error messages, or display them to the user
6460	 *  @param {string} msg error message
6461	 *  @param {int} tn Technical note id to get more information about the error.
6462	 *  @memberof DataTable#oApi
6463	 */
6464	function _fnLog( settings, level, msg, tn )
6465	{
6466		msg = 'DataTables warning: '+
6467			(settings ? 'table id='+settings.sTableId+' - ' : '')+msg;
6468	
6469		if ( tn ) {
6470			msg += '. For more information about this error, please see '+
6471			'http://datatables.net/tn/'+tn;
6472		}
6473	
6474		if ( ! level  ) {
6475			// Backwards compatibility pre 1.10
6476			var ext = DataTable.ext;
6477			var type = ext.sErrMode || ext.errMode;
6478	
6479			if ( settings ) {
6480				_fnCallbackFire( settings, null, 'error', [ settings, tn, msg ] );
6481			}
6482	
6483			if ( type == 'alert' ) {
6484				alert( msg );
6485			}
6486			else if ( type == 'throw' ) {
6487				throw new Error(msg);
6488			}
6489			else if ( typeof type == 'function' ) {
6490				type( settings, tn, msg );
6491			}
6492		}
6493		else if ( window.console && console.log ) {
6494			console.log( msg );
6495		}
6496	}
6497	
6498	
6499	/**
6500	 * See if a property is defined on one object, if so assign it to the other object
6501	 *  @param {object} ret target object
6502	 *  @param {object} src source object
6503	 *  @param {string} name property
6504	 *  @param {string} [mappedName] name to map too - optional, name used if not given
6505	 *  @memberof DataTable#oApi
6506	 */
6507	function _fnMap( ret, src, name, mappedName )
6508	{
6509		if ( $.isArray( name ) ) {
6510			$.each( name, function (i, val) {
6511				if ( $.isArray( val ) ) {
6512					_fnMap( ret, src, val[0], val[1] );
6513				}
6514				else {
6515					_fnMap( ret, src, val );
6516				}
6517			} );
6518	
6519			return;
6520		}
6521	
6522		if ( mappedName === undefined ) {
6523			mappedName = name;
6524		}
6525	
6526		if ( src[name] !== undefined ) {
6527			ret[mappedName] = src[name];
6528		}
6529	}
6530	
6531	
6532	/**
6533	 * Extend objects - very similar to jQuery.extend, but deep copy objects, and
6534	 * shallow copy arrays. The reason we need to do this, is that we don't want to
6535	 * deep copy array init values (such as aaSorting) since the dev wouldn't be
6536	 * able to override them, but we do want to deep copy arrays.
6537	 *  @param {object} out Object to extend
6538	 *  @param {object} extender Object from which the properties will be applied to
6539	 *      out
6540	 *  @param {boolean} breakRefs If true, then arrays will be sliced to take an
6541	 *      independent copy with the exception of the `data` or `aaData` parameters
6542	 *      if they are present. This is so you can pass in a collection to
6543	 *      DataTables and have that used as your data source without breaking the
6544	 *      references
6545	 *  @returns {object} out Reference, just for convenience - out === the return.
6546	 *  @memberof DataTable#oApi
6547	 *  @todo This doesn't take account of arrays inside the deep copied objects.
6548	 */
6549	function _fnExtend( out, extender, breakRefs )
6550	{
6551		var val;
6552	
6553		for ( var prop in extender ) {
6554			if ( extender.hasOwnProperty(prop) ) {
6555				val = extender[prop];
6556	
6557				if ( $.isPlainObject( val ) ) {
6558					if ( ! $.isPlainObject( out[prop] ) ) {
6559						out[prop] = {};
6560					}
6561					$.extend( true, out[prop], val );
6562				}
6563				else if ( breakRefs && prop !== 'data' && prop !== 'aaData' && $.isArray(val) ) {
6564					out[prop] = val.slice();
6565				}
6566				else {
6567					out[prop] = val;
6568				}
6569			}
6570		}
6571	
6572		return out;
6573	}
6574	
6575	
6576	/**
6577	 * Bind an event handers to allow a click or return key to activate the callback.
6578	 * This is good for accessibility since a return on the keyboard will have the
6579	 * same effect as a click, if the element has focus.
6580	 *  @param {element} n Element to bind the action to
6581	 *  @param {object} oData Data object to pass to the triggered function
6582	 *  @param {function} fn Callback function for when the event is triggered
6583	 *  @memberof DataTable#oApi
6584	 */
6585	function _fnBindAction( n, oData, fn )
6586	{
6587		$(n)
6588			.on( 'click.DT', oData, function (e) {
6589					$(n).trigger('blur'); // Remove focus outline for mouse users
6590					fn(e);
6591				} )
6592			.on( 'keypress.DT', oData, function (e){
6593					if ( e.which === 13 ) {
6594						e.preventDefault();
6595						fn(e);
6596					}
6597				} )
6598			.on( 'selectstart.DT', function () {
6599					/* Take the brutal approach to cancelling text selection */
6600					return false;
6601				} );
6602	}
6603	
6604	
6605	/**
6606	 * Register a callback function. Easily allows a callback function to be added to
6607	 * an array store of callback functions that can then all be called together.
6608	 *  @param {object} oSettings dataTables settings object
6609	 *  @param {string} sStore Name of the array storage for the callbacks in oSettings
6610	 *  @param {function} fn Function to be called back
6611	 *  @param {string} sName Identifying name for the callback (i.e. a label)
6612	 *  @memberof DataTable#oApi
6613	 */
6614	function _fnCallbackReg( oSettings, sStore, fn, sName )
6615	{
6616		if ( fn )
6617		{
6618			oSettings[sStore].push( {
6619				"fn": fn,
6620				"sName": sName
6621			} );
6622		}
6623	}
6624	
6625	
6626	/**
6627	 * Fire callback functions and trigger events. Note that the loop over the
6628	 * callback array store is done backwards! Further note that you do not want to
6629	 * fire off triggers in time sensitive applications (for example cell creation)
6630	 * as its slow.
6631	 *  @param {object} settings dataTables settings object
6632	 *  @param {string} callbackArr Name of the array storage for the callbacks in
6633	 *      oSettings
6634	 *  @param {string} eventName Name of the jQuery custom event to trigger. If
6635	 *      null no trigger is fired
6636	 *  @param {array} args Array of arguments to pass to the callback function /
6637	 *      trigger
6638	 *  @memberof DataTable#oApi
6639	 */
6640	function _fnCallbackFire( settings, callbackArr, eventName, args )
6641	{
6642		var ret = [];
6643	
6644		if ( callbackArr ) {
6645			ret = $.map( settings[callbackArr].slice().reverse(), function (val, i) {
6646				return val.fn.apply( settings.oInstance, args );
6647			} );
6648		}
6649	
6650		if ( eventName !== null ) {
6651			var e = $.Event( eventName+'.dt' );
6652	
6653			$(settings.nTable).trigger( e, args );
6654	
6655			ret.push( e.result );
6656		}
6657	
6658		return ret;
6659	}
6660	
6661	
6662	function _fnLengthOverflow ( settings )
6663	{
6664		var
6665			start = settings._iDisplayStart,
6666			end = settings.fnDisplayEnd(),
6667			len = settings._iDisplayLength;
6668	
6669		/* If we have space to show extra rows (backing up from the end point - then do so */
6670		if ( start >= end )
6671		{
6672			start = end - len;
6673		}
6674	
6675		// Keep the start record on the current page
6676		start -= (start % len);
6677	
6678		if ( len === -1 || start < 0 )
6679		{
6680			start = 0;
6681		}
6682	
6683		settings._iDisplayStart = start;
6684	}
6685	
6686	
6687	function _fnRenderer( settings, type )
6688	{
6689		var renderer = settings.renderer;
6690		var host = DataTable.ext.renderer[type];
6691	
6692		if ( $.isPlainObject( renderer ) && renderer[type] ) {
6693			// Specific renderer for this type. If available use it, otherwise use
6694			// the default.
6695			return host[renderer[type]] || host._;
6696		}
6697		else if ( typeof renderer === 'string' ) {
6698			// Common renderer - if there is one available for this type use it,
6699			// otherwise use the default
6700			return host[renderer] || host._;
6701		}
6702	
6703		// Use the default
6704		return host._;
6705	}
6706	
6707	
6708	/**
6709	 * Detect the data source being used for the table. Used to simplify the code
6710	 * a little (ajax) and to make it compress a little smaller.
6711	 *
6712	 *  @param {object} settings dataTables settings object
6713	 *  @returns {string} Data source
6714	 *  @memberof DataTable#oApi
6715	 */
6716	function _fnDataSource ( settings )
6717	{
6718		if ( settings.oFeatures.bServerSide ) {
6719			return 'ssp';
6720		}
6721		else if ( settings.ajax || settings.sAjaxSource ) {
6722			return 'ajax';
6723		}
6724		return 'dom';
6725	}
6726	
6727
6728	
6729	
6730	/**
6731	 * Computed structure of the DataTables API, defined by the options passed to
6732	 * `DataTable.Api.register()` when building the API.
6733	 *
6734	 * The structure is built in order to speed creation and extension of the Api
6735	 * objects since the extensions are effectively pre-parsed.
6736	 *
6737	 * The array is an array of objects with the following structure, where this
6738	 * base array represents the Api prototype base:
6739	 *
6740	 *     [
6741	 *       {
6742	 *         name:      'data'                -- string   - Property name
6743	 *         val:       function () {},       -- function - Api method (or undefined if just an object
6744	 *         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
6745	 *         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
6746	 *       },
6747	 *       {
6748	 *         name:     'row'
6749	 *         val:       {},
6750	 *         methodExt: [ ... ],
6751	 *         propExt:   [
6752	 *           {
6753	 *             name:      'data'
6754	 *             val:       function () {},
6755	 *             methodExt: [ ... ],
6756	 *             propExt:   [ ... ]
6757	 *           },
6758	 *           ...
6759	 *         ]
6760	 *       }
6761	 *     ]
6762	 *
6763	 * @type {Array}
6764	 * @ignore
6765	 */
6766	var __apiStruct = [];
6767	
6768	
6769	/**
6770	 * `Array.prototype` reference.
6771	 *
6772	 * @type object
6773	 * @ignore
6774	 */
6775	var __arrayProto = Array.prototype;
6776	
6777	
6778	/**
6779	 * Abstraction for `context` parameter of the `Api` constructor to allow it to
6780	 * take several different forms for ease of use.
6781	 *
6782	 * Each of the input parameter types will be converted to a DataTables settings
6783	 * object where possible.
6784	 *
6785	 * @param  {string|node|jQuery|object} mixed DataTable identifier. Can be one
6786	 *   of:
6787	 *
6788	 *   * `string` - jQuery selector. Any DataTables' matching the given selector
6789	 *     with be found and used.
6790	 *   * `node` - `TABLE` node which has already been formed into a DataTable.
6791	 *   * `jQuery` - A jQuery object of `TABLE` nodes.
6792	 *   * `object` - DataTables settings object
6793	 *   * `DataTables.Api` - API instance
6794	 * @return {array|null} Matching DataTables settings objects. `null` or
6795	 *   `undefined` is returned if no matching DataTable is found.
6796	 * @ignore
6797	 */
6798	var _toSettings = function ( mixed )
6799	{
6800		var idx, jq;
6801		var settings = DataTable.settings;
6802		var tables = $.map( settings, function (el, i) {
6803			return el.nTable;
6804		} );
6805	
6806		if ( ! mixed ) {
6807			return [];
6808		}
6809		else if ( mixed.nTable && mixed.oApi ) {
6810			// DataTables settings object
6811			return [ mixed ];
6812		}
6813		else if ( mixed.nodeName && mixed.nodeName.toLowerCase() === 'table' ) {
6814			// Table node
6815			idx = $.inArray( mixed, tables );
6816			return idx !== -1 ? [ settings[idx] ] : null;
6817		}
6818		else if ( mixed && typeof mixed.settings === 'function' ) {
6819			return mixed.settings().toArray();
6820		}
6821		else if ( typeof mixed === 'string' ) {
6822			// jQuery selector
6823			jq = $(mixed);
6824		}
6825		else if ( mixed instanceof $ ) {
6826			// jQuery object (also DataTables instance)
6827			jq = mixed;
6828		}
6829	
6830		if ( jq ) {
6831			return jq.map( function(i) {
6832				idx = $.inArray( this, tables );
6833				return idx !== -1 ? settings[idx] : null;
6834			} ).toArray();
6835		}
6836	};
6837	
6838	
6839	/**
6840	 * DataTables API class - used to control and interface with  one or more
6841	 * DataTables enhanced tables.
6842	 *
6843	 * The API class is heavily based on jQuery, presenting a chainable interface
6844	 * that you can use to interact with tables. Each instance of the API class has
6845	 * a "context" - i.e. the tables that it will operate on. This could be a single
6846	 * table, all tables on a page or a sub-set thereof.
6847	 *
6848	 * Additionally the API is designed to allow you to easily work with the data in
6849	 * the tables, retrieving and manipulating it as required. This is done by
6850	 * presenting the API class as an array like interface. The contents of the
6851	 * array depend upon the actions requested by each method (for example
6852	 * `rows().nodes()` will return an array of nodes, while `rows().data()` will
6853	 * return an array of objects or arrays depending upon your table's
6854	 * configuration). The API object has a number of array like methods (`push`,
6855	 * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`,
6856	 * `unique` etc) to assist your working with the data held in a table.
6857	 *
6858	 * Most methods (those which return an Api instance) are chainable, which means
6859	 * the return from a method call also has all of the methods available that the
6860	 * top level object had. For example, these two calls are equivalent:
6861	 *
6862	 *     // Not chained
6863	 *     api.row.add( {...} );
6864	 *     api.draw();
6865	 *
6866	 *     // Chained
6867	 *     api.row.add( {...} ).draw();
6868	 *
6869	 * @class DataTable.Api
6870	 * @param {array|object|string|jQuery} context DataTable identifier. This is
6871	 *   used to define which DataTables enhanced tables this API will operate on.
6872	 *   Can be one of:
6873	 *
6874	 *   * `string` - jQuery selector. Any DataTables' matching the given selector
6875	 *     with be found and used.
6876	 *   * `node` - `TABLE` node which has already been formed into a DataTable.
6877	 *   * `jQuery` - A jQuery object of `TABLE` nodes.
6878	 *   * `object` - DataTables settings object
6879	 * @param {array} [data] Data to initialise the Api instance with.
6880	 *
6881	 * @example
6882	 *   // Direct initialisation during DataTables construction
6883	 *   var api = $('#example').DataTable();
6884	 *
6885	 * @example
6886	 *   // Initialisation using a DataTables jQuery object
6887	 *   var api = $('#example').dataTable().api();
6888	 *
6889	 * @example
6890	 *   // Initialisation as a constructor
6891	 *   var api = new $.fn.DataTable.Api( 'table.dataTable' );
6892	 */
6893	_Api = function ( context, data )
6894	{
6895		if ( ! (this instanceof _Api) ) {
6896			return new _Api( context, data );
6897		}
6898	
6899		var settings = [];
6900		var ctxSettings = function ( o ) {
6901			var a = _toSettings( o );
6902			if ( a ) {
6903				settings.push.apply( settings, a );
6904			}
6905		};
6906	
6907		if ( $.isArray( context ) ) {
6908			for ( var i=0, ien=context.length ; i<ien ; i++ ) {
6909				ctxSettings( context[i] );
6910			}
6911		}
6912		else {
6913			ctxSettings( context );
6914		}
6915	
6916		// Remove duplicates
6917		this.context = _unique( settings );
6918	
6919		// Initial data
6920		if ( data ) {
6921			$.merge( this, data );
6922		}
6923	
6924		// selector
6925		this.selector = {
6926			rows: null,
6927			cols: null,
6928			opts: null
6929		};
6930	
6931		_Api.extend( this, this, __apiStruct );
6932	};
6933	
6934	DataTable.Api = _Api;
6935	
6936	// Don't destroy the existing prototype, just extend it. Required for jQuery 2's
6937	// isPlainObject.
6938	$.extend( _Api.prototype, {
6939		any: function ()
6940		{
6941			return this.count() !== 0;
6942		},
6943	
6944	
6945		concat:  __arrayProto.concat,
6946	
6947	
6948		context: [], // array of table settings objects
6949	
6950	
6951		count: function ()
6952		{
6953			return this.flatten().length;
6954		},
6955	
6956	
6957		each: function ( fn )
6958		{
6959			for ( var i=0, ien=this.length ; i<ien; i++ ) {
6960				fn.call( this, this[i], i, this );
6961			}
6962	
6963			return this;
6964		},
6965	
6966	
6967		eq: function ( idx )
6968		{
6969			var ctx = this.context;
6970	
6971			return ctx.length > idx ?
6972				new _Api( ctx[idx], this[idx] ) :
6973				null;
6974		},
6975	
6976	
6977		filter: function ( fn )
6978		{
6979			var a = [];
6980	
6981			if ( __arrayProto.filter ) {
6982				a = __arrayProto.filter.call( this, fn, this );
6983			}
6984			else {
6985				// Compatibility for browsers without EMCA-252-5 (JS 1.6)
6986				for ( var i=0, ien=this.length ; i<ien ; i++ ) {
6987					if ( fn.call( this, this[i], i, this ) ) {
6988						a.push( this[i] );
6989					}
6990				}
6991			}
6992	
6993			return new _Api( this.context, a );
6994		},
6995	
6996	
6997		flatten: function ()
6998		{
6999			var a = [];
7000			return new _Api( this.context, a.concat.apply( a, this.toArray() ) );
7001		},
7002	
7003	
7004		join:    __arrayProto.join,
7005	
7006	
7007		indexOf: __arrayProto.indexOf || function (obj, start)
7008		{
7009			for ( var i=(start || 0), ien=this.length ; i<ien ; i++ ) {
7010				if ( this[i] === obj ) {
7011					return i;
7012				}
7013			}
7014			return -1;
7015		},
7016	
7017		iterator: function ( flatten, type, fn, alwaysNew ) {
7018			var
7019				a = [], ret,
7020				i, ien, j, jen,
7021				context = this.context,
7022				rows, items, item,
7023				selector = this.selector;
7024	
7025			// Argument shifting
7026			if ( typeof flatten === 'string' ) {
7027				alwaysNew = fn;
7028				fn = type;
7029				type = flatten;
7030				flatten = false;
7031			}
7032	
7033			for ( i=0, ien=context.length ; i<ien ; i++ ) {
7034				var apiInst = new _Api( context[i] );
7035	
7036				if ( type === 'table' ) {
7037					ret = fn.call( apiInst, context[i], i );
7038	
7039					if ( ret !== undefined ) {
7040						a.push( ret );
7041					}
7042				}
7043				else if ( type === 'columns' || type === 'rows' ) {
7044					// this has same length as context - one entry for each table
7045					ret = fn.call( apiInst, context[i], this[i], i );
7046	
7047					if ( ret !== undefined ) {
7048						a.push( ret );
7049					}
7050				}
7051				else if ( type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell' ) {
7052					// columns and rows share the same structure.
7053					// 'this' is an array of column indexes for each context
7054					items = this[i];
7055	
7056					if ( type === 'column-rows' ) {
7057						rows = _selector_row_indexes( context[i], selector.opts );
7058					}
7059	
7060					for ( j=0, jen=items.length ; j<jen ; j++ ) {
7061						item = items[j];
7062	
7063						if ( type === 'cell' ) {
7064							ret = fn.call( apiInst, context[i], item.row, item.column, i, j );
7065						}
7066						else {
7067							ret = fn.call( apiInst, context[i], item, i, j, rows );
7068						}
7069	
7070						if ( ret !== undefined ) {
7071							a.push( ret );
7072						}
7073					}
7074				}
7075			}
7076	
7077			if ( a.length || alwaysNew ) {
7078				var api = new _Api( context, flatten ? a.concat.apply( [], a ) : a );
7079				var apiSelector = api.selector;
7080				apiSelector.rows = selector.rows;
7081				apiSelector.cols = selector.cols;
7082				apiSelector.opts = selector.opts;
7083				return api;
7084			}
7085			return this;
7086		},
7087	
7088	
7089		lastIndexOf: __arrayProto.lastIndexOf || function (obj, start)
7090		{
7091			// Bit cheeky...
7092			return this.indexOf.apply( this.toArray.reverse(), arguments );
7093		},
7094	
7095	
7096		length:  0,
7097	
7098	
7099		map: function ( fn )
7100		{
7101			var a = [];
7102	
7103			if ( __arrayProto.map ) {
7104				a = __arrayProto.map.call( this, fn, this );
7105			}
7106			else {
7107				// Compatibility for browsers without EMCA-252-5 (JS 1.6)
7108				for ( var i=0, ien=this.length ; i<ien ; i++ ) {
7109					a.push( fn.call( this, this[i], i ) );
7110				}
7111			}
7112	
7113			return new _Api( this.context, a );
7114		},
7115	
7116	
7117		pluck: function ( prop )
7118		{
7119			return this.map( function ( el ) {
7120				return el[ prop ];
7121			} );
7122		},
7123	
7124		pop:     __arrayProto.pop,
7125	
7126	
7127		push:    __arrayProto.push,
7128	
7129	
7130		// Does not return an API instance
7131		reduce: __arrayProto.reduce || function ( fn, init )
7132		{
7133			return _fnReduce( this, fn, init, 0, this.length, 1 );
7134		},
7135	
7136	
7137		reduceRight: __arrayProto.reduceRight || function ( fn, init )
7138		{
7139			return _fnReduce( this, fn, init, this.length-1, -1, -1 );
7140		},
7141	
7142	
7143		reverse: __arrayProto.reverse,
7144	
7145	
7146		// Object with rows, columns and opts
7147		selector: null,
7148	
7149	
7150		shift:   __arrayProto.shift,
7151	
7152	
7153		slice: function () {
7154			return new _Api( this.context, this );
7155		},
7156	
7157	
7158		sort:    __arrayProto.sort, // ? name - order?
7159	
7160	
7161		splice:  __arrayProto.splice,
7162	
7163	
7164		toArray: function ()
7165		{
7166			return __arrayProto.slice.call( this );
7167		},
7168	
7169	
7170		to$: function ()
7171		{
7172			return $( this );
7173		},
7174	
7175	
7176		toJQuery: function ()
7177		{
7178			return $( this );
7179		},
7180	
7181	
7182		unique: function ()
7183		{
7184			return new _Api( this.context, _unique(this) );
7185		},
7186	
7187	
7188		unshift: __arrayProto.unshift
7189	} );
7190	
7191	
7192	_Api.extend = function ( scope, obj, ext )
7193	{
7194		// Only extend API instances and static properties of the API
7195		if ( ! ext.length || ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) {
7196			return;
7197		}
7198	
7199		var
7200			i, ien,
7201			struct,
7202			methodScoping = function ( scope, fn, struc ) {
7203				return function () {
7204					var ret = fn.apply( scope, arguments );
7205	
7206					// Method extension
7207					_Api.extend( ret, ret, struc.methodExt );
7208					return ret;
7209				};
7210			};
7211	
7212		for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7213			struct = ext[i];
7214	
7215			// Value
7216			obj[ struct.name ] = struct.type === 'function' ?
7217				methodScoping( scope, struct.val, struct ) :
7218				struct.type === 'object' ?
7219					{} :
7220					struct.val;
7221	
7222			obj[ struct.name ].__dt_wrapper = true;
7223	
7224			// Property extension
7225			_Api.extend( scope, obj[ struct.name ], struct.propExt );
7226		}
7227	};
7228	
7229	
7230	// @todo - Is there need for an augment function?
7231	// _Api.augment = function ( inst, name )
7232	// {
7233	// 	// Find src object in the structure from the name
7234	// 	var parts = name.split('.');
7235	
7236	// 	_Api.extend( inst, obj );
7237	// };
7238	
7239	
7240	//     [
7241	//       {
7242	//         name:      'data'                -- string   - Property name
7243	//         val:       function () {},       -- function - Api method (or undefined if just an object
7244	//         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
7245	//         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
7246	//       },
7247	//       {
7248	//         name:     'row'
7249	//         val:       {},
7250	//         methodExt: [ ... ],
7251	//         propExt:   [
7252	//           {
7253	//             name:      'data'
7254	//             val:       function () {},
7255	//             methodExt: [ ... ],
7256	//             propExt:   [ ... ]
7257	//           },
7258	//           ...
7259	//         ]
7260	//       }
7261	//     ]
7262	
7263	_Api.register = _api_register = function ( name, val )
7264	{
7265		if ( $.isArray( name ) ) {
7266			for ( var j=0, jen=name.length ; j<jen ; j++ ) {
7267				_Api.register( name[j], val );
7268			}
7269			return;
7270		}
7271	
7272		var
7273			i, ien,
7274			heir = name.split('.'),
7275			struct = __apiStruct,
7276			key, method;
7277	
7278		var find = function ( src, name ) {
7279			for ( var i=0, ien=src.length ; i<ien ; i++ ) {
7280				if ( src[i].name === name ) {
7281					return src[i];
7282				}
7283			}
7284			return null;
7285		};
7286	
7287		for ( i=0, ien=heir.length ; i<ien ; i++ ) {
7288			method = heir[i].indexOf('()') !== -1;
7289			key = method ?
7290				heir[i].replace('()', '') :
7291				heir[i];
7292	
7293			var src = find( struct, key );
7294			if ( ! src ) {
7295				src = {
7296					name:      key,
7297					val:       {},
7298					methodExt: [],
7299					propExt:   [],
7300					type:      'object'
7301				};
7302				struct.push( src );
7303			}
7304	
7305			if ( i === ien-1 ) {
7306				src.val = val;
7307				src.type = typeof val === 'function' ?
7308					'function' :
7309					$.isPlainObject( val ) ?
7310						'object' :
7311						'other';
7312			}
7313			else {
7314				struct = method ?
7315					src.methodExt :
7316					src.propExt;
7317			}
7318		}
7319	};
7320	
7321	_Api.registerPlural = _api_registerPlural = function ( pluralName, singularName, val ) {
7322		_Api.register( pluralName, val );
7323	
7324		_Api.register( singularName, function () {
7325			var ret = val.apply( this, arguments );
7326	
7327			if ( ret === this ) {
7328				// Returned item is the API instance that was passed in, return it
7329				return this;
7330			}
7331			else if ( ret instanceof _Api ) {
7332				// New API instance returned, want the value from the first item
7333				// in the returned array for the singular result.
7334				return ret.length ?
7335					$.isArray( ret[0] ) ?
7336						new _Api( ret.context, ret[0] ) : // Array results are 'enhanced'
7337						ret[0] :
7338					undefined;
7339			}
7340	
7341			// Non-API return - just fire it back
7342			return ret;
7343		} );
7344	};
7345	
7346	
7347	/**
7348	 * Selector for HTML tables. Apply the given selector to the give array of
7349	 * DataTables settings objects.
7350	 *
7351	 * @param {string|integer} [selector] jQuery selector string or integer
7352	 * @param  {array} Array of DataTables settings objects to be filtered
7353	 * @return {array}
7354	 * @ignore
7355	 */
7356	var __table_selector = function ( selector, a )
7357	{
7358		if ( $
vendor: 10,923 bytes, lines 7358-7747
7358.isArray(selector) ) {
7359			return $.map( selector, function (item) {
7360				return __table_selector(item, a);
7361			} );
7362		}
7363	
7364		// Integer is used to pick out a table by index
7365		if ( typeof selector === 'number' ) {
7366			return [ a[ selector ] ];
7367		}
7368	
7369		// Perform a jQuery selector on the table nodes
7370		var nodes = $.map( a, function (el, i) {
7371			return el.nTable;
7372		} );
7373	
7374		return $(nodes)
7375			.filter( selector )
7376			.map( function (i) {
7377				// Need to translate back from the table node to the settings
7378				var idx = $.inArray( this, nodes );
7379				return a[ idx ];
7380			} )
7381			.toArray();
7382	};
7383	
7384	
7385	
7386	/**
7387	 * Context selector for the API's context (i.e. the tables the API instance
7388	 * refers to.
7389	 *
7390	 * @name    DataTable.Api#tables
7391	 * @param {string|integer} [selector] Selector to pick which tables the iterator
7392	 *   should operate on. If not given, all tables in the current context are
7393	 *   used. This can be given as a jQuery selector (for example `':gt(0)'`) to
7394	 *   select multiple tables or as an integer to select a single table.
7395	 * @returns {DataTable.Api} Returns a new API instance if a selector is given.
7396	 */
7397	_api_register( 'tables()', function ( selector ) {
7398		// A new instance is created if there was a selector specified
7399		return selector !== undefined && selector !== null ?
7400			new _Api( __table_selector( selector, this.context ) ) :
7401			this;
7402	} );
7403	
7404	
7405	_api_register( 'table()', function ( selector ) {
7406		var tables = this.tables( selector );
7407		var ctx = tables.context;
7408	
7409		// Truncate to the first matched table
7410		return ctx.length ?
7411			new _Api( ctx[0] ) :
7412			tables;
7413	} );
7414	
7415	
7416	_api_registerPlural( 'tables().nodes()', 'table().node()' , function () {
7417		return this.iterator( 'table', function ( ctx ) {
7418			return ctx.nTable;
7419		}, 1 );
7420	} );
7421	
7422	
7423	_api_registerPlural( 'tables().body()', 'table().body()' , function () {
7424		return this.iterator( 'table', function ( ctx ) {
7425			return ctx.nTBody;
7426		}, 1 );
7427	} );
7428	
7429	
7430	_api_registerPlural( 'tables().header()', 'table().header()' , function () {
7431		return this.iterator( 'table', function ( ctx ) {
7432			return ctx.nTHead;
7433		}, 1 );
7434	} );
7435	
7436	
7437	_api_registerPlural( 'tables().footer()', 'table().footer()' , function () {
7438		return this.iterator( 'table', function ( ctx ) {
7439			return ctx.nTFoot;
7440		}, 1 );
7441	} );
7442	
7443	
7444	_api_registerPlural( 'tables().containers()', 'table().container()' , function () {
7445		return this.iterator( 'table', function ( ctx ) {
7446			return ctx.nTableWrapper;
7447		}, 1 );
7448	} );
7449	
7450	
7451	
7452	/**
7453	 * Redraw the tables in the current context.
7454	 */
7455	_api_register( 'draw()', function ( paging ) {
7456		return this.iterator( 'table', function ( settings ) {
7457			if ( paging === 'page' ) {
7458				_fnDraw( settings );
7459			}
7460			else {
7461				if ( typeof paging === 'string' ) {
7462					paging = paging === 'full-hold' ?
7463						false :
7464						true;
7465				}
7466	
7467				_fnReDraw( settings, paging===false );
7468			}
7469		} );
7470	} );
7471	
7472	
7473	
7474	/**
7475	 * Get the current page index.
7476	 *
7477	 * @return {integer} Current page index (zero based)
7478	 *//**
7479	 * Set the current page.
7480	 *
7481	 * Note that if you attempt to show a page which does not exist, DataTables will
7482	 * not throw an error, but rather reset the paging.
7483	 *
7484	 * @param {integer|string} action The paging action to take. This can be one of:
7485	 *  * `integer` - The page index to jump to
7486	 *  * `string` - An action to take:
7487	 *    * `first` - Jump to first page.
7488	 *    * `next` - Jump to the next page
7489	 *    * `previous` - Jump to previous page
7490	 *    * `last` - Jump to the last page.
7491	 * @returns {DataTables.Api} this
7492	 */
7493	_api_register( 'page()', function ( action ) {
7494		if ( action === undefined ) {
7495			return this.page.info().page; // not an expensive call
7496		}
7497	
7498		// else, have an action to take on all tables
7499		return this.iterator( 'table', function ( settings ) {
7500			_fnPageChange( settings, action );
7501		} );
7502	} );
7503	
7504	
7505	/**
7506	 * Paging information for the first table in the current context.
7507	 *
7508	 * If you require paging information for another table, use the `table()` method
7509	 * with a suitable selector.
7510	 *
7511	 * @return {object} Object with the following properties set:
7512	 *  * `page` - Current page index (zero based - i.e. the first page is `0`)
7513	 *  * `pages` - Total number of pages
7514	 *  * `start` - Display index for the first record shown on the current page
7515	 *  * `end` - Display index for the last record shown on the current page
7516	 *  * `length` - Display length (number of records). Note that generally `start
7517	 *    + length = end`, but this is not always true, for example if there are
7518	 *    only 2 records to show on the final page, with a length of 10.
7519	 *  * `recordsTotal` - Full data set length
7520	 *  * `recordsDisplay` - Data set length once the current filtering criterion
7521	 *    are applied.
7522	 */
7523	_api_register( 'page.info()', function ( action ) {
7524		if ( this.context.length === 0 ) {
7525			return undefined;
7526		}
7527	
7528		var
7529			settings   = this.context[0],
7530			start      = settings._iDisplayStart,
7531			len        = settings.oFeatures.bPaginate ? settings._iDisplayLength : -1,
7532			visRecords = settings.fnRecordsDisplay(),
7533			all        = len === -1;
7534	
7535		return {
7536			"page":           all ? 0 : Math.floor( start / len ),
7537			"pages":          all ? 1 : Math.ceil( visRecords / len ),
7538			"start":          start,
7539			"end":            settings.fnDisplayEnd(),
7540			"length":         len,
7541			"recordsTotal":   settings.fnRecordsTotal(),
7542			"recordsDisplay": visRecords,
7543			"serverSide":     _fnDataSource( settings ) === 'ssp'
7544		};
7545	} );
7546	
7547	
7548	/**
7549	 * Get the current page length.
7550	 *
7551	 * @return {integer} Current page length. Note `-1` indicates that all records
7552	 *   are to be shown.
7553	 *//**
7554	 * Set the current page length.
7555	 *
7556	 * @param {integer} Page length to set. Use `-1` to show all records.
7557	 * @returns {DataTables.Api} this
7558	 */
7559	_api_register( 'page.len()', function ( len ) {
7560		// Note that we can't call this function 'length()' because `length`
7561		// is a Javascript property of functions which defines how many arguments
7562		// the function expects.
7563		if ( len === undefined ) {
7564			return this.context.length !== 0 ?
7565				this.context[0]._iDisplayLength :
7566				undefined;
7567		}
7568	
7569		// else, set the page length
7570		return this.iterator( 'table', function ( settings ) {
7571			_fnLengthChange( settings, len );
7572		} );
7573	} );
7574	
7575	
7576	
7577	var __reload = function ( settings, holdPosition, callback ) {
7578		// Use the draw event to trigger a callback
7579		if ( callback ) {
7580			var api = new _Api( settings );
7581	
7582			api.one( 'draw', function () {
7583				callback( api.ajax.json() );
7584			} );
7585		}
7586	
7587		if ( _fnDataSource( settings ) == 'ssp' ) {
7588			_fnReDraw( settings, holdPosition );
7589		}
7590		else {
7591			_fnProcessingDisplay( settings, true );
7592	
7593			// Cancel an existing request
7594			var xhr = settings.jqXHR;
7595			if ( xhr && xhr.readyState !== 4 ) {
7596				xhr.abort();
7597			}
7598	
7599			// Trigger xhr
7600			_fnBuildAjax( settings, [], function( json ) {
7601				_fnClearTable( settings );
7602	
7603				var data = _fnAjaxDataSrc( settings, json );
7604				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7605					_fnAddData( settings, data[i] );
7606				}
7607	
7608				_fnReDraw( settings, holdPosition );
7609				_fnProcessingDisplay( settings, false );
7610			} );
7611		}
7612	};
7613	
7614	
7615	/**
7616	 * Get the JSON response from the last Ajax request that DataTables made to the
7617	 * server. Note that this returns the JSON from the first table in the current
7618	 * context.
7619	 *
7620	 * @return {object} JSON received from the server.
7621	 */
7622	_api_register( 'ajax.json()', function () {
7623		var ctx = this.context;
7624	
7625		if ( ctx.length > 0 ) {
7626			return ctx[0].json;
7627		}
7628	
7629		// else return undefined;
7630	} );
7631	
7632	
7633	/**
7634	 * Get the data submitted in the last Ajax request
7635	 */
7636	_api_register( 'ajax.params()', function () {
7637		var ctx = this.context;
7638	
7639		if ( ctx.length > 0 ) {
7640			return ctx[0].oAjaxData;
7641		}
7642	
7643		// else return undefined;
7644	} );
7645	
7646	
7647	/**
7648	 * Reload tables from the Ajax data source. Note that this function will
7649	 * automatically re-draw the table when the remote data has been loaded.
7650	 *
7651	 * @param {boolean} [reset=true] Reset (default) or hold the current paging
7652	 *   position. A full re-sort and re-filter is performed when this method is
7653	 *   called, which is why the pagination reset is the default action.
7654	 * @returns {DataTables.Api} this
7655	 */
7656	_api_register( 'ajax.reload()', function ( callback, resetPaging ) {
7657		return this.iterator( 'table', function (settings) {
7658			__reload( settings, resetPaging===false, callback );
7659		} );
7660	} );
7661	
7662	
7663	/**
7664	 * Get the current Ajax URL. Note that this returns the URL from the first
7665	 * table in the current context.
7666	 *
7667	 * @return {string} Current Ajax source URL
7668	 *//**
7669	 * Set the Ajax URL. Note that this will set the URL for all tables in the
7670	 * current context.
7671	 *
7672	 * @param {string} url URL to set.
7673	 * @returns {DataTables.Api} this
7674	 */
7675	_api_register( 'ajax.url()', function ( url ) {
7676		var ctx = this.context;
7677	
7678		if ( url === undefined ) {
7679			// get
7680			if ( ctx.length === 0 ) {
7681				return undefined;
7682			}
7683			ctx = ctx[0];
7684	
7685			return ctx.ajax ?
7686				$.isPlainObject( ctx.ajax ) ?
7687					ctx.ajax.url :
7688					ctx.ajax :
7689				ctx.sAjaxSource;
7690		}
7691	
7692		// set
7693		return this.iterator( 'table', function ( settings ) {
7694			if ( $.isPlainObject( settings.ajax ) ) {
7695				settings.ajax.url = url;
7696			}
7697			else {
7698				settings.ajax = url;
7699			}
7700			// No need to consider sAjaxSource here since DataTables gives priority
7701			// to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any
7702			// value of `sAjaxSource` redundant.
7703		} );
7704	} );
7705	
7706	
7707	/**
7708	 * Load data from the newly set Ajax URL. Note that this method is only
7709	 * available when `ajax.url()` is used to set a URL. Additionally, this method
7710	 * has the same effect as calling `ajax.reload()` but is provided for
7711	 * convenience when setting a new URL. Like `ajax.reload()` it will
7712	 * automatically redraw the table once the remote data has been loaded.
7713	 *
7714	 * @returns {DataTables.Api} this
7715	 */
7716	_api_register( 'ajax.url().load()', function ( callback, resetPaging ) {
7717		// Same as a reload, but makes sense to present it for easy access after a
7718		// url change
7719		return this.iterator( 'table', function ( ctx ) {
7720			__reload( ctx, resetPaging===false, callback );
7721		} );
7722	} );
7723	
7724	
7725	
7726	
7727	var _selector_run = function ( type, selector, selectFn, settings, opts )
7728	{
7729		var
7730			out = [], res,
7731			a, i, ien, j, jen,
7732			selectorType = typeof selector;
7733	
7734		// Can't just check for isArray here, as an API or jQuery instance might be
7735		// given with their array like look
7736		if ( ! selector || selectorType === 'string' || selectorType === 'function' || selector.length === undefined ) {
7737			selector = [ selector ];
7738		}
7739	
7740		for ( i=0, ien=selector.length ; i<ien ; i++ ) {
7741			// Only split on simple strings - complex expressions will be jQuery selectors
7742			a = selector[i] && selector[i].split && ! selector[i].match(/[\[\(:]/) ?
7743				selector[i].split(',') :
7744				[ selector[i] ];
7745	
7746			for ( j=0, jen=a.length ; j<jen ; j++ ) {
7747				res = selectFn( typeof a[j] === 'string' ? 
vendor: 2,006 bytes, lines 7747-7831
7747$.trim(a[j]) : a[j] );
7748	
7749				if ( res && res.length ) {
7750					out = out.concat( res );
7751				}
7752			}
7753		}
7754	
7755		// selector extensions
7756		var ext = _ext.selector[ type ];
7757		if ( ext.length ) {
7758			for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7759				out = ext[i]( settings, opts, out );
7760			}
7761		}
7762	
7763		return _unique( out );
7764	};
7765	
7766	
7767	var _selector_opts = function ( opts )
7768	{
7769		if ( ! opts ) {
7770			opts = {};
7771		}
7772	
7773		// Backwards compatibility for 1.9- which used the terminology filter rather
7774		// than search
7775		if ( opts.filter && opts.search === undefined ) {
7776			opts.search = opts.filter;
7777		}
7778	
7779		return $.extend( {
7780			search: 'none',
7781			order: 'current',
7782			page: 'all'
7783		}, opts );
7784	};
7785	
7786	
7787	var _selector_first = function ( inst )
7788	{
7789		// Reduce the API instance to the first item found
7790		for ( var i=0, ien=inst.length ; i<ien ; i++ ) {
7791			if ( inst[i].length > 0 ) {
7792				// Assign the first element to the first item in the instance
7793				// and truncate the instance and context
7794				inst[0] = inst[i];
7795				inst[0].length = 1;
7796				inst.length = 1;
7797				inst.context = [ inst.context[i] ];
7798	
7799				return inst;
7800			}
7801		}
7802	
7803		// Not found - return an empty instance
7804		inst.length = 0;
7805		return inst;
7806	};
7807	
7808	
7809	var _selector_row_indexes = function ( settings, opts )
7810	{
7811		var
7812			i, ien, tmp, a=[],
7813			displayFiltered = settings.aiDisplay,
7814			displayMaster = settings.aiDisplayMaster;
7815	
7816		var
7817			search = opts.search,  // none, applied, removed
7818			order  = opts.order,   // applied, current, index (original - compatibility with 1.9)
7819			page   = opts.page;    // all, current
7820	
7821		if ( _fnDataSource( settings ) == 'ssp' ) {
7822			// In server-side processing mode, most options are irrelevant since
7823			// rows not shown don't exist and the index order is the applied order
7824			// Removed is a special case - for consistency just return an empty
7825			// array
7826			return search === 'removed' ?
7827				[] :
7828				_range( 0, displayMaster.length );
7829		}
7830		else if ( page == 'current' ) {
7831			// Current page implies that order=current and fitl
vendor: 9,343 bytes, lines 7831-8173
7831er=applied, since it is
7832			// fairly senseless otherwise, regardless of what order and search actually
7833			// are
7834			for ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i<ien ; i++ ) {
7835				a.push( displayFiltered[i] );
7836			}
7837		}
7838		else if ( order == 'current' || order == 'applied' ) {
7839			if ( search == 'none') {
7840				a = displayMaster.slice();
7841			}
7842			else if ( search == 'applied' ) {
7843				a = displayFiltered.slice();
7844			}
7845			else if ( search == 'removed' ) {
7846				// O(n+m) solution by creating a hash map
7847				var displayFilteredMap = {};
7848	
7849				for ( var i=0, ien=displayFiltered.length ; i<ien ; i++ ) {
7850					displayFilteredMap[displayFiltered[i]] = null;
7851				}
7852	
7853				a = $.map( displayMaster, function (el) {
7854					return ! displayFilteredMap.hasOwnProperty(el) ?
7855						el :
7856						null;
7857				} );
7858			}
7859		}
7860		else if ( order == 'index' || order == 'original' ) {
7861			for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
7862				if ( search == 'none' ) {
7863					a.push( i );
7864				}
7865				else { // applied | removed
7866					tmp = $.inArray( i, displayFiltered );
7867	
7868					if ((tmp === -1 && search == 'removed') ||
7869						(tmp >= 0   && search == 'applied') )
7870					{
7871						a.push( i );
7872					}
7873				}
7874			}
7875		}
7876	
7877		return a;
7878	};
7879	
7880	
7881	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
7882	 * Rows
7883	 *
7884	 * {}          - no selector - use all available rows
7885	 * {integer}   - row aoData index
7886	 * {node}      - TR node
7887	 * {string}    - jQuery selector to apply to the TR elements
7888	 * {array}     - jQuery array of nodes, or simply an array of TR nodes
7889	 *
7890	 */
7891	var __row_selector = function ( settings, selector, opts )
7892	{
7893		var rows;
7894		var run = function ( sel ) {
7895			var selInt = _intVal( sel );
7896			var i, ien;
7897			var aoData = settings.aoData;
7898	
7899			// Short cut - selector is a number and no options provided (default is
7900			// all records, so no need to check if the index is in there, since it
7901			// must be - dev error if the index doesn't exist).
7902			if ( selInt !== null && ! opts ) {
7903				return [ selInt ];
7904			}
7905	
7906			if ( ! rows ) {
7907				rows = _selector_row_indexes( settings, opts );
7908			}
7909	
7910			if ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) {
7911				// Selector - integer
7912				return [ selInt ];
7913			}
7914			else if ( sel === null || sel === undefined || sel === '' ) {
7915				// Selector - none
7916				return rows;
7917			}
7918	
7919			// Selector - function
7920			if ( typeof sel === 'function' ) {
7921				return $.map( rows, function (idx) {
7922					var row = aoData[ idx ];
7923					return sel( idx, row._aData, row.nTr ) ? idx : null;
7924				} );
7925			}
7926	
7927			// Selector - node
7928			if ( sel.nodeName ) {
7929				var rowIdx = sel._DT_RowIndex;  // Property added by DT for fast lookup
7930				var cellIdx = sel._DT_CellIndex;
7931	
7932				if ( rowIdx !== undefined ) {
7933					// Make sure that the row is actually still present in the table
7934					return aoData[ rowIdx ] && aoData[ rowIdx ].nTr === sel ?
7935						[ rowIdx ] :
7936						[];
7937				}
7938				else if ( cellIdx ) {
7939					return aoData[ cellIdx.row ] && aoData[ cellIdx.row ].nTr === sel.parentNode ?
7940						[ cellIdx.row ] :
7941						[];
7942				}
7943				else {
7944					var host = $(sel).closest('*[data-dt-row]');
7945					return host.length ?
7946						[ host.data('dt-row') ] :
7947						[];
7948				}
7949			}
7950	
7951			// ID selector. Want to always be able to select rows by id, regardless
7952			// of if the tr element has been created or not, so can't rely upon
7953			// jQuery here - hence a custom implementation. This does not match
7954			// Sizzle's fast selector or HTML4 - in HTML5 the ID can be anything,
7955			// but to select it using a CSS selector engine (like Sizzle or
7956			// querySelect) it would need to need to be escaped for some characters.
7957			// DataTables simplifies this for row selectors since you can select
7958			// only a row. A # indicates an id any anything that follows is the id -
7959			// unescaped.
7960			if ( typeof sel === 'string' && sel.charAt(0) === '#' ) {
7961				// get row index from id
7962				var rowObj = settings.aIds[ sel.replace( /^#/, '' ) ];
7963				if ( rowObj !== undefined ) {
7964					return [ rowObj.idx ];
7965				}
7966	
7967				// need to fall through to jQuery in case there is DOM id that
7968				// matches
7969			}
7970			
7971			// Get nodes in the order from the `rows` array with null values removed
7972			var nodes = _removeEmpty(
7973				_pluck_order( settings.aoData, rows, 'nTr' )
7974			);
7975	
7976			// Selector - jQuery selector string, array of nodes or jQuery object/
7977			// As jQuery's .filter() allows jQuery objects to be passed in filter,
7978			// it also allows arrays, so this will cope with all three options
7979			return $(nodes)
7980				.filter( sel )
7981				.map( function () {
7982					return this._DT_RowIndex;
7983				} )
7984				.toArray();
7985		};
7986	
7987		return _selector_run( 'row', selector, run, settings, opts );
7988	};
7989	
7990	
7991	_api_register( 'rows()', function ( selector, opts ) {
7992		// argument shifting
7993		if ( selector === undefined ) {
7994			selector = '';
7995		}
7996		else if ( $.isPlainObject( selector ) ) {
7997			opts = selector;
7998			selector = '';
7999		}
8000	
8001		opts = _selector_opts( opts );
8002	
8003		var inst = this.iterator( 'table', function ( settings ) {
8004			return __row_selector( settings, selector, opts );
8005		}, 1 );
8006	
8007		// Want argument shifting here and in __row_selector?
8008		inst.selector.rows = selector;
8009		inst.selector.opts = opts;
8010	
8011		return inst;
8012	} );
8013	
8014	_api_register( 'rows().nodes()', function () {
8015		return this.iterator( 'row', function ( settings, row ) {
8016			return settings.aoData[ row ].nTr || undefined;
8017		}, 1 );
8018	} );
8019	
8020	_api_register( 'rows().data()', function () {
8021		return this.iterator( true, 'rows', function ( settings, rows ) {
8022			return _pluck_order( settings.aoData, rows, '_aData' );
8023		}, 1 );
8024	} );
8025	
8026	_api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) {
8027		return this.iterator( 'row', function ( settings, row ) {
8028			var r = settings.aoData[ row ];
8029			return type === 'search' ? r._aFilterData : r._aSortData;
8030		}, 1 );
8031	} );
8032	
8033	_api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) {
8034		return this.iterator( 'row', function ( settings, row ) {
8035			_fnInvalidate( settings, row, src );
8036		} );
8037	} );
8038	
8039	_api_registerPlural( 'rows().indexes()', 'row().index()', function () {
8040		return this.iterator( 'row', function ( settings, row ) {
8041			return row;
8042		}, 1 );
8043	} );
8044	
8045	_api_registerPlural( 'rows().ids()', 'row().id()', function ( hash ) {
8046		var a = [];
8047		var context = this.context;
8048	
8049		// `iterator` will drop undefined values, but in this case we want them
8050		for ( var i=0, ien=context.length ; i<ien ; i++ ) {
8051			for ( var j=0, jen=this[i].length ; j<jen ; j++ ) {
8052				var id = context[i].rowIdFn( context[i].aoData[ this[i][j] ]._aData );
8053				a.push( (hash === true ? '#' : '' )+ id );
8054			}
8055		}
8056	
8057		return new _Api( context, a );
8058	} );
8059	
8060	_api_registerPlural( 'rows().remove()', 'row().remove()', function () {
8061		var that = this;
8062	
8063		this.iterator( 'row', function ( settings, row, thatIdx ) {
8064			var data = settings.aoData;
8065			var rowData = data[ row ];
8066			var i, ien, j, jen;
8067			var loopRow, loopCells;
8068	
8069			data.splice( row, 1 );
8070	
8071			// Update the cached indexes
8072			for ( i=0, ien=data.length ; i<ien ; i++ ) {
8073				loopRow = data[i];
8074				loopCells = loopRow.anCells;
8075	
8076				// Rows
8077				if ( loopRow.nTr !== null ) {
8078					loopRow.nTr._DT_RowIndex = i;
8079				}
8080	
8081				// Cells
8082				if ( loopCells !== null ) {
8083					for ( j=0, jen=loopCells.length ; j<jen ; j++ ) {
8084						loopCells[j]._DT_CellIndex.row = i;
8085					}
8086				}
8087			}
8088	
8089			// Delete from the display arrays
8090			_fnDeleteIndex( settings.aiDisplayMaster, row );
8091			_fnDeleteIndex( settings.aiDisplay, row );
8092			_fnDeleteIndex( that[ thatIdx ], row, false ); // maintain local indexes
8093	
8094			// For server-side processing tables - subtract the deleted row from the count
8095			if ( settings._iRecordsDisplay > 0 ) {
8096				settings._iRecordsDisplay--;
8097			}
8098	
8099			// Check for an 'overflow' they case for displaying the table
8100			_fnLengthOverflow( settings );
8101	
8102			// Remove the row's ID reference if there is one
8103			var id = settings.rowIdFn( rowData._aData );
8104			if ( id !== undefined ) {
8105				delete settings.aIds[ id ];
8106			}
8107		} );
8108	
8109		this.iterator( 'table', function ( settings ) {
8110			for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
8111				settings.aoData[i].idx = i;
8112			}
8113		} );
8114	
8115		return this;
8116	} );
8117	
8118	
8119	_api_register( 'rows.add()', function ( rows ) {
8120		var newRows = this.iterator( 'table', function ( settings ) {
8121				var row, i, ien;
8122				var out = [];
8123	
8124				for ( i=0, ien=rows.length ; i<ien ; i++ ) {
8125					row = rows[i];
8126	
8127					if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
8128						out.push( _fnAddTr( settings, row )[0] );
8129					}
8130					else {
8131						out.push( _fnAddData( settings, row ) );
8132					}
8133				}
8134	
8135				return out;
8136			}, 1 );
8137	
8138		// Return an Api.rows() extended instance, so rows().nodes() etc can be used
8139		var modRows = this.rows( -1 );
8140		modRows.pop();
8141		$.merge( modRows, newRows );
8142	
8143		return modRows;
8144	} );
8145	
8146	
8147	
8148	
8149	
8150	/**
8151	 *
8152	 */
8153	_api_register( 'row()', function ( selector, opts ) {
8154		return _selector_first( this.rows( selector, opts ) );
8155	} );
8156	
8157	
8158	_api_register( 'row().data()', function ( data ) {
8159		var ctx = this.context;
8160	
8161		if ( data === undefined ) {
8162			// Get
8163			return ctx.length && this.length ?
8164				ctx[0].aoData[ this[0] ]._aData :
8165				undefined;
8166		}
8167	
8168		// Set
8169		var row = ctx[0].aoData[ this[0] ];
8170		row._aData = data;
8171	
8172		// If the DOM has an id, and the data source is an array
8173		if ( 
vendor: 14,764 bytes, lines 8173-8736
8173$.isArray( data ) && row.nTr && row.nTr.id ) {
8174			_fnSetObjectDataFn( ctx[0].rowId )( data, row.nTr.id );
8175		}
8176	
8177		// Automatically invalidate
8178		_fnInvalidate( ctx[0], this[0], 'data' );
8179	
8180		return this;
8181	} );
8182	
8183	
8184	_api_register( 'row().node()', function () {
8185		var ctx = this.context;
8186	
8187		return ctx.length && this.length ?
8188			ctx[0].aoData[ this[0] ].nTr || null :
8189			null;
8190	} );
8191	
8192	
8193	_api_register( 'row.add()', function ( row ) {
8194		// Allow a jQuery object to be passed in - only a single row is added from
8195		// it though - the first element in the set
8196		if ( row instanceof $ && row.length ) {
8197			row = row[0];
8198		}
8199	
8200		var rows = this.iterator( 'table', function ( settings ) {
8201			if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
8202				return _fnAddTr( settings, row )[0];
8203			}
8204			return _fnAddData( settings, row );
8205		} );
8206	
8207		// Return an Api.rows() extended instance, with the newly added row selected
8208		return this.row( rows[0] );
8209	} );
8210	
8211	
8212	
8213	var __details_add = function ( ctx, row, data, klass )
8214	{
8215		// Convert to array of TR elements
8216		var rows = [];
8217		var addRow = function ( r, k ) {
8218			// Recursion to allow for arrays of jQuery objects
8219			if ( $.isArray( r ) || r instanceof $ ) {
8220				for ( var i=0, ien=r.length ; i<ien ; i++ ) {
8221					addRow( r[i], k );
8222				}
8223				return;
8224			}
8225	
8226			// If we get a TR element, then just add it directly - up to the dev
8227			// to add the correct number of columns etc
8228			if ( r.nodeName && r.nodeName.toLowerCase() === 'tr' ) {
8229				rows.push( r );
8230			}
8231			else {
8232				// Otherwise create a row with a wrapper
8233				var created = $('<tr><td/></tr>').addClass( k );
8234				$('td', created)
8235					.addClass( k )
8236					.html( r )
8237					[0].colSpan = _fnVisbleColumns( ctx );
8238	
8239				rows.push( created[0] );
8240			}
8241		};
8242	
8243		addRow( data, klass );
8244	
8245		if ( row._details ) {
8246			row._details.detach();
8247		}
8248	
8249		row._details = $(rows);
8250	
8251		// If the children were already shown, that state should be retained
8252		if ( row._detailsShow ) {
8253			row._details.insertAfter( row.nTr );
8254		}
8255	};
8256	
8257	
8258	var __details_remove = function ( api, idx )
8259	{
8260		var ctx = api.context;
8261	
8262		if ( ctx.length ) {
8263			var row = ctx[0].aoData[ idx !== undefined ? idx : api[0] ];
8264	
8265			if ( row && row._details ) {
8266				row._details.remove();
8267	
8268				row._detailsShow = undefined;
8269				row._details = undefined;
8270			}
8271		}
8272	};
8273	
8274	
8275	var __details_display = function ( api, show ) {
8276		var ctx = api.context;
8277	
8278		if ( ctx.length && api.length ) {
8279			var row = ctx[0].aoData[ api[0] ];
8280	
8281			if ( row._details ) {
8282				row._detailsShow = show;
8283	
8284				if ( show ) {
8285					row._details.insertAfter( row.nTr );
8286				}
8287				else {
8288					row._details.detach();
8289				}
8290	
8291				__details_events( ctx[0] );
8292			}
8293		}
8294	};
8295	
8296	
8297	var __details_events = function ( settings )
8298	{
8299		var api = new _Api( settings );
8300		var namespace = '.dt.DT_details';
8301		var drawEvent = 'draw'+namespace;
8302		var colvisEvent = 'column-visibility'+namespace;
8303		var destroyEvent = 'destroy'+namespace;
8304		var data = settings.aoData;
8305	
8306		api.off( drawEvent +' '+ colvisEvent +' '+ destroyEvent );
8307	
8308		if ( _pluck( data, '_details' ).length > 0 ) {
8309			// On each draw, insert the required elements into the document
8310			api.on( drawEvent, function ( e, ctx ) {
8311				if ( settings !== ctx ) {
8312					return;
8313				}
8314	
8315				api.rows( {page:'current'} ).eq(0).each( function (idx) {
8316					// Internal data grab
8317					var row = data[ idx ];
8318	
8319					if ( row._detailsShow ) {
8320						row._details.insertAfter( row.nTr );
8321					}
8322				} );
8323			} );
8324	
8325			// Column visibility change - update the colspan
8326			api.on( colvisEvent, function ( e, ctx, idx, vis ) {
8327				if ( settings !== ctx ) {
8328					return;
8329				}
8330	
8331				// Update the colspan for the details rows (note, only if it already has
8332				// a colspan)
8333				var row, visible = _fnVisbleColumns( ctx );
8334	
8335				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
8336					row = data[i];
8337	
8338					if ( row._details ) {
8339						row._details.children('td[colspan]').attr('colspan', visible );
8340					}
8341				}
8342			} );
8343	
8344			// Table destroyed - nuke any child rows
8345			api.on( destroyEvent, function ( e, ctx ) {
8346				if ( settings !== ctx ) {
8347					return;
8348				}
8349	
8350				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
8351					if ( data[i]._details ) {
8352						__details_remove( api, i );
8353					}
8354				}
8355			} );
8356		}
8357	};
8358	
8359	// Strings for the method names to help minification
8360	var _emp = '';
8361	var _child_obj = _emp+'row().child';
8362	var _child_mth = _child_obj+'()';
8363	
8364	// data can be:
8365	//  tr
8366	//  string
8367	//  jQuery or array of any of the above
8368	_api_register( _child_mth, function ( data, klass ) {
8369		var ctx = this.context;
8370	
8371		if ( data === undefined ) {
8372			// get
8373			return ctx.length && this.length ?
8374				ctx[0].aoData[ this[0] ]._details :
8375				undefined;
8376		}
8377		else if ( data === true ) {
8378			// show
8379			this.child.show();
8380		}
8381		else if ( data === false ) {
8382			// remove
8383			__details_remove( this );
8384		}
8385		else if ( ctx.length && this.length ) {
8386			// set
8387			__details_add( ctx[0], ctx[0].aoData[ this[0] ], data, klass );
8388		}
8389	
8390		return this;
8391	} );
8392	
8393	
8394	_api_register( [
8395		_child_obj+'.show()',
8396		_child_mth+'.show()' // only when `child()` was called with parameters (without
8397	], function ( show ) {   // it returns an object and this method is not executed)
8398		__details_display( this, true );
8399		return this;
8400	} );
8401	
8402	
8403	_api_register( [
8404		_child_obj+'.hide()',
8405		_child_mth+'.hide()' // only when `child()` was called with parameters (without
8406	], function () {         // it returns an object and this method is not executed)
8407		__details_display( this, false );
8408		return this;
8409	} );
8410	
8411	
8412	_api_register( [
8413		_child_obj+'.remove()',
8414		_child_mth+'.remove()' // only when `child()` was called with parameters (without
8415	], function () {           // it returns an object and this method is not executed)
8416		__details_remove( this );
8417		return this;
8418	} );
8419	
8420	
8421	_api_register( _child_obj+'.isShown()', function () {
8422		var ctx = this.context;
8423	
8424		if ( ctx.length && this.length ) {
8425			// _detailsShown as false or undefined will fall through to return false
8426			return ctx[0].aoData[ this[0] ]._detailsShow || false;
8427		}
8428		return false;
8429	} );
8430	
8431	
8432	
8433	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
8434	 * Columns
8435	 *
8436	 * {integer}           - column index (>=0 count from left, <0 count from right)
8437	 * "{integer}:visIdx"  - visible column index (i.e. translate to column index)  (>=0 count from left, <0 count from right)
8438	 * "{integer}:visible" - alias for {integer}:visIdx  (>=0 count from left, <0 count from right)
8439	 * "{string}:name"     - column name
8440	 * "{string}"          - jQuery selector on column header nodes
8441	 *
8442	 */
8443	
8444	// can be an array of these items, comma separated list, or an array of comma
8445	// separated lists
8446	
8447	var __re_column_selector = /^([^:]+):(name|visIdx|visible)$/;
8448	
8449	
8450	// r1 and r2 are redundant - but it means that the parameters match for the
8451	// iterator callback in columns().data()
8452	var __columnData = function ( settings, column, r1, r2, rows ) {
8453		var a = [];
8454		for ( var row=0, ien=rows.length ; row<ien ; row++ ) {
8455			a.push( _fnGetCellData( settings, rows[row], column ) );
8456		}
8457		return a;
8458	};
8459	
8460	
8461	var __column_selector = function ( settings, selector, opts )
8462	{
8463		var
8464			columns = settings.aoColumns,
8465			names = _pluck( columns, 'sName' ),
8466			nodes = _pluck( columns, 'nTh' );
8467	
8468		var run = function ( s ) {
8469			var selInt = _intVal( s );
8470	
8471			// Selector - all
8472			if ( s === '' ) {
8473				return _range( columns.length );
8474			}
8475	
8476			// Selector - index
8477			if ( selInt !== null ) {
8478				return [ selInt >= 0 ?
8479					selInt : // Count from left
8480					columns.length + selInt // Count from right (+ because its a negative value)
8481				];
8482			}
8483	
8484			// Selector = function
8485			if ( typeof s === 'function' ) {
8486				var rows = _selector_row_indexes( settings, opts );
8487	
8488				return $.map( columns, function (col, idx) {
8489					return s(
8490							idx,
8491							__columnData( settings, idx, 0, 0, rows ),
8492							nodes[ idx ]
8493						) ? idx : null;
8494				} );
8495			}
8496	
8497			// jQuery or string selector
8498			var match = typeof s === 'string' ?
8499				s.match( __re_column_selector ) :
8500				'';
8501	
8502			if ( match ) {
8503				switch( match[2] ) {
8504					case 'visIdx':
8505					case 'visible':
8506						var idx = parseInt( match[1], 10 );
8507						// Visible index given, convert to column index
8508						if ( idx < 0 ) {
8509							// Counting from the right
8510							var visColumns = $.map( columns, function (col,i) {
8511								return col.bVisible ? i : null;
8512							} );
8513							return [ visColumns[ visColumns.length + idx ] ];
8514						}
8515						// Counting from the left
8516						return [ _fnVisibleToColumnIndex( settings, idx ) ];
8517	
8518					case 'name':
8519						// match by name. `names` is column index complete and in order
8520						return $.map( names, function (name, i) {
8521							return name === match[1] ? i : null;
8522						} );
8523	
8524					default:
8525						return [];
8526				}
8527			}
8528	
8529			// Cell in the table body
8530			if ( s.nodeName && s._DT_CellIndex ) {
8531				return [ s._DT_CellIndex.column ];
8532			}
8533	
8534			// jQuery selector on the TH elements for the columns
8535			var jqResult = $( nodes )
8536				.filter( s )
8537				.map( function () {
8538					return $.inArray( this, nodes ); // `nodes` is column index complete and in order
8539				} )
8540				.toArray();
8541	
8542			if ( jqResult.length || ! s.nodeName ) {
8543				return jqResult;
8544			}
8545	
8546			// Otherwise a node which might have a `dt-column` data attribute, or be
8547			// a child or such an element
8548			var host = $(s).closest('*[data-dt-column]');
8549			return host.length ?
8550				[ host.data('dt-column') ] :
8551				[];
8552		};
8553	
8554		return _selector_run( 'column', selector, run, settings, opts );
8555	};
8556	
8557	
8558	var __setColumnVis = function ( settings, column, vis ) {
8559		var
8560			cols = settings.aoColumns,
8561			col  = cols[ column ],
8562			data = settings.aoData,
8563			row, cells, i, ien, tr;
8564	
8565		// Get
8566		if ( vis === undefined ) {
8567			return col.bVisible;
8568		}
8569	
8570		// Set
8571		// No change
8572		if ( col.bVisible === vis ) {
8573			return;
8574		}
8575	
8576		if ( vis ) {
8577			// Insert column
8578			// Need to decide if we should use appendChild or insertBefore
8579			var insertBefore = $.inArray( true, _pluck(cols, 'bVisible'), column+1 );
8580	
8581			for ( i=0, ien=data.length ; i<ien ; i++ ) {
8582				tr = data[i].nTr;
8583				cells = data[i].anCells;
8584	
8585				if ( tr ) {
8586					// insertBefore can act like appendChild if 2nd arg is null
8587					tr.insertBefore( cells[ column ], cells[ insertBefore ] || null );
8588				}
8589			}
8590		}
8591		else {
8592			// Remove column
8593			$( _pluck( settings.aoData, 'anCells', column ) ).detach();
8594		}
8595	
8596		// Common actions
8597		col.bVisible = vis;
8598	};
8599	
8600	
8601	_api_register( 'columns()', function ( selector, opts ) {
8602		// argument shifting
8603		if ( selector === undefined ) {
8604			selector = '';
8605		}
8606		else if ( $.isPlainObject( selector ) ) {
8607			opts = selector;
8608			selector = '';
8609		}
8610	
8611		opts = _selector_opts( opts );
8612	
8613		var inst = this.iterator( 'table', function ( settings ) {
8614			return __column_selector( settings, selector, opts );
8615		}, 1 );
8616	
8617		// Want argument shifting here and in _row_selector?
8618		inst.selector.cols = selector;
8619		inst.selector.opts = opts;
8620	
8621		return inst;
8622	} );
8623	
8624	_api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) {
8625		return this.iterator( 'column', function ( settings, column ) {
8626			return settings.aoColumns[column].nTh;
8627		}, 1 );
8628	} );
8629	
8630	_api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) {
8631		return this.iterator( 'column', function ( settings, column ) {
8632			return settings.aoColumns[column].nTf;
8633		}, 1 );
8634	} );
8635	
8636	_api_registerPlural( 'columns().data()', 'column().data()', function () {
8637		return this.iterator( 'column-rows', __columnData, 1 );
8638	} );
8639	
8640	_api_registerPlural( 'columns().dataSrc()', 'column().dataSrc()', function () {
8641		return this.iterator( 'column', function ( settings, column ) {
8642			return settings.aoColumns[column].mData;
8643		}, 1 );
8644	} );
8645	
8646	_api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) {
8647		return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8648			return _pluck_order( settings.aoData, rows,
8649				type === 'search' ? '_aFilterData' : '_aSortData', column
8650			);
8651		}, 1 );
8652	} );
8653	
8654	_api_registerPlural( 'columns().nodes()', 'column().nodes()', function () {
8655		return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8656			return _pluck_order( settings.aoData, rows, 'anCells', column ) ;
8657		}, 1 );
8658	} );
8659	
8660	_api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis, calc ) {
8661		var that = this;
8662		var ret = this.iterator( 'column', function ( settings, column ) {
8663			if ( vis === undefined ) {
8664				return settings.aoColumns[ column ].bVisible;
8665			} // else
8666			__setColumnVis( settings, column, vis );
8667		} );
8668	
8669		// Group the column visibility changes
8670		if ( vis !== undefined ) {
8671			this.iterator( 'table', function ( settings ) {
8672				// Redraw the header after changes
8673				_fnDrawHead( settings, settings.aoHeader );
8674				_fnDrawHead( settings, settings.aoFooter );
8675		
8676				// Update colspan for no records display. Child rows and extensions will use their own
8677				// listeners to do this - only need to update the empty table item here
8678				if ( ! settings.aiDisplay.length ) {
8679					$(settings.nTBody).find('td[colspan]').attr('colspan', _fnVisbleColumns(settings));
8680				}
8681		
8682				_fnSaveState( settings );
8683	
8684				// Second loop once the first is done for events
8685				that.iterator( 'column', function ( settings, column ) {
8686					_fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis, calc] );
8687				} );
8688	
8689				if ( calc === undefined || calc ) {
8690					that.columns.adjust();
8691				}
8692			});
8693		}
8694	
8695		return ret;
8696	} );
8697	
8698	_api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) {
8699		return this.iterator( 'column', function ( settings, column ) {
8700			return type === 'visible' ?
8701				_fnColumnIndexToVisible( settings, column ) :
8702				column;
8703		}, 1 );
8704	} );
8705	
8706	_api_register( 'columns.adjust()', function () {
8707		return this.iterator( 'table', function ( settings ) {
8708			_fnAdjustColumnSizing( settings );
8709		}, 1 );
8710	} );
8711	
8712	_api_register( 'column.index()', function ( type, idx ) {
8713		if ( this.context.length !== 0 ) {
8714			var ctx = this.context[0];
8715	
8716			if ( type === 'fromVisible' || type === 'toData' ) {
8717				return _fnVisibleToColumnIndex( ctx, idx );
8718			}
8719			else if ( type === 'fromData' || type === 'toVisible' ) {
8720				return _fnColumnIndexToVisible( ctx, idx );
8721			}
8722		}
8723	} );
8724	
8725	_api_register( 'column()', function ( selector, opts ) {
8726		return _selector_first( this.columns( selector, opts ) );
8727	} );
8728	
8729	
8730	
8731	var __cell_selector = function ( settings, selector, opts )
8732	{
8733		var data = settings.aoData;
8734		var rows = _selector_row_indexes( settings, opts );
8735		var cells = _removeEmpty( _pluck_order( data, rows, 'anCells' ) );
8736		var allCells = $( [].concat.apply([], cells) 
vendor: 7,274 bytes, lines 8736-9008
8736);
8737		var row;
8738		var columns = settings.aoColumns.length;
8739		var a, i, ien, j, o, host;
8740	
8741		var run = function ( s ) {
8742			var fnSelector = typeof s === 'function';
8743	
8744			if ( s === null || s === undefined || fnSelector ) {
8745				// All cells and function selectors
8746				a = [];
8747	
8748				for ( i=0, ien=rows.length ; i<ien ; i++ ) {
8749					row = rows[i];
8750	
8751					for ( j=0 ; j<columns ; j++ ) {
8752						o = {
8753							row: row,
8754							column: j
8755						};
8756	
8757						if ( fnSelector ) {
8758							// Selector - function
8759							host = data[ row ];
8760	
8761							if ( s( o, _fnGetCellData(settings, row, j), host.anCells ? host.anCells[j] : null ) ) {
8762								a.push( o );
8763							}
8764						}
8765						else {
8766							// Selector - all
8767							a.push( o );
8768						}
8769					}
8770				}
8771	
8772				return a;
8773			}
8774			
8775			// Selector - index
8776			if ( $.isPlainObject( s ) ) {
8777				// Valid cell index and its in the array of selectable rows
8778				return s.column !== undefined && s.row !== undefined && $.inArray( s.row, rows ) !== -1 ?
8779					[s] :
8780					[];
8781			}
8782	
8783			// Selector - jQuery filtered cells
8784			var jqResult = allCells
8785				.filter( s )
8786				.map( function (i, el) {
8787					return { // use a new object, in case someone changes the values
8788						row:    el._DT_CellIndex.row,
8789						column: el._DT_CellIndex.column
8790	 				};
8791				} )
8792				.toArray();
8793	
8794			if ( jqResult.length || ! s.nodeName ) {
8795				return jqResult;
8796			}
8797	
8798			// Otherwise the selector is a node, and there is one last option - the
8799			// element might be a child of an element which has dt-row and dt-column
8800			// data attributes
8801			host = $(s).closest('*[data-dt-row]');
8802			return host.length ?
8803				[ {
8804					row: host.data('dt-row'),
8805					column: host.data('dt-column')
8806				} ] :
8807				[];
8808		};
8809	
8810		return _selector_run( 'cell', selector, run, settings, opts );
8811	};
8812	
8813	
8814	
8815	
8816	_api_register( 'cells()', function ( rowSelector, columnSelector, opts ) {
8817		// Argument shifting
8818		if ( $.isPlainObject( rowSelector ) ) {
8819			// Indexes
8820			if ( rowSelector.row === undefined ) {
8821				// Selector options in first parameter
8822				opts = rowSelector;
8823				rowSelector = null;
8824			}
8825			else {
8826				// Cell index objects in first parameter
8827				opts = columnSelector;
8828				columnSelector = null;
8829			}
8830		}
8831		if ( $.isPlainObject( columnSelector ) ) {
8832			opts = columnSelector;
8833			columnSelector = null;
8834		}
8835	
8836		// Cell selector
8837		if ( columnSelector === null || columnSelector === undefined ) {
8838			return this.iterator( 'table', function ( settings ) {
8839				return __cell_selector( settings, rowSelector, _selector_opts( opts ) );
8840			} );
8841		}
8842	
8843		// The default built in options need to apply to row and columns
8844		var internalOpts = opts ? {
8845			page: opts.page,
8846			order: opts.order,
8847			search: opts.search
8848		} : {};
8849	
8850		// Row + column selector
8851		var columns = this.columns( columnSelector, internalOpts );
8852		var rows = this.rows( rowSelector, internalOpts );
8853		var i, ien, j, jen;
8854	
8855		var cellsNoOpts = this.iterator( 'table', function ( settings, idx ) {
8856			var a = [];
8857	
8858			for ( i=0, ien=rows[idx].length ; i<ien ; i++ ) {
8859				for ( j=0, jen=columns[idx].length ; j<jen ; j++ ) {
8860					a.push( {
8861						row:    rows[idx][i],
8862						column: columns[idx][j]
8863					} );
8864				}
8865			}
8866	
8867			return a;
8868		}, 1 );
8869	
8870		// There is currently only one extension which uses a cell selector extension
8871		// It is a _major_ performance drag to run this if it isn't needed, so this is
8872		// an extension specific check at the moment
8873		var cells = opts && opts.selected ?
8874			this.cells( cellsNoOpts, opts ) :
8875			cellsNoOpts;
8876	
8877		$.extend( cells.selector, {
8878			cols: columnSelector,
8879			rows: rowSelector,
8880			opts: opts
8881		} );
8882	
8883		return cells;
8884	} );
8885	
8886	
8887	_api_registerPlural( 'cells().nodes()', 'cell().node()', function () {
8888		return this.iterator( 'cell', function ( settings, row, column ) {
8889			var data = settings.aoData[ row ];
8890	
8891			return data && data.anCells ?
8892				data.anCells[ column ] :
8893				undefined;
8894		}, 1 );
8895	} );
8896	
8897	
8898	_api_register( 'cells().data()', function () {
8899		return this.iterator( 'cell', function ( settings, row, column ) {
8900			return _fnGetCellData( settings, row, column );
8901		}, 1 );
8902	} );
8903	
8904	
8905	_api_registerPlural( 'cells().cache()', 'cell().cache()', function ( type ) {
8906		type = type === 'search' ? '_aFilterData' : '_aSortData';
8907	
8908		return this.iterator( 'cell', function ( settings, row, column ) {
8909			return settings.aoData[ row ][ type ][ column ];
8910		}, 1 );
8911	} );
8912	
8913	
8914	_api_registerPlural( 'cells().render()', 'cell().render()', function ( type ) {
8915		return this.iterator( 'cell', function ( settings, row, column ) {
8916			return _fnGetCellData( settings, row, column, type );
8917		}, 1 );
8918	} );
8919	
8920	
8921	_api_registerPlural( 'cells().indexes()', 'cell().index()', function () {
8922		return this.iterator( 'cell', function ( settings, row, column ) {
8923			return {
8924				row: row,
8925				column: column,
8926				columnVisible: _fnColumnIndexToVisible( settings, column )
8927			};
8928		}, 1 );
8929	} );
8930	
8931	
8932	_api_registerPlural( 'cells().invalidate()', 'cell().invalidate()', function ( src ) {
8933		return this.iterator( 'cell', function ( settings, row, column ) {
8934			_fnInvalidate( settings, row, src, column );
8935		} );
8936	} );
8937	
8938	
8939	
8940	_api_register( 'cell()', function ( rowSelector, columnSelector, opts ) {
8941		return _selector_first( this.cells( rowSelector, columnSelector, opts ) );
8942	} );
8943	
8944	
8945	_api_register( 'cell().data()', function ( data ) {
8946		var ctx = this.context;
8947		var cell = this[0];
8948	
8949		if ( data === undefined ) {
8950			// Get
8951			return ctx.length && cell.length ?
8952				_fnGetCellData( ctx[0], cell[0].row, cell[0].column ) :
8953				undefined;
8954		}
8955	
8956		// Set
8957		_fnSetCellData( ctx[0], cell[0].row, cell[0].column, data );
8958		_fnInvalidate( ctx[0], cell[0].row, 'data', cell[0].column );
8959	
8960		return this;
8961	} );
8962	
8963	
8964	
8965	/**
8966	 * Get current ordering (sorting) that has been applied to the table.
8967	 *
8968	 * @returns {array} 2D array containing the sorting information for the first
8969	 *   table in the current context. Each element in the parent array represents
8970	 *   a column being sorted upon (i.e. multi-sorting with two columns would have
8971	 *   2 inner arrays). The inner arrays may have 2 or 3 elements. The first is
8972	 *   the column index that the sorting condition applies to, the second is the
8973	 *   direction of the sort (`desc` or `asc`) and, optionally, the third is the
8974	 *   index of the sorting order from the `column.sorting` initialisation array.
8975	 *//**
8976	 * Set the ordering for the table.
8977	 *
8978	 * @param {integer} order Column index to sort upon.
8979	 * @param {string} direction Direction of the sort to be applied (`asc` or `desc`)
8980	 * @returns {DataTables.Api} this
8981	 *//**
8982	 * Set the ordering for the table.
8983	 *
8984	 * @param {array} order 1D array of sorting information to be applied.
8985	 * @param {array} [...] Optional additional sorting conditions
8986	 * @returns {DataTables.Api} this
8987	 *//**
8988	 * Set the ordering for the table.
8989	 *
8990	 * @param {array} order 2D array of sorting information to be applied.
8991	 * @returns {DataTables.Api} this
8992	 */
8993	_api_register( 'order()', function ( order, dir ) {
8994		var ctx = this.context;
8995	
8996		if ( order === undefined ) {
8997			// get
8998			return ctx.length !== 0 ?
8999				ctx[0].aaSorting :
9000				undefined;
9001		}
9002	
9003		// set
9004		if ( typeof order === 'number' ) {
9005			// Simple column / direction passed in
9006			order = [ [ order, dir ] ];
9007		}
9008		else if ( order.length && ! 
vendor: 15,088 bytes, lines 9008-9564
9008$.isArray( order[0] ) ) {
9009			// Arguments passed in (list of 1D arrays)
9010			order = Array.prototype.slice.call( arguments );
9011		}
9012		// otherwise a 2D array was passed in
9013	
9014		return this.iterator( 'table', function ( settings ) {
9015			settings.aaSorting = order.slice();
9016		} );
9017	} );
9018	
9019	
9020	/**
9021	 * Attach a sort listener to an element for a given column
9022	 *
9023	 * @param {node|jQuery|string} node Identifier for the element(s) to attach the
9024	 *   listener to. This can take the form of a single DOM node, a jQuery
9025	 *   collection of nodes or a jQuery selector which will identify the node(s).
9026	 * @param {integer} column the column that a click on this node will sort on
9027	 * @param {function} [callback] callback function when sort is run
9028	 * @returns {DataTables.Api} this
9029	 */
9030	_api_register( 'order.listener()', function ( node, column, callback ) {
9031		return this.iterator( 'table', function ( settings ) {
9032			_fnSortAttachListener( settings, node, column, callback );
9033		} );
9034	} );
9035	
9036	
9037	_api_register( 'order.fixed()', function ( set ) {
9038		if ( ! set ) {
9039			var ctx = this.context;
9040			var fixed = ctx.length ?
9041				ctx[0].aaSortingFixed :
9042				undefined;
9043	
9044			return $.isArray( fixed ) ?
9045				{ pre: fixed } :
9046				fixed;
9047		}
9048	
9049		return this.iterator( 'table', function ( settings ) {
9050			settings.aaSortingFixed = $.extend( true, {}, set );
9051		} );
9052	} );
9053	
9054	
9055	// Order by the selected column(s)
9056	_api_register( [
9057		'columns().order()',
9058		'column().order()'
9059	], function ( dir ) {
9060		var that = this;
9061	
9062		return this.iterator( 'table', function ( settings, i ) {
9063			var sort = [];
9064	
9065			$.each( that[i], function (j, col) {
9066				sort.push( [ col, dir ] );
9067			} );
9068	
9069			settings.aaSorting = sort;
9070		} );
9071	} );
9072	
9073	
9074	
9075	_api_register( 'search()', function ( input, regex, smart, caseInsen ) {
9076		var ctx = this.context;
9077	
9078		if ( input === undefined ) {
9079			// get
9080			return ctx.length !== 0 ?
9081				ctx[0].oPreviousSearch.sSearch :
9082				undefined;
9083		}
9084	
9085		// set
9086		return this.iterator( 'table', function ( settings ) {
9087			if ( ! settings.oFeatures.bFilter ) {
9088				return;
9089			}
9090	
9091			_fnFilterComplete( settings, $.extend( {}, settings.oPreviousSearch, {
9092				"sSearch": input+"",
9093				"bRegex":  regex === null ? false : regex,
9094				"bSmart":  smart === null ? true  : smart,
9095				"bCaseInsensitive": caseInsen === null ? true : caseInsen
9096			} ), 1 );
9097		} );
9098	} );
9099	
9100	
9101	_api_registerPlural(
9102		'columns().search()',
9103		'column().search()',
9104		function ( input, regex, smart, caseInsen ) {
9105			return this.iterator( 'column', function ( settings, column ) {
9106				var preSearch = settings.aoPreSearchCols;
9107	
9108				if ( input === undefined ) {
9109					// get
9110					return preSearch[ column ].sSearch;
9111				}
9112	
9113				// set
9114				if ( ! settings.oFeatures.bFilter ) {
9115					return;
9116				}
9117	
9118				$.extend( preSearch[ column ], {
9119					"sSearch": input+"",
9120					"bRegex":  regex === null ? false : regex,
9121					"bSmart":  smart === null ? true  : smart,
9122					"bCaseInsensitive": caseInsen === null ? true : caseInsen
9123				} );
9124	
9125				_fnFilterComplete( settings, settings.oPreviousSearch, 1 );
9126			} );
9127		}
9128	);
9129	
9130	/*
9131	 * State API methods
9132	 */
9133	
9134	_api_register( 'state()', function () {
9135		return this.context.length ?
9136			this.context[0].oSavedState :
9137			null;
9138	} );
9139	
9140	
9141	_api_register( 'state.clear()', function () {
9142		return this.iterator( 'table', function ( settings ) {
9143			// Save an empty object
9144			settings.fnStateSaveCallback.call( settings.oInstance, settings, {} );
9145		} );
9146	} );
9147	
9148	
9149	_api_register( 'state.loaded()', function () {
9150		return this.context.length ?
9151			this.context[0].oLoadedState :
9152			null;
9153	} );
9154	
9155	
9156	_api_register( 'state.save()', function () {
9157		return this.iterator( 'table', function ( settings ) {
9158			_fnSaveState( settings );
9159		} );
9160	} );
9161	
9162	
9163	
9164	/**
9165	 * Provide a common method for plug-ins to check the version of DataTables being
9166	 * used, in order to ensure compatibility.
9167	 *
9168	 *  @param {string} version Version string to check for, in the format "X.Y.Z".
9169	 *    Note that the formats "X" and "X.Y" are also acceptable.
9170	 *  @returns {boolean} true if this version of DataTables is greater or equal to
9171	 *    the required version, or false if this version of DataTales is not
9172	 *    suitable
9173	 *  @static
9174	 *  @dtopt API-Static
9175	 *
9176	 *  @example
9177	 *    alert( $.fn.dataTable.versionCheck( '1.9.0' ) );
9178	 */
9179	DataTable.versionCheck = DataTable.fnVersionCheck = function( version )
9180	{
9181		var aThis = DataTable.version.split('.');
9182		var aThat = version.split('.');
9183		var iThis, iThat;
9184	
9185		for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) {
9186			iThis = parseInt( aThis[i], 10 ) || 0;
9187			iThat = parseInt( aThat[i], 10 ) || 0;
9188	
9189			// Parts are the same, keep comparing
9190			if (iThis === iThat) {
9191				continue;
9192			}
9193	
9194			// Parts are different, return immediately
9195			return iThis > iThat;
9196		}
9197	
9198		return true;
9199	};
9200	
9201	
9202	/**
9203	 * Check if a `<table>` node is a DataTable table already or not.
9204	 *
9205	 *  @param {node|jquery|string} table Table node, jQuery object or jQuery
9206	 *      selector for the table to test. Note that if more than more than one
9207	 *      table is passed on, only the first will be checked
9208	 *  @returns {boolean} true the table given is a DataTable, or false otherwise
9209	 *  @static
9210	 *  @dtopt API-Static
9211	 *
9212	 *  @example
9213	 *    if ( ! $.fn.DataTable.isDataTable( '#example' ) ) {
9214	 *      $('#example').dataTable();
9215	 *    }
9216	 */
9217	DataTable.isDataTable = DataTable.fnIsDataTable = function ( table )
9218	{
9219		var t = $(table).get(0);
9220		var is = false;
9221	
9222		if ( table instanceof DataTable.Api ) {
9223			return true;
9224		}
9225	
9226		$.each( DataTable.settings, function (i, o) {
9227			var head = o.nScrollHead ? $('table', o.nScrollHead)[0] : null;
9228			var foot = o.nScrollFoot ? $('table', o.nScrollFoot)[0] : null;
9229	
9230			if ( o.nTable === t || head === t || foot === t ) {
9231				is = true;
9232			}
9233		} );
9234	
9235		return is;
9236	};
9237	
9238	
9239	/**
9240	 * Get all DataTable tables that have been initialised - optionally you can
9241	 * select to get only currently visible tables.
9242	 *
9243	 *  @param {boolean} [visible=false] Flag to indicate if you want all (default)
9244	 *    or visible tables only.
9245	 *  @returns {array} Array of `table` nodes (not DataTable instances) which are
9246	 *    DataTables
9247	 *  @static
9248	 *  @dtopt API-Static
9249	 *
9250	 *  @example
9251	 *    $.each( $.fn.dataTable.tables(true), function () {
9252	 *      $(table).DataTable().columns.adjust();
9253	 *    } );
9254	 */
9255	DataTable.tables = DataTable.fnTables = function ( visible )
9256	{
9257		var api = false;
9258	
9259		if ( $.isPlainObject( visible ) ) {
9260			api = visible.api;
9261			visible = visible.visible;
9262		}
9263	
9264		var a = $.map( DataTable.settings, function (o) {
9265			if ( !visible || (visible && $(o.nTable).is(':visible')) ) {
9266				return o.nTable;
9267			}
9268		} );
9269	
9270		return api ?
9271			new _Api( a ) :
9272			a;
9273	};
9274	
9275	
9276	/**
9277	 * Convert from camel case parameters to Hungarian notation. This is made public
9278	 * for the extensions to provide the same ability as DataTables core to accept
9279	 * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase
9280	 * parameters.
9281	 *
9282	 *  @param {object} src The model object which holds all parameters that can be
9283	 *    mapped.
9284	 *  @param {object} user The object to convert from camel case to Hungarian.
9285	 *  @param {boolean} force When set to `true`, properties which already have a
9286	 *    Hungarian value in the `user` object will be overwritten. Otherwise they
9287	 *    won't be.
9288	 */
9289	DataTable.camelToHungarian = _fnCamelToHungarian;
9290	
9291	
9292	
9293	/**
9294	 *
9295	 */
9296	_api_register( '$()', function ( selector, opts ) {
9297		var
9298			rows   = this.rows( opts ).nodes(), // Get all rows
9299			jqRows = $(rows);
9300	
9301		return $( [].concat(
9302			jqRows.filter( selector ).toArray(),
9303			jqRows.find( selector ).toArray()
9304		) );
9305	} );
9306	
9307	
9308	// jQuery functions to operate on the tables
9309	$.each( [ 'on', 'one', 'off' ], function (i, key) {
9310		_api_register( key+'()', function ( /* event, handler */ ) {
9311			var args = Array.prototype.slice.call(arguments);
9312	
9313			// Add the `dt` namespace automatically if it isn't already present
9314			args[0] = $.map( args[0].split( /\s/ ), function ( e ) {
9315				return ! e.match(/\.dt\b/) ?
9316					e+'.dt' :
9317					e;
9318				} ).join( ' ' );
9319	
9320			var inst = $( this.tables().nodes() );
9321			inst[key].apply( inst, args );
9322			return this;
9323		} );
9324	} );
9325	
9326	
9327	_api_register( 'clear()', function () {
9328		return this.iterator( 'table', function ( settings ) {
9329			_fnClearTable( settings );
9330		} );
9331	} );
9332	
9333	
9334	_api_register( 'settings()', function () {
9335		return new _Api( this.context, this.context );
9336	} );
9337	
9338	
9339	_api_register( 'init()', function () {
9340		var ctx = this.context;
9341		return ctx.length ? ctx[0].oInit : null;
9342	} );
9343	
9344	
9345	_api_register( 'data()', function () {
9346		return this.iterator( 'table', function ( settings ) {
9347			return _pluck( settings.aoData, '_aData' );
9348		} ).flatten();
9349	} );
9350	
9351	
9352	_api_register( 'destroy()', function ( remove ) {
9353		remove = remove || false;
9354	
9355		return this.iterator( 'table', function ( settings ) {
9356			var orig      = settings.nTableWrapper.parentNode;
9357			var classes   = settings.oClasses;
9358			var table     = settings.nTable;
9359			var tbody     = settings.nTBody;
9360			var thead     = settings.nTHead;
9361			var tfoot     = settings.nTFoot;
9362			var jqTable   = $(table);
9363			var jqTbody   = $(tbody);
9364			var jqWrapper = $(settings.nTableWrapper);
9365			var rows      = $.map( settings.aoData, function (r) { return r.nTr; } );
9366			var i, ien;
9367	
9368			// Flag to note that the table is currently being destroyed - no action
9369			// should be taken
9370			settings.bDestroying = true;
9371	
9372			// Fire off the destroy callbacks for plug-ins etc
9373			_fnCallbackFire( settings, "aoDestroyCallback", "destroy", [settings] );
9374	
9375			// If not being removed from the document, make all columns visible
9376			if ( ! remove ) {
9377				new _Api( settings ).columns().visible( true );
9378			}
9379	
9380			// Blitz all `DT` namespaced events (these are internal events, the
9381			// lowercase, `dt` events are user subscribed and they are responsible
9382			// for removing them
9383			jqWrapper.off('.DT').find(':not(tbody *)').off('.DT');
9384			$(window).off('.DT-'+settings.sInstance);
9385	
9386			// When scrolling we had to break the table up - restore it
9387			if ( table != thead.parentNode ) {
9388				jqTable.children('thead').detach();
9389				jqTable.append( thead );
9390			}
9391	
9392			if ( tfoot && table != tfoot.parentNode ) {
9393				jqTable.children('tfoot').detach();
9394				jqTable.append( tfoot );
9395			}
9396	
9397			settings.aaSorting = [];
9398			settings.aaSortingFixed = [];
9399			_fnSortingClasses( settings );
9400	
9401			$( rows ).removeClass( settings.asStripeClasses.join(' ') );
9402	
9403			$('th, td', thead).removeClass( classes.sSortable+' '+
9404				classes.sSortableAsc+' '+classes.sSortableDesc+' '+classes.sSortableNone
9405			);
9406	
9407			// Add the TR elements back into the table in their original order
9408			jqTbody.children().detach();
9409			jqTbody.append( rows );
9410	
9411			// Remove the DataTables generated nodes, events and classes
9412			var removedMethod = remove ? 'remove' : 'detach';
9413			jqTable[ removedMethod ]();
9414			jqWrapper[ removedMethod ]();
9415	
9416			// If we need to reattach the table to the document
9417			if ( ! remove && orig ) {
9418				// insertBefore acts like appendChild if !arg[1]
9419				orig.insertBefore( table, settings.nTableReinsertBefore );
9420	
9421				// Restore the width of the original table - was read from the style property,
9422				// so we can restore directly to that
9423				jqTable
9424					.css( 'width', settings.sDestroyWidth )
9425					.removeClass( classes.sTable );
9426	
9427				// If the were originally stripe classes - then we add them back here.
9428				// Note this is not fool proof (for example if not all rows had stripe
9429				// classes - but it's a good effort without getting carried away
9430				ien = settings.asDestroyStripes.length;
9431	
9432				if ( ien ) {
9433					jqTbody.children().each( function (i) {
9434						$(this).addClass( settings.asDestroyStripes[i % ien] );
9435					} );
9436				}
9437			}
9438	
9439			/* Remove the settings object from the settings array */
9440			var idx = $.inArray( settings, DataTable.settings );
9441			if ( idx !== -1 ) {
9442				DataTable.settings.splice( idx, 1 );
9443			}
9444		} );
9445	} );
9446	
9447	
9448	// Add the `every()` method for rows, columns and cells in a compact form
9449	$.each( [ 'column', 'row', 'cell' ], function ( i, type ) {
9450		_api_register( type+'s().every()', function ( fn ) {
9451			var opts = this.selector.opts;
9452			var api = this;
9453	
9454			return this.iterator( type, function ( settings, arg1, arg2, arg3, arg4 ) {
9455				// Rows and columns:
9456				//  arg1 - index
9457				//  arg2 - table counter
9458				//  arg3 - loop counter
9459				//  arg4 - undefined
9460				// Cells:
9461				//  arg1 - row index
9462				//  arg2 - column index
9463				//  arg3 - table counter
9464				//  arg4 - loop counter
9465				fn.call(
9466					api[ type ](
9467						arg1,
9468						type==='cell' ? arg2 : opts,
9469						type==='cell' ? opts : undefined
9470					),
9471					arg1, arg2, arg3, arg4
9472				);
9473			} );
9474		} );
9475	} );
9476	
9477	
9478	// i18n method for extensions to be able to use the language object from the
9479	// DataTable
9480	_api_register( 'i18n()', function ( token, def, plural ) {
9481		var ctx = this.context[0];
9482		var resolved = _fnGetObjectDataFn( token )( ctx.oLanguage );
9483	
9484		if ( resolved === undefined ) {
9485			resolved = def;
9486		}
9487	
9488		if ( plural !== undefined && $.isPlainObject( resolved ) ) {
9489			resolved = resolved[ plural ] !== undefined ?
9490				resolved[ plural ] :
9491				resolved._;
9492		}
9493	
9494		return resolved.replace( '%d', plural ); // nb: plural might be undefined,
9495	} );
9496	/**
9497	 * Version string for plug-ins to check compatibility. Allowed format is
9498	 * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used
9499	 * only for non-release builds. See http://semver.org/ for more information.
9500	 *  @member
9501	 *  @type string
9502	 *  @default Version number
9503	 */
9504	DataTable.version = "1.10.21";
9505
9506	/**
9507	 * Private data store, containing all of the settings objects that are
9508	 * created for the tables on a given page.
9509	 *
9510	 * Note that the `DataTable.settings` object is aliased to
9511	 * `jQuery.fn.dataTableExt` through which it may be accessed and
9512	 * manipulated, or `jQuery.fn.dataTable.settings`.
9513	 *  @member
9514	 *  @type array
9515	 *  @default []
9516	 *  @private
9517	 */
9518	DataTable.settings = [];
9519
9520	/**
9521	 * Object models container, for the various models that DataTables has
9522	 * available to it. These models define the objects that are used to hold
9523	 * the active state and configuration of the table.
9524	 *  @namespace
9525	 */
9526	DataTable.models = {};
9527	
9528	
9529	
9530	/**
9531	 * Template object for the way in which DataTables holds information about
9532	 * search information for the global filter and individual column filters.
9533	 *  @namespace
9534	 */
9535	DataTable.models.oSearch = {
9536		/**
9537		 * Flag to indicate if the filtering should be case insensitive or not
9538		 *  @type boolean
9539		 *  @default true
9540		 */
9541		"bCaseInsensitive": true,
9542	
9543		/**
9544		 * Applied search term
9545		 *  @type string
9546		 *  @default <i>Empty string</i>
9547		 */
9548		"sSearch": "",
9549	
9550		/**
9551		 * Flag to indicate if the search term should be interpreted as a
9552		 * regular expression (true) or not (false) and therefore and special
9553		 * regex characters escaped.
9554		 *  @type boolean
9555		 *  @default false
9556		 */
9557		"bRegex": false,
9558	
9559		/**
9560		 * Flag to indicate if DataTables is to use its smart filtering or not.
9561		 *  @type boolean
9562		 *  @default true
9563		 */
9564		"bSmart": tru
vendor: 11,217 bytes, lines 9564-9922
9564e
9565	};
9566	
9567	
9568	
9569	
9570	/**
9571	 * Template object for the way in which DataTables holds information about
9572	 * each individual row. This is the object format used for the settings
9573	 * aoData array.
9574	 *  @namespace
9575	 */
9576	DataTable.models.oRow = {
9577		/**
9578		 * TR element for the row
9579		 *  @type node
9580		 *  @default null
9581		 */
9582		"nTr": null,
9583	
9584		/**
9585		 * Array of TD elements for each row. This is null until the row has been
9586		 * created.
9587		 *  @type array nodes
9588		 *  @default []
9589		 */
9590		"anCells": null,
9591	
9592		/**
9593		 * Data object from the original data source for the row. This is either
9594		 * an array if using the traditional form of DataTables, or an object if
9595		 * using mData options. The exact type will depend on the passed in
9596		 * data from the data source, or will be an array if using DOM a data
9597		 * source.
9598		 *  @type array|object
9599		 *  @default []
9600		 */
9601		"_aData": [],
9602	
9603		/**
9604		 * Sorting data cache - this array is ostensibly the same length as the
9605		 * number of columns (although each index is generated only as it is
9606		 * needed), and holds the data that is used for sorting each column in the
9607		 * row. We do this cache generation at the start of the sort in order that
9608		 * the formatting of the sort data need be done only once for each cell
9609		 * per sort. This array should not be read from or written to by anything
9610		 * other than the master sorting methods.
9611		 *  @type array
9612		 *  @default null
9613		 *  @private
9614		 */
9615		"_aSortData": null,
9616	
9617		/**
9618		 * Per cell filtering data cache. As per the sort data cache, used to
9619		 * increase the performance of the filtering in DataTables
9620		 *  @type array
9621		 *  @default null
9622		 *  @private
9623		 */
9624		"_aFilterData": null,
9625	
9626		/**
9627		 * Filtering data cache. This is the same as the cell filtering cache, but
9628		 * in this case a string rather than an array. This is easily computed with
9629		 * a join on `_aFilterData`, but is provided as a cache so the join isn't
9630		 * needed on every search (memory traded for performance)
9631		 *  @type array
9632		 *  @default null
9633		 *  @private
9634		 */
9635		"_sFilterRow": null,
9636	
9637		/**
9638		 * Cache of the class name that DataTables has applied to the row, so we
9639		 * can quickly look at this variable rather than needing to do a DOM check
9640		 * on className for the nTr property.
9641		 *  @type string
9642		 *  @default <i>Empty string</i>
9643		 *  @private
9644		 */
9645		"_sRowStripe": "",
9646	
9647		/**
9648		 * Denote if the original data source was from the DOM, or the data source
9649		 * object. This is used for invalidating data, so DataTables can
9650		 * automatically read data from the original source, unless uninstructed
9651		 * otherwise.
9652		 *  @type string
9653		 *  @default null
9654		 *  @private
9655		 */
9656		"src": null,
9657	
9658		/**
9659		 * Index in the aoData array. This saves an indexOf lookup when we have the
9660		 * object, but want to know the index
9661		 *  @type integer
9662		 *  @default -1
9663		 *  @private
9664		 */
9665		"idx": -1
9666	};
9667	
9668	
9669	/**
9670	 * Template object for the column information object in DataTables. This object
9671	 * is held in the settings aoColumns array and contains all the information that
9672	 * DataTables needs about each individual column.
9673	 *
9674	 * Note that this object is related to {@link DataTable.defaults.column}
9675	 * but this one is the internal data store for DataTables's cache of columns.
9676	 * It should NOT be manipulated outside of DataTables. Any configuration should
9677	 * be done through the initialisation options.
9678	 *  @namespace
9679	 */
9680	DataTable.models.oColumn = {
9681		/**
9682		 * Column index. This could be worked out on-the-fly with $.inArray, but it
9683		 * is faster to just hold it as a variable
9684		 *  @type integer
9685		 *  @default null
9686		 */
9687		"idx": null,
9688	
9689		/**
9690		 * A list of the columns that sorting should occur on when this column
9691		 * is sorted. That this property is an array allows multi-column sorting
9692		 * to be defined for a column (for example first name / last name columns
9693		 * would benefit from this). The values are integers pointing to the
9694		 * columns to be sorted on (typically it will be a single integer pointing
9695		 * at itself, but that doesn't need to be the case).
9696		 *  @type array
9697		 */
9698		"aDataSort": null,
9699	
9700		/**
9701		 * Define the sorting directions that are applied to the column, in sequence
9702		 * as the column is repeatedly sorted upon - i.e. the first value is used
9703		 * as the sorting direction when the column if first sorted (clicked on).
9704		 * Sort it again (click again) and it will move on to the next index.
9705		 * Repeat until loop.
9706		 *  @type array
9707		 */
9708		"asSorting": null,
9709	
9710		/**
9711		 * Flag to indicate if the column is searchable, and thus should be included
9712		 * in the filtering or not.
9713		 *  @type boolean
9714		 */
9715		"bSearchable": null,
9716	
9717		/**
9718		 * Flag to indicate if the column is sortable or not.
9719		 *  @type boolean
9720		 */
9721		"bSortable": null,
9722	
9723		/**
9724		 * Flag to indicate if the column is currently visible in the table or not
9725		 *  @type boolean
9726		 */
9727		"bVisible": null,
9728	
9729		/**
9730		 * Store for manual type assignment using the `column.type` option. This
9731		 * is held in store so we can manipulate the column's `sType` property.
9732		 *  @type string
9733		 *  @default null
9734		 *  @private
9735		 */
9736		"_sManualType": null,
9737	
9738		/**
9739		 * Flag to indicate if HTML5 data attributes should be used as the data
9740		 * source for filtering or sorting. True is either are.
9741		 *  @type boolean
9742		 *  @default false
9743		 *  @private
9744		 */
9745		"_bAttrSrc": false,
9746	
9747		/**
9748		 * Developer definable function that is called whenever a cell is created (Ajax source,
9749		 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
9750		 * allowing you to modify the DOM element (add background colour for example) when the
9751		 * element is available.
9752		 *  @type function
9753		 *  @param {element} nTd The TD node that has been created
9754		 *  @param {*} sData The Data for the cell
9755		 *  @param {array|object} oData The data for the whole row
9756		 *  @param {int} iRow The row index for the aoData data store
9757		 *  @default null
9758		 */
9759		"fnCreatedCell": null,
9760	
9761		/**
9762		 * Function to get data from a cell in a column. You should <b>never</b>
9763		 * access data directly through _aData internally in DataTables - always use
9764		 * the method attached to this property. It allows mData to function as
9765		 * required. This function is automatically assigned by the column
9766		 * initialisation method
9767		 *  @type function
9768		 *  @param {array|object} oData The data array/object for the array
9769		 *    (i.e. aoData[]._aData)
9770		 *  @param {string} sSpecific The specific data type you want to get -
9771		 *    'display', 'type' 'filter' 'sort'
9772		 *  @returns {*} The data for the cell from the given row's data
9773		 *  @default null
9774		 */
9775		"fnGetData": null,
9776	
9777		/**
9778		 * Function to set data for a cell in the column. You should <b>never</b>
9779		 * set the data directly to _aData internally in DataTables - always use
9780		 * this method. It allows mData to function as required. This function
9781		 * is automatically assigned by the column initialisation method
9782		 *  @type function
9783		 *  @param {array|object} oData The data array/object for the array
9784		 *    (i.e. aoData[]._aData)
9785		 *  @param {*} sValue Value to set
9786		 *  @default null
9787		 */
9788		"fnSetData": null,
9789	
9790		/**
9791		 * Property to read the value for the cells in the column from the data
9792		 * source array / object. If null, then the default content is used, if a
9793		 * function is given then the return from the function is used.
9794		 *  @type function|int|string|null
9795		 *  @default null
9796		 */
9797		"mData": null,
9798	
9799		/**
9800		 * Partner property to mData which is used (only when defined) to get
9801		 * the data - i.e. it is basically the same as mData, but without the
9802		 * 'set' option, and also the data fed to it is the result from mData.
9803		 * This is the rendering method to match the data method of mData.
9804		 *  @type function|int|string|null
9805		 *  @default null
9806		 */
9807		"mRender": null,
9808	
9809		/**
9810		 * Unique header TH/TD element for this column - this is what the sorting
9811		 * listener is attached to (if sorting is enabled.)
9812		 *  @type node
9813		 *  @default null
9814		 */
9815		"nTh": null,
9816	
9817		/**
9818		 * Unique footer TH/TD element for this column (if there is one). Not used
9819		 * in DataTables as such, but can be used for plug-ins to reference the
9820		 * footer for each column.
9821		 *  @type node
9822		 *  @default null
9823		 */
9824		"nTf": null,
9825	
9826		/**
9827		 * The class to apply to all TD elements in the table's TBODY for the column
9828		 *  @type string
9829		 *  @default null
9830		 */
9831		"sClass": null,
9832	
9833		/**
9834		 * When DataTables calculates the column widths to assign to each column,
9835		 * it finds the longest string in each column and then constructs a
9836		 * temporary table and reads the widths from that. The problem with this
9837		 * is that "mmm" is much wider then "iiii", but the latter is a longer
9838		 * string - thus the calculation can go wrong (doing it properly and putting
9839		 * it into an DOM object and measuring that is horribly(!) slow). Thus as
9840		 * a "work around" we provide this option. It will append its value to the
9841		 * text that is found to be the longest string for the column - i.e. padding.
9842		 *  @type string
9843		 */
9844		"sContentPadding": null,
9845	
9846		/**
9847		 * Allows a default value to be given for a column's data, and will be used
9848		 * whenever a null data source is encountered (this can be because mData
9849		 * is set to null, or because the data source itself is null).
9850		 *  @type string
9851		 *  @default null
9852		 */
9853		"sDefaultContent": null,
9854	
9855		/**
9856		 * Name for the column, allowing reference to the column by name as well as
9857		 * by index (needs a lookup to work by name).
9858		 *  @type string
9859		 */
9860		"sName": null,
9861	
9862		/**
9863		 * Custom sorting data type - defines which of the available plug-ins in
9864		 * afnSortData the custom sorting will use - if any is defined.
9865		 *  @type string
9866		 *  @default std
9867		 */
9868		"sSortDataType": 'std',
9869	
9870		/**
9871		 * Class to be applied to the header element when sorting on this column
9872		 *  @type string
9873		 *  @default null
9874		 */
9875		"sSortingClass": null,
9876	
9877		/**
9878		 * Class to be applied to the header element when sorting on this column -
9879		 * when jQuery UI theming is used.
9880		 *  @type string
9881		 *  @default null
9882		 */
9883		"sSortingClassJUI": null,
9884	
9885		/**
9886		 * Title of the column - what is seen in the TH element (nTh).
9887		 *  @type string
9888		 */
9889		"sTitle": null,
9890	
9891		/**
9892		 * Column sorting and filtering type
9893		 *  @type string
9894		 *  @default null
9895		 */
9896		"sType": null,
9897	
9898		/**
9899		 * Width of the column
9900		 *  @type string
9901		 *  @default null
9902		 */
9903		"sWidth": null,
9904	
9905		/**
9906		 * Width of the column when it was first "encountered"
9907		 *  @type string
9908		 *  @default null
9909		 */
9910		"sWidthOrig": null
9911	};
9912	
9913	
9914	/*
9915	 * Developer note: The properties of the object below are given in Hungarian
9916	 * notation, that was used as the interface for DataTables prior to v1.10, however
9917	 * from v1.10 onwards the primary interface is camel case. In order to avoid
9918	 * breaking backwards compatibility utterly with this change, the Hungarian
9919	 * version is still, internally the primary interface, but is is not documented
9920	 * - hence the @name tags in each doc comment. This allows a Javascript function
9921	 * to create a map from Hungarian notation to camel case (going the other direction
9922	 * would require each property to be listed, which would a
9922t around 3K to the size
9923	 * of DataTables, while this method is about a 0.5K hit
vendor: 57,106 bytes, lines 9923-11701
9923.
9924	 *
9925	 * Ultimately this does pave the way for Hungarian notation to be dropped
9926	 * completely, but that is a massive amount of work and will break current
9927	 * installs (therefore is on-hold until v2).
9928	 */
9929	
9930	/**
9931	 * Initialisation options that can be given to DataTables at initialisation
9932	 * time.
9933	 *  @namespace
9934	 */
9935	DataTable.defaults = {
9936		/**
9937		 * An array of data to use for the table, passed in at initialisation which
9938		 * will be used in preference to any data which is already in the DOM. This is
9939		 * particularly useful for constructing tables purely in Javascript, for
9940		 * example with a custom Ajax call.
9941		 *  @type array
9942		 *  @default null
9943		 *
9944		 *  @dtopt Option
9945		 *  @name DataTable.defaults.data
9946		 *
9947		 *  @example
9948		 *    // Using a 2D array data source
9949		 *    $(document).ready( function () {
9950		 *      $('#example').dataTable( {
9951		 *        "data": [
9952		 *          ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
9953		 *          ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
9954		 *        ],
9955		 *        "columns": [
9956		 *          { "title": "Engine" },
9957		 *          { "title": "Browser" },
9958		 *          { "title": "Platform" },
9959		 *          { "title": "Version" },
9960		 *          { "title": "Grade" }
9961		 *        ]
9962		 *      } );
9963		 *    } );
9964		 *
9965		 *  @example
9966		 *    // Using an array of objects as a data source (`data`)
9967		 *    $(document).ready( function () {
9968		 *      $('#example').dataTable( {
9969		 *        "data": [
9970		 *          {
9971		 *            "engine":   "Trident",
9972		 *            "browser":  "Internet Explorer 4.0",
9973		 *            "platform": "Win 95+",
9974		 *            "version":  4,
9975		 *            "grade":    "X"
9976		 *          },
9977		 *          {
9978		 *            "engine":   "Trident",
9979		 *            "browser":  "Internet Explorer 5.0",
9980		 *            "platform": "Win 95+",
9981		 *            "version":  5,
9982		 *            "grade":    "C"
9983		 *          }
9984		 *        ],
9985		 *        "columns": [
9986		 *          { "title": "Engine",   "data": "engine" },
9987		 *          { "title": "Browser",  "data": "browser" },
9988		 *          { "title": "Platform", "data": "platform" },
9989		 *          { "title": "Version",  "data": "version" },
9990		 *          { "title": "Grade",    "data": "grade" }
9991		 *        ]
9992		 *      } );
9993		 *    } );
9994		 */
9995		"aaData": null,
9996	
9997	
9998		/**
9999		 * If ordering is enabled, then DataTables will perform a first pass sort on
10000		 * initialisation. You can define which column(s) the sort is performed
10001		 * upon, and the sorting direction, with this variable. The `sorting` array
10002		 * should contain an array for each column to be sorted initially containing
10003		 * the column's index and a direction string ('asc' or 'desc').
10004		 *  @type array
10005		 *  @default [[0,'asc']]
10006		 *
10007		 *  @dtopt Option
10008		 *  @name DataTable.defaults.order
10009		 *
10010		 *  @example
10011		 *    // Sort by 3rd column first, and then 4th column
10012		 *    $(document).ready( function() {
10013		 *      $('#example').dataTable( {
10014		 *        "order": [[2,'asc'], [3,'desc']]
10015		 *      } );
10016		 *    } );
10017		 *
10018		 *    // No initial sorting
10019		 *    $(document).ready( function() {
10020		 *      $('#example').dataTable( {
10021		 *        "order": []
10022		 *      } );
10023		 *    } );
10024		 */
10025		"aaSorting": [[0,'asc']],
10026	
10027	
10028		/**
10029		 * This parameter is basically identical to the `sorting` parameter, but
10030		 * cannot be overridden by user interaction with the table. What this means
10031		 * is that you could have a column (visible or hidden) which the sorting
10032		 * will always be forced on first - any sorting after that (from the user)
10033		 * will then be performed as required. This can be useful for grouping rows
10034		 * together.
10035		 *  @type array
10036		 *  @default null
10037		 *
10038		 *  @dtopt Option
10039		 *  @name DataTable.defaults.orderFixed
10040		 *
10041		 *  @example
10042		 *    $(document).ready( function() {
10043		 *      $('#example').dataTable( {
10044		 *        "orderFixed": [[0,'asc']]
10045		 *      } );
10046		 *    } )
10047		 */
10048		"aaSortingFixed": [],
10049	
10050	
10051		/**
10052		 * DataTables can be instructed to load data to display in the table from a
10053		 * Ajax source. This option defines how that Ajax call is made and where to.
10054		 *
10055		 * The `ajax` property has three different modes of operation, depending on
10056		 * how it is defined. These are:
10057		 *
10058		 * * `string` - Set the URL from where the data should be loaded from.
10059		 * * `object` - Define properties for `jQuery.ajax`.
10060		 * * `function` - Custom data get function
10061		 *
10062		 * `string`
10063		 * --------
10064		 *
10065		 * As a string, the `ajax` property simply defines the URL from which
10066		 * DataTables will load data.
10067		 *
10068		 * `object`
10069		 * --------
10070		 *
10071		 * As an object, the parameters in the object are passed to
10072		 * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control
10073		 * of the Ajax request. DataTables has a number of default parameters which
10074		 * you can override using this option. Please refer to the jQuery
10075		 * documentation for a full description of the options available, although
10076		 * the following parameters provide additional options in DataTables or
10077		 * require special consideration:
10078		 *
10079		 * * `data` - As with jQuery, `data` can be provided as an object, but it
10080		 *   can also be used as a function to manipulate the data DataTables sends
10081		 *   to the server. The function takes a single parameter, an object of
10082		 *   parameters with the values that DataTables has readied for sending. An
10083		 *   object may be returned which will be merged into the DataTables
10084		 *   defaults, or you can add the items to the object that was passed in and
10085		 *   not return anything from the function. This supersedes `fnServerParams`
10086		 *   from DataTables 1.9-.
10087		 *
10088		 * * `dataSrc` - By default DataTables will look for the property `data` (or
10089		 *   `aaData` for compatibility with DataTables 1.9-) when obtaining data
10090		 *   from an Ajax source or for server-side processing - this parameter
10091		 *   allows that property to be changed. You can use Javascript dotted
10092		 *   object notation to get a data source for multiple levels of nesting, or
10093		 *   it my be used as a function. As a function it takes a single parameter,
10094		 *   the JSON returned from the server, which can be manipulated as
10095		 *   required, with the returned value being that used by DataTables as the
10096		 *   data source for the table. This supersedes `sAjaxDataProp` from
10097		 *   DataTables 1.9-.
10098		 *
10099		 * * `success` - Should not be overridden it is used internally in
10100		 *   DataTables. To manipulate / transform the data returned by the server
10101		 *   use `ajax.dataSrc`, or use `ajax` as a function (see below).
10102		 *
10103		 * `function`
10104		 * ----------
10105		 *
10106		 * As a function, making the Ajax call is left up to yourself allowing
10107		 * complete control of the Ajax request. Indeed, if desired, a method other
10108		 * than Ajax could be used to obtain the required data, such as Web storage
10109		 * or an AIR database.
10110		 *
10111		 * The function is given four parameters and no return is required. The
10112		 * parameters are:
10113		 *
10114		 * 1. _object_ - Data to send to the server
10115		 * 2. _function_ - Callback function that must be executed when the required
10116		 *    data has been obtained. That data should be passed into the callback
10117		 *    as the only parameter
10118		 * 3. _object_ - DataTables settings object for the table
10119		 *
10120		 * Note that this supersedes `fnServerData` from DataTables 1.9-.
10121		 *
10122		 *  @type string|object|function
10123		 *  @default null
10124		 *
10125		 *  @dtopt Option
10126		 *  @name DataTable.defaults.ajax
10127		 *  @since 1.10.0
10128		 *
10129		 * @example
10130		 *   // Get JSON data from a file via Ajax.
10131		 *   // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default).
10132		 *   $('#example').dataTable( {
10133		 *     "ajax": "data.json"
10134		 *   } );
10135		 *
10136		 * @example
10137		 *   // Get JSON data from a file via Ajax, using `dataSrc` to change
10138		 *   // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`)
10139		 *   $('#example').dataTable( {
10140		 *     "ajax": {
10141		 *       "url": "data.json",
10142		 *       "dataSrc": "tableData"
10143		 *     }
10144		 *   } );
10145		 *
10146		 * @example
10147		 *   // Get JSON data from a file via Ajax, using `dataSrc` to read data
10148		 *   // from a plain array rather than an array in an object
10149		 *   $('#example').dataTable( {
10150		 *     "ajax": {
10151		 *       "url": "data.json",
10152		 *       "dataSrc": ""
10153		 *     }
10154		 *   } );
10155		 *
10156		 * @example
10157		 *   // Manipulate the data returned from the server - add a link to data
10158		 *   // (note this can, should, be done using `render` for the column - this
10159		 *   // is just a simple example of how the data can be manipulated).
10160		 *   $('#example').dataTable( {
10161		 *     "ajax": {
10162		 *       "url": "data.json",
10163		 *       "dataSrc": function ( json ) {
10164		 *         for ( var i=0, ien=json.length ; i<ien ; i++ ) {
10165		 *           json[i][0] = '<a href="/message/'+json[i][0]+'>View message</a>';
10166		 *         }
10167		 *         return json;
10168		 *       }
10169		 *     }
10170		 *   } );
10171		 *
10172		 * @example
10173		 *   // Add data to the request
10174		 *   $('#example').dataTable( {
10175		 *     "ajax": {
10176		 *       "url": "data.json",
10177		 *       "data": function ( d ) {
10178		 *         return {
10179		 *           "extra_search": $('#extra').val()
10180		 *         };
10181		 *       }
10182		 *     }
10183		 *   } );
10184		 *
10185		 * @example
10186		 *   // Send request as POST
10187		 *   $('#example').dataTable( {
10188		 *     "ajax": {
10189		 *       "url": "data.json",
10190		 *       "type": "POST"
10191		 *     }
10192		 *   } );
10193		 *
10194		 * @example
10195		 *   // Get the data from localStorage (could interface with a form for
10196		 *   // adding, editing and removing rows).
10197		 *   $('#example').dataTable( {
10198		 *     "ajax": function (data, callback, settings) {
10199		 *       callback(
10200		 *         JSON.parse( localStorage.getItem('dataTablesData') )
10201		 *       );
10202		 *     }
10203		 *   } );
10204		 */
10205		"ajax": null,
10206	
10207	
10208		/**
10209		 * This parameter allows you to readily specify the entries in the length drop
10210		 * down menu that DataTables shows when pagination is enabled. It can be
10211		 * either a 1D array of options which will be used for both the displayed
10212		 * option and the value, or a 2D array which will use the array in the first
10213		 * position as the value, and the array in the second position as the
10214		 * displayed options (useful for language strings such as 'All').
10215		 *
10216		 * Note that the `pageLength` property will be automatically set to the
10217		 * first value given in this array, unless `pageLength` is also provided.
10218		 *  @type array
10219		 *  @default [ 10, 25, 50, 100 ]
10220		 *
10221		 *  @dtopt Option
10222		 *  @name DataTable.defaults.lengthMenu
10223		 *
10224		 *  @example
10225		 *    $(document).ready( function() {
10226		 *      $('#example').dataTable( {
10227		 *        "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
10228		 *      } );
10229		 *    } );
10230		 */
10231		"aLengthMenu": [ 10, 25, 50, 100 ],
10232	
10233	
10234		/**
10235		 * The `columns` option in the initialisation parameter allows you to define
10236		 * details about the way individual columns behave. For a full list of
10237		 * column options that can be set, please see
10238		 * {@link DataTable.defaults.column}. Note that if you use `columns` to
10239		 * define your columns, you must have an entry in the array for every single
10240		 * column that you have in your table (these can be null if you don't which
10241		 * to specify any options).
10242		 *  @member
10243		 *
10244		 *  @name DataTable.defaults.column
10245		 */
10246		"aoColumns": null,
10247	
10248		/**
10249		 * Very similar to `columns`, `columnDefs` allows you to target a specific
10250		 * column, multiple columns, or all columns, using the `targets` property of
10251		 * each object in the array. This allows great flexibility when creating
10252		 * tables, as the `columnDefs` arrays can be of any length, targeting the
10253		 * columns you specifically want. `columnDefs` may use any of the column
10254		 * options available: {@link DataTable.defaults.column}, but it _must_
10255		 * have `targets` defined in each object in the array. Values in the `targets`
10256		 * array may be:
10257		 *   <ul>
10258		 *     <li>a string - class name will be matched on the TH for the column</li>
10259		 *     <li>0 or a positive integer - column index counting from the left</li>
10260		 *     <li>a negative integer - column index counting from the right</li>
10261		 *     <li>the string "_all" - all columns (i.e. assign a default)</li>
10262		 *   </ul>
10263		 *  @member
10264		 *
10265		 *  @name DataTable.defaults.columnDefs
10266		 */
10267		"aoColumnDefs": null,
10268	
10269	
10270		/**
10271		 * Basically the same as `search`, this parameter defines the individual column
10272		 * filtering state at initialisation time. The array must be of the same size
10273		 * as the number of columns, and each element be an object with the parameters
10274		 * `search` and `escapeRegex` (the latter is optional). 'null' is also
10275		 * accepted and the default will be used.
10276		 *  @type array
10277		 *  @default []
10278		 *
10279		 *  @dtopt Option
10280		 *  @name DataTable.defaults.searchCols
10281		 *
10282		 *  @example
10283		 *    $(document).ready( function() {
10284		 *      $('#example').dataTable( {
10285		 *        "searchCols": [
10286		 *          null,
10287		 *          { "search": "My filter" },
10288		 *          null,
10289		 *          { "search": "^[0-9]", "escapeRegex": false }
10290		 *        ]
10291		 *      } );
10292		 *    } )
10293		 */
10294		"aoSearchCols": [],
10295	
10296	
10297		/**
10298		 * An array of CSS classes that should be applied to displayed rows. This
10299		 * array may be of any length, and DataTables will apply each class
10300		 * sequentially, looping when required.
10301		 *  @type array
10302		 *  @default null <i>Will take the values determined by the `oClasses.stripe*`
10303		 *    options</i>
10304		 *
10305		 *  @dtopt Option
10306		 *  @name DataTable.defaults.stripeClasses
10307		 *
10308		 *  @example
10309		 *    $(document).ready( function() {
10310		 *      $('#example').dataTable( {
10311		 *        "stripeClasses": [ 'strip1', 'strip2', 'strip3' ]
10312		 *      } );
10313		 *    } )
10314		 */
10315		"asStripeClasses": null,
10316	
10317	
10318		/**
10319		 * Enable or disable automatic column width calculation. This can be disabled
10320		 * as an optimisation (it takes some time to calculate the widths) if the
10321		 * tables widths are passed in using `columns`.
10322		 *  @type boolean
10323		 *  @default true
10324		 *
10325		 *  @dtopt Features
10326		 *  @name DataTable.defaults.autoWidth
10327		 *
10328		 *  @example
10329		 *    $(document).ready( function () {
10330		 *      $('#example').dataTable( {
10331		 *        "autoWidth": false
10332		 *      } );
10333		 *    } );
10334		 */
10335		"bAutoWidth": true,
10336	
10337	
10338		/**
10339		 * Deferred rendering can provide DataTables with a huge speed boost when you
10340		 * are using an Ajax or JS data source for the table. This option, when set to
10341		 * true, will cause DataTables to defer the creation of the table elements for
10342		 * each row until they are needed for a draw - saving a significant amount of
10343		 * time.
10344		 *  @type boolean
10345		 *  @default false
10346		 *
10347		 *  @dtopt Features
10348		 *  @name DataTable.defaults.deferRender
10349		 *
10350		 *  @example
10351		 *    $(document).ready( function() {
10352		 *      $('#example').dataTable( {
10353		 *        "ajax": "sources/arrays.txt",
10354		 *        "deferRender": true
10355		 *      } );
10356		 *    } );
10357		 */
10358		"bDeferRender": false,
10359	
10360	
10361		/**
10362		 * Replace a DataTable which matches the given selector and replace it with
10363		 * one which has the properties of the new initialisation object passed. If no
10364		 * table matches the selector, then the new DataTable will be constructed as
10365		 * per normal.
10366		 *  @type boolean
10367		 *  @default false
10368		 *
10369		 *  @dtopt Options
10370		 *  @name DataTable.defaults.destroy
10371		 *
10372		 *  @example
10373		 *    $(document).ready( function() {
10374		 *      $('#example').dataTable( {
10375		 *        "srollY": "200px",
10376		 *        "paginate": false
10377		 *      } );
10378		 *
10379		 *      // Some time later....
10380		 *      $('#example').dataTable( {
10381		 *        "filter": false,
10382		 *        "destroy": true
10383		 *      } );
10384		 *    } );
10385		 */
10386		"bDestroy": false,
10387	
10388	
10389		/**
10390		 * Enable or disable filtering of data. Filtering in DataTables is "smart" in
10391		 * that it allows the end user to input multiple words (space separated) and
10392		 * will match a row containing those words, even if not in the order that was
10393		 * specified (this allow matching across multiple columns). Note that if you
10394		 * wish to use filtering in DataTables this must remain 'true' - to remove the
10395		 * default filtering input box and retain filtering abilities, please use
10396		 * {@link DataTable.defaults.dom}.
10397		 *  @type boolean
10398		 *  @default true
10399		 *
10400		 *  @dtopt Features
10401		 *  @name DataTable.defaults.searching
10402		 *
10403		 *  @example
10404		 *    $(document).ready( function () {
10405		 *      $('#example').dataTable( {
10406		 *        "searching": false
10407		 *      } );
10408		 *    } );
10409		 */
10410		"bFilter": true,
10411	
10412	
10413		/**
10414		 * Enable or disable the table information display. This shows information
10415		 * about the data that is currently visible on the page, including information
10416		 * about filtered data if that action is being performed.
10417		 *  @type boolean
10418		 *  @default true
10419		 *
10420		 *  @dtopt Features
10421		 *  @name DataTable.defaults.info
10422		 *
10423		 *  @example
10424		 *    $(document).ready( function () {
10425		 *      $('#example').dataTable( {
10426		 *        "info": false
10427		 *      } );
10428		 *    } );
10429		 */
10430		"bInfo": true,
10431	
10432	
10433		/**
10434		 * Allows the end user to select the size of a formatted page from a select
10435		 * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`).
10436		 *  @type boolean
10437		 *  @default true
10438		 *
10439		 *  @dtopt Features
10440		 *  @name DataTable.defaults.lengthChange
10441		 *
10442		 *  @example
10443		 *    $(document).ready( function () {
10444		 *      $('#example').dataTable( {
10445		 *        "lengthChange": false
10446		 *      } );
10447		 *    } );
10448		 */
10449		"bLengthChange": true,
10450	
10451	
10452		/**
10453		 * Enable or disable pagination.
10454		 *  @type boolean
10455		 *  @default true
10456		 *
10457		 *  @dtopt Features
10458		 *  @name DataTable.defaults.paging
10459		 *
10460		 *  @example
10461		 *    $(document).ready( function () {
10462		 *      $('#example').dataTable( {
10463		 *        "paging": false
10464		 *      } );
10465		 *    } );
10466		 */
10467		"bPaginate": true,
10468	
10469	
10470		/**
10471		 * Enable or disable the display of a 'processing' indicator when the table is
10472		 * being processed (e.g. a sort). This is particularly useful for tables with
10473		 * large amounts of data where it can take a noticeable amount of time to sort
10474		 * the entries.
10475		 *  @type boolean
10476		 *  @default false
10477		 *
10478		 *  @dtopt Features
10479		 *  @name DataTable.defaults.processing
10480		 *
10481		 *  @example
10482		 *    $(document).ready( function () {
10483		 *      $('#example').dataTable( {
10484		 *        "processing": true
10485		 *      } );
10486		 *    } );
10487		 */
10488		"bProcessing": false,
10489	
10490	
10491		/**
10492		 * Retrieve the DataTables object for the given selector. Note that if the
10493		 * table has already been initialised, this parameter will cause DataTables
10494		 * to simply return the object that has already been set up - it will not take
10495		 * account of any changes you might have made to the initialisation object
10496		 * passed to DataTables (setting this parameter to true is an acknowledgement
10497		 * that you understand this). `destroy` can be used to reinitialise a table if
10498		 * you need.
10499		 *  @type boolean
10500		 *  @default false
10501		 *
10502		 *  @dtopt Options
10503		 *  @name DataTable.defaults.retrieve
10504		 *
10505		 *  @example
10506		 *    $(document).ready( function() {
10507		 *      initTable();
10508		 *      tableActions();
10509		 *    } );
10510		 *
10511		 *    function initTable ()
10512		 *    {
10513		 *      return $('#example').dataTable( {
10514		 *        "scrollY": "200px",
10515		 *        "paginate": false,
10516		 *        "retrieve": true
10517		 *      } );
10518		 *    }
10519		 *
10520		 *    function tableActions ()
10521		 *    {
10522		 *      var table = initTable();
10523		 *      // perform API operations with oTable
10524		 *    }
10525		 */
10526		"bRetrieve": false,
10527	
10528	
10529		/**
10530		 * When vertical (y) scrolling is enabled, DataTables will force the height of
10531		 * the table's viewport to the given height at all times (useful for layout).
10532		 * However, this can look odd when filtering data down to a small data set,
10533		 * and the footer is left "floating" further down. This parameter (when
10534		 * enabled) will cause DataTables to collapse the table's viewport down when
10535		 * the result set will fit within the given Y height.
10536		 *  @type boolean
10537		 *  @default false
10538		 *
10539		 *  @dtopt Options
10540		 *  @name DataTable.defaults.scrollCollapse
10541		 *
10542		 *  @example
10543		 *    $(document).ready( function() {
10544		 *      $('#example').dataTable( {
10545		 *        "scrollY": "200",
10546		 *        "scrollCollapse": true
10547		 *      } );
10548		 *    } );
10549		 */
10550		"bScrollCollapse": false,
10551	
10552	
10553		/**
10554		 * Configure DataTables to use server-side processing. Note that the
10555		 * `ajax` parameter must also be given in order to give DataTables a
10556		 * source to obtain the required data for each draw.
10557		 *  @type boolean
10558		 *  @default false
10559		 *
10560		 *  @dtopt Features
10561		 *  @dtopt Server-side
10562		 *  @name DataTable.defaults.serverSide
10563		 *
10564		 *  @example
10565		 *    $(document).ready( function () {
10566		 *      $('#example').dataTable( {
10567		 *        "serverSide": true,
10568		 *        "ajax": "xhr.php"
10569		 *      } );
10570		 *    } );
10571		 */
10572		"bServerSide": false,
10573	
10574	
10575		/**
10576		 * Enable or disable sorting of columns. Sorting of individual columns can be
10577		 * disabled by the `sortable` option for each column.
10578		 *  @type boolean
10579		 *  @default true
10580		 *
10581		 *  @dtopt Features
10582		 *  @name DataTable.defaults.ordering
10583		 *
10584		 *  @example
10585		 *    $(document).ready( function () {
10586		 *      $('#example').dataTable( {
10587		 *        "ordering": false
10588		 *      } );
10589		 *    } );
10590		 */
10591		"bSort": true,
10592	
10593	
10594		/**
10595		 * Enable or display DataTables' ability to sort multiple columns at the
10596		 * same time (activated by shift-click by the user).
10597		 *  @type boolean
10598		 *  @default true
10599		 *
10600		 *  @dtopt Options
10601		 *  @name DataTable.defaults.orderMulti
10602		 *
10603		 *  @example
10604		 *    // Disable multiple column sorting ability
10605		 *    $(document).ready( function () {
10606		 *      $('#example').dataTable( {
10607		 *        "orderMulti": false
10608		 *      } );
10609		 *    } );
10610		 */
10611		"bSortMulti": true,
10612	
10613	
10614		/**
10615		 * Allows control over whether DataTables should use the top (true) unique
10616		 * cell that is found for a single column, or the bottom (false - default).
10617		 * This is useful when using complex headers.
10618		 *  @type boolean
10619		 *  @default false
10620		 *
10621		 *  @dtopt Options
10622		 *  @name DataTable.defaults.orderCellsTop
10623		 *
10624		 *  @example
10625		 *    $(document).ready( function() {
10626		 *      $('#example').dataTable( {
10627		 *        "orderCellsTop": true
10628		 *      } );
10629		 *    } );
10630		 */
10631		"bSortCellsTop": false,
10632	
10633	
10634		/**
10635		 * Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and
10636		 * `sorting\_3` to the columns which are currently being sorted on. This is
10637		 * presented as a feature switch as it can increase processing time (while
10638		 * classes are removed and added) so for large data sets you might want to
10639		 * turn this off.
10640		 *  @type boolean
10641		 *  @default true
10642		 *
10643		 *  @dtopt Features
10644		 *  @name DataTable.defaults.orderClasses
10645		 *
10646		 *  @example
10647		 *    $(document).ready( function () {
10648		 *      $('#example').dataTable( {
10649		 *        "orderClasses": false
10650		 *      } );
10651		 *    } );
10652		 */
10653		"bSortClasses": true,
10654	
10655	
10656		/**
10657		 * Enable or disable state saving. When enabled HTML5 `localStorage` will be
10658		 * used to save table display information such as pagination information,
10659		 * display length, filtering and sorting. As such when the end user reloads
10660		 * the page the display display will match what thy had previously set up.
10661		 *
10662		 * Due to the use of `localStorage` the default state saving is not supported
10663		 * in IE6 or 7. If state saving is required in those browsers, use
10664		 * `stateSaveCallback` to provide a storage solution such as cookies.
10665		 *  @type boolean
10666		 *  @default false
10667		 *
10668		 *  @dtopt Features
10669		 *  @name DataTable.defaults.stateSave
10670		 *
10671		 *  @example
10672		 *    $(document).ready( function () {
10673		 *      $('#example').dataTable( {
10674		 *        "stateSave": true
10675		 *      } );
10676		 *    } );
10677		 */
10678		"bStateSave": false,
10679	
10680	
10681		/**
10682		 * This function is called when a TR element is created (and all TD child
10683		 * elements have been inserted), or registered if using a DOM source, allowing
10684		 * manipulation of the TR element (adding classes etc).
10685		 *  @type function
10686		 *  @param {node} row "TR" element for the current row
10687		 *  @param {array} data Raw data array for this row
10688		 *  @param {int} dataIndex The index of this row in the internal aoData array
10689		 *
10690		 *  @dtopt Callbacks
10691		 *  @name DataTable.defaults.createdRow
10692		 *
10693		 *  @example
10694		 *    $(document).ready( function() {
10695		 *      $('#example').dataTable( {
10696		 *        "createdRow": function( row, data, dataIndex ) {
10697		 *          // Bold the grade for all 'A' grade browsers
10698		 *          if ( data[4] == "A" )
10699		 *          {
10700		 *            $('td:eq(4)', row).html( '<b>A</b>' );
10701		 *          }
10702		 *        }
10703		 *      } );
10704		 *    } );
10705		 */
10706		"fnCreatedRow": null,
10707	
10708	
10709		/**
10710		 * This function is called on every 'draw' event, and allows you to
10711		 * dynamically modify any aspect you want about the created DOM.
10712		 *  @type function
10713		 *  @param {object} settings DataTables settings object
10714		 *
10715		 *  @dtopt Callbacks
10716		 *  @name DataTable.defaults.drawCallback
10717		 *
10718		 *  @example
10719		 *    $(document).ready( function() {
10720		 *      $('#example').dataTable( {
10721		 *        "drawCallback": function( settings ) {
10722		 *          alert( 'DataTables has redrawn the table' );
10723		 *        }
10724		 *      } );
10725		 *    } );
10726		 */
10727		"fnDrawCallback": null,
10728	
10729	
10730		/**
10731		 * Identical to fnHeaderCallback() but for the table footer this function
10732		 * allows you to modify the table footer on every 'draw' event.
10733		 *  @type function
10734		 *  @param {node} foot "TR" element for the footer
10735		 *  @param {array} data Full table data (as derived from the original HTML)
10736		 *  @param {int} start Index for the current display starting point in the
10737		 *    display array
10738		 *  @param {int} end Index for the current display ending point in the
10739		 *    display array
10740		 *  @param {array int} display Index array to translate the visual position
10741		 *    to the full data array
10742		 *
10743		 *  @dtopt Callbacks
10744		 *  @name DataTable.defaults.footerCallback
10745		 *
10746		 *  @example
10747		 *    $(document).ready( function() {
10748		 *      $('#example').dataTable( {
10749		 *        "footerCallback": function( tfoot, data, start, end, display ) {
10750		 *          tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start;
10751		 *        }
10752		 *      } );
10753		 *    } )
10754		 */
10755		"fnFooterCallback": null,
10756	
10757	
10758		/**
10759		 * When rendering large numbers in the information element for the table
10760		 * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
10761		 * to have a comma separator for the 'thousands' units (e.g. 1 million is
10762		 * rendered as "1,000,000") to help readability for the end user. This
10763		 * function will override the default method DataTables uses.
10764		 *  @type function
10765		 *  @member
10766		 *  @param {int} toFormat number to be formatted
10767		 *  @returns {string} formatted string for DataTables to show the number
10768		 *
10769		 *  @dtopt Callbacks
10770		 *  @name DataTable.defaults.formatNumber
10771		 *
10772		 *  @example
10773		 *    // Format a number using a single quote for the separator (note that
10774		 *    // this can also be done with the language.thousands option)
10775		 *    $(document).ready( function() {
10776		 *      $('#example').dataTable( {
10777		 *        "formatNumber": function ( toFormat ) {
10778		 *          return toFormat.toString().replace(
10779		 *            /\B(?=(\d{3})+(?!\d))/g, "'"
10780		 *          );
10781		 *        };
10782		 *      } );
10783		 *    } );
10784		 */
10785		"fnFormatNumber": function ( toFormat ) {
10786			return toFormat.toString().replace(
10787				/\B(?=(\d{3})+(?!\d))/g,
10788				this.oLanguage.sThousands
10789			);
10790		},
10791	
10792	
10793		/**
10794		 * This function is called on every 'draw' event, and allows you to
10795		 * dynamically modify the header row. This can be used to calculate and
10796		 * display useful information about the table.
10797		 *  @type function
10798		 *  @param {node} head "TR" element for the header
10799		 *  @param {array} data Full table data (as derived from the original HTML)
10800		 *  @param {int} start Index for the current display starting point in the
10801		 *    display array
10802		 *  @param {int} end Index for the current display ending point in the
10803		 *    display array
10804		 *  @param {array int} display Index array to translate the visual position
10805		 *    to the full data array
10806		 *
10807		 *  @dtopt Callbacks
10808		 *  @name DataTable.defaults.headerCallback
10809		 *
10810		 *  @example
10811		 *    $(document).ready( function() {
10812		 *      $('#example').dataTable( {
10813		 *        "fheaderCallback": function( head, data, start, end, display ) {
10814		 *          head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records";
10815		 *        }
10816		 *      } );
10817		 *    } )
10818		 */
10819		"fnHeaderCallback": null,
10820	
10821	
10822		/**
10823		 * The information element can be used to convey information about the current
10824		 * state of the table. Although the internationalisation options presented by
10825		 * DataTables are quite capable of dealing with most customisations, there may
10826		 * be times where you wish to customise the string further. This callback
10827		 * allows you to do exactly that.
10828		 *  @type function
10829		 *  @param {object} oSettings DataTables settings object
10830		 *  @param {int} start Starting position in data for the draw
10831		 *  @param {int} end End position in data for the draw
10832		 *  @param {int} max Total number of rows in the table (regardless of
10833		 *    filtering)
10834		 *  @param {int} total Total number of rows in the data set, after filtering
10835		 *  @param {string} pre The string that DataTables has formatted using it's
10836		 *    own rules
10837		 *  @returns {string} The string to be displayed in the information element.
10838		 *
10839		 *  @dtopt Callbacks
10840		 *  @name DataTable.defaults.infoCallback
10841		 *
10842		 *  @example
10843		 *    $('#example').dataTable( {
10844		 *      "infoCallback": function( settings, start, end, max, total, pre ) {
10845		 *        return start +" to "+ end;
10846		 *      }
10847		 *    } );
10848		 */
10849		"fnInfoCallback": null,
10850	
10851	
10852		/**
10853		 * Called when the table has been initialised. Normally DataTables will
10854		 * initialise sequentially and there will be no need for this function,
10855		 * however, this does not hold true when using external language information
10856		 * since that is obtained using an async XHR call.
10857		 *  @type function
10858		 *  @param {object} settings DataTables settings object
10859		 *  @param {object} json The JSON object request from the server - only
10860		 *    present if client-side Ajax sourced data is used
10861		 *
10862		 *  @dtopt Callbacks
10863		 *  @name DataTable.defaults.initComplete
10864		 *
10865		 *  @example
10866		 *    $(document).ready( function() {
10867		 *      $('#example').dataTable( {
10868		 *        "initComplete": function(settings, json) {
10869		 *          alert( 'DataTables has finished its initialisation.' );
10870		 *        }
10871		 *      } );
10872		 *    } )
10873		 */
10874		"fnInitComplete": null,
10875	
10876	
10877		/**
10878		 * Called at the very start of each table draw and can be used to cancel the
10879		 * draw by returning false, any other return (including undefined) results in
10880		 * the full draw occurring).
10881		 *  @type function
10882		 *  @param {object} settings DataTables settings object
10883		 *  @returns {boolean} False will cancel the draw, anything else (including no
10884		 *    return) will allow it to complete.
10885		 *
10886		 *  @dtopt Callbacks
10887		 *  @name DataTable.defaults.preDrawCallback
10888		 *
10889		 *  @example
10890		 *    $(document).ready( function() {
10891		 *      $('#example').dataTable( {
10892		 *        "preDrawCallback": function( settings ) {
10893		 *          if ( $('#test').val() == 1 ) {
10894		 *            return false;
10895		 *          }
10896		 *        }
10897		 *      } );
10898		 *    } );
10899		 */
10900		"fnPreDrawCallback": null,
10901	
10902	
10903		/**
10904		 * This function allows you to 'post process' each row after it have been
10905		 * generated for each table draw, but before it is rendered on screen. This
10906		 * function might be used for setting the row class name etc.
10907		 *  @type function
10908		 *  @param {node} row "TR" element for the current row
10909		 *  @param {array} data Raw data array for this row
10910		 *  @param {int} displayIndex The display index for the current table draw
10911		 *  @param {int} displayIndexFull The index of the data in the full list of
10912		 *    rows (after filtering)
10913		 *
10914		 *  @dtopt Callbacks
10915		 *  @name DataTable.defaults.rowCallback
10916		 *
10917		 *  @example
10918		 *    $(document).ready( function() {
10919		 *      $('#example').dataTable( {
10920		 *        "rowCallback": function( row, data, displayIndex, displayIndexFull ) {
10921		 *          // Bold the grade for all 'A' grade browsers
10922		 *          if ( data[4] == "A" ) {
10923		 *            $('td:eq(4)', row).html( '<b>A</b>' );
10924		 *          }
10925		 *        }
10926		 *      } );
10927		 *    } );
10928		 */
10929		"fnRowCallback": null,
10930	
10931	
10932		/**
10933		 * __Deprecated__ The functionality provided by this parameter has now been
10934		 * superseded by that provided through `ajax`, which should be used instead.
10935		 *
10936		 * This parameter allows you to override the default function which obtains
10937		 * the data from the server so something more suitable for your application.
10938		 * For example you could use POST data, or pull information from a Gears or
10939		 * AIR database.
10940		 *  @type function
10941		 *  @member
10942		 *  @param {string} source HTTP source to obtain the data from (`ajax`)
10943		 *  @param {array} data A key/value pair object containing the data to send
10944		 *    to the server
10945		 *  @param {function} callback to be called on completion of the data get
10946		 *    process that will draw the data on the page.
10947		 *  @param {object} settings DataTables settings object
10948		 *
10949		 *  @dtopt Callbacks
10950		 *  @dtopt Server-side
10951		 *  @name DataTable.defaults.serverData
10952		 *
10953		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
10954		 */
10955		"fnServerData": null,
10956	
10957	
10958		/**
10959		 * __Deprecated__ The functionality provided by this parameter has now been
10960		 * superseded by that provided through `ajax`, which should be used instead.
10961		 *
10962		 *  It is often useful to send extra data to the server when making an Ajax
10963		 * request - for example custom filtering information, and this callback
10964		 * function makes it trivial to send extra information to the server. The
10965		 * passed in parameter is the data set that has been constructed by
10966		 * DataTables, and you can add to this or modify it as you require.
10967		 *  @type function
10968		 *  @param {array} data Data array (array of objects which are name/value
10969		 *    pairs) that has been constructed by DataTables and will be sent to the
10970		 *    server. In the case of Ajax sourced data with server-side processing
10971		 *    this will be an empty array, for server-side processing there will be a
10972		 *    significant number of parameters!
10973		 *  @returns {undefined} Ensure that you modify the data array passed in,
10974		 *    as this is passed by reference.
10975		 *
10976		 *  @dtopt Callbacks
10977		 *  @dtopt Server-side
10978		 *  @name DataTable.defaults.serverParams
10979		 *
10980		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
10981		 */
10982		"fnServerParams": null,
10983	
10984	
10985		/**
10986		 * Load the table state. With this function you can define from where, and how, the
10987		 * state of a table is loaded. By default DataTables will load from `localStorage`
10988		 * but you might wish to use a server-side database or cookies.
10989		 *  @type function
10990		 *  @member
10991		 *  @param {object} settings DataTables settings object
10992		 *  @param {object} callback Callback that can be executed when done. It
10993		 *    should be passed the loaded state object.
10994		 *  @return {object} The DataTables state object to be loaded
10995		 *
10996		 *  @dtopt Callbacks
10997		 *  @name DataTable.defaults.stateLoadCallback
10998		 *
10999		 *  @example
11000		 *    $(document).ready( function() {
11001		 *      $('#example').dataTable( {
11002		 *        "stateSave": true,
11003		 *        "stateLoadCallback": function (settings, callback) {
11004		 *          $.ajax( {
11005		 *            "url": "/state_load",
11006		 *            "dataType": "json",
11007		 *            "success": function (json) {
11008		 *              callback( json );
11009		 *            }
11010		 *          } );
11011		 *        }
11012		 *      } );
11013		 *    } );
11014		 */
11015		"fnStateLoadCallback": function ( settings ) {
11016			try {
11017				return JSON.parse(
11018					(settings.iStateDuration === -1 ? sessionStorage : localStorage).getItem(
11019						'DataTables_'+settings.sInstance+'_'+location.pathname
11020					)
11021				);
11022			} catch (e) {
11023				return {};
11024			}
11025		},
11026	
11027	
11028		/**
11029		 * Callback which allows modification of the saved state prior to loading that state.
11030		 * This callback is called when the table is loading state from the stored data, but
11031		 * prior to the settings object being modified by the saved state. Note that for
11032		 * plug-in authors, you should use the `stateLoadParams` event to load parameters for
11033		 * a plug-in.
11034		 *  @type function
11035		 *  @param {object} settings DataTables settings object
11036		 *  @param {object} data The state object that is to be loaded
11037		 *
11038		 *  @dtopt Callbacks
11039		 *  @name DataTable.defaults.stateLoadParams
11040		 *
11041		 *  @example
11042		 *    // Remove a saved filter, so filtering is never loaded
11043		 *    $(document).ready( function() {
11044		 *      $('#example').dataTable( {
11045		 *        "stateSave": true,
11046		 *        "stateLoadParams": function (settings, data) {
11047		 *          data.oSearch.sSearch = "";
11048		 *        }
11049		 *      } );
11050		 *    } );
11051		 *
11052		 *  @example
11053		 *    // Disallow state loading by returning false
11054		 *    $(document).ready( function() {
11055		 *      $('#example').dataTable( {
11056		 *        "stateSave": true,
11057		 *        "stateLoadParams": function (settings, data) {
11058		 *          return false;
11059		 *        }
11060		 *      } );
11061		 *    } );
11062		 */
11063		"fnStateLoadParams": null,
11064	
11065	
11066		/**
11067		 * Callback that is called when the state has been loaded from the state saving method
11068		 * and the DataTables settings object has been modified as a result of the loaded state.
11069		 *  @type function
11070		 *  @param {object} settings DataTables settings object
11071		 *  @param {object} data The state object that was loaded
11072		 *
11073		 *  @dtopt Callbacks
11074		 *  @name DataTable.defaults.stateLoaded
11075		 *
11076		 *  @example
11077		 *    // Show an alert with the filtering value that was saved
11078		 *    $(document).ready( function() {
11079		 *      $('#example').dataTable( {
11080		 *        "stateSave": true,
11081		 *        "stateLoaded": function (settings, data) {
11082		 *          alert( 'Saved filter was: '+data.oSearch.sSearch );
11083		 *        }
11084		 *      } );
11085		 *    } );
11086		 */
11087		"fnStateLoaded": null,
11088	
11089	
11090		/**
11091		 * Save the table state. This function allows you to define where and how the state
11092		 * information for the table is stored By default DataTables will use `localStorage`
11093		 * but you might wish to use a server-side database or cookies.
11094		 *  @type function
11095		 *  @member
11096		 *  @param {object} settings DataTables settings object
11097		 *  @param {object} data The state object to be saved
11098		 *
11099		 *  @dtopt Callbacks
11100		 *  @name DataTable.defaults.stateSaveCallback
11101		 *
11102		 *  @example
11103		 *    $(document).ready( function() {
11104		 *      $('#example').dataTable( {
11105		 *        "stateSave": true,
11106		 *        "stateSaveCallback": function (settings, data) {
11107		 *          // Send an Ajax request to the server with the state object
11108		 *          $.ajax( {
11109		 *            "url": "/state_save",
11110		 *            "data": data,
11111		 *            "dataType": "json",
11112		 *            "method": "POST"
11113		 *            "success": function () {}
11114		 *          } );
11115		 *        }
11116		 *      } );
11117		 *    } );
11118		 */
11119		"fnStateSaveCallback": function ( settings, data ) {
11120			try {
11121				(settings.iStateDuration === -1 ? sessionStorage : localStorage).setItem(
11122					'DataTables_'+settings.sInstance+'_'+location.pathname,
11123					JSON.stringify( data )
11124				);
11125			} catch (e) {}
11126		},
11127	
11128	
11129		/**
11130		 * Callback which allows modification of the state to be saved. Called when the table
11131		 * has changed state a new state save is required. This method allows modification of
11132		 * the state saving object prior to actually doing the save, including addition or
11133		 * other state properties or modification. Note that for plug-in authors, you should
11134		 * use the `stateSaveParams` event to save parameters for a plug-in.
11135		 *  @type function
11136		 *  @param {object} settings DataTables settings object
11137		 *  @param {object} data The state object to be saved
11138		 *
11139		 *  @dtopt Callbacks
11140		 *  @name DataTable.defaults.stateSaveParams
11141		 *
11142		 *  @example
11143		 *    // Remove a saved filter, so filtering is never saved
11144		 *    $(document).ready( function() {
11145		 *      $('#example').dataTable( {
11146		 *        "stateSave": true,
11147		 *        "stateSaveParams": function (settings, data) {
11148		 *          data.oSearch.sSearch = "";
11149		 *        }
11150		 *      } );
11151		 *    } );
11152		 */
11153		"fnStateSaveParams": null,
11154	
11155	
11156		/**
11157		 * Duration for which the saved state information is considered valid. After this period
11158		 * has elapsed the state will be returned to the default.
11159		 * Value is given in seconds.
11160		 *  @type int
11161		 *  @default 7200 <i>(2 hours)</i>
11162		 *
11163		 *  @dtopt Options
11164		 *  @name DataTable.defaults.stateDuration
11165		 *
11166		 *  @example
11167		 *    $(document).ready( function() {
11168		 *      $('#example').dataTable( {
11169		 *        "stateDuration": 60*60*24; // 1 day
11170		 *      } );
11171		 *    } )
11172		 */
11173		"iStateDuration": 7200,
11174	
11175	
11176		/**
11177		 * When enabled DataTables will not make a request to the server for the first
11178		 * page draw - rather it will use the data already on the page (no sorting etc
11179		 * will be applied to it), thus saving on an XHR at load time. `deferLoading`
11180		 * is used to indicate that deferred loading is required, but it is also used
11181		 * to tell DataTables how many records there are in the full table (allowing
11182		 * the information element and pagination to be displayed correctly). In the case
11183		 * where a filtering is applied to the table on initial load, this can be
11184		 * indicated by giving the parameter as an array, where the first element is
11185		 * the number of records available after filtering and the second element is the
11186		 * number of records without filtering (allowing the table information element
11187		 * to be shown correctly).
11188		 *  @type int | array
11189		 *  @default null
11190		 *
11191		 *  @dtopt Options
11192		 *  @name DataTable.defaults.deferLoading
11193		 *
11194		 *  @example
11195		 *    // 57 records available in the table, no filtering applied
11196		 *    $(document).ready( function() {
11197		 *      $('#example').dataTable( {
11198		 *        "serverSide": true,
11199		 *        "ajax": "scripts/server_processing.php",
11200		 *        "deferLoading": 57
11201		 *      } );
11202		 *    } );
11203		 *
11204		 *  @example
11205		 *    // 57 records after filtering, 100 without filtering (an initial filter applied)
11206		 *    $(document).ready( function() {
11207		 *      $('#example').dataTable( {
11208		 *        "serverSide": true,
11209		 *        "ajax": "scripts/server_processing.php",
11210		 *        "deferLoading": [ 57, 100 ],
11211		 *        "search": {
11212		 *          "search": "my_filter"
11213		 *        }
11214		 *      } );
11215		 *    } );
11216		 */
11217		"iDeferLoading": null,
11218	
11219	
11220		/**
11221		 * Number of rows to display on a single page when using pagination. If
11222		 * feature enabled (`lengthChange`) then the end user will be able to override
11223		 * this to a custom setting using a pop-up menu.
11224		 *  @type int
11225		 *  @default 10
11226		 *
11227		 *  @dtopt Options
11228		 *  @name DataTable.defaults.pageLength
11229		 *
11230		 *  @example
11231		 *    $(document).ready( function() {
11232		 *      $('#example').dataTable( {
11233		 *        "pageLength": 50
11234		 *      } );
11235		 *    } )
11236		 */
11237		"iDisplayLength": 10,
11238	
11239	
11240		/**
11241		 * Define the starting point for data display when using DataTables with
11242		 * pagination. Note that this parameter is the number of records, rather than
11243		 * the page number, so if you have 10 records per page and want to start on
11244		 * the third page, it should be "20".
11245		 *  @type int
11246		 *  @default 0
11247		 *
11248		 *  @dtopt Options
11249		 *  @name DataTable.defaults.displayStart
11250		 *
11251		 *  @example
11252		 *    $(document).ready( function() {
11253		 *      $('#example').dataTable( {
11254		 *        "displayStart": 20
11255		 *      } );
11256		 *    } )
11257		 */
11258		"iDisplayStart": 0,
11259	
11260	
11261		/**
11262		 * By default DataTables allows keyboard navigation of the table (sorting, paging,
11263		 * and filtering) by adding a `tabindex` attribute to the required elements. This
11264		 * allows you to tab through the controls and press the enter key to activate them.
11265		 * The tabindex is default 0, meaning that the tab follows the flow of the document.
11266		 * You can overrule this using this parameter if you wish. Use a value of -1 to
11267		 * disable built-in keyboard navigation.
11268		 *  @type int
11269		 *  @default 0
11270		 *
11271		 *  @dtopt Options
11272		 *  @name DataTable.defaults.tabIndex
11273		 *
11274		 *  @example
11275		 *    $(document).ready( function() {
11276		 *      $('#example').dataTable( {
11277		 *        "tabIndex": 1
11278		 *      } );
11279		 *    } );
11280		 */
11281		"iTabIndex": 0,
11282	
11283	
11284		/**
11285		 * Classes that DataTables assigns to the various components and features
11286		 * that it adds to the HTML table. This allows classes to be configured
11287		 * during initialisation in addition to through the static
11288		 * {@link DataTable.ext.oStdClasses} object).
11289		 *  @namespace
11290		 *  @name DataTable.defaults.classes
11291		 */
11292		"oClasses": {},
11293	
11294	
11295		/**
11296		 * All strings that DataTables uses in the user interface that it creates
11297		 * are defined in this object, allowing you to modified them individually or
11298		 * completely replace them all as required.
11299		 *  @namespace
11300		 *  @name DataTable.defaults.language
11301		 */
11302		"oLanguage": {
11303			/**
11304			 * Strings that are used for WAI-ARIA labels and controls only (these are not
11305			 * actually visible on the page, but will be read by screenreaders, and thus
11306			 * must be internationalised as well).
11307			 *  @namespace
11308			 *  @name DataTable.defaults.language.aria
11309			 */
11310			"oAria": {
11311				/**
11312				 * ARIA label that is added to the table headers when the column may be
11313				 * sorted ascending by activing the column (click or return when focused).
11314				 * Note that the column header is prefixed to this string.
11315				 *  @type string
11316				 *  @default : activate to sort column ascending
11317				 *
11318				 *  @dtopt Language
11319				 *  @name DataTable.defaults.language.aria.sortAscending
11320				 *
11321				 *  @example
11322				 *    $(document).ready( function() {
11323				 *      $('#example').dataTable( {
11324				 *        "language": {
11325				 *          "aria": {
11326				 *            "sortAscending": " - click/return to sort ascending"
11327				 *          }
11328				 *        }
11329				 *      } );
11330				 *    } );
11331				 */
11332				"sSortAscending": ": activate to sort column ascending",
11333	
11334				/**
11335				 * ARIA label that is added to the table headers when the column may be
11336				 * sorted descending by activing the column (click or return when focused).
11337				 * Note that the column header is prefixed to this string.
11338				 *  @type string
11339				 *  @default : activate to sort column ascending
11340				 *
11341				 *  @dtopt Language
11342				 *  @name DataTable.defaults.language.aria.sortDescending
11343				 *
11344				 *  @example
11345				 *    $(document).ready( function() {
11346				 *      $('#example').dataTable( {
11347				 *        "language": {
11348				 *          "aria": {
11349				 *            "sortDescending": " - click/return to sort descending"
11350				 *          }
11351				 *        }
11352				 *      } );
11353				 *    } );
11354				 */
11355				"sSortDescending": ": activate to sort column descending"
11356			},
11357	
11358			/**
11359			 * Pagination string used by DataTables for the built-in pagination
11360			 * control types.
11361			 *  @namespace
11362			 *  @name DataTable.defaults.language.paginate
11363			 */
11364			"oPaginate": {
11365				/**
11366				 * Text to use when using the 'full_numbers' type of pagination for the
11367				 * button to take the user to the first page.
11368				 *  @type string
11369				 *  @default First
11370				 *
11371				 *  @dtopt Language
11372				 *  @name DataTable.defaults.language.paginate.first
11373				 *
11374				 *  @example
11375				 *    $(document).ready( function() {
11376				 *      $('#example').dataTable( {
11377				 *        "language": {
11378				 *          "paginate": {
11379				 *            "first": "First page"
11380				 *          }
11381				 *        }
11382				 *      } );
11383				 *    } );
11384				 */
11385				"sFirst": "First",
11386	
11387	
11388				/**
11389				 * Text to use when using the 'full_numbers' type of pagination for the
11390				 * button to take the user to the last page.
11391				 *  @type string
11392				 *  @default Last
11393				 *
11394				 *  @dtopt Language
11395				 *  @name DataTable.defaults.language.paginate.last
11396				 *
11397				 *  @example
11398				 *    $(document).ready( function() {
11399				 *      $('#example').dataTable( {
11400				 *        "language": {
11401				 *          "paginate": {
11402				 *            "last": "Last page"
11403				 *          }
11404				 *        }
11405				 *      } );
11406				 *    } );
11407				 */
11408				"sLast": "Last",
11409	
11410	
11411				/**
11412				 * Text to use for the 'next' pagination button (to take the user to the
11413				 * next page).
11414				 *  @type string
11415				 *  @default Next
11416				 *
11417				 *  @dtopt Language
11418				 *  @name DataTable.defaults.language.paginate.next
11419				 *
11420				 *  @example
11421				 *    $(document).ready( function() {
11422				 *      $('#example').dataTable( {
11423				 *        "language": {
11424				 *          "paginate": {
11425				 *            "next": "Next page"
11426				 *          }
11427				 *        }
11428				 *      } );
11429				 *    } );
11430				 */
11431				"sNext": "Next",
11432	
11433	
11434				/**
11435				 * Text to use for the 'previous' pagination button (to take the user to
11436				 * the previous page).
11437				 *  @type string
11438				 *  @default Previous
11439				 *
11440				 *  @dtopt Language
11441				 *  @name DataTable.defaults.language.paginate.previous
11442				 *
11443				 *  @example
11444				 *    $(document).ready( function() {
11445				 *      $('#example').dataTable( {
11446				 *        "language": {
11447				 *          "paginate": {
11448				 *            "previous": "Previous page"
11449				 *          }
11450				 *        }
11451				 *      } );
11452				 *    } );
11453				 */
11454				"sPrevious": "Previous"
11455			},
11456	
11457			/**
11458			 * This string is shown in preference to `zeroRecords` when the table is
11459			 * empty of data (regardless of filtering). Note that this is an optional
11460			 * parameter - if it is not given, the value of `zeroRecords` will be used
11461			 * instead (either the default or given value).
11462			 *  @type string
11463			 *  @default No data available in table
11464			 *
11465			 *  @dtopt Language
11466			 *  @name DataTable.defaults.language.emptyTable
11467			 *
11468			 *  @example
11469			 *    $(document).ready( function() {
11470			 *      $('#example').dataTable( {
11471			 *        "language": {
11472			 *          "emptyTable": "No data available in table"
11473			 *        }
11474			 *      } );
11475			 *    } );
11476			 */
11477			"sEmptyTable": "No data available in table",
11478	
11479	
11480			/**
11481			 * This string gives information to the end user about the information
11482			 * that is current on display on the page. The following tokens can be
11483			 * used in the string and will be dynamically replaced as the table
11484			 * display updates. This tokens can be placed anywhere in the string, or
11485			 * removed as needed by the language requires:
11486			 *
11487			 * * `\_START\_` - Display index of the first record on the current page
11488			 * * `\_END\_` - Display index of the last record on the current page
11489			 * * `\_TOTAL\_` - Number of records in the table after filtering
11490			 * * `\_MAX\_` - Number of records in the table without filtering
11491			 * * `\_PAGE\_` - Current page number
11492			 * * `\_PAGES\_` - Total number of pages of data in the table
11493			 *
11494			 *  @type string
11495			 *  @default Showing _START_ to _END_ of _TOTAL_ entries
11496			 *
11497			 *  @dtopt Language
11498			 *  @name DataTable.defaults.language.info
11499			 *
11500			 *  @example
11501			 *    $(document).ready( function() {
11502			 *      $('#example').dataTable( {
11503			 *        "language": {
11504			 *          "info": "Showing page _PAGE_ of _PAGES_"
11505			 *        }
11506			 *      } );
11507			 *    } );
11508			 */
11509			"sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
11510	
11511	
11512			/**
11513			 * Display information string for when the table is empty. Typically the
11514			 * format of this string should match `info`.
11515			 *  @type string
11516			 *  @default Showing 0 to 0 of 0 entries
11517			 *
11518			 *  @dtopt Language
11519			 *  @name DataTable.defaults.language.infoEmpty
11520			 *
11521			 *  @example
11522			 *    $(document).ready( function() {
11523			 *      $('#example').dataTable( {
11524			 *        "language": {
11525			 *          "infoEmpty": "No entries to show"
11526			 *        }
11527			 *      } );
11528			 *    } );
11529			 */
11530			"sInfoEmpty": "Showing 0 to 0 of 0 entries",
11531	
11532	
11533			/**
11534			 * When a user filters the information in a table, this string is appended
11535			 * to the information (`info`) to give an idea of how strong the filtering
11536			 * is. The variable _MAX_ is dynamically updated.
11537			 *  @type string
11538			 *  @default (filtered from _MAX_ total entries)
11539			 *
11540			 *  @dtopt Language
11541			 *  @name DataTable.defaults.language.infoFiltered
11542			 *
11543			 *  @example
11544			 *    $(document).ready( function() {
11545			 *      $('#example').dataTable( {
11546			 *        "language": {
11547			 *          "infoFiltered": " - filtering from _MAX_ records"
11548			 *        }
11549			 *      } );
11550			 *    } );
11551			 */
11552			"sInfoFiltered": "(filtered from _MAX_ total entries)",
11553	
11554	
11555			/**
11556			 * If can be useful to append extra information to the info string at times,
11557			 * and this variable does exactly that. This information will be appended to
11558			 * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are
11559			 * being used) at all times.
11560			 *  @type string
11561			 *  @default <i>Empty string</i>
11562			 *
11563			 *  @dtopt Language
11564			 *  @name DataTable.defaults.language.infoPostFix
11565			 *
11566			 *  @example
11567			 *    $(document).ready( function() {
11568			 *      $('#example').dataTable( {
11569			 *        "language": {
11570			 *          "infoPostFix": "All records shown are derived from real information."
11571			 *        }
11572			 *      } );
11573			 *    } );
11574			 */
11575			"sInfoPostFix": "",
11576	
11577	
11578			/**
11579			 * This decimal place operator is a little different from the other
11580			 * language options since DataTables doesn't output floating point
11581			 * numbers, so it won't ever use this for display of a number. Rather,
11582			 * what this parameter does is modify the sort methods of the table so
11583			 * that numbers which are in a format which has a character other than
11584			 * a period (`.`) as a decimal place will be sorted numerically.
11585			 *
11586			 * Note that numbers with different decimal places cannot be shown in
11587			 * the same table and still be sortable, the table must be consistent.
11588			 * However, multiple different tables on the page can use different
11589			 * decimal place characters.
11590			 *  @type string
11591			 *  @default 
11592			 *
11593			 *  @dtopt Language
11594			 *  @name DataTable.defaults.language.decimal
11595			 *
11596			 *  @example
11597			 *    $(document).ready( function() {
11598			 *      $('#example').dataTable( {
11599			 *        "language": {
11600			 *          "decimal": ","
11601			 *          "thousands": "."
11602			 *        }
11603			 *      } );
11604			 *    } );
11605			 */
11606			"sDecimal": "",
11607	
11608	
11609			/**
11610			 * DataTables has a build in number formatter (`formatNumber`) which is
11611			 * used to format large numbers that are used in the table information.
11612			 * By default a comma is used, but this can be trivially changed to any
11613			 * character you wish with this parameter.
11614			 *  @type string
11615			 *  @default ,
11616			 *
11617			 *  @dtopt Language
11618			 *  @name DataTable.defaults.language.thousands
11619			 *
11620			 *  @example
11621			 *    $(document).ready( function() {
11622			 *      $('#example').dataTable( {
11623			 *        "language": {
11624			 *          "thousands": "'"
11625			 *        }
11626			 *      } );
11627			 *    } );
11628			 */
11629			"sThousands": ",",
11630	
11631	
11632			/**
11633			 * Detail the action that will be taken when the drop down menu for the
11634			 * pagination length option is changed. The '_MENU_' variable is replaced
11635			 * with a default select list of 10, 25, 50 and 100, and can be replaced
11636			 * with a custom select box if required.
11637			 *  @type string
11638			 *  @default Show _MENU_ entries
11639			 *
11640			 *  @dtopt Language
11641			 *  @name DataTable.defaults.language.lengthMenu
11642			 *
11643			 *  @example
11644			 *    // Language change only
11645			 *    $(document).ready( function() {
11646			 *      $('#example').dataTable( {
11647			 *        "language": {
11648			 *          "lengthMenu": "Display _MENU_ records"
11649			 *        }
11650			 *      } );
11651			 *    } );
11652			 *
11653			 *  @example
11654			 *    // Language and options change
11655			 *    $(document).ready( function() {
11656			 *      $('#example').dataTable( {
11657			 *        "language": {
11658			 *          "lengthMenu": 'Display <select>'+
11659			 *            '<option value="10">10</option>'+
11660			 *            '<option value="20">20</option>'+
11661			 *            '<option value="30">30</option>'+
11662			 *            '<option value="40">40</option>'+
11663			 *            '<option value="50">50</option>'+
11664			 *            '<option value="-1">All</option>'+
11665			 *            '</select> records'
11666			 *        }
11667			 *      } );
11668			 *    } );
11669			 */
11670			"sLengthMenu": "Show _MENU_ entries",
11671	
11672	
11673			/**
11674			 * When using Ajax sourced data and during the first draw when DataTables is
11675			 * gathering the data, this message is shown in an empty row in the table to
11676			 * indicate to the end user the the data is being loaded. Note that this
11677			 * parameter is not used when loading data by server-side processing, just
11678			 * Ajax sourced data with client-side processing.
11679			 *  @type string
11680			 *  @default Loading...
11681			 *
11682			 *  @dtopt Language
11683			 *  @name DataTable.defaults.language.loadingRecords
11684			 *
11685			 *  @example
11686			 *    $(document).ready( function() {
11687			 *      $('#example').dataTable( {
11688			 *        "language": {
11689			 *          "loadingRecords": "Please wait - loading..."
11690			 *        }
11691			 *      } );
11692			 *    } );
11693			 */
11694			"sLoadingRecords": "Loading...",
11695	
11696	
11697			/**
11698			 * Text which is displayed when the table is processing a user action
11699			 * (usually a sort command or similar).
11700			 *  @type string
11701			 *
11701  @default Processing...
11702			 *
11703			 *  @dtopt Language
11704			 *  @name DataTable.defaults.language.processing
11705			 *
11706			 *  @example
11707			 *    $(document).ready( function() {
11708			 *      $('#example').dataTable( {
11709			 *        "language": {
11710			 *          "processing": "DataTables is currently busy"
11711			 *        }
11712			 *      } );
11713			 *    } );
11714			 */
11715			"sProcessing": "Processing...
vendor: 42,942 bytes, lines 11715-13009
11715",
11716	
11717	
11718			/**
11719			 * Details the actions that will be taken when the user types into the
11720			 * filtering input text box. The variable "_INPUT_", if used in the string,
11721			 * is replaced with the HTML text box for the filtering input allowing
11722			 * control over where it appears in the string. If "_INPUT_" is not given
11723			 * then the input box is appended to the string automatically.
11724			 *  @type string
11725			 *  @default Search:
11726			 *
11727			 *  @dtopt Language
11728			 *  @name DataTable.defaults.language.search
11729			 *
11730			 *  @example
11731			 *    // Input text box will be appended at the end automatically
11732			 *    $(document).ready( function() {
11733			 *      $('#example').dataTable( {
11734			 *        "language": {
11735			 *          "search": "Filter records:"
11736			 *        }
11737			 *      } );
11738			 *    } );
11739			 *
11740			 *  @example
11741			 *    // Specify where the filter should appear
11742			 *    $(document).ready( function() {
11743			 *      $('#example').dataTable( {
11744			 *        "language": {
11745			 *          "search": "Apply filter _INPUT_ to table"
11746			 *        }
11747			 *      } );
11748			 *    } );
11749			 */
11750			"sSearch": "Search:",
11751	
11752	
11753			/**
11754			 * Assign a `placeholder` attribute to the search `input` element
11755			 *  @type string
11756			 *  @default 
11757			 *
11758			 *  @dtopt Language
11759			 *  @name DataTable.defaults.language.searchPlaceholder
11760			 */
11761			"sSearchPlaceholder": "",
11762	
11763	
11764			/**
11765			 * All of the language information can be stored in a file on the
11766			 * server-side, which DataTables will look up if this parameter is passed.
11767			 * It must store the URL of the language file, which is in a JSON format,
11768			 * and the object has the same properties as the oLanguage object in the
11769			 * initialiser object (i.e. the above parameters). Please refer to one of
11770			 * the example language files to see how this works in action.
11771			 *  @type string
11772			 *  @default <i>Empty string - i.e. disabled</i>
11773			 *
11774			 *  @dtopt Language
11775			 *  @name DataTable.defaults.language.url
11776			 *
11777			 *  @example
11778			 *    $(document).ready( function() {
11779			 *      $('#example').dataTable( {
11780			 *        "language": {
11781			 *          "url": "http://www.sprymedia.co.uk/dataTables/lang.txt"
11782			 *        }
11783			 *      } );
11784			 *    } );
11785			 */
11786			"sUrl": "",
11787	
11788	
11789			/**
11790			 * Text shown inside the table records when the is no information to be
11791			 * displayed after filtering. `emptyTable` is shown when there is simply no
11792			 * information in the table at all (regardless of filtering).
11793			 *  @type string
11794			 *  @default No matching records found
11795			 *
11796			 *  @dtopt Language
11797			 *  @name DataTable.defaults.language.zeroRecords
11798			 *
11799			 *  @example
11800			 *    $(document).ready( function() {
11801			 *      $('#example').dataTable( {
11802			 *        "language": {
11803			 *          "zeroRecords": "No records to display"
11804			 *        }
11805			 *      } );
11806			 *    } );
11807			 */
11808			"sZeroRecords": "No matching records found"
11809		},
11810	
11811	
11812		/**
11813		 * This parameter allows you to have define the global filtering state at
11814		 * initialisation time. As an object the `search` parameter must be
11815		 * defined, but all other parameters are optional. When `regex` is true,
11816		 * the search string will be treated as a regular expression, when false
11817		 * (default) it will be treated as a straight string. When `smart`
11818		 * DataTables will use it's smart filtering methods (to word match at
11819		 * any point in the data), when false this will not be done.
11820		 *  @namespace
11821		 *  @extends DataTable.models.oSearch
11822		 *
11823		 *  @dtopt Options
11824		 *  @name DataTable.defaults.search
11825		 *
11826		 *  @example
11827		 *    $(document).ready( function() {
11828		 *      $('#example').dataTable( {
11829		 *        "search": {"search": "Initial search"}
11830		 *      } );
11831		 *    } )
11832		 */
11833		"oSearch": $.extend( {}, DataTable.models.oSearch ),
11834	
11835	
11836		/**
11837		 * __Deprecated__ The functionality provided by this parameter has now been
11838		 * superseded by that provided through `ajax`, which should be used instead.
11839		 *
11840		 * By default DataTables will look for the property `data` (or `aaData` for
11841		 * compatibility with DataTables 1.9-) when obtaining data from an Ajax
11842		 * source or for server-side processing - this parameter allows that
11843		 * property to be changed. You can use Javascript dotted object notation to
11844		 * get a data source for multiple levels of nesting.
11845		 *  @type string
11846		 *  @default data
11847		 *
11848		 *  @dtopt Options
11849		 *  @dtopt Server-side
11850		 *  @name DataTable.defaults.ajaxDataProp
11851		 *
11852		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11853		 */
11854		"sAjaxDataProp": "data",
11855	
11856	
11857		/**
11858		 * __Deprecated__ The functionality provided by this parameter has now been
11859		 * superseded by that provided through `ajax`, which should be used instead.
11860		 *
11861		 * You can instruct DataTables to load data from an external
11862		 * source using this parameter (use aData if you want to pass data in you
11863		 * already have). Simply provide a url a JSON object can be obtained from.
11864		 *  @type string
11865		 *  @default null
11866		 *
11867		 *  @dtopt Options
11868		 *  @dtopt Server-side
11869		 *  @name DataTable.defaults.ajaxSource
11870		 *
11871		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11872		 */
11873		"sAjaxSource": null,
11874	
11875	
11876		/**
11877		 * This initialisation variable allows you to specify exactly where in the
11878		 * DOM you want DataTables to inject the various controls it adds to the page
11879		 * (for example you might want the pagination controls at the top of the
11880		 * table). DIV elements (with or without a custom class) can also be added to
11881		 * aid styling. The follow syntax is used:
11882		 *   <ul>
11883		 *     <li>The following options are allowed:
11884		 *       <ul>
11885		 *         <li>'l' - Length changing</li>
11886		 *         <li>'f' - Filtering input</li>
11887		 *         <li>'t' - The table!</li>
11888		 *         <li>'i' - Information</li>
11889		 *         <li>'p' - Pagination</li>
11890		 *         <li>'r' - pRocessing</li>
11891		 *       </ul>
11892		 *     </li>
11893		 *     <li>The following constants are allowed:
11894		 *       <ul>
11895		 *         <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>
11896		 *         <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>
11897		 *       </ul>
11898		 *     </li>
11899		 *     <li>The following syntax is expected:
11900		 *       <ul>
11901		 *         <li>'&lt;' and '&gt;' - div elements</li>
11902		 *         <li>'&lt;"class" and '&gt;' - div with a class</li>
11903		 *         <li>'&lt;"#id" and '&gt;' - div with an ID</li>
11904		 *       </ul>
11905		 *     </li>
11906		 *     <li>Examples:
11907		 *       <ul>
11908		 *         <li>'&lt;"wrapper"flipt&gt;'</li>
11909		 *         <li>'&lt;lf&lt;t&gt;ip&gt;'</li>
11910		 *       </ul>
11911		 *     </li>
11912		 *   </ul>
11913		 *  @type string
11914		 *  @default lfrtip <i>(when `jQueryUI` is false)</i> <b>or</b>
11915		 *    <"H"lfr>t<"F"ip> <i>(when `jQueryUI` is true)</i>
11916		 *
11917		 *  @dtopt Options
11918		 *  @name DataTable.defaults.dom
11919		 *
11920		 *  @example
11921		 *    $(document).ready( function() {
11922		 *      $('#example').dataTable( {
11923		 *        "dom": '&lt;"top"i&gt;rt&lt;"bottom"flp&gt;&lt;"clear"&gt;'
11924		 *      } );
11925		 *    } );
11926		 */
11927		"sDom": "lfrtip",
11928	
11929	
11930		/**
11931		 * Search delay option. This will throttle full table searches that use the
11932		 * DataTables provided search input element (it does not effect calls to
11933		 * `dt-api search()`, providing a delay before the search is made.
11934		 *  @type integer
11935		 *  @default 0
11936		 *
11937		 *  @dtopt Options
11938		 *  @name DataTable.defaults.searchDelay
11939		 *
11940		 *  @example
11941		 *    $(document).ready( function() {
11942		 *      $('#example').dataTable( {
11943		 *        "searchDelay": 200
11944		 *      } );
11945		 *    } )
11946		 */
11947		"searchDelay": null,
11948	
11949	
11950		/**
11951		 * DataTables features six different built-in options for the buttons to
11952		 * display for pagination control:
11953		 *
11954		 * * `numbers` - Page number buttons only
11955		 * * `simple` - 'Previous' and 'Next' buttons only
11956		 * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers
11957		 * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons
11958		 * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus page numbers
11959		 * * `first_last_numbers` - 'First' and 'Last' buttons, plus page numbers
11960		 *  
11961		 * Further methods can be added using {@link DataTable.ext.oPagination}.
11962		 *  @type string
11963		 *  @default simple_numbers
11964		 *
11965		 *  @dtopt Options
11966		 *  @name DataTable.defaults.pagingType
11967		 *
11968		 *  @example
11969		 *    $(document).ready( function() {
11970		 *      $('#example').dataTable( {
11971		 *        "pagingType": "full_numbers"
11972		 *      } );
11973		 *    } )
11974		 */
11975		"sPaginationType": "simple_numbers",
11976	
11977	
11978		/**
11979		 * Enable horizontal scrolling. When a table is too wide to fit into a
11980		 * certain layout, or you have a large number of columns in the table, you
11981		 * can enable x-scrolling to show the table in a viewport, which can be
11982		 * scrolled. This property can be `true` which will allow the table to
11983		 * scroll horizontally when needed, or any CSS unit, or a number (in which
11984		 * case it will be treated as a pixel measurement). Setting as simply `true`
11985		 * is recommended.
11986		 *  @type boolean|string
11987		 *  @default <i>blank string - i.e. disabled</i>
11988		 *
11989		 *  @dtopt Features
11990		 *  @name DataTable.defaults.scrollX
11991		 *
11992		 *  @example
11993		 *    $(document).ready( function() {
11994		 *      $('#example').dataTable( {
11995		 *        "scrollX": true,
11996		 *        "scrollCollapse": true
11997		 *      } );
11998		 *    } );
11999		 */
12000		"sScrollX": "",
12001	
12002	
12003		/**
12004		 * This property can be used to force a DataTable to use more width than it
12005		 * might otherwise do when x-scrolling is enabled. For example if you have a
12006		 * table which requires to be well spaced, this parameter is useful for
12007		 * "over-sizing" the table, and thus forcing scrolling. This property can by
12008		 * any CSS unit, or a number (in which case it will be treated as a pixel
12009		 * measurement).
12010		 *  @type string
12011		 *  @default <i>blank string - i.e. disabled</i>
12012		 *
12013		 *  @dtopt Options
12014		 *  @name DataTable.defaults.scrollXInner
12015		 *
12016		 *  @example
12017		 *    $(document).ready( function() {
12018		 *      $('#example').dataTable( {
12019		 *        "scrollX": "100%",
12020		 *        "scrollXInner": "110%"
12021		 *      } );
12022		 *    } );
12023		 */
12024		"sScrollXInner": "",
12025	
12026	
12027		/**
12028		 * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
12029		 * to the given height, and enable scrolling for any data which overflows the
12030		 * current viewport. This can be used as an alternative to paging to display
12031		 * a lot of data in a small area (although paging and scrolling can both be
12032		 * enabled at the same time). This property can be any CSS unit, or a number
12033		 * (in which case it will be treated as a pixel measurement).
12034		 *  @type string
12035		 *  @default <i>blank string - i.e. disabled</i>
12036		 *
12037		 *  @dtopt Features
12038		 *  @name DataTable.defaults.scrollY
12039		 *
12040		 *  @example
12041		 *    $(document).ready( function() {
12042		 *      $('#example').dataTable( {
12043		 *        "scrollY": "200px",
12044		 *        "paginate": false
12045		 *      } );
12046		 *    } );
12047		 */
12048		"sScrollY": "",
12049	
12050	
12051		/**
12052		 * __Deprecated__ The functionality provided by this parameter has now been
12053		 * superseded by that provided through `ajax`, which should be used instead.
12054		 *
12055		 * Set the HTTP method that is used to make the Ajax call for server-side
12056		 * processing or Ajax sourced data.
12057		 *  @type string
12058		 *  @default GET
12059		 *
12060		 *  @dtopt Options
12061		 *  @dtopt Server-side
12062		 *  @name DataTable.defaults.serverMethod
12063		 *
12064		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
12065		 */
12066		"sServerMethod": "GET",
12067	
12068	
12069		/**
12070		 * DataTables makes use of renderers when displaying HTML elements for
12071		 * a table. These renderers can be added or modified by plug-ins to
12072		 * generate suitable mark-up for a site. For example the Bootstrap
12073		 * integration plug-in for DataTables uses a paging button renderer to
12074		 * display pagination buttons in the mark-up required by Bootstrap.
12075		 *
12076		 * For further information about the renderers available see
12077		 * DataTable.ext.renderer
12078		 *  @type string|object
12079		 *  @default null
12080		 *
12081		 *  @name DataTable.defaults.renderer
12082		 *
12083		 */
12084		"renderer": null,
12085	
12086	
12087		/**
12088		 * Set the data property name that DataTables should use to get a row's id
12089		 * to set as the `id` property in the node.
12090		 *  @type string
12091		 *  @default DT_RowId
12092		 *
12093		 *  @name DataTable.defaults.rowId
12094		 */
12095		"rowId": "DT_RowId"
12096	};
12097	
12098	_fnHungarianMap( DataTable.defaults );
12099	
12100	
12101	
12102	/*
12103	 * Developer note - See note in model.defaults.js about the use of Hungarian
12104	 * notation and camel case.
12105	 */
12106	
12107	/**
12108	 * Column options that can be given to DataTables at initialisation time.
12109	 *  @namespace
12110	 */
12111	DataTable.defaults.column = {
12112		/**
12113		 * Define which column(s) an order will occur on for this column. This
12114		 * allows a column's ordering to take multiple columns into account when
12115		 * doing a sort or use the data from a different column. For example first
12116		 * name / last name columns make sense to do a multi-column sort over the
12117		 * two columns.
12118		 *  @type array|int
12119		 *  @default null <i>Takes the value of the column index automatically</i>
12120		 *
12121		 *  @name DataTable.defaults.column.orderData
12122		 *  @dtopt Columns
12123		 *
12124		 *  @example
12125		 *    // Using `columnDefs`
12126		 *    $(document).ready( function() {
12127		 *      $('#example').dataTable( {
12128		 *        "columnDefs": [
12129		 *          { "orderData": [ 0, 1 ], "targets": [ 0 ] },
12130		 *          { "orderData": [ 1, 0 ], "targets": [ 1 ] },
12131		 *          { "orderData": 2, "targets": [ 2 ] }
12132		 *        ]
12133		 *      } );
12134		 *    } );
12135		 *
12136		 *  @example
12137		 *    // Using `columns`
12138		 *    $(document).ready( function() {
12139		 *      $('#example').dataTable( {
12140		 *        "columns": [
12141		 *          { "orderData": [ 0, 1 ] },
12142		 *          { "orderData": [ 1, 0 ] },
12143		 *          { "orderData": 2 },
12144		 *          null,
12145		 *          null
12146		 *        ]
12147		 *      } );
12148		 *    } );
12149		 */
12150		"aDataSort": null,
12151		"iDataSort": -1,
12152	
12153	
12154		/**
12155		 * You can control the default ordering direction, and even alter the
12156		 * behaviour of the sort handler (i.e. only allow ascending ordering etc)
12157		 * using this parameter.
12158		 *  @type array
12159		 *  @default [ 'asc', 'desc' ]
12160		 *
12161		 *  @name DataTable.defaults.column.orderSequence
12162		 *  @dtopt Columns
12163		 *
12164		 *  @example
12165		 *    // Using `columnDefs`
12166		 *    $(document).ready( function() {
12167		 *      $('#example').dataTable( {
12168		 *        "columnDefs": [
12169		 *          { "orderSequence": [ "asc" ], "targets": [ 1 ] },
12170		 *          { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] },
12171		 *          { "orderSequence": [ "desc" ], "targets": [ 3 ] }
12172		 *        ]
12173		 *      } );
12174		 *    } );
12175		 *
12176		 *  @example
12177		 *    // Using `columns`
12178		 *    $(document).ready( function() {
12179		 *      $('#example').dataTable( {
12180		 *        "columns": [
12181		 *          null,
12182		 *          { "orderSequence": [ "asc" ] },
12183		 *          { "orderSequence": [ "desc", "asc", "asc" ] },
12184		 *          { "orderSequence": [ "desc" ] },
12185		 *          null
12186		 *        ]
12187		 *      } );
12188		 *    } );
12189		 */
12190		"asSorting": [ 'asc', 'desc' ],
12191	
12192	
12193		/**
12194		 * Enable or disable filtering on the data in this column.
12195		 *  @type boolean
12196		 *  @default true
12197		 *
12198		 *  @name DataTable.defaults.column.searchable
12199		 *  @dtopt Columns
12200		 *
12201		 *  @example
12202		 *    // Using `columnDefs`
12203		 *    $(document).ready( function() {
12204		 *      $('#example').dataTable( {
12205		 *        "columnDefs": [
12206		 *          { "searchable": false, "targets": [ 0 ] }
12207		 *        ] } );
12208		 *    } );
12209		 *
12210		 *  @example
12211		 *    // Using `columns`
12212		 *    $(document).ready( function() {
12213		 *      $('#example').dataTable( {
12214		 *        "columns": [
12215		 *          { "searchable": false },
12216		 *          null,
12217		 *          null,
12218		 *          null,
12219		 *          null
12220		 *        ] } );
12221		 *    } );
12222		 */
12223		"bSearchable": true,
12224	
12225	
12226		/**
12227		 * Enable or disable ordering on this column.
12228		 *  @type boolean
12229		 *  @default true
12230		 *
12231		 *  @name DataTable.defaults.column.orderable
12232		 *  @dtopt Columns
12233		 *
12234		 *  @example
12235		 *    // Using `columnDefs`
12236		 *    $(document).ready( function() {
12237		 *      $('#example').dataTable( {
12238		 *        "columnDefs": [
12239		 *          { "orderable": false, "targets": [ 0 ] }
12240		 *        ] } );
12241		 *    } );
12242		 *
12243		 *  @example
12244		 *    // Using `columns`
12245		 *    $(document).ready( function() {
12246		 *      $('#example').dataTable( {
12247		 *        "columns": [
12248		 *          { "orderable": false },
12249		 *          null,
12250		 *          null,
12251		 *          null,
12252		 *          null
12253		 *        ] } );
12254		 *    } );
12255		 */
12256		"bSortable": true,
12257	
12258	
12259		/**
12260		 * Enable or disable the display of this column.
12261		 *  @type boolean
12262		 *  @default true
12263		 *
12264		 *  @name DataTable.defaults.column.visible
12265		 *  @dtopt Columns
12266		 *
12267		 *  @example
12268		 *    // Using `columnDefs`
12269		 *    $(document).ready( function() {
12270		 *      $('#example').dataTable( {
12271		 *        "columnDefs": [
12272		 *          { "visible": false, "targets": [ 0 ] }
12273		 *        ] } );
12274		 *    } );
12275		 *
12276		 *  @example
12277		 *    // Using `columns`
12278		 *    $(document).ready( function() {
12279		 *      $('#example').dataTable( {
12280		 *        "columns": [
12281		 *          { "visible": false },
12282		 *          null,
12283		 *          null,
12284		 *          null,
12285		 *          null
12286		 *        ] } );
12287		 *    } );
12288		 */
12289		"bVisible": true,
12290	
12291	
12292		/**
12293		 * Developer definable function that is called whenever a cell is created (Ajax source,
12294		 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
12295		 * allowing you to modify the DOM element (add background colour for example) when the
12296		 * element is available.
12297		 *  @type function
12298		 *  @param {element} td The TD node that has been created
12299		 *  @param {*} cellData The Data for the cell
12300		 *  @param {array|object} rowData The data for the whole row
12301		 *  @param {int} row The row index for the aoData data store
12302		 *  @param {int} col The column index for aoColumns
12303		 *
12304		 *  @name DataTable.defaults.column.createdCell
12305		 *  @dtopt Columns
12306		 *
12307		 *  @example
12308		 *    $(document).ready( function() {
12309		 *      $('#example').dataTable( {
12310		 *        "columnDefs": [ {
12311		 *          "targets": [3],
12312		 *          "createdCell": function (td, cellData, rowData, row, col) {
12313		 *            if ( cellData == "1.7" ) {
12314		 *              $(td).css('color', 'blue')
12315		 *            }
12316		 *          }
12317		 *        } ]
12318		 *      });
12319		 *    } );
12320		 */
12321		"fnCreatedCell": null,
12322	
12323	
12324		/**
12325		 * This parameter has been replaced by `data` in DataTables to ensure naming
12326		 * consistency. `dataProp` can still be used, as there is backwards
12327		 * compatibility in DataTables for this option, but it is strongly
12328		 * recommended that you use `data` in preference to `dataProp`.
12329		 *  @name DataTable.defaults.column.dataProp
12330		 */
12331	
12332	
12333		/**
12334		 * This property can be used to read data from any data source property,
12335		 * including deeply nested objects / properties. `data` can be given in a
12336		 * number of different ways which effect its behaviour:
12337		 *
12338		 * * `integer` - treated as an array index for the data source. This is the
12339		 *   default that DataTables uses (incrementally increased for each column).
12340		 * * `string` - read an object property from the data source. There are
12341		 *   three 'special' options that can be used in the string to alter how
12342		 *   DataTables reads the data from the source object:
12343		 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
12344		 *      Javascript to read from nested objects, so to can the options
12345		 *      specified in `data`. For example: `browser.version` or
12346		 *      `browser.name`. If your object parameter name contains a period, use
12347		 *      `\\` to escape it - i.e. `first\\.name`.
12348		 *    * `[]` - Array notation. DataTables can automatically combine data
12349		 *      from and array source, joining the data with the characters provided
12350		 *      between the two brackets. For example: `name[, ]` would provide a
12351		 *      comma-space separated list from the source array. If no characters
12352		 *      are provided between the brackets, the original array source is
12353		 *      returned.
12354		 *    * `()` - Function notation. Adding `()` to the end of a parameter will
12355		 *      execute a function of the name given. For example: `browser()` for a
12356		 *      simple function on the data source, `browser.version()` for a
12357		 *      function in a nested property or even `browser().version` to get an
12358		 *      object property if the function called returns an object. Note that
12359		 *      function notation is recommended for use in `render` rather than
12360		 *      `data` as it is much simpler to use as a renderer.
12361		 * * `null` - use the original data source for the row rather than plucking
12362		 *   data directly from it. This action has effects on two other
12363		 *   initialisation options:
12364		 *    * `defaultContent` - When null is given as the `data` option and
12365		 *      `defaultContent` is specified for the column, the value defined by
12366		 *      `defaultContent` will be used for the cell.
12367		 *    * `render` - When null is used for the `data` option and the `render`
12368		 *      option is specified for the column, the whole data source for the
12369		 *      row is used for the renderer.
12370		 * * `function` - the function given will be executed whenever DataTables
12371		 *   needs to set or get the data for a cell in the column. The function
12372		 *   takes three parameters:
12373		 *    * Parameters:
12374		 *      * `{array|object}` The data source for the row
12375		 *      * `{string}` The type call data requested - this will be 'set' when
12376		 *        setting data or 'filter', 'display', 'type', 'sort' or undefined
12377		 *        when gathering data. Note that when `undefined` is given for the
12378		 *        type DataTables expects to get the raw data for the object back<
12379		 *      * `{*}` Data to set when the second parameter is 'set'.
12380		 *    * Return:
12381		 *      * The return value from the function is not required when 'set' is
12382		 *        the type of call, but otherwise the return is what will be used
12383		 *        for the data requested.
12384		 *
12385		 * Note that `data` is a getter and setter option. If you just require
12386		 * formatting of data for output, you will likely want to use `render` which
12387		 * is simply a getter and thus simpler to use.
12388		 *
12389		 * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The
12390		 * name change reflects the flexibility of this property and is consistent
12391		 * with the naming of mRender. If 'mDataProp' is given, then it will still
12392		 * be used by DataTables, as it automatically maps the old name to the new
12393		 * if required.
12394		 *
12395		 *  @type string|int|function|null
12396		 *  @default null <i>Use automatically calculated column index</i>
12397		 *
12398		 *  @name DataTable.defaults.column.data
12399		 *  @dtopt Columns
12400		 *
12401		 *  @example
12402		 *    // Read table data from objects
12403		 *    // JSON structure for each row:
12404		 *    //   {
12405		 *    //      "engine": {value},
12406		 *    //      "browser": {value},
12407		 *    //      "platform": {value},
12408		 *    //      "version": {value},
12409		 *    //      "grade": {value}
12410		 *    //   }
12411		 *    $(document).ready( function() {
12412		 *      $('#example').dataTable( {
12413		 *        "ajaxSource": "sources/objects.txt",
12414		 *        "columns": [
12415		 *          { "data": "engine" },
12416		 *          { "data": "browser" },
12417		 *          { "data": "platform" },
12418		 *          { "data": "version" },
12419		 *          { "data": "grade" }
12420		 *        ]
12421		 *      } );
12422		 *    } );
12423		 *
12424		 *  @example
12425		 *    // Read information from deeply nested objects
12426		 *    // JSON structure for each row:
12427		 *    //   {
12428		 *    //      "engine": {value},
12429		 *    //      "browser": {value},
12430		 *    //      "platform": {
12431		 *    //         "inner": {value}
12432		 *    //      },
12433		 *    //      "details": [
12434		 *    //         {value}, {value}
12435		 *    //      ]
12436		 *    //   }
12437		 *    $(document).ready( function() {
12438		 *      $('#example').dataTable( {
12439		 *        "ajaxSource": "sources/deep.txt",
12440		 *        "columns": [
12441		 *          { "data": "engine" },
12442		 *          { "data": "browser" },
12443		 *          { "data": "platform.inner" },
12444		 *          { "data": "details.0" },
12445		 *          { "data": "details.1" }
12446		 *        ]
12447		 *      } );
12448		 *    } );
12449		 *
12450		 *  @example
12451		 *    // Using `data` as a function to provide different information for
12452		 *    // sorting, filtering and display. In this case, currency (price)
12453		 *    $(document).ready( function() {
12454		 *      $('#example').dataTable( {
12455		 *        "columnDefs": [ {
12456		 *          "targets": [ 0 ],
12457		 *          "data": function ( source, type, val ) {
12458		 *            if (type === 'set') {
12459		 *              source.price = val;
12460		 *              // Store the computed dislay and filter values for efficiency
12461		 *              source.price_display = val=="" ? "" : "$"+numberFormat(val);
12462		 *              source.price_filter  = val=="" ? "" : "$"+numberFormat(val)+" "+val;
12463		 *              return;
12464		 *            }
12465		 *            else if (type === 'display') {
12466		 *              return source.price_display;
12467		 *            }
12468		 *            else if (type === 'filter') {
12469		 *              return source.price_filter;
12470		 *            }
12471		 *            // 'sort', 'type' and undefined all just use the integer
12472		 *            return source.price;
12473		 *          }
12474		 *        } ]
12475		 *      } );
12476		 *    } );
12477		 *
12478		 *  @example
12479		 *    // Using default content
12480		 *    $(document).ready( function() {
12481		 *      $('#example').dataTable( {
12482		 *        "columnDefs": [ {
12483		 *          "targets": [ 0 ],
12484		 *          "data": null,
12485		 *          "defaultContent": "Click to edit"
12486		 *        } ]
12487		 *      } );
12488		 *    } );
12489		 *
12490		 *  @example
12491		 *    // Using array notation - outputting a list from an array
12492		 *    $(document).ready( function() {
12493		 *      $('#example').dataTable( {
12494		 *        "columnDefs": [ {
12495		 *          "targets": [ 0 ],
12496		 *          "data": "name[, ]"
12497		 *        } ]
12498		 *      } );
12499		 *    } );
12500		 *
12501		 */
12502		"mData": null,
12503	
12504	
12505		/**
12506		 * This property is the rendering partner to `data` and it is suggested that
12507		 * when you want to manipulate data for display (including filtering,
12508		 * sorting etc) without altering the underlying data for the table, use this
12509		 * property. `render` can be considered to be the the read only companion to
12510		 * `data` which is read / write (then as such more complex). Like `data`
12511		 * this option can be given in a number of different ways to effect its
12512		 * behaviour:
12513		 *
12514		 * * `integer` - treated as an array index for the data source. This is the
12515		 *   default that DataTables uses (incrementally increased for each column).
12516		 * * `string` - read an object property from the data source. There are
12517		 *   three 'special' options that can be used in the string to alter how
12518		 *   DataTables reads the data from the source object:
12519		 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
12520		 *      Javascript to read from nested objects, so to can the options
12521		 *      specified in `data`. For example: `browser.version` or
12522		 *      `browser.name`. If your object parameter name contains a period, use
12523		 *      `\\` to escape it - i.e. `first\\.name`.
12524		 *    * `[]` - Array notation. DataTables can automatically combine data
12525		 *      from and array source, joining the data with the characters provided
12526		 *      between the two brackets. For example: `name[, ]` would provide a
12527		 *      comma-space separated list from the source array. If no characters
12528		 *      are provided between the brackets, the original array source is
12529		 *      returned.
12530		 *    * `()` - Function notation. Adding `()` to the end of a parameter will
12531		 *      execute a function of the name given. For example: `browser()` for a
12532		 *      simple function on the data source, `browser.version()` for a
12533		 *      function in a nested property or even `browser().version` to get an
12534		 *      object property if the function called returns an object.
12535		 * * `object` - use different data for the different data types requested by
12536		 *   DataTables ('filter', 'display', 'type' or 'sort'). The property names
12537		 *   of the object is the data type the property refers to and the value can
12538		 *   defined using an integer, string or function using the same rules as
12539		 *   `render` normally does. Note that an `_` option _must_ be specified.
12540		 *   This is the default value to use if you haven't specified a value for
12541		 *   the data type requested by DataTables.
12542		 * * `function` - the function given will be executed whenever DataTables
12543		 *   needs to set or get the data for a cell in the column. The function
12544		 *   takes three parameters:
12545		 *    * Parameters:
12546		 *      * {array|object} The data source for the row (based on `data`)
12547		 *      * {string} The type call data requested - this will be 'filter',
12548		 *        'display', 'type' or 'sort'.
12549		 *      * {array|object} The full data source for the row (not based on
12550		 *        `data`)
12551		 *    * Return:
12552		 *      * The return value from the function is what will be used for the
12553		 *        data requested.
12554		 *
12555		 *  @type string|int|function|object|null
12556		 *  @default null Use the data source value.
12557		 *
12558		 *  @name DataTable.defaults.column.render
12559		 *  @dtopt Columns
12560		 *
12561		 *  @example
12562		 *    // Create a comma separated list from an array of objects
12563		 *    $(document).ready( function() {
12564		 *      $('#example').dataTable( {
12565		 *        "ajaxSource": "sources/deep.txt",
12566		 *        "columns": [
12567		 *          { "data": "engine" },
12568		 *          { "data": "browser" },
12569		 *          {
12570		 *            "data": "platform",
12571		 *            "render": "[, ].name"
12572		 *          }
12573		 *        ]
12574		 *      } );
12575		 *    } );
12576		 *
12577		 *  @example
12578		 *    // Execute a function to obtain data
12579		 *    $(document).ready( function() {
12580		 *      $('#example').dataTable( {
12581		 *        "columnDefs": [ {
12582		 *          "targets": [ 0 ],
12583		 *          "data": null, // Use the full data source object for the renderer's source
12584		 *          "render": "browserName()"
12585		 *        } ]
12586		 *      } );
12587		 *    } );
12588		 *
12589		 *  @example
12590		 *    // As an object, extracting different data for the different types
12591		 *    // This would be used with a data source such as:
12592		 *    //   { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" }
12593		 *    // Here the `phone` integer is used for sorting and type detection, while `phone_filter`
12594		 *    // (which has both forms) is used for filtering for if a user inputs either format, while
12595		 *    // the formatted phone number is the one that is shown in the table.
12596		 *    $(document).ready( function() {
12597		 *      $('#example').dataTable( {
12598		 *        "columnDefs": [ {
12599		 *          "targets": [ 0 ],
12600		 *          "data": null, // Use the full data source object for the renderer's source
12601		 *          "render": {
12602		 *            "_": "phone",
12603		 *            "filter": "phone_filter",
12604		 *            "display": "phone_display"
12605		 *          }
12606		 *        } ]
12607		 *      } );
12608		 *    } );
12609		 *
12610		 *  @example
12611		 *    // Use as a function to create a link from the data source
12612		 *    $(document).ready( function() {
12613		 *      $('#example').dataTable( {
12614		 *        "columnDefs": [ {
12615		 *          "targets": [ 0 ],
12616		 *          "data": "download_link",
12617		 *          "render": function ( data, type, full ) {
12618		 *            return '<a href="'+data+'">Download</a>';
12619		 *          }
12620		 *        } ]
12621		 *      } );
12622		 *    } );
12623		 */
12624		"mRender": null,
12625	
12626	
12627		/**
12628		 * Change the cell type created for the column - either TD cells or TH cells. This
12629		 * can be useful as TH cells have semantic meaning in the table body, allowing them
12630		 * to act as a header for a row (you may wish to add scope='row' to the TH elements).
12631		 *  @type string
12632		 *  @default td
12633		 *
12634		 *  @name DataTable.defaults.column.cellType
12635		 *  @dtopt Columns
12636		 *
12637		 *  @example
12638		 *    // Make the first column use TH cells
12639		 *    $(document).ready( function() {
12640		 *      $('#example').dataTable( {
12641		 *        "columnDefs": [ {
12642		 *          "targets": [ 0 ],
12643		 *          "cellType": "th"
12644		 *        } ]
12645		 *      } );
12646		 *    } );
12647		 */
12648		"sCellType": "td",
12649	
12650	
12651		/**
12652		 * Class to give to each cell in this column.
12653		 *  @type string
12654		 *  @default <i>Empty string</i>
12655		 *
12656		 *  @name DataTable.defaults.column.class
12657		 *  @dtopt Columns
12658		 *
12659		 *  @example
12660		 *    // Using `columnDefs`
12661		 *    $(document).ready( function() {
12662		 *      $('#example').dataTable( {
12663		 *        "columnDefs": [
12664		 *          { "class": "my_class", "targets": [ 0 ] }
12665		 *        ]
12666		 *      } );
12667		 *    } );
12668		 *
12669		 *  @example
12670		 *    // Using `columns`
12671		 *    $(document).ready( function() {
12672		 *      $('#example').dataTable( {
12673		 *        "columns": [
12674		 *          { "class": "my_class" },
12675		 *          null,
12676		 *          null,
12677		 *          null,
12678		 *          null
12679		 *        ]
12680		 *      } );
12681		 *    } );
12682		 */
12683		"sClass": "",
12684	
12685		/**
12686		 * When DataTables calculates the column widths to assign to each column,
12687		 * it finds the longest string in each column and then constructs a
12688		 * temporary table and reads the widths from that. The problem with this
12689		 * is that "mmm" is much wider then "iiii", but the latter is a longer
12690		 * string - thus the calculation can go wrong (doing it properly and putting
12691		 * it into an DOM object and measuring that is horribly(!) slow). Thus as
12692		 * a "work around" we provide this option. It will append its value to the
12693		 * text that is found to be the longest string for the column - i.e. padding.
12694		 * Generally you shouldn't need this!
12695		 *  @type string
12696		 *  @default <i>Empty string<i>
12697		 *
12698		 *  @name DataTable.defaults.column.contentPadding
12699		 *  @dtopt Columns
12700		 *
12701		 *  @example
12702		 *    // Using `columns`
12703		 *    $(document).ready( function() {
12704		 *      $('#example').dataTable( {
12705		 *        "columns": [
12706		 *          null,
12707		 *          null,
12708		 *          null,
12709		 *          {
12710		 *            "contentPadding": "mmm"
12711		 *          }
12712		 *        ]
12713		 *      } );
12714		 *    } );
12715		 */
12716		"sContentPadding": "",
12717	
12718	
12719		/**
12720		 * Allows a default value to be given for a column's data, and will be used
12721		 * whenever a null data source is encountered (this can be because `data`
12722		 * is set to null, or because the data source itself is null).
12723		 *  @type string
12724		 *  @default null
12725		 *
12726		 *  @name DataTable.defaults.column.defaultContent
12727		 *  @dtopt Columns
12728		 *
12729		 *  @example
12730		 *    // Using `columnDefs`
12731		 *    $(document).ready( function() {
12732		 *      $('#example').dataTable( {
12733		 *        "columnDefs": [
12734		 *          {
12735		 *            "data": null,
12736		 *            "defaultContent": "Edit",
12737		 *            "targets": [ -1 ]
12738		 *          }
12739		 *        ]
12740		 *      } );
12741		 *    } );
12742		 *
12743		 *  @example
12744		 *    // Using `columns`
12745		 *    $(document).ready( function() {
12746		 *      $('#example').dataTable( {
12747		 *        "columns": [
12748		 *          null,
12749		 *          null,
12750		 *          null,
12751		 *          {
12752		 *            "data": null,
12753		 *            "defaultContent": "Edit"
12754		 *          }
12755		 *        ]
12756		 *      } );
12757		 *    } );
12758		 */
12759		"sDefaultContent": null,
12760	
12761	
12762		/**
12763		 * This parameter is only used in DataTables' server-side processing. It can
12764		 * be exceptionally useful to know what columns are being displayed on the
12765		 * client side, and to map these to database fields. When defined, the names
12766		 * also allow DataTables to reorder information from the server if it comes
12767		 * back in an unexpected order (i.e. if you switch your columns around on the
12768		 * client-side, your server-side code does not also need updating).
12769		 *  @type string
12770		 *  @default <i>Empty string</i>
12771		 *
12772		 *  @name DataTable.defaults.column.name
12773		 *  @dtopt Columns
12774		 *
12775		 *  @example
12776		 *    // Using `columnDefs`
12777		 *    $(document).ready( function() {
12778		 *      $('#example').dataTable( {
12779		 *        "columnDefs": [
12780		 *          { "name": "engine", "targets": [ 0 ] },
12781		 *          { "name": "browser", "targets": [ 1 ] },
12782		 *          { "name": "platform", "targets": [ 2 ] },
12783		 *          { "name": "version", "targets": [ 3 ] },
12784		 *          { "name": "grade", "targets": [ 4 ] }
12785		 *        ]
12786		 *      } );
12787		 *    } );
12788		 *
12789		 *  @example
12790		 *    // Using `columns`
12791		 *    $(document).ready( function() {
12792		 *      $('#example').dataTable( {
12793		 *        "columns": [
12794		 *          { "name": "engine" },
12795		 *          { "name": "browser" },
12796		 *          { "name": "platform" },
12797		 *          { "name": "version" },
12798		 *          { "name": "grade" }
12799		 *        ]
12800		 *      } );
12801		 *    } );
12802		 */
12803		"sName": "",
12804	
12805	
12806		/**
12807		 * Defines a data source type for the ordering which can be used to read
12808		 * real-time information from the table (updating the internally cached
12809		 * version) prior to ordering. This allows ordering to occur on user
12810		 * editable elements such as form inputs.
12811		 *  @type string
12812		 *  @default std
12813		 *
12814		 *  @name DataTable.defaults.column.orderDataType
12815		 *  @dtopt Columns
12816		 *
12817		 *  @example
12818		 *    // Using `columnDefs`
12819		 *    $(document).ready( function() {
12820		 *      $('#example').dataTable( {
12821		 *        "columnDefs": [
12822		 *          { "orderDataType": "dom-text", "targets": [ 2, 3 ] },
12823		 *          { "type": "numeric", "targets": [ 3 ] },
12824		 *          { "orderDataType": "dom-select", "targets": [ 4 ] },
12825		 *          { "orderDataType": "dom-checkbox", "targets": [ 5 ] }
12826		 *        ]
12827		 *      } );
12828		 *    } );
12829		 *
12830		 *  @example
12831		 *    // Using `columns`
12832		 *    $(document).ready( function() {
12833		 *      $('#example').dataTable( {
12834		 *        "columns": [
12835		 *          null,
12836		 *          null,
12837		 *          { "orderDataType": "dom-text" },
12838		 *          { "orderDataType": "dom-text", "type": "numeric" },
12839		 *          { "orderDataType": "dom-select" },
12840		 *          { "orderDataType": "dom-checkbox" }
12841		 *        ]
12842		 *      } );
12843		 *    } );
12844		 */
12845		"sSortDataType": "std",
12846	
12847	
12848		/**
12849		 * The title of this column.
12850		 *  @type string
12851		 *  @default null <i>Derived from the 'TH' value for this column in the
12852		 *    original HTML table.</i>
12853		 *
12854		 *  @name DataTable.defaults.column.title
12855		 *  @dtopt Columns
12856		 *
12857		 *  @example
12858		 *    // Using `columnDefs`
12859		 *    $(document).ready( function() {
12860		 *      $('#example').dataTable( {
12861		 *        "columnDefs": [
12862		 *          { "title": "My column title", "targets": [ 0 ] }
12863		 *        ]
12864		 *      } );
12865		 *    } );
12866		 *
12867		 *  @example
12868		 *    // Using `columns`
12869		 *    $(document).ready( function() {
12870		 *      $('#example').dataTable( {
12871		 *        "columns": [
12872		 *          { "title": "My column title" },
12873		 *          null,
12874		 *          null,
12875		 *          null,
12876		 *          null
12877		 *        ]
12878		 *      } );
12879		 *    } );
12880		 */
12881		"sTitle": null,
12882	
12883	
12884		/**
12885		 * The type allows you to specify how the data for this column will be
12886		 * ordered. Four types (string, numeric, date and html (which will strip
12887		 * HTML tags before ordering)) are currently available. Note that only date
12888		 * formats understood by Javascript's Date() object will be accepted as type
12889		 * date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string',
12890		 * 'numeric', 'date' or 'html' (by default). Further types can be adding
12891		 * through plug-ins.
12892		 *  @type string
12893		 *  @default null <i>Auto-detected from raw data</i>
12894		 *
12895		 *  @name DataTable.defaults.column.type
12896		 *  @dtopt Columns
12897		 *
12898		 *  @example
12899		 *    // Using `columnDefs`
12900		 *    $(document).ready( function() {
12901		 *      $('#example').dataTable( {
12902		 *        "columnDefs": [
12903		 *          { "type": "html", "targets": [ 0 ] }
12904		 *        ]
12905		 *      } );
12906		 *    } );
12907		 *
12908		 *  @example
12909		 *    // Using `columns`
12910		 *    $(document).ready( function() {
12911		 *      $('#example').dataTable( {
12912		 *        "columns": [
12913		 *          { "type": "html" },
12914		 *          null,
12915		 *          null,
12916		 *          null,
12917		 *          null
12918		 *        ]
12919		 *      } );
12920		 *    } );
12921		 */
12922		"sType": null,
12923	
12924	
12925		/**
12926		 * Defining the width of the column, this parameter may take any CSS value
12927		 * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not
12928		 * been given a specific width through this interface ensuring that the table
12929		 * remains readable.
12930		 *  @type string
12931		 *  @default null <i>Automatic</i>
12932		 *
12933		 *  @name DataTable.defaults.column.width
12934		 *  @dtopt Columns
12935		 *
12936		 *  @example
12937		 *    // Using `columnDefs`
12938		 *    $(document).ready( function() {
12939		 *      $('#example').dataTable( {
12940		 *        "columnDefs": [
12941		 *          { "width": "20%", "targets": [ 0 ] }
12942		 *        ]
12943		 *      } );
12944		 *    } );
12945		 *
12946		 *  @example
12947		 *    // Using `columns`
12948		 *    $(document).ready( function() {
12949		 *      $('#example').dataTable( {
12950		 *        "columns": [
12951		 *          { "width": "20%" },
12952		 *          null,
12953		 *          null,
12954		 *          null,
12955		 *          null
12956		 *        ]
12957		 *      } );
12958		 *    } );
12959		 */
12960		"sWidth": null
12961	};
12962	
12963	_fnHungarianMap( DataTable.defaults.column );
12964	
12965	
12966	
12967	/**
12968	 * DataTables settings object - this holds all the information needed for a
12969	 * given table, including configuration, data and current application of the
12970	 * table options. DataTables does not have a single instance for each DataTable
12971	 * with the settings attached to that instance, but rather instances of the
12972	 * DataTable "class" are created on-the-fly as needed (typically by a
12973	 * $().dataTable() call) and the settings object is then applied to that
12974	 * instance.
12975	 *
12976	 * Note that this object is related to {@link DataTable.defaults} but this
12977	 * one is the internal data store for DataTables's cache of columns. It should
12978	 * NOT be manipulated outside of DataTables. Any configuration should be done
12979	 * through the initialisation options.
12980	 *  @namespace
12981	 *  @todo Really should attach the settings object to individual instances so we
12982	 *    don't need to create new instances on each $().dataTable() call (if the
12983	 *    table already exists). It would also save passing oSettings around and
12984	 *    into every single function. However, this is a very significant
12985	 *    architecture change for DataTables and will almost certainly break
12986	 *    backwards compatibility with older installations. This is something that
12987	 *    will be done in 2.0.
12988	 */
12989	DataTable.models.oSettings = {
12990		/**
12991		 * Primary features of DataTables and their enablement state.
12992		 *  @namespace
12993		 */
12994		"oFeatures": {
12995	
12996			/**
12997			 * Flag to say if DataTables should automatically try to calculate the
12998			 * optimum table and columns widths (true) or not (false).
12999			 * Note that this parameter will be set by the initialisation routine. To
13000			 * set a default use {@link DataTable.defaults}.
13001			 *  @type boolean
13002			 */
13003			"bAutoWidth": null,
13004	
13005			/**
13006			 * Delay the creation of TR and TD elements until they are actually
13007			 * needed by a driven page draw. This can give a significant speed
13008			 * increase for Ajax source and Javascript source data, but makes no
13009			 * difference at all f
13009ro
vendor: 14,836 bytes, lines 13009-13586
13009 DOM and server-side processing tables.
13010			 * Note that this parameter will be set by the initialisation routine. To
13011			 * set a default use {@link DataTable.defaults}.
13012			 *  @type boolean
13013			 */
13014			"bDeferRender": null,
13015	
13016			/**
13017			 * Enable filtering on the table or not. Note that if this is disabled
13018			 * then there is no filtering at all on the table, including fnFilter.
13019			 * To just remove the filtering input use sDom and remove the 'f' option.
13020			 * Note that this parameter will be set by the initialisation routine. To
13021			 * set a default use {@link DataTable.defaults}.
13022			 *  @type boolean
13023			 */
13024			"bFilter": null,
13025	
13026			/**
13027			 * Table information element (the 'Showing x of y records' div) enable
13028			 * flag.
13029			 * Note that this parameter will be set by the initialisation routine. To
13030			 * set a default use {@link DataTable.defaults}.
13031			 *  @type boolean
13032			 */
13033			"bInfo": null,
13034	
13035			/**
13036			 * Present a user control allowing the end user to change the page size
13037			 * when pagination is enabled.
13038			 * Note that this parameter will be set by the initialisation routine. To
13039			 * set a default use {@link DataTable.defaults}.
13040			 *  @type boolean
13041			 */
13042			"bLengthChange": null,
13043	
13044			/**
13045			 * Pagination enabled or not. Note that if this is disabled then length
13046			 * changing must also be disabled.
13047			 * Note that this parameter will be set by the initialisation routine. To
13048			 * set a default use {@link DataTable.defaults}.
13049			 *  @type boolean
13050			 */
13051			"bPaginate": null,
13052	
13053			/**
13054			 * Processing indicator enable flag whenever DataTables is enacting a
13055			 * user request - typically an Ajax request for server-side processing.
13056			 * Note that this parameter will be set by the initialisation routine. To
13057			 * set a default use {@link DataTable.defaults}.
13058			 *  @type boolean
13059			 */
13060			"bProcessing": null,
13061	
13062			/**
13063			 * Server-side processing enabled flag - when enabled DataTables will
13064			 * get all data from the server for every draw - there is no filtering,
13065			 * sorting or paging done on the client-side.
13066			 * Note that this parameter will be set by the initialisation routine. To
13067			 * set a default use {@link DataTable.defaults}.
13068			 *  @type boolean
13069			 */
13070			"bServerSide": null,
13071	
13072			/**
13073			 * Sorting enablement flag.
13074			 * Note that this parameter will be set by the initialisation routine. To
13075			 * set a default use {@link DataTable.defaults}.
13076			 *  @type boolean
13077			 */
13078			"bSort": null,
13079	
13080			/**
13081			 * Multi-column sorting
13082			 * Note that this parameter will be set by the initialisation routine. To
13083			 * set a default use {@link DataTable.defaults}.
13084			 *  @type boolean
13085			 */
13086			"bSortMulti": null,
13087	
13088			/**
13089			 * Apply a class to the columns which are being sorted to provide a
13090			 * visual highlight or not. This can slow things down when enabled since
13091			 * there is a lot of DOM interaction.
13092			 * Note that this parameter will be set by the initialisation routine. To
13093			 * set a default use {@link DataTable.defaults}.
13094			 *  @type boolean
13095			 */
13096			"bSortClasses": null,
13097	
13098			/**
13099			 * State saving enablement flag.
13100			 * Note that this parameter will be set by the initialisation routine. To
13101			 * set a default use {@link DataTable.defaults}.
13102			 *  @type boolean
13103			 */
13104			"bStateSave": null
13105		},
13106	
13107	
13108		/**
13109		 * Scrolling settings for a table.
13110		 *  @namespace
13111		 */
13112		"oScroll": {
13113			/**
13114			 * When the table is shorter in height than sScrollY, collapse the
13115			 * table container down to the height of the table (when true).
13116			 * Note that this parameter will be set by the initialisation routine. To
13117			 * set a default use {@link DataTable.defaults}.
13118			 *  @type boolean
13119			 */
13120			"bCollapse": null,
13121	
13122			/**
13123			 * Width of the scrollbar for the web-browser's platform. Calculated
13124			 * during table initialisation.
13125			 *  @type int
13126			 *  @default 0
13127			 */
13128			"iBarWidth": 0,
13129	
13130			/**
13131			 * Viewport width for horizontal scrolling. Horizontal scrolling is
13132			 * disabled if an empty string.
13133			 * Note that this parameter will be set by the initialisation routine. To
13134			 * set a default use {@link DataTable.defaults}.
13135			 *  @type string
13136			 */
13137			"sX": null,
13138	
13139			/**
13140			 * Width to expand the table to when using x-scrolling. Typically you
13141			 * should not need to use this.
13142			 * Note that this parameter will be set by the initialisation routine. To
13143			 * set a default use {@link DataTable.defaults}.
13144			 *  @type string
13145			 *  @deprecated
13146			 */
13147			"sXInner": null,
13148	
13149			/**
13150			 * Viewport height for vertical scrolling. Vertical scrolling is disabled
13151			 * if an empty string.
13152			 * Note that this parameter will be set by the initialisation routine. To
13153			 * set a default use {@link DataTable.defaults}.
13154			 *  @type string
13155			 */
13156			"sY": null
13157		},
13158	
13159		/**
13160		 * Language information for the table.
13161		 *  @namespace
13162		 *  @extends DataTable.defaults.oLanguage
13163		 */
13164		"oLanguage": {
13165			/**
13166			 * Information callback function. See
13167			 * {@link DataTable.defaults.fnInfoCallback}
13168			 *  @type function
13169			 *  @default null
13170			 */
13171			"fnInfoCallback": null
13172		},
13173	
13174		/**
13175		 * Browser support parameters
13176		 *  @namespace
13177		 */
13178		"oBrowser": {
13179			/**
13180			 * Indicate if the browser incorrectly calculates width:100% inside a
13181			 * scrolling element (IE6/7)
13182			 *  @type boolean
13183			 *  @default false
13184			 */
13185			"bScrollOversize": false,
13186	
13187			/**
13188			 * Determine if the vertical scrollbar is on the right or left of the
13189			 * scrolling container - needed for rtl language layout, although not
13190			 * all browsers move the scrollbar (Safari).
13191			 *  @type boolean
13192			 *  @default false
13193			 */
13194			"bScrollbarLeft": false,
13195	
13196			/**
13197			 * Flag for if `getBoundingClientRect` is fully supported or not
13198			 *  @type boolean
13199			 *  @default false
13200			 */
13201			"bBounding": false,
13202	
13203			/**
13204			 * Browser scrollbar width
13205			 *  @type integer
13206			 *  @default 0
13207			 */
13208			"barWidth": 0
13209		},
13210	
13211	
13212		"ajax": null,
13213	
13214	
13215		/**
13216		 * Array referencing the nodes which are used for the features. The
13217		 * parameters of this object match what is allowed by sDom - i.e.
13218		 *   <ul>
13219		 *     <li>'l' - Length changing</li>
13220		 *     <li>'f' - Filtering input</li>
13221		 *     <li>'t' - The table!</li>
13222		 *     <li>'i' - Information</li>
13223		 *     <li>'p' - Pagination</li>
13224		 *     <li>'r' - pRocessing</li>
13225		 *   </ul>
13226		 *  @type array
13227		 *  @default []
13228		 */
13229		"aanFeatures": [],
13230	
13231		/**
13232		 * Store data information - see {@link DataTable.models.oRow} for detailed
13233		 * information.
13234		 *  @type array
13235		 *  @default []
13236		 */
13237		"aoData": [],
13238	
13239		/**
13240		 * Array of indexes which are in the current display (after filtering etc)
13241		 *  @type array
13242		 *  @default []
13243		 */
13244		"aiDisplay": [],
13245	
13246		/**
13247		 * Array of indexes for display - no filtering
13248		 *  @type array
13249		 *  @default []
13250		 */
13251		"aiDisplayMaster": [],
13252	
13253		/**
13254		 * Map of row ids to data indexes
13255		 *  @type object
13256		 *  @default {}
13257		 */
13258		"aIds": {},
13259	
13260		/**
13261		 * Store information about each column that is in use
13262		 *  @type array
13263		 *  @default []
13264		 */
13265		"aoColumns": [],
13266	
13267		/**
13268		 * Store information about the table's header
13269		 *  @type array
13270		 *  @default []
13271		 */
13272		"aoHeader": [],
13273	
13274		/**
13275		 * Store information about the table's footer
13276		 *  @type array
13277		 *  @default []
13278		 */
13279		"aoFooter": [],
13280	
13281		/**
13282		 * Store the applied global search information in case we want to force a
13283		 * research or compare the old search to a new one.
13284		 * Note that this parameter will be set by the initialisation routine. To
13285		 * set a default use {@link DataTable.defaults}.
13286		 *  @namespace
13287		 *  @extends DataTable.models.oSearch
13288		 */
13289		"oPreviousSearch": {},
13290	
13291		/**
13292		 * Store the applied search for each column - see
13293		 * {@link DataTable.models.oSearch} for the format that is used for the
13294		 * filtering information for each column.
13295		 *  @type array
13296		 *  @default []
13297		 */
13298		"aoPreSearchCols": [],
13299	
13300		/**
13301		 * Sorting that is applied to the table. Note that the inner arrays are
13302		 * used in the following manner:
13303		 * <ul>
13304		 *   <li>Index 0 - column number</li>
13305		 *   <li>Index 1 - current sorting direction</li>
13306		 * </ul>
13307		 * Note that this parameter will be set by the initialisation routine. To
13308		 * set a default use {@link DataTable.defaults}.
13309		 *  @type array
13310		 *  @todo These inner arrays should really be objects
13311		 */
13312		"aaSorting": null,
13313	
13314		/**
13315		 * Sorting that is always applied to the table (i.e. prefixed in front of
13316		 * aaSorting).
13317		 * Note that this parameter will be set by the initialisation routine. To
13318		 * set a default use {@link DataTable.defaults}.
13319		 *  @type array
13320		 *  @default []
13321		 */
13322		"aaSortingFixed": [],
13323	
13324		/**
13325		 * Classes to use for the striping of a table.
13326		 * Note that this parameter will be set by the initialisation routine. To
13327		 * set a default use {@link DataTable.defaults}.
13328		 *  @type array
13329		 *  @default []
13330		 */
13331		"asStripeClasses": null,
13332	
13333		/**
13334		 * If restoring a table - we should restore its striping classes as well
13335		 *  @type array
13336		 *  @default []
13337		 */
13338		"asDestroyStripes": [],
13339	
13340		/**
13341		 * If restoring a table - we should restore its width
13342		 *  @type int
13343		 *  @default 0
13344		 */
13345		"sDestroyWidth": 0,
13346	
13347		/**
13348		 * Callback functions array for every time a row is inserted (i.e. on a draw).
13349		 *  @type array
13350		 *  @default []
13351		 */
13352		"aoRowCallback": [],
13353	
13354		/**
13355		 * Callback functions for the header on each draw.
13356		 *  @type array
13357		 *  @default []
13358		 */
13359		"aoHeaderCallback": [],
13360	
13361		/**
13362		 * Callback function for the footer on each draw.
13363		 *  @type array
13364		 *  @default []
13365		 */
13366		"aoFooterCallback": [],
13367	
13368		/**
13369		 * Array of callback functions for draw callback functions
13370		 *  @type array
13371		 *  @default []
13372		 */
13373		"aoDrawCallback": [],
13374	
13375		/**
13376		 * Array of callback functions for row created function
13377		 *  @type array
13378		 *  @default []
13379		 */
13380		"aoRowCreatedCallback": [],
13381	
13382		/**
13383		 * Callback functions for just before the table is redrawn. A return of
13384		 * false will be used to cancel the draw.
13385		 *  @type array
13386		 *  @default []
13387		 */
13388		"aoPreDrawCallback": [],
13389	
13390		/**
13391		 * Callback functions for when the table has been initialised.
13392		 *  @type array
13393		 *  @default []
13394		 */
13395		"aoInitComplete": [],
13396	
13397	
13398		/**
13399		 * Callbacks for modifying the settings to be stored for state saving, prior to
13400		 * saving state.
13401		 *  @type array
13402		 *  @default []
13403		 */
13404		"aoStateSaveParams": [],
13405	
13406		/**
13407		 * Callbacks for modifying the settings that have been stored for state saving
13408		 * prior to using the stored values to restore the state.
13409		 *  @type array
13410		 *  @default []
13411		 */
13412		"aoStateLoadParams": [],
13413	
13414		/**
13415		 * Callbacks for operating on the settings object once the saved state has been
13416		 * loaded
13417		 *  @type array
13418		 *  @default []
13419		 */
13420		"aoStateLoaded": [],
13421	
13422		/**
13423		 * Cache the table ID for quick access
13424		 *  @type string
13425		 *  @default <i>Empty string</i>
13426		 */
13427		"sTableId": "",
13428	
13429		/**
13430		 * The TABLE node for the main table
13431		 *  @type node
13432		 *  @default null
13433		 */
13434		"nTable": null,
13435	
13436		/**
13437		 * Permanent ref to the thead element
13438		 *  @type node
13439		 *  @default null
13440		 */
13441		"nTHead": null,
13442	
13443		/**
13444		 * Permanent ref to the tfoot element - if it exists
13445		 *  @type node
13446		 *  @default null
13447		 */
13448		"nTFoot": null,
13449	
13450		/**
13451		 * Permanent ref to the tbody element
13452		 *  @type node
13453		 *  @default null
13454		 */
13455		"nTBody": null,
13456	
13457		/**
13458		 * Cache the wrapper node (contains all DataTables controlled elements)
13459		 *  @type node
13460		 *  @default null
13461		 */
13462		"nTableWrapper": null,
13463	
13464		/**
13465		 * Indicate if when using server-side processing the loading of data
13466		 * should be deferred until the second draw.
13467		 * Note that this parameter will be set by the initialisation routine. To
13468		 * set a default use {@link DataTable.defaults}.
13469		 *  @type boolean
13470		 *  @default false
13471		 */
13472		"bDeferLoading": false,
13473	
13474		/**
13475		 * Indicate if all required information has been read in
13476		 *  @type boolean
13477		 *  @default false
13478		 */
13479		"bInitialised": false,
13480	
13481		/**
13482		 * Information about open rows. Each object in the array has the parameters
13483		 * 'nTr' and 'nParent'
13484		 *  @type array
13485		 *  @default []
13486		 */
13487		"aoOpenRows": [],
13488	
13489		/**
13490		 * Dictate the positioning of DataTables' control elements - see
13491		 * {@link DataTable.model.oInit.sDom}.
13492		 * Note that this parameter will be set by the initialisation routine. To
13493		 * set a default use {@link DataTable.defaults}.
13494		 *  @type string
13495		 *  @default null
13496		 */
13497		"sDom": null,
13498	
13499		/**
13500		 * Search delay (in mS)
13501		 *  @type integer
13502		 *  @default null
13503		 */
13504		"searchDelay": null,
13505	
13506		/**
13507		 * Which type of pagination should be used.
13508		 * Note that this parameter will be set by the initialisation routine. To
13509		 * set a default use {@link DataTable.defaults}.
13510		 *  @type string
13511		 *  @default two_button
13512		 */
13513		"sPaginationType": "two_button",
13514	
13515		/**
13516		 * The state duration (for `stateSave`) in seconds.
13517		 * Note that this parameter will be set by the initialisation routine. To
13518		 * set a default use {@link DataTable.defaults}.
13519		 *  @type int
13520		 *  @default 0
13521		 */
13522		"iStateDuration": 0,
13523	
13524		/**
13525		 * Array of callback functions for state saving. Each array element is an
13526		 * object with the following parameters:
13527		 *   <ul>
13528		 *     <li>function:fn - function to call. Takes two parameters, oSettings
13529		 *       and the JSON string to save that has been thus far created. Returns
13530		 *       a JSON string to be inserted into a json object
13531		 *       (i.e. '"param": [ 0, 1, 2]')</li>
13532		 *     <li>string:sName - name of callback</li>
13533		 *   </ul>
13534		 *  @type array
13535		 *  @default []
13536		 */
13537		"aoStateSave": [],
13538	
13539		/**
13540		 * Array of callback functions for state loading. Each array element is an
13541		 * object with the following parameters:
13542		 *   <ul>
13543		 *     <li>function:fn - function to call. Takes two parameters, oSettings
13544		 *       and the object stored. May return false to cancel state loading</li>
13545		 *     <li>string:sName - name of callback</li>
13546		 *   </ul>
13547		 *  @type array
13548		 *  @default []
13549		 */
13550		"aoStateLoad": [],
13551	
13552		/**
13553		 * State that was saved. Useful for back reference
13554		 *  @type object
13555		 *  @default null
13556		 */
13557		"oSavedState": null,
13558	
13559		/**
13560		 * State that was loaded. Useful for back reference
13561		 *  @type object
13562		 *  @default null
13563		 */
13564		"oLoadedState": null,
13565	
13566		/**
13567		 * Source url for AJAX data for the table.
13568		 * Note that this parameter will be set by the initialisation routine. To
13569		 * set a default use {@link DataTable.defaults}.
13570		 *  @type string
13571		 *  @default null
13572		 */
13573		"sAjaxSource": null,
13574	
13575		/**
13576		 * Property from a given object from which to read the table data from. This
13577		 * can be an empty string (when not server-side processing), in which case
13578		 * it is  assumed an an array is given directly.
13579		 * Note that this parameter will be set by the initialisation routine. To
13580		 * set a default use {@link DataTable.defaults}.
13581		 *  @type string
13582		 */
13583		"sAjaxDataProp": null,
13584	
13585		/**
13586		 * 
13586Note if draw should be blocked while getting data
13587		 *  @type boolean
13588		 *  @default true
13589		 */
13590		"bAjaxDataGet": true,
13591	
13592		/**
13593		 * The last jQuery XHR object that was used for server-side data gathering.
13594		 * This can be used for working with the XHR information in one of the
13595		 * callbacks
13596		 *  @type object
13597		 *  @default null
13598		 */
13599		"jqXHR": null,
13600	
13601		/**
13602		 * JSON returned from the server in the last Ajax request
13603		 *  @type object
13604		 *  @default undefined
13605		 */
13606		"json": undefined,
13607	
13608		/**
13609		 * Data submitted as part of the last Ajax request
13610		 *  @type object
13611		 *  @default undefined
13612		 */
13613		"oAjaxData": undefined,
13614	
13615		/**
13616		 * Function to get the server-side data.
13617		 * Note that this parameter will be set by the initialisation routine. To
13618		 * set a default use {@link DataTable.defaults}.
13619		 *  @type function
13620		 */
13621		"fnServerData": null,
13622	
13623		/**
13624		 * Functions which are called prior to sending an Ajax request so extra
13625		 * parameters can easily be sent to the server
13626		 *  @type array
13627		 *  @default []
13628		 */
13629		"aoServerParams": [],
13630	
13631		/**
13632		 * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
13633		 * required).
13634		 * Note that this parameter will be set by the initialisation routine. To
13635		 * set a default use {@link DataTable.defaults}.
13636		 *  @type string
13637		 */
13638		"sServerMethod": null,
13639	
13640		/**
13641		 * Format numbers for display.
13642		 * Note that this parameter will be set by the initialisation routine. To
13643		 * set a default use {@link DataTable.defaults}.
13644		 *  @type function
13645		 */
13646		"fnFormatNumber": null,
13647	
13648		/**
13649		 * List of options that can be used for the user selectable length menu.
13650		 * Note that this parameter will be set by the initialisation routine. To
13651		 * set a default use {@link DataTable.defaults}.
13652		 *  @type array
13653		 *  @default []
13654		 */
13655		"aLengthMenu": null,
13656	
13657		/**
13658		 * Counter for the draws that the table does. Also used as a tracker for
13659		 * server-side processing
13660		 *  @type int
13661		 *  @default 0
13662		 */
13663		"iDraw": 0,
13664	
13665		/**
13666		 * Indicate if a redraw is being done - useful for Ajax
13667		 *  @type boolean
13668		 *  @default false
13669		 */
13670		"bDrawing": false,
13671	
13672		/**
13673		 * Draw index (iDraw) of the last error when parsing the returned data
13674		 *  @type int
13675		 *  @default -1
13676		 */
13677		"iDrawError": -1,
13678	
13679		/**
13680		 * Paging display length
13681		 *  @type int
13682		 *  @default 10
13683		 */
13684		"_iDisplayLength": 10,
13685	
13686		/**
13687		 * Paging start point - aiDisplay index
13688		 *  @type int
13689		 *  @default 0
13690		 */
13691		"_iDisplayStart": 0,
13692	
13693		/**
13694		 * Server-side processing - number of records in the result set
13695		 * (i.e. before filtering), Use fnRecordsTotal rather than
13696		 * this property to get the value of the number of records, regardless of
13697		 * the server-side processing setting.
13698		 *  @type int
13699		 *  @default 0
13700		 *  @private
13701		 */
13702		"_iRecordsTotal": 0,
13703	
13704		/**
13705		 * Server-side processing - number of records in the current display set
13706		 * (i.e. after filtering). Use fnRecordsDisplay rather than
13707		 * this property to get the value of the number of records, regardless of
13708		 * the server-side processing setting.
13709		 *  @type boolean
13710		 *  @default 0
13711		 *  @private
13712		 */
13713		"_iRecordsDisplay": 0,
13714	
13715		/**
13716		 * The classes to use for the table
13717		 *  @type object
13718		 *  @default {}
13719		 */
vendor: 3,548 bytes, lines 13720-13875
13720		"oClasses": {},
13721	
13722		/**
13723		 * Flag attached to the settings object so you can check in the draw
13724		 * callback if filtering has been done in the draw. Deprecated in favour of
13725		 * events.
13726		 *  @type boolean
13727		 *  @default false
13728		 *  @deprecated
13729		 */
13730		"bFiltered": false,
13731	
13732		/**
13733		 * Flag attached to the settings object so you can check in the draw
13734		 * callback if sorting has been done in the draw. Deprecated in favour of
13735		 * events.
13736		 *  @type boolean
13737		 *  @default false
13738		 *  @deprecated
13739		 */
13740		"bSorted": false,
13741	
13742		/**
13743		 * Indicate that if multiple rows are in the header and there is more than
13744		 * one unique cell per column, if the top one (true) or bottom one (false)
13745		 * should be used for sorting / title by DataTables.
13746		 * Note that this parameter will be set by the initialisation routine. To
13747		 * set a default use {@link DataTable.defaults}.
13748		 *  @type boolean
13749		 */
13750		"bSortCellsTop": null,
13751	
13752		/**
13753		 * Initialisation object that is used for the table
13754		 *  @type object
13755		 *  @default null
13756		 */
13757		"oInit": null,
13758	
13759		/**
13760		 * Destroy callback functions - for plug-ins to attach themselves to the
13761		 * destroy so they can clean up markup and events.
13762		 *  @type array
13763		 *  @default []
13764		 */
13765		"aoDestroyCallback": [],
13766	
13767	
13768		/**
13769		 * Get the number of records in the current record set, before filtering
13770		 *  @type function
13771		 */
13772		"fnRecordsTotal": function ()
13773		{
13774			return _fnDataSource( this ) == 'ssp' ?
13775				this._iRecordsTotal * 1 :
13776				this.aiDisplayMaster.length;
13777		},
13778	
13779		/**
13780		 * Get the number of records in the current record set, after filtering
13781		 *  @type function
13782		 */
13783		"fnRecordsDisplay": function ()
13784		{
13785			return _fnDataSource( this ) == 'ssp' ?
13786				this._iRecordsDisplay * 1 :
13787				this.aiDisplay.length;
13788		},
13789	
13790		/**
13791		 * Get the display end point - aiDisplay index
13792		 *  @type function
13793		 */
13794		"fnDisplayEnd": function ()
13795		{
13796			var
13797				len      = this._iDisplayLength,
13798				start    = this._iDisplayStart,
13799				calc     = start + len,
13800				records  = this.aiDisplay.length,
13801				features = this.oFeatures,
13802				paginate = features.bPaginate;
13803	
13804			if ( features.bServerSide ) {
13805				return paginate === false || len === -1 ?
13806					start + records :
13807					Math.min( start+len, this._iRecordsDisplay );
13808			}
13809			else {
13810				return ! paginate || calc>records || len===-1 ?
13811					records :
13812					calc;
13813			}
13814		},
13815	
13816		/**
13817		 * The DataTables object for this table
13818		 *  @type object
13819		 *  @default null
13820		 */
13821		"oInstance": null,
13822	
13823		/**
13824		 * Unique identifier for each instance of the DataTables object. If there
13825		 * is an ID on the table node, then it takes that value, otherwise an
13826		 * incrementing internal counter is used.
13827		 *  @type string
13828		 *  @default null
13829		 */
13830		"sInstance": null,
13831	
13832		/**
13833		 * tabindex attribute value that is added to DataTables control elements, allowing
13834		 * keyboard navigation of the table and its controls.
13835		 */
13836		"iTabIndex": 0,
13837	
13838		/**
13839		 * DIV container for the footer scrolling table if scrolling
13840		 */
13841		"nScrollHead": null,
13842	
13843		/**
13844		 * DIV container for the footer scrolling table if scrolling
13845		 */
13846		"nScrollFoot": null,
13847	
13848		/**
13849		 * Last applied sort
13850		 *  @type array
13851		 *  @default []
13852		 */
13853		"aLastSort": [],
13854	
13855		/**
13856		 * Stored plug-in instances
13857		 *  @type object
13858		 *  @default {}
13859		 */
13860		"oPlugins": {},
13861	
13862		/**
13863		 * Function used to get a row's id from the row's data
13864		 *  @type function
13865		 *  @default null
13866		 */
13867		"rowIdFn": null,
13868	
13869		/**
13870		 * Data location where to store a row's id
13871		 *  @type string
13872		 *  @default null
13873		 */
13874		"rowId": null
13875	};
vendor: 16,410 bytes, lines 13876-14374
13876
13877	/**
13878	 * Extension object for DataTables that is used to provide all extension
13879	 * options.
13880	 *
13881	 * Note that the `DataTable.ext` object is available through
13882	 * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is
13883	 * also aliased to `jQuery.fn.dataTableExt` for historic reasons.
13884	 *  @namespace
13885	 *  @extends DataTable.models.ext
13886	 */
13887	
13888	
13889	/**
13890	 * DataTables extensions
13891	 * 
13892	 * This namespace acts as a collection area for plug-ins that can be used to
13893	 * extend DataTables capabilities. Indeed many of the build in methods
13894	 * use this method to provide their own capabilities (sorting methods for
13895	 * example).
13896	 *
13897	 * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy
13898	 * reasons
13899	 *
13900	 *  @namespace
13901	 */
13902	DataTable.ext = _ext = {
13903		/**
13904		 * Buttons. For use with the Buttons extension for DataTables. This is
13905		 * defined here so other extensions can define buttons regardless of load
13906		 * order. It is _not_ used by DataTables core.
13907		 *
13908		 *  @type object
13909		 *  @default {}
13910		 */
13911		buttons: {},
13912	
13913	
13914		/**
13915		 * Element class names
13916		 *
13917		 *  @type object
13918		 *  @default {}
13919		 */
13920		classes: {},
13921	
13922	
13923		/**
13924		 * DataTables build type (expanded by the download builder)
13925		 *
13926		 *  @type string
13927		 */
13928		builder: "-source-",
13929	
13930	
13931		/**
13932		 * Error reporting.
13933		 * 
13934		 * How should DataTables report an error. Can take the value 'alert',
13935		 * 'throw', 'none' or a function.
13936		 *
13937		 *  @type string|function
13938		 *  @default alert
13939		 */
13940		errMode: "alert",
13941	
13942	
13943		/**
13944		 * Feature plug-ins.
13945		 * 
13946		 * This is an array of objects which describe the feature plug-ins that are
13947		 * available to DataTables. These feature plug-ins are then available for
13948		 * use through the `dom` initialisation option.
13949		 * 
13950		 * Each feature plug-in is described by an object which must have the
13951		 * following properties:
13952		 * 
13953		 * * `fnInit` - function that is used to initialise the plug-in,
13954		 * * `cFeature` - a character so the feature can be enabled by the `dom`
13955		 *   instillation option. This is case sensitive.
13956		 *
13957		 * The `fnInit` function has the following input parameters:
13958		 *
13959		 * 1. `{object}` DataTables settings object: see
13960		 *    {@link DataTable.models.oSettings}
13961		 *
13962		 * And the following return is expected:
13963		 * 
13964		 * * {node|null} The element which contains your feature. Note that the
13965		 *   return may also be void if your plug-in does not require to inject any
13966		 *   DOM elements into DataTables control (`dom`) - for example this might
13967		 *   be useful when developing a plug-in which allows table control via
13968		 *   keyboard entry
13969		 *
13970		 *  @type array
13971		 *
13972		 *  @example
13973		 *    $.fn.dataTable.ext.features.push( {
13974		 *      "fnInit": function( oSettings ) {
13975		 *        return new TableTools( { "oDTSettings": oSettings } );
13976		 *      },
13977		 *      "cFeature": "T"
13978		 *    } );
13979		 */
13980		feature: [],
13981	
13982	
13983		/**
13984		 * Row searching.
13985		 * 
13986		 * This method of searching is complimentary to the default type based
13987		 * searching, and a lot more comprehensive as it allows you complete control
13988		 * over the searching logic. Each element in this array is a function
13989		 * (parameters described below) that is called for every row in the table,
13990		 * and your logic decides if it should be included in the searching data set
13991		 * or not.
13992		 *
13993		 * Searching functions have the following input parameters:
13994		 *
13995		 * 1. `{object}` DataTables settings object: see
13996		 *    {@link DataTable.models.oSettings}
13997		 * 2. `{array|object}` Data for the row to be processed (same as the
13998		 *    original format that was passed in as the data source, or an array
13999		 *    from a DOM data source
14000		 * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which
14001		 *    can be useful to retrieve the `TR` element if you need DOM interaction.
14002		 *
14003		 * And the following return is expected:
14004		 *
14005		 * * {boolean} Include the row in the searched result set (true) or not
14006		 *   (false)
14007		 *
14008		 * Note that as with the main search ability in DataTables, technically this
14009		 * is "filtering", since it is subtractive. However, for consistency in
14010		 * naming we call it searching here.
14011		 *
14012		 *  @type array
14013		 *  @default []
14014		 *
14015		 *  @example
14016		 *    // The following example shows custom search being applied to the
14017		 *    // fourth column (i.e. the data[3] index) based on two input values
14018		 *    // from the end-user, matching the data in a certain range.
14019		 *    $.fn.dataTable.ext.search.push(
14020		 *      function( settings, data, dataIndex ) {
14021		 *        var min = document.getElementById('min').value * 1;
14022		 *        var max = document.getElementById('max').value * 1;
14023		 *        var version = data[3] == "-" ? 0 : data[3]*1;
14024		 *
14025		 *        if ( min == "" && max == "" ) {
14026		 *          return true;
14027		 *        }
14028		 *        else if ( min == "" && version < max ) {
14029		 *          return true;
14030		 *        }
14031		 *        else if ( min < version && "" == max ) {
14032		 *          return true;
14033		 *        }
14034		 *        else if ( min < version && version < max ) {
14035		 *          return true;
14036		 *        }
14037		 *        return false;
14038		 *      }
14039		 *    );
14040		 */
14041		search: [],
14042	
14043	
14044		/**
14045		 * Selector extensions
14046		 *
14047		 * The `selector` option can be used to extend the options available for the
14048		 * selector modifier options (`selector-modifier` object data type) that
14049		 * each of the three built in selector types offer (row, column and cell +
14050		 * their plural counterparts). For example the Select extension uses this
14051		 * mechanism to provide an option to select only rows, columns and cells
14052		 * that have been marked as selected by the end user (`{selected: true}`),
14053		 * which can be used in conjunction with the existing built in selector
14054		 * options.
14055		 *
14056		 * Each property is an array to which functions can be pushed. The functions
14057		 * take three attributes:
14058		 *
14059		 * * Settings object for the host table
14060		 * * Options object (`selector-modifier` object type)
14061		 * * Array of selected item indexes
14062		 *
14063		 * The return is an array of the resulting item indexes after the custom
14064		 * selector has been applied.
14065		 *
14066		 *  @type object
14067		 */
14068		selector: {
14069			cell: [],
14070			column: [],
14071			row: []
14072		},
14073	
14074	
14075		/**
14076		 * Internal functions, exposed for used in plug-ins.
14077		 * 
14078		 * Please note that you should not need to use the internal methods for
14079		 * anything other than a plug-in (and even then, try to avoid if possible).
14080		 * The internal function may change between releases.
14081		 *
14082		 *  @type object
14083		 *  @default {}
14084		 */
14085		internal: {},
14086	
14087	
14088		/**
14089		 * Legacy configuration options. Enable and disable legacy options that
14090		 * are available in DataTables.
14091		 *
14092		 *  @type object
14093		 */
14094		legacy: {
14095			/**
14096			 * Enable / disable DataTables 1.9 compatible server-side processing
14097			 * requests
14098			 *
14099			 *  @type boolean
14100			 *  @default null
14101			 */
14102			ajax: null
14103		},
14104	
14105	
14106		/**
14107		 * Pagination plug-in methods.
14108		 * 
14109		 * Each entry in this object is a function and defines which buttons should
14110		 * be shown by the pagination rendering method that is used for the table:
14111		 * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the
14112		 * buttons are displayed in the document, while the functions here tell it
14113		 * what buttons to display. This is done by returning an array of button
14114		 * descriptions (what each button will do).
14115		 *
14116		 * Pagination types (the four built in options and any additional plug-in
14117		 * options defined here) can be used through the `paginationType`
14118		 * initialisation parameter.
14119		 *
14120		 * The functions defined take two parameters:
14121		 *
14122		 * 1. `{int} page` The current page index
14123		 * 2. `{int} pages` The number of pages in the table
14124		 *
14125		 * Each function is expected to return an array where each element of the
14126		 * array can be one of:
14127		 *
14128		 * * `first` - Jump to first page when activated
14129		 * * `last` - Jump to last page when activated
14130		 * * `previous` - Show previous page when activated
14131		 * * `next` - Show next page when activated
14132		 * * `{int}` - Show page of the index given
14133		 * * `{array}` - A nested array containing the above elements to add a
14134		 *   containing 'DIV' element (might be useful for styling).
14135		 *
14136		 * Note that DataTables v1.9- used this object slightly differently whereby
14137		 * an object with two functions would be defined for each plug-in. That
14138		 * ability is still supported by DataTables 1.10+ to provide backwards
14139		 * compatibility, but this option of use is now decremented and no longer
14140		 * documented in DataTables 1.10+.
14141		 *
14142		 *  @type object
14143		 *  @default {}
14144		 *
14145		 *  @example
14146		 *    // Show previous, next and current page buttons only
14147		 *    $.fn.dataTableExt.oPagination.current = function ( page, pages ) {
14148		 *      return [ 'previous', page, 'next' ];
14149		 *    };
14150		 */
14151		pager: {},
14152	
14153	
14154		renderer: {
14155			pageButton: {},
14156			header: {}
14157		},
14158	
14159	
14160		/**
14161		 * Ordering plug-ins - custom data source
14162		 * 
14163		 * The extension options for ordering of data available here is complimentary
14164		 * to the default type based ordering that DataTables typically uses. It
14165		 * allows much greater control over the the data that is being used to
14166		 * order a column, but is necessarily therefore more complex.
14167		 * 
14168		 * This type of ordering is useful if you want to do ordering based on data
14169		 * live from the DOM (for example the contents of an 'input' element) rather
14170		 * than just the static string that DataTables knows of.
14171		 * 
14172		 * The way these plug-ins work is that you create an array of the values you
14173		 * wish to be ordering for the column in question and then return that
14174		 * array. The data in the array much be in the index order of the rows in
14175		 * the table (not the currently ordering order!). Which order data gathering
14176		 * function is run here depends on the `dt-init columns.orderDataType`
14177		 * parameter that is used for the column (if any).
14178		 *
14179		 * The functions defined take two parameters:
14180		 *
14181		 * 1. `{object}` DataTables settings object: see
14182		 *    {@link DataTable.models.oSettings}
14183		 * 2. `{int}` Target column index
14184		 *
14185		 * Each function is expected to return an array:
14186		 *
14187		 * * `{array}` Data for the column to be ordering upon
14188		 *
14189		 *  @type array
14190		 *
14191		 *  @example
14192		 *    // Ordering using `input` node values
14193		 *    $.fn.dataTable.ext.order['dom-text'] = function  ( settings, col )
14194		 *    {
14195		 *      return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
14196		 *        return $('input', td).val();
14197		 *      } );
14198		 *    }
14199		 */
14200		order: {},
14201	
14202	
14203		/**
14204		 * Type based plug-ins.
14205		 *
14206		 * Each column in DataTables has a type assigned to it, either by automatic
14207		 * detection or by direct assignment using the `type` option for the column.
14208		 * The type of a column will effect how it is ordering and search (plug-ins
14209		 * can also make use of the column type if required).
14210		 *
14211		 * @namespace
14212		 */
14213		type: {
14214			/**
14215			 * Type detection functions.
14216			 *
14217			 * The functions defined in this object are used to automatically detect
14218			 * a column's type, making initialisation of DataTables super easy, even
14219			 * when complex data is in the table.
14220			 *
14221			 * The functions defined take two parameters:
14222			 *
14223		     *  1. `{*}` Data from the column cell to be analysed
14224		     *  2. `{settings}` DataTables settings object. This can be used to
14225		     *     perform context specific type detection - for example detection
14226		     *     based on language settings such as using a comma for a decimal
14227		     *     place. Generally speaking the options from the settings will not
14228		     *     be required
14229			 *
14230			 * Each function is expected to return:
14231			 *
14232			 * * `{string|null}` Data type detected, or null if unknown (and thus
14233			 *   pass it on to the other type detection functions.
14234			 *
14235			 *  @type array
14236			 *
14237			 *  @example
14238			 *    // Currency type detection plug-in:
14239			 *    $.fn.dataTable.ext.type.detect.push(
14240			 *      function ( data, settings ) {
14241			 *        // Check the numeric part
14242			 *        if ( ! data.substring(1).match(/[0-9]/) ) {
14243			 *          return null;
14244			 *        }
14245			 *
14246			 *        // Check prefixed by currency
14247			 *        if ( data.charAt(0) == '$' || data.charAt(0) == '&pound;' ) {
14248			 *          return 'currency';
14249			 *        }
14250			 *        return null;
14251			 *      }
14252			 *    );
14253			 */
14254			detect: [],
14255	
14256	
14257			/**
14258			 * Type based search formatting.
14259			 *
14260			 * The type based searching functions can be used to pre-format the
14261			 * data to be search on. For example, it can be used to strip HTML
14262			 * tags or to de-format telephone numbers for numeric only searching.
14263			 *
14264			 * Note that is a search is not defined for a column of a given type,
14265			 * no search formatting will be performed.
14266			 * 
14267			 * Pre-processing of searching data plug-ins - When you assign the sType
14268			 * for a column (or have it automatically detected for you by DataTables
14269			 * or a type detection plug-in), you will typically be using this for
14270			 * custom sorting, but it can also be used to provide custom searching
14271			 * by allowing you to pre-processing the data and returning the data in
14272			 * the format that should be searched upon. This is done by adding
14273			 * functions this object with a parameter name which matches the sType
14274			 * for that target column. This is the corollary of <i>afnSortData</i>
14275			 * for searching data.
14276			 *
14277			 * The functions defined take a single parameter:
14278			 *
14279		     *  1. `{*}` Data from the column cell to be prepared for searching
14280			 *
14281			 * Each function is expected to return:
14282			 *
14283			 * * `{string|null}` Formatted string that will be used for the searching.
14284			 *
14285			 *  @type object
14286			 *  @default {}
14287			 *
14288			 *  @example
14289			 *    $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) {
14290			 *      return d.replace(/\n/g," ").replace( /<.*?>/g, "" );
14291			 *    }
14292			 */
14293			search: {},
14294	
14295	
14296			/**
14297			 * Type based ordering.
14298			 *
14299			 * The column type tells DataTables what ordering to apply to the table
14300			 * when a column is sorted upon. The order for each type that is defined,
14301			 * is defined by the functions available in this object.
14302			 *
14303			 * Each ordering option can be described by three properties added to
14304			 * this object:
14305			 *
14306			 * * `{type}-pre` - Pre-formatting function
14307			 * * `{type}-asc` - Ascending order function
14308			 * * `{type}-desc` - Descending order function
14309			 *
14310			 * All three can be used together, only `{type}-pre` or only
14311			 * `{type}-asc` and `{type}-desc` together. It is generally recommended
14312			 * that only `{type}-pre` is used, as this provides the optimal
14313			 * implementation in terms of speed, although the others are provided
14314			 * for compatibility with existing Javascript sort functions.
14315			 *
14316			 * `{type}-pre`: Functions defined take a single parameter:
14317			 *
14318		     *  1. `{*}` Data from the column cell to be prepared for ordering
14319			 *
14320			 * And return:
14321			 *
14322			 * * `{*}` Data to be sorted upon
14323			 *
14324			 * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort
14325			 * functions, taking two parameters:
14326			 *
14327		     *  1. `{*}` Data to compare to the second parameter
14328		     *  2. `{*}` Data to compare to the first parameter
14329			 *
14330			 * And returning:
14331			 *
14332			 * * `{*}` Ordering match: <0 if first parameter should be sorted lower
14333			 *   than the second parameter, ===0 if the two parameters are equal and
14334			 *   >0 if the first parameter should be sorted height than the second
14335			 *   parameter.
14336			 * 
14337			 *  @type object
14338			 *  @default {}
14339			 *
14340			 *  @example
14341			 *    // Numeric ordering of formatted numbers with a pre-formatter
14342			 *    $.extend( $.fn.dataTable.ext.type.order, {
14343			 *      "string-pre": function(x) {
14344			 *        a = (a === "-" || a === "") ? 0 : a.replace( /[^\d\-\.]/g, "" );
14345			 *        return parseFloat( a );
14346			 *      }
14347			 *    } );
14348			 *
14349			 *  @example
14350			 *    // Case-sensitive string ordering, with no pre-formatting method
14351			 *    $.extend( $.fn.dataTable.ext.order, {
14352			 *      "string-case-asc": function(x,y) {
14353			 *        return ((x < y) ? -1 : ((x > y) ? 1 : 0));
14354			 *      },
14355			 *      "string-case-desc": function(x,y) {
14356			 *        return ((x < y) ? 1 : ((x > y) ? -1 : 0));
14357			 *      }
14358			 *    } );
14359			 */
14360			order: {}
14361		},
14362	
14363		/**
14364		 * Unique DataTables instance counter
14365		 *
14366		 * @type int
14367		 * @private
14368		 */
14369		_unique: 0,
14370	
14371	
14372		//
14373		// Depreciated
14374		// The following properties are retained for backwards compatib
vendor: 25,973 bytes, lines 14374-15289
14374lity only.
14375		// The should not be used in new projects and will be removed in a future
14376		// version
14377		//
14378	
14379		/**
14380		 * Version check function.
14381		 *  @type function
14382		 *  @depreciated Since 1.10
14383		 */
14384		fnVersionCheck: DataTable.fnVersionCheck,
14385	
14386	
14387		/**
14388		 * Index for what 'this' index API functions should use
14389		 *  @type int
14390		 *  @deprecated Since v1.10
14391		 */
14392		iApiIndex: 0,
14393	
14394	
14395		/**
14396		 * jQuery UI class container
14397		 *  @type object
14398		 *  @deprecated Since v1.10
14399		 */
14400		oJUIClasses: {},
14401	
14402	
14403		/**
14404		 * Software version
14405		 *  @type string
14406		 *  @deprecated Since v1.10
14407		 */
14408		sVersion: DataTable.version
14409	};
14410	
14411	
14412	//
14413	// Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts
14414	//
14415	$.extend( _ext, {
14416		afnFiltering: _ext.search,
14417		aTypes:       _ext.type.detect,
14418		ofnSearch:    _ext.type.search,
14419		oSort:        _ext.type.order,
14420		afnSortData:  _ext.order,
14421		aoFeatures:   _ext.feature,
14422		oApi:         _ext.internal,
14423		oStdClasses:  _ext.classes,
14424		oPagination:  _ext.pager
14425	} );
14426	
14427	
14428	$.extend( DataTable.ext.classes, {
14429		"sTable": "dataTable",
14430		"sNoFooter": "no-footer",
14431	
14432		/* Paging buttons */
14433		"sPageButton": "paginate_button",
14434		"sPageButtonActive": "current",
14435		"sPageButtonDisabled": "disabled",
14436	
14437		/* Striping classes */
14438		"sStripeOdd": "odd",
14439		"sStripeEven": "even",
14440	
14441		/* Empty row */
14442		"sRowEmpty": "dataTables_empty",
14443	
14444		/* Features */
14445		"sWrapper": "dataTables_wrapper",
14446		"sFilter": "dataTables_filter",
14447		"sInfo": "dataTables_info",
14448		"sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
14449		"sLength": "dataTables_length",
14450		"sProcessing": "dataTables_processing",
14451	
14452		/* Sorting */
14453		"sSortAsc": "sorting_asc",
14454		"sSortDesc": "sorting_desc",
14455		"sSortable": "sorting", /* Sortable in both directions */
14456		"sSortableAsc": "sorting_asc_disabled",
14457		"sSortableDesc": "sorting_desc_disabled",
14458		"sSortableNone": "sorting_disabled",
14459		"sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
14460	
14461		/* Filtering */
14462		"sFilterInput": "",
14463	
14464		/* Page length */
14465		"sLengthSelect": "",
14466	
14467		/* Scrolling */
14468		"sScrollWrapper": "dataTables_scroll",
14469		"sScrollHead": "dataTables_scrollHead",
14470		"sScrollHeadInner": "dataTables_scrollHeadInner",
14471		"sScrollBody": "dataTables_scrollBody",
14472		"sScrollFoot": "dataTables_scrollFoot",
14473		"sScrollFootInner": "dataTables_scrollFootInner",
14474	
14475		/* Misc */
14476		"sHeaderTH": "",
14477		"sFooterTH": "",
14478	
14479		// Deprecated
14480		"sSortJUIAsc": "",
14481		"sSortJUIDesc": "",
14482		"sSortJUI": "",
14483		"sSortJUIAscAllowed": "",
14484		"sSortJUIDescAllowed": "",
14485		"sSortJUIWrapper": "",
14486		"sSortIcon": "",
14487		"sJUIHeader": "",
14488		"sJUIFooter": ""
14489	} );
14490	
14491	
14492	var extPagination = DataTable.ext.pager;
14493	
14494	function _numbers ( page, pages ) {
14495		var
14496			numbers = [],
14497			buttons = extPagination.numbers_length,
14498			half = Math.floor( buttons / 2 ),
14499			i = 1;
14500	
14501		if ( pages <= buttons ) {
14502			numbers = _range( 0, pages );
14503		}
14504		else if ( page <= half ) {
14505			numbers = _range( 0, buttons-2 );
14506			numbers.push( 'ellipsis' );
14507			numbers.push( pages-1 );
14508		}
14509		else if ( page >= pages - 1 - half ) {
14510			numbers = _range( pages-(buttons-2), pages );
14511			numbers.splice( 0, 0, 'ellipsis' ); // no unshift in ie6
14512			numbers.splice( 0, 0, 0 );
14513		}
14514		else {
14515			numbers = _range( page-half+2, page+half-1 );
14516			numbers.push( 'ellipsis' );
14517			numbers.push( pages-1 );
14518			numbers.splice( 0, 0, 'ellipsis' );
14519			numbers.splice( 0, 0, 0 );
14520		}
14521	
14522		numbers.DT_el = 'span';
14523		return numbers;
14524	}
14525	
14526	
14527	$.extend( extPagination, {
14528		simple: function ( page, pages ) {
14529			return [ 'previous', 'next' ];
14530		},
14531	
14532		full: function ( page, pages ) {
14533			return [  'first', 'previous', 'next', 'last' ];
14534		},
14535	
14536		numbers: function ( page, pages ) {
14537			return [ _numbers(page, pages) ];
14538		},
14539	
14540		simple_numbers: function ( page, pages ) {
14541			return [ 'previous', _numbers(page, pages), 'next' ];
14542		},
14543	
14544		full_numbers: function ( page, pages ) {
14545			return [ 'first', 'previous', _numbers(page, pages), 'next', 'last' ];
14546		},
14547		
14548		first_last_numbers: function (page, pages) {
14549	 		return ['first', _numbers(page, pages), 'last'];
14550	 	},
14551	
14552		// For testing and plug-ins to use
14553		_numbers: _numbers,
14554	
14555		// Number of number buttons (including ellipsis) to show. _Must be odd!_
14556		numbers_length: 7
14557	} );
14558	
14559	
14560	$.extend( true, DataTable.ext.renderer, {
14561		pageButton: {
14562			_: function ( settings, host, idx, buttons, page, pages ) {
14563				var classes = settings.oClasses;
14564				var lang = settings.oLanguage.oPaginate;
14565				var aria = settings.oLanguage.oAria.paginate || {};
14566				var btnDisplay, btnClass, counter=0;
14567	
14568				var attach = function( container, buttons ) {
14569					var i, ien, node, button, tabIndex;
14570					var disabledClass = classes.sPageButtonDisabled;
14571					var clickHandler = function ( e ) {
14572						_fnPageChange( settings, e.data.action, true );
14573					};
14574	
14575					for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
14576						button = buttons[i];
14577	
14578						if ( $.isArray( button ) ) {
14579							var inner = $( '<'+(button.DT_el || 'div')+'/>' )
14580								.appendTo( container );
14581							attach( inner, button );
14582						}
14583						else {
14584							btnDisplay = null;
14585							btnClass = button;
14586							tabIndex = settings.iTabIndex;
14587	
14588							switch ( button ) {
14589								case 'ellipsis':
14590									container.append('<span class="ellipsis">&#x2026;</span>');
14591									break;
14592	
14593								case 'first':
14594									btnDisplay = lang.sFirst;
14595	
14596									if ( page === 0 ) {
14597										tabIndex = -1;
14598										btnClass += ' ' + disabledClass;
14599									}
14600									break;
14601	
14602								case 'previous':
14603									btnDisplay = lang.sPrevious;
14604	
14605									if ( page === 0 ) {
14606										tabIndex = -1;
14607										btnClass += ' ' + disabledClass;
14608									}
14609									break;
14610	
14611								case 'next':
14612									btnDisplay = lang.sNext;
14613	
14614									if ( pages === 0 || page === pages-1 ) {
14615										tabIndex = -1;
14616										btnClass += ' ' + disabledClass;
14617									}
14618									break;
14619	
14620								case 'last':
14621									btnDisplay = lang.sLast;
14622	
14623									if ( page === pages-1 ) {
14624										tabIndex = -1;
14625										btnClass += ' ' + disabledClass;
14626									}
14627									break;
14628	
14629								default:
14630									btnDisplay = button + 1;
14631									btnClass = page === button ?
14632										classes.sPageButtonActive : '';
14633									break;
14634							}
14635	
14636							if ( btnDisplay !== null ) {
14637								node = $('<a>', {
14638										'class': classes.sPageButton+' '+btnClass,
14639										'aria-controls': settings.sTableId,
14640										'aria-label': aria[ button ],
14641										'data-dt-idx': counter,
14642										'tabindex': tabIndex,
14643										'id': idx === 0 && typeof button === 'string' ?
14644											settings.sTableId +'_'+ button :
14645											null
14646									} )
14647									.html( btnDisplay )
14648									.appendTo( container );
14649	
14650								_fnBindAction(
14651									node, {action: button}, clickHandler
14652								);
14653	
14654								counter++;
14655							}
14656						}
14657					}
14658				};
14659	
14660				// IE9 throws an 'unknown error' if document.activeElement is used
14661				// inside an iframe or frame. Try / catch the error. Not good for
14662				// accessibility, but neither are frames.
14663				var activeEl;
14664	
14665				try {
14666					// Because this approach is destroying and recreating the paging
14667					// elements, focus is lost on the select button which is bad for
14668					// accessibility. So we want to restore focus once the draw has
14669					// completed
14670					activeEl = $(host).find(document.activeElement).data('dt-idx');
14671				}
14672				catch (e) {}
14673	
14674				attach( $(host).empty(), buttons );
14675	
14676				if ( activeEl !== undefined ) {
14677					$(host).find( '[data-dt-idx='+activeEl+']' ).trigger('focus');
14678				}
14679			}
14680		}
14681	} );
14682	
14683	
14684	
14685	// Built in type detection. See model.ext.aTypes for information about
14686	// what is required from this methods.
14687	$.extend( DataTable.ext.type.detect, [
14688		// Plain numbers - first since V8 detects some plain numbers as dates
14689		// e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...).
14690		function ( d, settings )
14691		{
14692			var decimal = settings.oLanguage.sDecimal;
14693			return _isNumber( d, decimal ) ? 'num'+decimal : null;
14694		},
14695	
14696		// Dates (only those recognised by the browser's Date.parse)
14697		function ( d, settings )
14698		{
14699			// V8 tries _very_ hard to make a string passed into `Date.parse()`
14700			// valid, so we need to use a regex to restrict date formats. Use a
14701			// plug-in for anything other than ISO8601 style strings
14702			if ( d && !(d instanceof Date) && ! _re_date.test(d) ) {
14703				return null;
14704			}
14705			var parsed = Date.parse(d);
14706			return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null;
14707		},
14708	
14709		// Formatted numbers
14710		function ( d, settings )
14711		{
14712			var decimal = settings.oLanguage.sDecimal;
14713			return _isNumber( d, decimal, true ) ? 'num-fmt'+decimal : null;
14714		},
14715	
14716		// HTML numeric
14717		function ( d, settings )
14718		{
14719			var decimal = settings.oLanguage.sDecimal;
14720			return _htmlNumeric( d, decimal ) ? 'html-num'+decimal : null;
14721		},
14722	
14723		// HTML numeric, formatted
14724		function ( d, settings )
14725		{
14726			var decimal = settings.oLanguage.sDecimal;
14727			return _htmlNumeric( d, decimal, true ) ? 'html-num-fmt'+decimal : null;
14728		},
14729	
14730		// HTML (this is strict checking - there must be html)
14731		function ( d, settings )
14732		{
14733			return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ?
14734				'html' : null;
14735		}
14736	] );
14737	
14738	
14739	
14740	// Filter formatting functions. See model.ext.ofnSearch for information about
14741	// what is required from these methods.
14742	// 
14743	// Note that additional search methods are added for the html numbers and
14744	// html formatted numbers by `_addNumericSort()` when we know what the decimal
14745	// place is
14746	
14747	
14748	$.extend( DataTable.ext.type.search, {
14749		html: function ( data ) {
14750			return _empty(data) ?
14751				data :
14752				typeof data === 'string' ?
14753					data
14754						.replace( _re_new_lines, " " )
14755						.replace( _re_html, "" ) :
14756					'';
14757		},
14758	
14759		string: function ( data ) {
14760			return _empty(data) ?
14761				data :
14762				typeof data === 'string' ?
14763					data.replace( _re_new_lines, " " ) :
14764					data;
14765		}
14766	} );
14767	
14768	
14769	
14770	var __numericReplace = function ( d, decimalPlace, re1, re2 ) {
14771		if ( d !== 0 && (!d || d === '-') ) {
14772			return -Infinity;
14773		}
14774	
14775		// If a decimal place other than `.` is used, it needs to be given to the
14776		// function so we can detect it and replace with a `.` which is the only
14777		// decimal place Javascript recognises - it is not locale aware.
14778		if ( decimalPlace ) {
14779			d = _numToDecimal( d, decimalPlace );
14780		}
14781	
14782		if ( d.replace ) {
14783			if ( re1 ) {
14784				d = d.replace( re1, '' );
14785			}
14786	
14787			if ( re2 ) {
14788				d = d.replace( re2, '' );
14789			}
14790		}
14791	
14792		return d * 1;
14793	};
14794	
14795	
14796	// Add the numeric 'deformatting' functions for sorting and search. This is done
14797	// in a function to provide an easy ability for the language options to add
14798	// additional methods if a non-period decimal place is used.
14799	function _addNumericSort ( decimalPlace ) {
14800		$.each(
14801			{
14802				// Plain numbers
14803				"num": function ( d ) {
14804					return __numericReplace( d, decimalPlace );
14805				},
14806	
14807				// Formatted numbers
14808				"num-fmt": function ( d ) {
14809					return __numericReplace( d, decimalPlace, _re_formatted_numeric );
14810				},
14811	
14812				// HTML numeric
14813				"html-num": function ( d ) {
14814					return __numericReplace( d, decimalPlace, _re_html );
14815				},
14816	
14817				// HTML numeric, formatted
14818				"html-num-fmt": function ( d ) {
14819					return __numericReplace( d, decimalPlace, _re_html, _re_formatted_numeric );
14820				}
14821			},
14822			function ( key, fn ) {
14823				// Add the ordering method
14824				_ext.type.order[ key+decimalPlace+'-pre' ] = fn;
14825	
14826				// For HTML types add a search formatter that will strip the HTML
14827				if ( key.match(/^html\-/) ) {
14828					_ext.type.search[ key+decimalPlace ] = _ext.type.search.html;
14829				}
14830			}
14831		);
14832	}
14833	
14834	
14835	// Default sort methods
14836	$.extend( _ext.type.order, {
14837		// Dates
14838		"date-pre": function ( d ) {
14839			var ts = Date.parse( d );
14840			return isNaN(ts) ? -Infinity : ts;
14841		},
14842	
14843		// html
14844		"html-pre": function ( a ) {
14845			return _empty(a) ?
14846				'' :
14847				a.replace ?
14848					a.replace( /<.*?>/g, "" ).toLowerCase() :
14849					a+'';
14850		},
14851	
14852		// string
14853		"string-pre": function ( a ) {
14854			// This is a little complex, but faster than always calling toString,
14855			// http://jsperf.com/tostring-v-check
14856			return _empty(a) ?
14857				'' :
14858				typeof a === 'string' ?
14859					a.toLowerCase() :
14860					! a.toString ?
14861						'' :
14862						a.toString();
14863		},
14864	
14865		// string-asc and -desc are retained only for compatibility with the old
14866		// sort methods
14867		"string-asc": function ( x, y ) {
14868			return ((x < y) ? -1 : ((x > y) ? 1 : 0));
14869		},
14870	
14871		"string-desc": function ( x, y ) {
14872			return ((x < y) ? 1 : ((x > y) ? -1 : 0));
14873		}
14874	} );
14875	
14876	
14877	// Numeric sorting types - order doesn't matter here
14878	_addNumericSort( '' );
14879	
14880	
14881	$.extend( true, DataTable.ext.renderer, {
14882		header: {
14883			_: function ( settings, cell, column, classes ) {
14884				// No additional mark-up required
14885				// Attach a sort listener to update on sort - note that using the
14886				// `DT` namespace will allow the event to be removed automatically
14887				// on destroy, while the `dt` namespaced event is the one we are
14888				// listening for
14889				$(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
14890					if ( settings !== ctx ) { // need to check this this is the host
14891						return;               // table, not a nested one
14892					}
14893	
14894					var colIdx = column.idx;
14895	
14896					cell
14897						.removeClass(
14898							column.sSortingClass +' '+
14899							classes.sSortAsc +' '+
14900							classes.sSortDesc
14901						)
14902						.addClass( columns[ colIdx ] == 'asc' ?
14903							classes.sSortAsc : columns[ colIdx ] == 'desc' ?
14904								classes.sSortDesc :
14905								column.sSortingClass
14906						);
14907				} );
14908			},
14909	
14910			jqueryui: function ( settings, cell, column, classes ) {
14911				$('<div/>')
14912					.addClass( classes.sSortJUIWrapper )
14913					.append( cell.contents() )
14914					.append( $('<span/>')
14915						.addClass( classes.sSortIcon+' '+column.sSortingClassJUI )
14916					)
14917					.appendTo( cell );
14918	
14919				// Attach a sort listener to update on sort
14920				$(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
14921					if ( settings !== ctx ) {
14922						return;
14923					}
14924	
14925					var colIdx = column.idx;
14926	
14927					cell
14928						.removeClass( classes.sSortAsc +" "+classes.sSortDesc )
14929						.addClass( columns[ colIdx ] == 'asc' ?
14930							classes.sSortAsc : columns[ colIdx ] == 'desc' ?
14931								classes.sSortDesc :
14932								column.sSortingClass
14933						);
14934	
14935					cell
14936						.find( 'span.'+classes.sSortIcon )
14937						.removeClass(
14938							classes.sSortJUIAsc +" "+
14939							classes.sSortJUIDesc +" "+
14940							classes.sSortJUI +" "+
14941							classes.sSortJUIAscAllowed +" "+
14942							classes.sSortJUIDescAllowed
14943						)
14944						.addClass( columns[ colIdx ] == 'asc' ?
14945							classes.sSortJUIAsc : columns[ colIdx ] == 'desc' ?
14946								classes.sSortJUIDesc :
14947								column.sSortingClassJUI
14948						);
14949				} );
14950			}
14951		}
14952	} );
14953	
14954	/*
14955	 * Public helper functions. These aren't used internally by DataTables, or
14956	 * called by any of the options passed into DataTables, but they can be used
14957	 * externally by developers working with DataTables. They are helper functions
14958	 * to make working with DataTables a little bit easier.
14959	 */
14960	
14961	var __htmlEscapeEntities = function ( d ) {
14962		return typeof d === 'string' ?
14963			d
14964				.replace(/&/g, '&amp;')
14965				.replace(/</g, '&lt;')
14966				.replace(/>/g, '&gt;')
14967				.replace(/"/g, '&quot;') :
14968			d;
14969	};
14970	
14971	/**
14972	 * Helpers for `columns.render`.
14973	 *
14974	 * The options defined here can be used with the `columns.render` initialisation
14975	 * option to provide a display renderer. The following functions are defined:
14976	 *
14977	 * * `number` - Will format numeric data (defined by `columns.data`) for
14978	 *   display, retaining the original unformatted data for sorting and filtering.
14979	 *   It takes 5 parameters:
14980	 *   * `string` - Thousands grouping separator
14981	 *   * `string` - Decimal point indicator
14982	 *   * `integer` - Number of decimal points to show
14983	 *   * `string` (optional) - Prefix.
14984	 *   * `string` (optional) - Postfix (/suffix).
14985	 * * `text` - Escape HTML to help prevent XSS attacks. It has no optional
14986	 *   parameters.
14987	 *
14988	 * @example
14989	 *   // Column definition using the number renderer
14990	 *   {
14991	 *     data: "salary",
14992	 *     render: $.fn.dataTable.render.number( '\'', '.', 0, '$' )
14993	 *   }
14994	 *
14995	 * @namespace
14996	 */
14997	DataTable.render = {
14998		number: function ( thousands, decimal, precision, prefix, postfix ) {
14999			return {
15000				display: function ( d ) {
15001					if ( typeof d !== 'number' && typeof d !== 'string' ) {
15002						return d;
15003					}
15004	
15005					var negative = d < 0 ? '-' : '';
15006					var flo = parseFloat( d );
15007	
15008					// If NaN then there isn't much formatting that we can do - just
15009					// return immediately, escaping any HTML (this was supposed to
15010					// be a number after all)
15011					if ( isNaN( flo ) ) {
15012						return __htmlEscapeEntities( d );
15013					}
15014	
15015					flo = flo.toFixed( precision );
15016					d = Math.abs( flo );
15017	
15018					var intPart = parseInt( d, 10 );
15019					var floatPart = precision ?
15020						decimal+(d - intPart).toFixed( precision ).substring( 2 ):
15021						'';
15022	
15023					return negative + (prefix||'') +
15024						intPart.toString().replace(
15025							/\B(?=(\d{3})+(?!\d))/g, thousands
15026						) +
15027						floatPart +
15028						(postfix||'');
15029				}
15030			};
15031		},
15032	
15033		text: function () {
15034			return {
15035				display: __htmlEscapeEntities,
15036				filter: __htmlEscapeEntities
15037			};
15038		}
15039	};
15040	
15041	
15042	/*
15043	 * This is really a good bit rubbish this method of exposing the internal methods
15044	 * publicly... - To be fixed in 2.0 using methods on the prototype
15045	 */
15046	
15047	
15048	/**
15049	 * Create a wrapper function for exporting an internal functions to an external API.
15050	 *  @param {string} fn API function name
15051	 *  @returns {function} wrapped function
15052	 *  @memberof DataTable#internal
15053	 */
15054	function _fnExternApiFunc (fn)
15055	{
15056		return function() {
15057			var args = [_fnSettingsFromNode( this[DataTable.ext.iApiIndex] )].concat(
15058				Array.prototype.slice.call(arguments)
15059			);
15060			return DataTable.ext.internal[fn].apply( this, args );
15061		};
15062	}
15063	
15064	
15065	/**
15066	 * Reference to internal functions for use by plug-in developers. Note that
15067	 * these methods are references to internal functions and are considered to be
15068	 * private. If you use these methods, be aware that they are liable to change
15069	 * between versions.
15070	 *  @namespace
15071	 */
15072	$.extend( DataTable.ext.internal, {
15073		_fnExternApiFunc: _fnExternApiFunc,
15074		_fnBuildAjax: _fnBuildAjax,
15075		_fnAjaxUpdate: _fnAjaxUpdate,
15076		_fnAjaxParameters: _fnAjaxParameters,
15077		_fnAjaxUpdateDraw: _fnAjaxUpdateDraw,
15078		_fnAjaxDataSrc: _fnAjaxDataSrc,
15079		_fnAddColumn: _fnAddColumn,
15080		_fnColumnOptions: _fnColumnOptions,
15081		_fnAdjustColumnSizing: _fnAdjustColumnSizing,
15082		_fnVisibleToColumnIndex: _fnVisibleToColumnIndex,
15083		_fnColumnIndexToVisible: _fnColumnIndexToVisible,
15084		_fnVisbleColumns: _fnVisbleColumns,
15085		_fnGetColumns: _fnGetColumns,
15086		_fnColumnTypes: _fnColumnTypes,
15087		_fnApplyColumnDefs: _fnApplyColumnDefs,
15088		_fnHungarianMap: _fnHungarianMap,
15089		_fnCamelToHungarian: _fnCamelToHungarian,
15090		_fnLanguageCompat: _fnLanguageCompat,
15091		_fnBrowserDetect: _fnBrowserDetect,
15092		_fnAddData: _fnAddData,
15093		_fnAddTr: _fnAddTr,
15094		_fnNodeToDataIndex: _fnNodeToDataIndex,
15095		_fnNodeToColumnIndex: _fnNodeToColumnIndex,
15096		_fnGetCellData: _fnGetCellData,
15097		_fnSetCellData: _fnSetCellData,
15098		_fnSplitObjNotation: _fnSplitObjNotation,
15099		_fnGetObjectDataFn: _fnGetObjectDataFn,
15100		_fnSetObjectDataFn: _fnSetObjectDataFn,
15101		_fnGetDataMaster: _fnGetDataMaster,
15102		_fnClearTable: _fnClearTable,
15103		_fnDeleteIndex: _fnDeleteIndex,
15104		_fnInvalidate: _fnInvalidate,
15105		_fnGetRowElements: _fnGetRowElements,
15106		_fnCreateTr: _fnCreateTr,
15107		_fnBuildHead: _fnBuildHead,
15108		_fnDrawHead: _fnDrawHead,
15109		_fnDraw: _fnDraw,
15110		_fnReDraw: _fnReDraw,
15111		_fnAddOptionsHtml: _fnAddOptionsHtml,
15112		_fnDetectHeader: _fnDetectHeader,
15113		_fnGetUniqueThs: _fnGetUniqueThs,
15114		_fnFeatureHtmlFilter: _fnFeatureHtmlFilter,
15115		_fnFilterComplete: _fnFilterComplete,
15116		_fnFilterCustom: _fnFilterCustom,
15117		_fnFilterColumn: _fnFilterColumn,
15118		_fnFilter: _fnFilter,
15119		_fnFilterCreateSearch: _fnFilterCreateSearch,
15120		_fnEscapeRegex: _fnEscapeRegex,
15121		_fnFilterData: _fnFilterData,
15122		_fnFeatureHtmlInfo: _fnFeatureHtmlInfo,
15123		_fnUpdateInfo: _fnUpdateInfo,
15124		_fnInfoMacros: _fnInfoMacros,
15125		_fnInitialise: _fnInitialise,
15126		_fnInitComplete: _fnInitComplete,
15127		_fnLengthChange: _fnLengthChange,
15128		_fnFeatureHtmlLength: _fnFeatureHtmlLength,
15129		_fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate,
15130		_fnPageChange: _fnPageChange,
15131		_fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing,
15132		_fnProcessingDisplay: _fnProcessingDisplay,
15133		_fnFeatureHtmlTable: _fnFeatureHtmlTable,
15134		_fnScrollDraw: _fnScrollDraw,
15135		_fnApplyToChildren: _fnApplyToChildren,
15136		_fnCalculateColumnWidths: _fnCalculateColumnWidths,
15137		_fnThrottle: _fnThrottle,
15138		_fnConvertToWidth: _fnConvertToWidth,
15139		_fnGetWidestNode: _fnGetWidestNode,
15140		_fnGetMaxLenString: _fnGetMaxLenString,
15141		_fnStringToCss: _fnStringToCss,
15142		_fnSortFlatten: _fnSortFlatten,
15143		_fnSort: _fnSort,
15144		_fnSortAria: _fnSortAria,
15145		_fnSortListener: _fnSortListener,
15146		_fnSortAttachListener: _fnSortAttachListener,
15147		_fnSortingClasses: _fnSortingClasses,
15148		_fnSortData: _fnSortData,
15149		_fnSaveState: _fnSaveState,
15150		_fnLoadState: _fnLoadState,
15151		_fnSettingsFromNode: _fnSettingsFromNode,
15152		_fnLog: _fnLog,
15153		_fnMap: _fnMap,
15154		_fnBindAction: _fnBindAction,
15155		_fnCallbackReg: _fnCallbackReg,
15156		_fnCallbackFire: _fnCallbackFire,
15157		_fnLengthOverflow: _fnLengthOverflow,
15158		_fnRenderer: _fnRenderer,
15159		_fnDataSource: _fnDataSource,
15160		_fnRowAttributes: _fnRowAttributes,
15161		_fnExtend: _fnExtend,
15162		_fnCalculateEnd: function () {} // Used by a lot of plug-ins, but redundant
15163		                                // in 1.10, so this dead-end function is
15164		                                // added to prevent errors
15165	} );
15166	
15167
15168	// jQuery access
15169	$.fn.dataTable = DataTable;
15170
15171	// Provide access to the host jQuery object (circular reference)
15172	DataTable.$ = $;
15173
15174	// Legacy aliases
15175	$.fn.dataTableSettings = DataTable.settings;
15176	$.fn.dataTableExt = DataTable.ext;
15177
15178	// With a capital `D` we return a DataTables API instance rather than a
15179	// jQuery object
15180	$.fn.DataTable = function ( opts ) {
15181		return $(this).dataTable( opts ).api();
15182	};
15183
15184	// All properties that are available to $.fn.dataTable should also be
15185	// available on $.fn.DataTable
15186	$.each( DataTable, function ( prop, val ) {
15187		$.fn.DataTable[ prop ] = val;
15188	} );
15189
15190
15191	// Information about events fired by DataTables - for documentation.
15192	/**
15193	 * Draw event, fired whenever the table is redrawn on the page, at the same
15194	 * point as fnDrawCallback. This may be useful for binding events or
15195	 * performing calculations when the table is altered at all.
15196	 *  @name DataTable#draw.dt
15197	 *  @event
15198	 *  @param {event} e jQuery event object
15199	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15200	 */
15201
15202	/**
15203	 * Search event, fired when the searching applied to the table (using the
15204	 * built-in global search, or column filters) is altered.
15205	 *  @name DataTable#search.dt
15206	 *  @event
15207	 *  @param {event} e jQuery event object
15208	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15209	 */
15210
15211	/**
15212	 * Page change event, fired when the paging of the table is altered.
15213	 *  @name DataTable#page.dt
15214	 *  @event
15215	 *  @param {event} e jQuery event object
15216	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15217	 */
15218
15219	/**
15220	 * Order event, fired when the ordering applied to the table is altered.
15221	 *  @name DataTable#order.dt
15222	 *  @event
15223	 *  @param {event} e jQuery event object
15224	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15225	 */
15226
15227	/**
15228	 * DataTables initialisation complete event, fired when the table is fully
15229	 * drawn, including Ajax data loaded, if Ajax data is required.
15230	 *  @name DataTable#init.dt
15231	 *  @event
15232	 *  @param {event} e jQuery event object
15233	 *  @param {object} oSettings DataTables settings object
15234	 *  @param {object} json The JSON object request from the server - only
15235	 *    present if client-side Ajax sourced data is used</li></ol>
15236	 */
15237
15238	/**
15239	 * State save event, fired when the table has changed state a new state save
15240	 * is required. This event allows modification of the state saving object
15241	 * prior to actually doing the save, including addition or other state
15242	 * properties (for plug-ins) or modification of a DataTables core property.
15243	 *  @name DataTable#stateSaveParams.dt
15244	 *  @event
15245	 *  @param {event} e jQuery event object
15246	 *  @param {object} oSettings DataTables settings object
15247	 *  @param {object} json The state information to be saved
15248	 */
15249
15250	/**
15251	 * State load event, fired when the table is loading state from the stored
15252	 * data, but prior to the settings object being modified by the saved state
15253	 * - allowing modification of the saved state is required or loading of
15254	 * state for a plug-in.
15255	 *  @name DataTable#stateLoadParams.dt
15256	 *  @event
15257	 *  @param {event} e jQuery event object
15258	 *  @param {object} oSettings DataTables settings object
15259	 *  @param {object} json The saved state information
15260	 */
15261
15262	/**
15263	 * State loaded event, fired when state has been loaded from stored data and
15264	 * the settings object has been modified by the loaded data.
15265	 *  @name DataTable#stateLoaded.dt
15266	 *  @event
15267	 *  @param {event} e jQuery event object
15268	 *  @param {object} oSettings DataTables settings object
15269	 *  @param {object} json The saved state information
15270	 */
15271
15272	/**
15273	 * Processing event, fired when DataTables is doing some kind of processing
15274	 * (be it, order, search or anything else). It can be used to indicate to
15275	 * the end user that there is something happening, or that something has
15276	 * finished.
15277	 *  @name DataTable#processing.dt
15278	 *  @event
15279	 *  @param {event} e jQuery event object
15280	 *  @param {object} oSettings DataTables settings object
15281	 *  @param {boolean} bShow Flag for if DataTables is doing processing or not
15282	 */
15283
15284	/**
15285	 * Ajax (XHR) event, fired whenever an Ajax request is completed from a
15286	 * request to made to the server for new data. This event is called before
15287	 * DataTables processed the returned data, so it can also be used to pre-
15288	 * process the data returned from the server, if needed.
15289	 *
15290	 * Note that this trigger is called in `fnServerData`, if you override
15291	 * `fnServerData` and which to use this event, you need to trigger it in you
15292	 * success function.
15293	 *  @name DataTable#xhr.dt
15294	 *  @event
15295	 *  @param {event} e jQuery event object
15296	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15297	 *  @param {object} json JSON returned from the server
15298	 *
15299	 *  @example
15300	 *     // Use a custom property returned from the server in another DOM element
15301	 *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
15302	 *       $('#status').html( json.status );
15303	 *     } );
15304	 *
15305	 *  @example
15306	 *     // Pre-process the data returned from the server
15307	 *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
15308	 *       for ( var i=0, ien=json.aaData.length ; i<ien ; i++ ) {
15309	 *         json.aaData[i].sum = json.aaData[i].one + json.aaData[i].two;
15310	 *       }
15311	 *       // Note no return - manipulate the data directly in the JSON object.
15312	 *     } );
15313	 */
15314
15315	/**
15316	 * Destroy event, fired when the DataTable is destroyed by calling fnDestroy
15317	 * or passing the bDestroy:true parameter in the initialisation object. This
15318	 * can be used to remove bound events, added DOM nodes, etc.
15319	 *  @name DataTable#destroy.dt
15320	 *  @event
15321	 *  @param {event} e jQuery event object
15322	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15323	 */
15324
15325	/**
15326	 * Page length change event, fired when number of records to show on each
15327	 * page (the length) is changed.
15328	 *  @name DataTable#length.dt
15329	 *  @event
15330	 *  @param {event} e jQuery event object
15331	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15332	 *  @param {integer} len New length
15333	 */
15334
15335	/**
15336	 * Column sizing has changed.
15337	 *  @name DataTable#column-sizing.dt
15338	 *  @event
15339	 *  @param {event} e jQuery event object
15340	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15341	 */
15342
15343	/**
15344	 * Column visibility has changed.
15345	 *  @name DataTable#column-visibility.dt
15346	 *  @event
15347	 *  @param {event} e jQuery event object
15348	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15349	 *  @param {int} column Column index
15350	 *  @param {bool} vis `false` if column now hidden, or `true` if visible
15351	 */
15352
15353	return $.fn.dataTable;
15354}));

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.