PageSourceSearch

https://faithiq.org/frontend/assets/js/datatables/jquery.dataTables.js

js faithiq.org collected 2026-09-28 15:21:01 UTC 447,569 bytes, 15,296 lines download raw bytes

1/*! DataTables 1.10.19
2 * ©2008-2018 SpryMedia Ltd - datatables.net/license
3 */
4
5/**
6 * @summary     DataTables
7 * @description Paginate, search and order HTML tables
8 * @version     1.10.19
9 * @file        jquery.dataTables.js
10 * @author      SpryMedia Ltd
11 * @contact     www.datatables.net
12 * @copyright   Copyright 2008-2018 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,803 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() ) );
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]/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 );
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: 10,997 bytes, lines 3010-3432
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;
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	
3103				nTd = nTrIn ? anTds[i] : document.createElement( oCol.sCellType );
3104				nTd._DT_CellIndex = {
3105					row: iRow,
3106					column: i
3107				};
3108				
3109				cells.push( nTd );
3110	
3111				// Need to create the HTML if new, or if a rendering function is defined
3112				if ( (!nTrIn || oCol.mRender || oCol.mData !== i) &&
3113					 (!$.isPlainObject(oCol.mData) || oCol.mData._ !== i+'.display')
3114				) {
3115					nTd.innerHTML = _fnGetCellData( oSettings, iRow, i, 'display' );
3116				}
3117	
3118				/* Add user defined class */
3119				if ( oCol.sClass )
3120				{
3121					nTd.className += ' '+oCol.sClass;
3122				}
3123	
3124				// Visibility - add or remove as required
3125				if ( oCol.bVisible && ! nTrIn )
3126				{
3127					nTr.appendChild( nTd );
3128				}
3129				else if ( ! oCol.bVisible && nTrIn )
3130				{
3131					nTd.parentNode.removeChild( nTd );
3132				}
3133	
3134				if ( oCol.fnCreatedCell )
3135				{
3136					oCol.fnCreatedCell.call( oSettings.oInstance,
3137						nTd, _fnGetCellData( oSettings, iRow, i ), rowData, iRow, i
3138					);
3139				}
3140			}
3141	
3142			_fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow, cells] );
3143		}
3144	
3145		// Remove once webkit bug 131819 and Chromium bug 365619 have been resolved
3146		// and deployed
3147		row.nTr.setAttribute( 'role', 'row' );
3148	}
3149	
3150	
3151	/**
3152	 * Add attributes to a row based on the special `DT_*` parameters in a data
3153	 * source object.
3154	 *  @param {object} settings DataTables settings object
3155	 *  @param {object} DataTables row object for the row to be modified
3156	 *  @memberof DataTable#oApi
3157	 */
3158	function _fnRowAttributes( settings, row )
3159	{
3160		var tr = row.nTr;
3161		var data = row._aData;
3162	
3163		if ( tr ) {
3164			var id = settings.rowIdFn( data );
3165	
3166			if ( id ) {
3167				tr.id = id;
3168			}
3169	
3170			if ( data.DT_RowClass ) {
3171				// Remove any classes added by DT_RowClass before
3172				var a = data.DT_RowClass.split(' ');
3173				row.__rowc = row.__rowc ?
3174					_unique( row.__rowc.concat( a ) ) :
3175					a;
3176	
3177				$(tr)
3178					.removeClass( row.__rowc.join(' ') )
3179					.addClass( data.DT_RowClass );
3180			}
3181	
3182			if ( data.DT_RowAttr ) {
3183				$(tr).attr( data.DT_RowAttr );
3184			}
3185	
3186			if ( data.DT_RowData ) {
3187				$(tr).data( data.DT_RowData );
3188			}
3189		}
3190	}
3191	
3192	
3193	/**
3194	 * Create the HTML header for the table
3195	 *  @param {object} oSettings dataTables settings object
3196	 *  @memberof DataTable#oApi
3197	 */
3198	function _fnBuildHead( oSettings )
3199	{
3200		var i, ien, cell, row, column;
3201		var thead = oSettings.nTHead;
3202		var tfoot = oSettings.nTFoot;
3203		var createHeader = $('th, td', thead).length === 0;
3204		var classes = oSettings.oClasses;
3205		var columns = oSettings.aoColumns;
3206	
3207		if ( createHeader ) {
3208			row = $('<tr/>').appendTo( thead );
3209		}
3210	
3211		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
3212			column = columns[i];
3213			cell = $( column.nTh ).addClass( column.sClass );
3214	
3215			if ( createHeader ) {
3216				cell.appendTo( row );
3217			}
3218	
3219			// 1.11 move into sorting
3220			if ( oSettings.oFeatures.bSort ) {
3221				cell.addClass( column.sSortingClass );
3222	
3223				if ( column.bSortable !== false ) {
3224					cell
3225						.attr( 'tabindex', oSettings.iTabIndex )
3226						.attr( 'aria-controls', oSettings.sTableId );
3227	
3228					_fnSortAttachListener( oSettings, column.nTh, i );
3229				}
3230			}
3231	
3232			if ( column.sTitle != cell[0].innerHTML ) {
3233				cell.html( column.sTitle );
3234			}
3235	
3236			_fnRenderer( oSettings, 'header' )(
3237				oSettings, cell, column, classes
3238			);
3239		}
3240	
3241		if ( createHeader ) {
3242			_fnDetectHeader( oSettings.aoHeader, thead );
3243		}
3244		
3245		/* ARIA role for the rows */
3246	 	$(thead).find('>tr').attr('role', 'row');
3247	
3248		/* Deal with the footer - add classes if required */
3249		$(thead).find('>tr>th, >tr>td').addClass( classes.sHeaderTH );
3250		$(tfoot).find('>tr>th, >tr>td').addClass( classes.sFooterTH );
3251	
3252		// Cache the footer cells. Note that we only take the cells from the first
3253		// row in the footer. If there is more than one row the user wants to
3254		// interact with, they need to use the table().foot() method. Note also this
3255		// allows cells to be used for multiple columns using colspan
3256		if ( tfoot !== null ) {
3257			var cells = oSettings.aoFooter[0];
3258	
3259			for ( i=0, ien=cells.length ; i<ien ; i++ ) {
3260				column = columns[i];
3261				column.nTf = cells[i].cell;
3262	
3263				if ( column.sClass ) {
3264					$(column.nTf).addClass( column.sClass );
3265				}
3266			}
3267		}
3268	}
3269	
3270	
3271	/**
3272	 * Draw the header (or footer) element based on the column visibility states. The
3273	 * methodology here is to use the layout array from _fnDetectHeader, modified for
3274	 * the instantaneous column visibility, to construct the new layout. The grid is
3275	 * traversed over cell at a time in a rows x columns grid fashion, although each
3276	 * cell insert can cover multiple elements in the grid - which is tracks using the
3277	 * aApplied array. Cell inserts in the grid will only occur where there isn't
3278	 * already a cell in that position.
3279	 *  @param {object} oSettings dataTables settings object
3280	 *  @param array {objects} aoSource Layout array from _fnDetectHeader
3281	 *  @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,
3282	 *  @memberof DataTable#oApi
3283	 */
3284	function _fnDrawHead( oSettings, aoSource, bIncludeHidden )
3285	{
3286		var i, iLen, j, jLen, k, kLen, n, nLocalTr;
3287		var aoLocal = [];
3288		var aApplied = [];
3289		var iColumns = oSettings.aoColumns.length;
3290		var iRowspan, iColspan;
3291	
3292		if ( ! aoSource )
3293		{
3294			return;
3295		}
3296	
3297		if (  bIncludeHidden === undefined )
3298		{
3299			bIncludeHidden = false;
3300		}
3301	
3302		/* Make a copy of the master layout array, but without the visible columns in it */
3303		for ( i=0, iLen=aoSource.length ; i<iLen ; i++ )
3304		{
3305			aoLocal[i] = aoSource[i].slice();
3306			aoLocal[i].nTr = aoSource[i].nTr;
3307	
3308			/* Remove any columns which are currently hidden */
3309			for ( j=iColumns-1 ; j>=0 ; j-- )
3310			{
3311				if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden )
3312				{
3313					aoLocal[i].splice( j, 1 );
3314				}
3315			}
3316	
3317			/* Prep the applied array - it needs an element for each row */
3318			aApplied.push( [] );
3319		}
3320	
3321		for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ )
3322		{
3323			nLocalTr = aoLocal[i].nTr;
3324	
3325			/* All cells are going to be replaced, so empty out the row */
3326			if ( nLocalTr )
3327			{
3328				while( (n = nLocalTr.firstChild) )
3329				{
3330					nLocalTr.removeChild( n );
3331				}
3332			}
3333	
3334			for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ )
3335			{
3336				iRowspan = 1;
3337				iColspan = 1;
3338	
3339				/* Check to see if there is already a cell (row/colspan) covering our target
3340				 * insert point. If there is, then there is nothing to do.
3341				 */
3342				if ( aApplied[i][j] === undefined )
3343				{
3344					nLocalTr.appendChild( aoLocal[i][j].cell );
3345					aApplied[i][j] = 1;
3346	
3347					/* Expand the cell to cover as many rows as needed */
3348					while ( aoLocal[i+iRowspan] !== undefined &&
3349					        aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell )
3350					{
3351						aApplied[i+iRowspan][j] = 1;
3352						iRowspan++;
3353					}
3354	
3355					/* Expand the cell to cover as many columns as needed */
3356					while ( aoLocal[i][j+iColspan] !== undefined &&
3357					        aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell )
3358					{
3359						/* Must update the applied array over the rows for the columns */
3360						for ( k=0 ; k<iRowspan ; k++ )
3361						{
3362							aApplied[i+k][j+iColspan] = 1;
3363						}
3364						iColspan++;
3365					}
3366	
3367					/* Do the actual expansion in the DOM */
3368					$(aoLocal[i][j].cell)
3369						.attr('rowspan', iRowspan)
3370						.attr('colspan', iColspan);
3371				}
3372			}
3373		}
3374	}
3375	
3376	
3377	/**
3378	 * Insert the required TR nodes into the table for display
3379	 *  @param {object} oSettings dataTables settings object
3380	 *  @memberof DataTable#oApi
3381	 */
3382	function _fnDraw( oSettings )
3383	{
3384		/* Provide a pre-callback function which can be used to cancel the draw is false is returned */
3385		var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] );
3386		if ( $.inArray( false, aPreDraw ) !== -1 )
3387		{
3388			_fnProcessingDisplay( oSettings, false );
3389			return;
3390		}
3391	
3392		var i, iLen, n;
3393		var anRows = [];
3394		var iRowCount = 0;
3395		var asStripeClasses = oSettings.asStripeClasses;
3396		var iStripes = asStripeClasses.length;
3397		var iOpenRows = oSettings.aoOpenRows.length;
3398		var oLang = oSettings.oLanguage;
3399		var iInitDisplayStart = oSettings.iInitDisplayStart;
3400		var bServerSide = _fnDataSource( oSettings ) == 'ssp';
3401		var aiDisplay = oSettings.aiDisplay;
3402	
3403		oSettings.bDrawing = true;
3404	
3405		/* Check and see if we have an initial draw position from state saving */
3406		if ( iInitDisplayStart !== undefined && iInitDisplayStart !== -1 )
3407		{
3408			oSettings._iDisplayStart = bServerSide ?
3409				iInitDisplayStart :
3410				iInitDisplayStart >= oSettings.fnRecordsDisplay() ?
3411					0 :
3412					iInitDisplayStart;
3413	
3414			oSettings.iInitDisplayStart = -1;
3415		}
3416	
3417		var iDisplayStart = oSettings._iDisplayStart;
3418		var iDisplayEnd = oSettings.fnDisplayEnd();
3419	
3420		/* Server-side processing draw intercept */
3421		if ( oSettings.bDeferLoading )
3422		{
3423			oSettings.bDeferLoading = false;
3424			oSettings.iDraw++;
3425			_fnProcessingDisplay( oSettings, false );
3426		}
3427		else if ( !bServerSide )
3428		{
3429			oSettings.iDraw++;
3430		}
3431		else if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) )
3432		{
vendor: 10,503 bytes, lines 3432-3821
3432
3433			return;
3434		}
3435	
3436		if ( aiDisplay.length !== 0 )
3437		{
3438			var iStart = bServerSide ? 0 : iDisplayStart;
3439			var iEnd = bServerSide ? oSettings.aoData.length : iDisplayEnd;
3440	
3441			for ( var j=iStart ; j<iEnd ; j++ )
3442			{
3443				var iDataIndex = aiDisplay[j];
3444				var aoData = oSettings.aoData[ iDataIndex ];
3445				if ( aoData.nTr === null )
3446				{
3447					_fnCreateTr( oSettings, iDataIndex );
3448				}
3449	
3450				var nRow = aoData.nTr;
3451	
3452				/* Remove the old striping classes and then add the new one */
3453				if ( iStripes !== 0 )
3454				{
3455					var sStripe = asStripeClasses[ iRowCount % iStripes ];
3456					if ( aoData._sRowStripe != sStripe )
3457					{
3458						$(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe );
3459						aoData._sRowStripe = sStripe;
3460					}
3461				}
3462	
3463				// Row callback functions - might want to manipulate the row
3464				// iRowCount and j are not currently documented. Are they at all
3465				// useful?
3466				_fnCallbackFire( oSettings, 'aoRowCallback', null,
3467					[nRow, aoData._aData, iRowCount, j, iDataIndex] );
3468	
3469				anRows.push( nRow );
3470				iRowCount++;
3471			}
3472		}
3473		else
3474		{
3475			/* Table is empty - create a row with an empty message in it */
3476			var sZero = oLang.sZeroRecords;
3477			if ( oSettings.iDraw == 1 &&  _fnDataSource( oSettings ) == 'ajax' )
3478			{
3479				sZero = oLang.sLoadingRecords;
3480			}
3481			else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 )
3482			{
3483				sZero = oLang.sEmptyTable;
3484			}
3485	
3486			anRows[ 0 ] = $( '<tr/>', { 'class': iStripes ? asStripeClasses[0] : '' } )
3487				.append( $('<td />', {
3488					'valign':  'top',
3489					'colSpan': _fnVisbleColumns( oSettings ),
3490					'class':   oSettings.oClasses.sRowEmpty
3491				} ).html( sZero ) )[0];
3492		}
3493	
3494		/* Header and footer callbacks */
3495		_fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0],
3496			_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
3497	
3498		_fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0],
3499			_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
3500	
3501		var body = $(oSettings.nTBody);
3502	
3503		body.children().detach();
3504		body.append( $(anRows) );
3505	
3506		/* Call all required callback functions for the end of a draw */
3507		_fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] );
3508	
3509		/* Draw is complete, sorting and filtering must be as well */
3510		oSettings.bSorted = false;
3511		oSettings.bFiltered = false;
3512		oSettings.bDrawing = false;
3513	}
3514	
3515	
3516	/**
3517	 * Redraw the table - taking account of the various features which are enabled
3518	 *  @param {object} oSettings dataTables settings object
3519	 *  @param {boolean} [holdPosition] Keep the current paging position. By default
3520	 *    the paging is reset to the first page
3521	 *  @memberof DataTable#oApi
3522	 */
3523	function _fnReDraw( settings, holdPosition )
3524	{
3525		var
3526			features = settings.oFeatures,
3527			sort     = features.bSort,
3528			filter   = features.bFilter;
3529	
3530		if ( sort ) {
3531			_fnSort( settings );
3532		}
3533	
3534		if ( filter ) {
3535			_fnFilterComplete( settings, settings.oPreviousSearch );
3536		}
3537		else {
3538			// No filtering, so we want to just use the display master
3539			settings.aiDisplay = settings.aiDisplayMaster.slice();
3540		}
3541	
3542		if ( holdPosition !== true ) {
3543			settings._iDisplayStart = 0;
3544		}
3545	
3546		// Let any modules know about the draw hold position state (used by
3547		// scrolling internally)
3548		settings._drawHold = holdPosition;
3549	
3550		_fnDraw( settings );
3551	
3552		settings._drawHold = false;
3553	}
3554	
3555	
3556	/**
3557	 * Add the options to the page HTML for the table
3558	 *  @param {object} oSettings dataTables settings object
3559	 *  @memberof DataTable#oApi
3560	 */
3561	function _fnAddOptionsHtml ( oSettings )
3562	{
3563		var classes = oSettings.oClasses;
3564		var table = $(oSettings.nTable);
3565		var holding = $('<div/>').insertBefore( table ); // Holding element for speed
3566		var features = oSettings.oFeatures;
3567	
3568		// All DataTables are wrapped in a div
3569		var insert = $('<div/>', {
3570			id:      oSettings.sTableId+'_wrapper',
3571			'class': classes.sWrapper + (oSettings.nTFoot ? '' : ' '+classes.sNoFooter)
3572		} );
3573	
3574		oSettings.nHolding = holding[0];
3575		oSettings.nTableWrapper = insert[0];
3576		oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;
3577	
3578		/* Loop over the user set positioning and place the elements as needed */
3579		var aDom = oSettings.sDom.split('');
3580		var featureNode, cOption, nNewNode, cNext, sAttr, j;
3581		for ( var i=0 ; i<aDom.length ; i++ )
3582		{
3583			featureNode = null;
3584			cOption = aDom[i];
3585	
3586			if ( cOption == '<' )
3587			{
3588				/* New container div */
3589				nNewNode = $('<div/>')[0];
3590	
3591				/* Check to see if we should append an id and/or a class name to the container */
3592				cNext = aDom[i+1];
3593				if ( cNext == "'" || cNext == '"' )
3594				{
3595					sAttr = "";
3596					j = 2;
3597					while ( aDom[i+j] != cNext )
3598					{
3599						sAttr += aDom[i+j];
3600						j++;
3601					}
3602	
3603					/* Replace jQuery UI constants @todo depreciated */
3604					if ( sAttr == "H" )
3605					{
3606						sAttr = classes.sJUIHeader;
3607					}
3608					else if ( sAttr == "F" )
3609					{
3610						sAttr = classes.sJUIFooter;
3611					}
3612	
3613					/* The attribute can be in the format of "#id.class", "#id" or "class" This logic
3614					 * breaks the string into parts and applies them as needed
3615					 */
3616					if ( sAttr.indexOf('.') != -1 )
3617					{
3618						var aSplit = sAttr.split('.');
3619						nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);
3620						nNewNode.className = aSplit[1];
3621					}
3622					else if ( sAttr.charAt(0) == "#" )
3623					{
3624						nNewNode.id = sAttr.substr(1, sAttr.length-1);
3625					}
3626					else
3627					{
3628						nNewNode.className = sAttr;
3629					}
3630	
3631					i += j; /* Move along the position array */
3632				}
3633	
3634				insert.append( nNewNode );
3635				insert = $(nNewNode);
3636			}
3637			else if ( cOption == '>' )
3638			{
3639				/* End container div */
3640				insert = insert.parent();
3641			}
3642			// @todo Move options into their own plugins?
3643			else if ( cOption == 'l' && features.bPaginate && features.bLengthChange )
3644			{
3645				/* Length */
3646				featureNode = _fnFeatureHtmlLength( oSettings );
3647			}
3648			else if ( cOption == 'f' && features.bFilter )
3649			{
3650				/* Filter */
3651				featureNode = _fnFeatureHtmlFilter( oSettings );
3652			}
3653			else if ( cOption == 'r' && features.bProcessing )
3654			{
3655				/* pRocessing */
3656				featureNode = _fnFeatureHtmlProcessing( oSettings );
3657			}
3658			else if ( cOption == 't' )
3659			{
3660				/* Table */
3661				featureNode = _fnFeatureHtmlTable( oSettings );
3662			}
3663			else if ( cOption ==  'i' && features.bInfo )
3664			{
3665				/* Info */
3666				featureNode = _fnFeatureHtmlInfo( oSettings );
3667			}
3668			else if ( cOption == 'p' && features.bPaginate )
3669			{
3670				/* Pagination */
3671				featureNode = _fnFeatureHtmlPaginate( oSettings );
3672			}
3673			else if ( DataTable.ext.feature.length !== 0 )
3674			{
3675				/* Plug-in features */
3676				var aoFeatures = DataTable.ext.feature;
3677				for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )
3678				{
3679					if ( cOption == aoFeatures[k].cFeature )
3680					{
3681						featureNode = aoFeatures[k].fnInit( oSettings );
3682						break;
3683					}
3684				}
3685			}
3686	
3687			/* Add to the 2D features array */
3688			if ( featureNode )
3689			{
3690				var aanFeatures = oSettings.aanFeatures;
3691	
3692				if ( ! aanFeatures[cOption] )
3693				{
3694					aanFeatures[cOption] = [];
3695				}
3696	
3697				aanFeatures[cOption].push( featureNode );
3698				insert.append( featureNode );
3699			}
3700		}
3701	
3702		/* Built our DOM structure - replace the holding div with what we want */
3703		holding.replaceWith( insert );
3704		oSettings.nHolding = null;
3705	}
3706	
3707	
3708	/**
3709	 * Use the DOM source to create up an array of header cells. The idea here is to
3710	 * create a layout grid (array) of rows x columns, which contains a reference
3711	 * to the cell that that point in the grid (regardless of col/rowspan), such that
3712	 * any column / row could be removed and the new grid constructed
3713	 *  @param array {object} aLayout Array to store the calculated layout in
3714	 *  @param {node} nThead The header/footer element for the table
3715	 *  @memberof DataTable#oApi
3716	 */
3717	function _fnDetectHeader ( aLayout, nThead )
3718	{
3719		var nTrs = $(nThead).children('tr');
3720		var nTr, nCell;
3721		var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan;
3722		var bUnique;
3723		var fnShiftCol = function ( a, i, j ) {
3724			var k = a[i];
3725	                while ( k[j] ) {
3726				j++;
3727			}
3728			return j;
3729		};
3730	
3731		aLayout.splice( 0, aLayout.length );
3732	
3733		/* We know how many rows there are in the layout - so prep it */
3734		for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
3735		{
3736			aLayout.push( [] );
3737		}
3738	
3739		/* Calculate a layout array */
3740		for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
3741		{
3742			nTr = nTrs[i];
3743			iColumn = 0;
3744	
3745			/* For every cell in the row... */
3746			nCell = nTr.firstChild;
3747			while ( nCell ) {
3748				if ( nCell.nodeName.toUpperCase() == "TD" ||
3749				     nCell.nodeName.toUpperCase() == "TH" )
3750				{
3751					/* Get the col and rowspan attributes from the DOM and sanitise them */
3752					iColspan = nCell.getAttribute('colspan') * 1;
3753					iRowspan = nCell.getAttribute('rowspan') * 1;
3754					iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan;
3755					iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan;
3756	
3757					/* There might be colspan cells already in this row, so shift our target
3758					 * accordingly
3759					 */
3760					iColShifted = fnShiftCol( aLayout, i, iColumn );
3761	
3762					/* Cache calculation for unique columns */
3763					bUnique = iColspan === 1 ? true : false;
3764	
3765					/* If there is col / rowspan, copy the information into the layout grid */
3766					for ( l=0 ; l<iColspan ; l++ )
3767					{
3768						for ( k=0 ; k<iRowspan ; k++ )
3769						{
3770							aLayout[i+k][iColShifted+l] = {
3771								"cell": nCell,
3772								"unique": bUnique
3773							};
3774							aLayout[i+k].nTr = nTr;
3775						}
3776					}
3777				}
3778				nCell = nCell.nextSibling;
3779			}
3780		}
3781	}
3782	
3783	
3784	/**
3785	 * Get an array of unique th elements, one for each column
3786	 *  @param {object} oSettings dataTables settings object
3787	 *  @param {node} nHeader automatically detect the layout from this node - optional
3788	 *  @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional
3789	 *  @returns array {node} aReturn list of unique th's
3790	 *  @memberof DataTable#oApi
3791	 */
3792	function _fnGetUniqueThs ( oSettings, nHeader, aLayout )
3793	{
3794		var aReturn = [];
3795		if ( !aLayout )
3796		{
3797			aLayout = oSettings.aoHeader;
3798			if ( nHeader )
3799			{
3800				aLayout = [];
3801				_fnDetectHeader( aLayout, nHeader );
3802			}
3803		}
3804	
3805		for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ )
3806		{
3807			for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ )
3808			{
3809				if ( aLayout[i][j].unique &&
3810					 (!aReturn[j] || !oSettings.bSortCellsTop) )
3811				{
3812					aReturn[j] = aLayout[i][j].cell;
3813				}
3814			}
3815		}
3816	
3817		return aReturn;
3818	}
3819	
3820	/**
3821	 * 
vendor: 47,598 bytes, lines 3821-5460
3821Create an Ajax call based on the table's settings, taking into account that
3822	 * parameters can have multiple forms, and backwards compatibility.
3823	 *
3824	 * @param {object} oSettings dataTables settings object
3825	 * @param {array} data Data to send to the server, required by
3826	 *     DataTables - may be augmented by developer callbacks
3827	 * @param {function} fn Callback function to run when data is obtained
3828	 */
3829	function _fnBuildAjax( oSettings, data, fn )
3830	{
3831		// Compatibility with 1.9-, allow fnServerData and event to manipulate
3832		_fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [data] );
3833	
3834		// Convert to object based for 1.10+ if using the old array scheme which can
3835		// come from server-side processing or serverParams
3836		if ( data && $.isArray(data) ) {
3837			var tmp = {};
3838			var rbracket = /(.*?)\[\]$/;
3839	
3840			$.each( data, function (key, val) {
3841				var match = val.name.match(rbracket);
3842	
3843				if ( match ) {
3844					// Support for arrays
3845					var name = match[0];
3846	
3847					if ( ! tmp[ name ] ) {
3848						tmp[ name ] = [];
3849					}
3850					tmp[ name ].push( val.value );
3851				}
3852				else {
3853					tmp[val.name] = val.value;
3854				}
3855			} );
3856			data = tmp;
3857		}
3858	
3859		var ajaxData;
3860		var ajax = oSettings.ajax;
3861		var instance = oSettings.oInstance;
3862		var callback = function ( json ) {
3863			_fnCallbackFire( oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR] );
3864			fn( json );
3865		};
3866	
3867		if ( $.isPlainObject( ajax ) && ajax.data )
3868		{
3869			ajaxData = ajax.data;
3870	
3871			var newData = typeof ajaxData === 'function' ?
3872				ajaxData( data, oSettings ) :  // fn can manipulate data or return
3873				ajaxData;                      // an object object or array to merge
3874	
3875			// If the function returned something, use that alone
3876			data = typeof ajaxData === 'function' && newData ?
3877				newData :
3878				$.extend( true, data, newData );
3879	
3880			// Remove the data property as we've resolved it already and don't want
3881			// jQuery to do it again (it is restored at the end of the function)
3882			delete ajax.data;
3883		}
3884	
3885		var baseAjax = {
3886			"data": data,
3887			"success": function (json) {
3888				var error = json.error || json.sError;
3889				if ( error ) {
3890					_fnLog( oSettings, 0, error );
3891				}
3892	
3893				oSettings.json = json;
3894				callback( json );
3895			},
3896			"dataType": "json",
3897			"cache": false,
3898			"type": oSettings.sServerMethod,
3899			"error": function (xhr, error, thrown) {
3900				var ret = _fnCallbackFire( oSettings, null, 'xhr', [oSettings, null, oSettings.jqXHR] );
3901	
3902				if ( $.inArray( true, ret ) === -1 ) {
3903					if ( error == "parsererror" ) {
3904						_fnLog( oSettings, 0, 'Invalid JSON response', 1 );
3905					}
3906					else if ( xhr.readyState === 4 ) {
3907						_fnLog( oSettings, 0, 'Ajax error', 7 );
3908					}
3909				}
3910	
3911				_fnProcessingDisplay( oSettings, false );
3912			}
3913		};
3914	
3915		// Store the data submitted for the API
3916		oSettings.oAjaxData = data;
3917	
3918		// Allow plug-ins and external processes to modify the data
3919		_fnCallbackFire( oSettings, null, 'preXhr', [oSettings, data] );
3920	
3921		if ( oSettings.fnServerData )
3922		{
3923			// DataTables 1.9- compatibility
3924			oSettings.fnServerData.call( instance,
3925				oSettings.sAjaxSource,
3926				$.map( data, function (val, key) { // Need to convert back to 1.9 trad format
3927					return { name: key, value: val };
3928				} ),
3929				callback,
3930				oSettings
3931			);
3932		}
3933		else if ( oSettings.sAjaxSource || typeof ajax === 'string' )
3934		{
3935			// DataTables 1.9- compatibility
3936			oSettings.jqXHR = $.ajax( $.extend( baseAjax, {
3937				url: ajax || oSettings.sAjaxSource
3938			} ) );
3939		}
3940		else if ( typeof ajax === 'function' )
3941		{
3942			// Is a function - let the caller define what needs to be done
3943			oSettings.jqXHR = ajax.call( instance, data, callback, oSettings );
3944		}
3945		else
3946		{
3947			// Object to extend the base settings
3948			oSettings.jqXHR = $.ajax( $.extend( baseAjax, ajax ) );
3949	
3950			// Restore for next time around
3951			ajax.data = ajaxData;
3952		}
3953	}
3954	
3955	
3956	/**
3957	 * Update the table using an Ajax call
3958	 *  @param {object} settings dataTables settings object
3959	 *  @returns {boolean} Block the table drawing or not
3960	 *  @memberof DataTable#oApi
3961	 */
3962	function _fnAjaxUpdate( settings )
3963	{
3964		if ( settings.bAjaxDataGet ) {
3965			settings.iDraw++;
3966			_fnProcessingDisplay( settings, true );
3967	
3968			_fnBuildAjax(
3969				settings,
3970				_fnAjaxParameters( settings ),
3971				function(json) {
3972					_fnAjaxUpdateDraw( settings, json );
3973				}
3974			);
3975	
3976			return false;
3977		}
3978		return true;
3979	}
3980	
3981	
3982	/**
3983	 * Build up the parameters in an object needed for a server-side processing
3984	 * request. Note that this is basically done twice, is different ways - a modern
3985	 * method which is used by default in DataTables 1.10 which uses objects and
3986	 * arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if
3987	 * the sAjaxSource option is used in the initialisation, or the legacyAjax
3988	 * option is set.
3989	 *  @param {object} oSettings dataTables settings object
3990	 *  @returns {bool} block the table drawing or not
3991	 *  @memberof DataTable#oApi
3992	 */
3993	function _fnAjaxParameters( settings )
3994	{
3995		var
3996			columns = settings.aoColumns,
3997			columnCount = columns.length,
3998			features = settings.oFeatures,
3999			preSearch = settings.oPreviousSearch,
4000			preColSearch = settings.aoPreSearchCols,
4001			i, data = [], dataProp, column, columnSearch,
4002			sort = _fnSortFlatten( settings ),
4003			displayStart = settings._iDisplayStart,
4004			displayLength = features.bPaginate !== false ?
4005				settings._iDisplayLength :
4006				-1;
4007	
4008		var param = function ( name, value ) {
4009			data.push( { 'name': name, 'value': value } );
4010		};
4011	
4012		// DataTables 1.9- compatible method
4013		param( 'sEcho',          settings.iDraw );
4014		param( 'iColumns',       columnCount );
4015		param( 'sColumns',       _pluck( columns, 'sName' ).join(',') );
4016		param( 'iDisplayStart',  displayStart );
4017		param( 'iDisplayLength', displayLength );
4018	
4019		// DataTables 1.10+ method
4020		var d = {
4021			draw:    settings.iDraw,
4022			columns: [],
4023			order:   [],
4024			start:   displayStart,
4025			length:  displayLength,
4026			search:  {
4027				value: preSearch.sSearch,
4028				regex: preSearch.bRegex
4029			}
4030		};
4031	
4032		for ( i=0 ; i<columnCount ; i++ ) {
4033			column = columns[i];
4034			columnSearch = preColSearch[i];
4035			dataProp = typeof column.mData=="function" ? 'function' : column.mData ;
4036	
4037			d.columns.push( {
4038				data:       dataProp,
4039				name:       column.sName,
4040				searchable: column.bSearchable,
4041				orderable:  column.bSortable,
4042				search:     {
4043					value: columnSearch.sSearch,
4044					regex: columnSearch.bRegex
4045				}
4046			} );
4047	
4048			param( "mDataProp_"+i, dataProp );
4049	
4050			if ( features.bFilter ) {
4051				param( 'sSearch_'+i,     columnSearch.sSearch );
4052				param( 'bRegex_'+i,      columnSearch.bRegex );
4053				param( 'bSearchable_'+i, column.bSearchable );
4054			}
4055	
4056			if ( features.bSort ) {
4057				param( 'bSortable_'+i, column.bSortable );
4058			}
4059		}
4060	
4061		if ( features.bFilter ) {
4062			param( 'sSearch', preSearch.sSearch );
4063			param( 'bRegex', preSearch.bRegex );
4064		}
4065	
4066		if ( features.bSort ) {
4067			$.each( sort, function ( i, val ) {
4068				d.order.push( { column: val.col, dir: val.dir } );
4069	
4070				param( 'iSortCol_'+i, val.col );
4071				param( 'sSortDir_'+i, val.dir );
4072			} );
4073	
4074			param( 'iSortingCols', sort.length );
4075		}
4076	
4077		// If the legacy.ajax parameter is null, then we automatically decide which
4078		// form to use, based on sAjaxSource
4079		var legacy = DataTable.ext.legacy.ajax;
4080		if ( legacy === null ) {
4081			return settings.sAjaxSource ? data : d;
4082		}
4083	
4084		// Otherwise, if legacy has been specified then we use that to decide on the
4085		// form
4086		return legacy ? data : d;
4087	}
4088	
4089	
4090	/**
4091	 * Data the data from the server (nuking the old) and redraw the table
4092	 *  @param {object} oSettings dataTables settings object
4093	 *  @param {object} json json data return from the server.
4094	 *  @param {string} json.sEcho Tracking flag for DataTables to match requests
4095	 *  @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering
4096	 *  @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering
4097	 *  @param {array} json.aaData The data to display on this page
4098	 *  @param {string} [json.sColumns] Column ordering (sName, comma separated)
4099	 *  @memberof DataTable#oApi
4100	 */
4101	function _fnAjaxUpdateDraw ( settings, json )
4102	{
4103		// v1.10 uses camelCase variables, while 1.9 uses Hungarian notation.
4104		// Support both
4105		var compat = function ( old, modern ) {
4106			return json[old] !== undefined ? json[old] : json[modern];
4107		};
4108	
4109		var data = _fnAjaxDataSrc( settings, json );
4110		var draw            = compat( 'sEcho',                'draw' );
4111		var recordsTotal    = compat( 'iTotalRecords',        'recordsTotal' );
4112		var recordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' );
4113	
4114		if ( draw ) {
4115			// Protect against out of sequence returns
4116			if ( draw*1 < settings.iDraw ) {
4117				return;
4118			}
4119			settings.iDraw = draw * 1;
4120		}
4121	
4122		_fnClearTable( settings );
4123		settings._iRecordsTotal   = parseInt(recordsTotal, 10);
4124		settings._iRecordsDisplay = parseInt(recordsFiltered, 10);
4125	
4126		for ( var i=0, ien=data.length ; i<ien ; i++ ) {
4127			_fnAddData( settings, data[i] );
4128		}
4129		settings.aiDisplay = settings.aiDisplayMaster.slice();
4130	
4131		settings.bAjaxDataGet = false;
4132		_fnDraw( settings );
4133	
4134		if ( ! settings._bInitComplete ) {
4135			_fnInitComplete( settings, json );
4136		}
4137	
4138		settings.bAjaxDataGet = true;
4139		_fnProcessingDisplay( settings, false );
4140	}
4141	
4142	
4143	/**
4144	 * Get the data from the JSON data source to use for drawing a table. Using
4145	 * `_fnGetObjectDataFn` allows the data to be sourced from a property of the
4146	 * source object, or from a processing function.
4147	 *  @param {object} oSettings dataTables settings object
4148	 *  @param  {object} json Data source object / array from the server
4149	 *  @return {array} Array of data to use
4150	 */
4151	function _fnAjaxDataSrc ( oSettings, json )
4152	{
4153		var dataSrc = $.isPlainObject( oSettings.ajax ) && oSettings.ajax.dataSrc !== undefined ?
4154			oSettings.ajax.dataSrc :
4155			oSettings.sAjaxDataProp; // Compatibility with 1.9-.
4156	
4157		// Compatibility with 1.9-. In order to read from aaData, check if the
4158		// default has been changed, if not, check for aaData
4159		if ( dataSrc === 'data' ) {
4160			return json.aaData || json[dataSrc];
4161		}
4162	
4163		return dataSrc !== "" ?
4164			_fnGetObjectDataFn( dataSrc )( json ) :
4165			json;
4166	}
4167	
4168	/**
4169	 * Generate the node required for filtering text
4170	 *  @returns {node} Filter control element
4171	 *  @param {object} oSettings dataTables settings object
4172	 *  @memberof DataTable#oApi
4173	 */
4174	function _fnFeatureHtmlFilter ( settings )
4175	{
4176		var classes = settings.oClasses;
4177		var tableId = settings.sTableId;
4178		var language = settings.oLanguage;
4179		var previousSearch = settings.oPreviousSearch;
4180		var features = settings.aanFeatures;
4181		var input = '<input type="search" class="'+classes.sFilterInput+'"/>';
4182	
4183		var str = language.sSearch;
4184		str = str.match(/_INPUT_/) ?
4185			str.replace('_INPUT_', input) :
4186			str+input;
4187	
4188		var filter = $('<div/>', {
4189				'id': ! features.f ? tableId+'_filter' : null,
4190				'class': classes.sFilter
4191			} )
4192			.append( $('<label/>' ).append( str ) );
4193	
4194		var searchFn = function() {
4195			/* Update all other filter input elements for the new display */
4196			var n = features.f;
4197			var val = !this.value ? "" : this.value; // mental IE8 fix :-(
4198	
4199			/* Now do the filter */
4200			if ( val != previousSearch.sSearch ) {
4201				_fnFilterComplete( settings, {
4202					"sSearch": val,
4203					"bRegex": previousSearch.bRegex,
4204					"bSmart": previousSearch.bSmart ,
4205					"bCaseInsensitive": previousSearch.bCaseInsensitive
4206				} );
4207	
4208				// Need to redraw, without resorting
4209				settings._iDisplayStart = 0;
4210				_fnDraw( settings );
4211			}
4212		};
4213	
4214		var searchDelay = settings.searchDelay !== null ?
4215			settings.searchDelay :
4216			_fnDataSource( settings ) === 'ssp' ?
4217				400 :
4218				0;
4219	
4220		var jqFilter = $('input', filter)
4221			.val( previousSearch.sSearch )
4222			.attr( 'placeholder', language.sSearchPlaceholder )
4223			.on(
4224				'keyup.DT search.DT input.DT paste.DT cut.DT',
4225				searchDelay ?
4226					_fnThrottle( searchFn, searchDelay ) :
4227					searchFn
4228			)
4229			.on( 'keypress.DT', function(e) {
4230				/* Prevent form submission */
4231				if ( e.keyCode == 13 ) {
4232					return false;
4233				}
4234			} )
4235			.attr('aria-controls', tableId);
4236	
4237		// Update the input elements whenever the table is filtered
4238		$(settings.nTable).on( 'search.dt.DT', function ( ev, s ) {
4239			if ( settings === s ) {
4240				// IE9 throws an 'unknown error' if document.activeElement is used
4241				// inside an iframe or frame...
4242				try {
4243					if ( jqFilter[0] !== document.activeElement ) {
4244						jqFilter.val( previousSearch.sSearch );
4245					}
4246				}
4247				catch ( e ) {}
4248			}
4249		} );
4250	
4251		return filter[0];
4252	}
4253	
4254	
4255	/**
4256	 * Filter the table using both the global filter and column based filtering
4257	 *  @param {object} oSettings dataTables settings object
4258	 *  @param {object} oSearch search information
4259	 *  @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)
4260	 *  @memberof DataTable#oApi
4261	 */
4262	function _fnFilterComplete ( oSettings, oInput, iForce )
4263	{
4264		var oPrevSearch = oSettings.oPreviousSearch;
4265		var aoPrevSearch = oSettings.aoPreSearchCols;
4266		var fnSaveFilter = function ( oFilter ) {
4267			/* Save the filtering values */
4268			oPrevSearch.sSearch = oFilter.sSearch;
4269			oPrevSearch.bRegex = oFilter.bRegex;
4270			oPrevSearch.bSmart = oFilter.bSmart;
4271			oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive;
4272		};
4273		var fnRegex = function ( o ) {
4274			// Backwards compatibility with the bEscapeRegex option
4275			return o.bEscapeRegex !== undefined ? !o.bEscapeRegex : o.bRegex;
4276		};
4277	
4278		// Resolve any column types that are unknown due to addition or invalidation
4279		// @todo As per sort - can this be moved into an event handler?
4280		_fnColumnTypes( oSettings );
4281	
4282		/* In server-side processing all filtering is done by the server, so no point hanging around here */
4283		if ( _fnDataSource( oSettings ) != 'ssp' )
4284		{
4285			/* Global filter */
4286			_fnFilter( oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive );
4287			fnSaveFilter( oInput );
4288	
4289			/* Now do the individual column filter */
4290			for ( var i=0 ; i<aoPrevSearch.length ; i++ )
4291			{
4292				_fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, fnRegex(aoPrevSearch[i]),
4293					aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive );
4294			}
4295	
4296			/* Custom filtering */
4297			_fnFilterCustom( oSettings );
4298		}
4299		else
4300		{
4301			fnSaveFilter( oInput );
4302		}
4303	
4304		/* Tell the draw function we have been filtering */
4305		oSettings.bFiltered = true;
4306		_fnCallbackFire( oSettings, null, 'search', [oSettings] );
4307	}
4308	
4309	
4310	/**
4311	 * Apply custom filtering functions
4312	 *  @param {object} oSettings dataTables settings object
4313	 *  @memberof DataTable#oApi
4314	 */
4315	function _fnFilterCustom( settings )
4316	{
4317		var filters = DataTable.ext.search;
4318		var displayRows = settings.aiDisplay;
4319		var row, rowIdx;
4320	
4321		for ( var i=0, ien=filters.length ; i<ien ; i++ ) {
4322			var rows = [];
4323	
4324			// Loop over each row and see if it should be included
4325			for ( var j=0, jen=displayRows.length ; j<jen ; j++ ) {
4326				rowIdx = displayRows[ j ];
4327				row = settings.aoData[ rowIdx ];
4328	
4329				if ( filters[i]( settings, row._aFilterData, rowIdx, row._aData, j ) ) {
4330					rows.push( rowIdx );
4331				}
4332			}
4333	
4334			// So the array reference doesn't break set the results into the
4335			// existing array
4336			displayRows.length = 0;
4337			$.merge( displayRows, rows );
4338		}
4339	}
4340	
4341	
4342	/**
4343	 * Filter the table on a per-column basis
4344	 *  @param {object} oSettings dataTables settings object
4345	 *  @param {string} sInput string to filter on
4346	 *  @param {int} iColumn column to filter
4347	 *  @param {bool} bRegex treat search string as a regular expression or not
4348	 *  @param {bool} bSmart use smart filtering or not
4349	 *  @param {bool} bCaseInsensitive Do case insenstive matching or not
4350	 *  @memberof DataTable#oApi
4351	 */
4352	function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, caseInsensitive )
4353	{
4354		if ( searchStr === '' ) {
4355			return;
4356		}
4357	
4358		var data;
4359		var out = [];
4360		var display = settings.aiDisplay;
4361		var rpSearch = _fnFilterCreateSearch( searchStr, regex, smart, caseInsensitive );
4362	
4363		for ( var i=0 ; i<display.length ; i++ ) {
4364			data = settings.aoData[ display[i] ]._aFilterData[ colIdx ];
4365	
4366			if ( rpSearch.test( data ) ) {
4367				out.push( display[i] );
4368			}
4369		}
4370	
4371		settings.aiDisplay = out;
4372	}
4373	
4374	
4375	/**
4376	 * Filter the data table based on user input and draw the table
4377	 *  @param {object} settings dataTables settings object
4378	 *  @param {string} input string to filter on
4379	 *  @param {int} force optional - force a research of the master array (1) or not (undefined or 0)
4380	 *  @param {bool} regex treat as a regular expression or not
4381	 *  @param {bool} smart perform smart filtering or not
4382	 *  @param {bool} caseInsensitive Do case insenstive matching or not
4383	 *  @memberof DataTable#oApi
4384	 */
4385	function _fnFilter( settings, input, force, regex, smart, caseInsensitive )
4386	{
4387		var rpSearch = _fnFilterCreateSearch( input, regex, smart, caseInsensitive );
4388		var prevSearch = settings.oPreviousSearch.sSearch;
4389		var displayMaster = settings.aiDisplayMaster;
4390		var display, invalidated, i;
4391		var filtered = [];
4392	
4393		// Need to take account of custom filtering functions - always filter
4394		if ( DataTable.ext.search.length !== 0 ) {
4395			force = true;
4396		}
4397	
4398		// Check if any of the rows were invalidated
4399		invalidated = _fnFilterData( settings );
4400	
4401		// If the input is blank - we just want the full data set
4402		if ( input.length <= 0 ) {
4403			settings.aiDisplay = displayMaster.slice();
4404		}
4405		else {
4406			// New search - start from the master array
4407			if ( invalidated ||
4408				 force ||
4409				 prevSearch.length > input.length ||
4410				 input.indexOf(prevSearch) !== 0 ||
4411				 settings.bSorted // On resort, the display master needs to be
4412				                  // re-filtered since indexes will have changed
4413			) {
4414				settings.aiDisplay = displayMaster.slice();
4415			}
4416	
4417			// Search the display array
4418			display = settings.aiDisplay;
4419	
4420			for ( i=0 ; i<display.length ; i++ ) {
4421				if ( rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) {
4422					filtered.push( display[i] );
4423				}
4424			}
4425	
4426			settings.aiDisplay = filtered;
4427		}
4428	}
4429	
4430	
4431	/**
4432	 * Build a regular expression object suitable for searching a table
4433	 *  @param {string} sSearch string to search for
4434	 *  @param {bool} bRegex treat as a regular expression or not
4435	 *  @param {bool} bSmart perform smart filtering or not
4436	 *  @param {bool} bCaseInsensitive Do case insensitive matching or not
4437	 *  @returns {RegExp} constructed object
4438	 *  @memberof DataTable#oApi
4439	 */
4440	function _fnFilterCreateSearch( search, regex, smart, caseInsensitive )
4441	{
4442		search = regex ?
4443			search :
4444			_fnEscapeRegex( search );
4445		
4446		if ( smart ) {
4447			/* For smart filtering we want to allow the search to work regardless of
4448			 * word order. We also want double quoted text to be preserved, so word
4449			 * order is important - a la google. So this is what we want to
4450			 * generate:
4451			 * 
4452			 * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$
4453			 */
4454			var a = $.map( search.match( /"[^"]+"|[^ ]+/g ) || [''], function ( word ) {
4455				if ( word.charAt(0) === '"' ) {
4456					var m = word.match( /^"(.*)"$/ );
4457					word = m ? m[1] : word;
4458				}
4459	
4460				return word.replace('"', '');
4461			} );
4462	
4463			search = '^(?=.*?'+a.join( ')(?=.*?' )+').*$';
4464		}
4465	
4466		return new RegExp( search, caseInsensitive ? 'i' : '' );
4467	}
4468	
4469	
4470	/**
4471	 * Escape a string such that it can be used in a regular expression
4472	 *  @param {string} sVal string to escape
4473	 *  @returns {string} escaped string
4474	 *  @memberof DataTable#oApi
4475	 */
4476	var _fnEscapeRegex = DataTable.util.escapeRegex;
4477	
4478	var __filter_div = $('<div>')[0];
4479	var __filter_div_textContent = __filter_div.textContent !== undefined;
4480	
4481	// Update the filtering data for each row if needed (by invalidation or first run)
4482	function _fnFilterData ( settings )
4483	{
4484		var columns = settings.aoColumns;
4485		var column;
4486		var i, j, ien, jen, filterData, cellData, row;
4487		var fomatters = DataTable.ext.type.search;
4488		var wasInvalidated = false;
4489	
4490		for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
4491			row = settings.aoData[i];
4492	
4493			if ( ! row._aFilterData ) {
4494				filterData = [];
4495	
4496				for ( j=0, jen=columns.length ; j<jen ; j++ ) {
4497					column = columns[j];
4498	
4499					if ( column.bSearchable ) {
4500						cellData = _fnGetCellData( settings, i, j, 'filter' );
4501	
4502						if ( fomatters[ column.sType ] ) {
4503							cellData = fomatters[ column.sType ]( cellData );
4504						}
4505	
4506						// Search in DataTables 1.10 is string based. In 1.11 this
4507						// should be altered to also allow strict type checking.
4508						if ( cellData === null ) {
4509							cellData = '';
4510						}
4511	
4512						if ( typeof cellData !== 'string' && cellData.toString ) {
4513							cellData = cellData.toString();
4514						}
4515					}
4516					else {
4517						cellData = '';
4518					}
4519	
4520					// If it looks like there is an HTML entity in the string,
4521					// attempt to decode it so sorting works as expected. Note that
4522					// we could use a single line of jQuery to do this, but the DOM
4523					// method used here is much faster http://jsperf.com/html-decode
4524					if ( cellData.indexOf && cellData.indexOf('&') !== -1 ) {
4525						__filter_div.innerHTML = cellData;
4526						cellData = __filter_div_textContent ?
4527							__filter_div.textContent :
4528							__filter_div.innerText;
4529					}
4530	
4531					if ( cellData.replace ) {
4532						cellData = cellData.replace(/[\r\n]/g, '');
4533					}
4534	
4535					filterData.push( cellData );
4536				}
4537	
4538				row._aFilterData = filterData;
4539				row._sFilterRow = filterData.join('  ');
4540				wasInvalidated = true;
4541			}
4542		}
4543	
4544		return wasInvalidated;
4545	}
4546	
4547	
4548	/**
4549	 * Convert from the internal Hungarian notation to camelCase for external
4550	 * interaction
4551	 *  @param {object} obj Object to convert
4552	 *  @returns {object} Inverted object
4553	 *  @memberof DataTable#oApi
4554	 */
4555	function _fnSearchToCamel ( obj )
4556	{
4557		return {
4558			search:          obj.sSearch,
4559			smart:           obj.bSmart,
4560			regex:           obj.bRegex,
4561			caseInsensitive: obj.bCaseInsensitive
4562		};
4563	}
4564	
4565	
4566	
4567	/**
4568	 * Convert from camelCase notation to the internal Hungarian. We could use the
4569	 * Hungarian convert function here, but this is cleaner
4570	 *  @param {object} obj Object to convert
4571	 *  @returns {object} Inverted object
4572	 *  @memberof DataTable#oApi
4573	 */
4574	function _fnSearchToHung ( obj )
4575	{
4576		return {
4577			sSearch:          obj.search,
4578			bSmart:           obj.smart,
4579			bRegex:           obj.regex,
4580			bCaseInsensitive: obj.caseInsensitive
4581		};
4582	}
4583	
4584	/**
4585	 * Generate the node required for the info display
4586	 *  @param {object} oSettings dataTables settings object
4587	 *  @returns {node} Information element
4588	 *  @memberof DataTable#oApi
4589	 */
4590	function _fnFeatureHtmlInfo ( settings )
4591	{
4592		var
4593			tid = settings.sTableId,
4594			nodes = settings.aanFeatures.i,
4595			n = $('<div/>', {
4596				'class': settings.oClasses.sInfo,
4597				'id': ! nodes ? tid+'_info' : null
4598			} );
4599	
4600		if ( ! nodes ) {
4601			// Update display on each draw
4602			settings.aoDrawCallback.push( {
4603				"fn": _fnUpdateInfo,
4604				"sName": "information"
4605			} );
4606	
4607			n
4608				.attr( 'role', 'status' )
4609				.attr( 'aria-live', 'polite' );
4610	
4611			// Table is described by our info div
4612			$(settings.nTable).attr( 'aria-describedby', tid+'_info' );
4613		}
4614	
4615		return n[0];
4616	}
4617	
4618	
4619	/**
4620	 * Update the information elements in the display
4621	 *  @param {object} settings dataTables settings object
4622	 *  @memberof DataTable#oApi
4623	 */
4624	function _fnUpdateInfo ( settings )
4625	{
4626		/* Show information about the table */
4627		var nodes = settings.aanFeatures.i;
4628		if ( nodes.length === 0 ) {
4629			return;
4630		}
4631	
4632		var
4633			lang  = settings.oLanguage,
4634			start = settings._iDisplayStart+1,
4635			end   = settings.fnDisplayEnd(),
4636			max   = settings.fnRecordsTotal(),
4637			total = settings.fnRecordsDisplay(),
4638			out   = total ?
4639				lang.sInfo :
4640				lang.sInfoEmpty;
4641	
4642		if ( total !== max ) {
4643			/* Record set after filtering */
4644			out += ' ' + lang.sInfoFiltered;
4645		}
4646	
4647		// Convert the macros
4648		out += lang.sInfoPostFix;
4649		out = _fnInfoMacros( settings, out );
4650	
4651		var callback = lang.fnInfoCallback;
4652		if ( callback !== null ) {
4653			out = callback.call( settings.oInstance,
4654				settings, start, end, max, total, out
4655			);
4656		}
4657	
4658		$(nodes).html( out );
4659	}
4660	
4661	
4662	function _fnInfoMacros ( settings, str )
4663	{
4664		// When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
4665		// internally
4666		var
4667			formatter  = settings.fnFormatNumber,
4668			start      = settings._iDisplayStart+1,
4669			len        = settings._iDisplayLength,
4670			vis        = settings.fnRecordsDisplay(),
4671			all        = len === -1;
4672	
4673		return str.
4674			replace(/_START_/g, formatter.call( settings, start ) ).
4675			replace(/_END_/g,   formatter.call( settings, settings.fnDisplayEnd() ) ).
4676			replace(/_MAX_/g,   formatter.call( settings, settings.fnRecordsTotal() ) ).
4677			replace(/_TOTAL_/g, formatter.call( settings, vis ) ).
4678			replace(/_PAGE_/g,  formatter.call( settings, all ? 1 : Math.ceil( start / len ) ) ).
4679			replace(/_PAGES_/g, formatter.call( settings, all ? 1 : Math.ceil( vis / len ) ) );
4680	}
4681	
4682	
4683	
4684	/**
4685	 * Draw the table for the first time, adding all required features
4686	 *  @param {object} settings dataTables settings object
4687	 *  @memberof DataTable#oApi
4688	 */
4689	function _fnInitialise ( settings )
4690	{
4691		var i, iLen, iAjaxStart=settings.iInitDisplayStart;
4692		var columns = settings.aoColumns, column;
4693		var features = settings.oFeatures;
4694		var deferLoading = settings.bDeferLoading; // value modified by the draw
4695	
4696		/* Ensure that the table data is fully initialised */
4697		if ( ! settings.bInitialised ) {
4698			setTimeout( function(){ _fnInitialise( settings ); }, 200 );
4699			return;
4700		}
4701	
4702		/* Show the display HTML options */
4703		_fnAddOptionsHtml( settings );
4704	
4705		/* Build and draw the header / footer for the table */
4706		_fnBuildHead( settings );
4707		_fnDrawHead( settings, settings.aoHeader );
4708		_fnDrawHead( settings, settings.aoFooter );
4709	
4710		/* Okay to show that something is going on now */
4711		_fnProcessingDisplay( settings, true );
4712	
4713		/* Calculate sizes for columns */
4714		if ( features.bAutoWidth ) {
4715			_fnCalculateColumnWidths( settings );
4716		}
4717	
4718		for ( i=0, iLen=columns.length ; i<iLen ; i++ ) {
4719			column = columns[i];
4720	
4721			if ( column.sWidth ) {
4722				column.nTh.style.width = _fnStringToCss( column.sWidth );
4723			}
4724		}
4725	
4726		_fnCallbackFire( settings, null, 'preInit', [settings] );
4727	
4728		// If there is default sorting required - let's do it. The sort function
4729		// will do the drawing for us. Otherwise we draw the table regardless of the
4730		// Ajax source - this allows the table to look initialised for Ajax sourcing
4731		// data (show 'loading' message possibly)
4732		_fnReDraw( settings );
4733	
4734		// Server-side processing init complete is done by _fnAjaxUpdateDraw
4735		var dataSrc = _fnDataSource( settings );
4736		if ( dataSrc != 'ssp' || deferLoading ) {
4737			// if there is an ajax source load the data
4738			if ( dataSrc == 'ajax' ) {
4739				_fnBuildAjax( settings, [], function(json) {
4740					var aData = _fnAjaxDataSrc( settings, json );
4741	
4742					// Got the data - add it to the table
4743					for ( i=0 ; i<aData.length ; i++ ) {
4744						_fnAddData( settings, aData[i] );
4745					}
4746	
4747					// Reset the init display for cookie saving. We've already done
4748					// a filter, and therefore cleared it before. So we need to make
4749					// it appear 'fresh'
4750					settings.iInitDisplayStart = iAjaxStart;
4751	
4752					_fnReDraw( settings );
4753	
4754					_fnProcessingDisplay( settings, false );
4755					_fnInitComplete( settings, json );
4756				}, settings );
4757			}
4758			else {
4759				_fnProcessingDisplay( settings, false );
4760				_fnInitComplete( settings );
4761			}
4762		}
4763	}
4764	
4765	
4766	/**
4767	 * Draw the table for the first time, adding all required features
4768	 *  @param {object} oSettings dataTables settings object
4769	 *  @param {object} [json] JSON from the server that completed the table, if using Ajax source
4770	 *    with client-side processing (optional)
4771	 *  @memberof DataTable#oApi
4772	 */
4773	function _fnInitComplete ( settings, json )
4774	{
4775		settings._bInitComplete = true;
4776	
4777		// When data was added after the initialisation (data or Ajax) we need to
4778		// calculate the column sizing
4779		if ( json || settings.oInit.aaData ) {
4780			_fnAdjustColumnSizing( settings );
4781		}
4782	
4783		_fnCallbackFire( settings, null, 'plugin-init', [settings, json] );
4784		_fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] );
4785	}
4786	
4787	
4788	function _fnLengthChange ( settings, val )
4789	{
4790		var len = parseInt( val, 10 );
4791		settings._iDisplayLength = len;
4792	
4793		_fnLengthOverflow( settings );
4794	
4795		// Fire length change event
4796		_fnCallbackFire( settings, null, 'length', [settings, len] );
4797	}
4798	
4799	
4800	/**
4801	 * Generate the node required for user display length changing
4802	 *  @param {object} settings dataTables settings object
4803	 *  @returns {node} Display length feature node
4804	 *  @memberof DataTable#oApi
4805	 */
4806	function _fnFeatureHtmlLength ( settings )
4807	{
4808		var
4809			classes  = settings.oClasses,
4810			tableId  = settings.sTableId,
4811			menu     = settings.aLengthMenu,
4812			d2       = $.isArray( menu[0] ),
4813			lengths  = d2 ? menu[0] : menu,
4814			language = d2 ? menu[1] : menu;
4815	
4816		var select = $('<select/>', {
4817			'name':          tableId+'_length',
4818			'aria-controls': tableId,
4819			'class':         classes.sLengthSelect
4820		} );
4821	
4822		for ( var i=0, ien=lengths.length ; i<ien ; i++ ) {
4823			select[0][ i ] = new Option(
4824				typeof language[i] === 'number' ?
4825					settings.fnFormatNumber( language[i] ) :
4826					language[i],
4827				lengths[i]
4828			);
4829		}
4830	
4831		var div = $('<div><label/></div>').addClass( classes.sLength );
4832		if ( ! settings.aanFeatures.l ) {
4833			div[0].id = tableId+'_length';
4834		}
4835	
4836		div.children().append(
4837			settings.oLanguage.sLengthMenu.replace( '_MENU_', select[0].outerHTML )
4838		);
4839	
4840		// Can't use `select` variable as user might provide their own and the
4841		// reference is broken by the use of outerHTML
4842		$('select', div)
4843			.val( settings._iDisplayLength )
4844			.on( 'change.DT', function(e) {
4845				_fnLengthChange( settings, $(this).val() );
4846				_fnDraw( settings );
4847			} );
4848	
4849		// Update node value whenever anything changes the table's length
4850		$(settings.nTable).on( 'length.dt.DT', function (e, s, len) {
4851			if ( settings === s ) {
4852				$('select', div).val( len );
4853			}
4854		} );
4855	
4856		return div[0];
4857	}
4858	
4859	
4860	
4861	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
4862	 * Note that most of the paging logic is done in
4863	 * DataTable.ext.pager
4864	 */
4865	
4866	/**
4867	 * Generate the node required for default pagination
4868	 *  @param {object} oSettings dataTables settings object
4869	 *  @returns {node} Pagination feature node
4870	 *  @memberof DataTable#oApi
4871	 */
4872	function _fnFeatureHtmlPaginate ( settings )
4873	{
4874		var
4875			type   = settings.sPaginationType,
4876			plugin = DataTable.ext.pager[ type ],
4877			modern = typeof plugin === 'function',
4878			redraw = function( settings ) {
4879				_fnDraw( settings );
4880			},
4881			node = $('<div/>').addClass( settings.oClasses.sPaging + type )[0],
4882			features = settings.aanFeatures;
4883	
4884		if ( ! modern ) {
4885			plugin.fnInit( settings, node, redraw );
4886		}
4887	
4888		/* Add a draw callback for the pagination on first instance, to update the paging display */
4889		if ( ! features.p )
4890		{
4891			node.id = settings.sTableId+'_paginate';
4892	
4893			settings.aoDrawCallback.push( {
4894				"fn": function( settings ) {
4895					if ( modern ) {
4896						var
4897							start      = settings._iDisplayStart,
4898							len        = settings._iDisplayLength,
4899							visRecords = settings.fnRecordsDisplay(),
4900							all        = len === -1,
4901							page = all ? 0 : Math.ceil( start / len ),
4902							pages = all ? 1 : Math.ceil( visRecords / len ),
4903							buttons = plugin(page, pages),
4904							i, ien;
4905	
4906						for ( i=0, ien=features.p.length ; i<ien ; i++ ) {
4907							_fnRenderer( settings, 'pageButton' )(
4908								settings, features.p[i], i, buttons, page, pages
4909							);
4910						}
4911					}
4912					else {
4913						plugin.fnUpdate( settings, redraw );
4914					}
4915				},
4916				"sName": "pagination"
4917			} );
4918		}
4919	
4920		return node;
4921	}
4922	
4923	
4924	/**
4925	 * Alter the display settings to change the page
4926	 *  @param {object} settings DataTables settings object
4927	 *  @param {string|int} action Paging action to take: "first", "previous",
4928	 *    "next" or "last" or page number to jump to (integer)
4929	 *  @param [bool] redraw Automatically draw the update or not
4930	 *  @returns {bool} true page has changed, false - no change
4931	 *  @memberof DataTable#oApi
4932	 */
4933	function _fnPageChange ( settings, action, redraw )
4934	{
4935		var
4936			start     = settings._iDisplayStart,
4937			len       = settings._iDisplayLength,
4938			records   = settings.fnRecordsDisplay();
4939	
4940		if ( records === 0 || len === -1 )
4941		{
4942			start = 0;
4943		}
4944		else if ( typeof action === "number" )
4945		{
4946			start = action * len;
4947	
4948			if ( start > records )
4949			{
4950				start = 0;
4951			}
4952		}
4953		else if ( action == "first" )
4954		{
4955			start = 0;
4956		}
4957		else if ( action == "previous" )
4958		{
4959			start = len >= 0 ?
4960				start - len :
4961				0;
4962	
4963			if ( start < 0 )
4964			{
4965			  start = 0;
4966			}
4967		}
4968		else if ( action == "next" )
4969		{
4970			if ( start + len < records )
4971			{
4972				start += len;
4973			}
4974		}
4975		else if ( action == "last" )
4976		{
4977			start = Math.floor( (records-1) / len) * len;
4978		}
4979		else
4980		{
4981			_fnLog( settings, 0, "Unknown paging action: "+action, 5 );
4982		}
4983	
4984		var changed = settings._iDisplayStart !== start;
4985		settings._iDisplayStart = start;
4986	
4987		if ( changed ) {
4988			_fnCallbackFire( settings, null, 'page', [settings] );
4989	
4990			if ( redraw ) {
4991				_fnDraw( settings );
4992			}
4993		}
4994	
4995		return changed;
4996	}
4997	
4998	
4999	
5000	/**
5001	 * Generate the node required for the processing node
5002	 *  @param {object} settings dataTables settings object
5003	 *  @returns {node} Processing element
5004	 *  @memberof DataTable#oApi
5005	 */
5006	function _fnFeatureHtmlProcessing ( settings )
5007	{
5008		return $('<div/>', {
5009				'id': ! settings.aanFeatures.r ? settings.sTableId+'_processing' : null,
5010				'class': settings.oClasses.sProcessing
5011			} )
5012			.html( settings.oLanguage.sProcessing )
5013			.insertBefore( settings.nTable )[0];
5014	}
5015	
5016	
5017	/**
5018	 * Display or hide the processing indicator
5019	 *  @param {object} settings dataTables settings object
5020	 *  @param {bool} show Show the processing indicator (true) or not (false)
5021	 *  @memberof DataTable#oApi
5022	 */
5023	function _fnProcessingDisplay ( settings, show )
5024	{
5025		if ( settings.oFeatures.bProcessing ) {
5026			$(settings.aanFeatures.r).css( 'display', show ? 'block' : 'none' );
5027		}
5028	
5029		_fnCallbackFire( settings, null, 'processing', [settings, show] );
5030	}
5031	
5032	/**
5033	 * Add any control elements for the table - specifically scrolling
5034	 *  @param {object} settings dataTables settings object
5035	 *  @returns {node} Node to add to the DOM
5036	 *  @memberof DataTable#oApi
5037	 */
5038	function _fnFeatureHtmlTable ( settings )
5039	{
5040		var table = $(settings.nTable);
5041	
5042		// Add the ARIA grid role to the table
5043		table.attr( 'role', 'grid' );
5044	
5045		// Scrolling from here on in
5046		var scroll = settings.oScroll;
5047	
5048		if ( scroll.sX === '' && scroll.sY === '' ) {
5049			return settings.nTable;
5050		}
5051	
5052		var scrollX = scroll.sX;
5053		var scrollY = scroll.sY;
5054		var classes = settings.oClasses;
5055		var caption = table.children('caption');
5056		var captionSide = caption.length ? caption[0]._captionSide : null;
5057		var headerClone = $( table[0].cloneNode(false) );
5058		var footerClone = $( table[0].cloneNode(false) );
5059		var footer = table.children('tfoot');
5060		var _div = '<div/>';
5061		var size = function ( s ) {
5062			return !s ? null : _fnStringToCss( s );
5063		};
5064	
5065		if ( ! footer.length ) {
5066			footer = null;
5067		}
5068	
5069		/*
5070		 * The HTML structure that we want to generate in this function is:
5071		 *  div - scroller
5072		 *    div - scroll head
5073		 *      div - scroll head inner
5074		 *        table - scroll head table
5075		 *          thead - thead
5076		 *    div - scroll body
5077		 *      table - table (master table)
5078		 *        thead - thead clone for sizing
5079		 *        tbody - tbody
5080		 *    div - scroll foot
5081		 *      div - scroll foot inner
5082		 *        table - scroll foot table
5083		 *          tfoot - tfoot
5084		 */
5085		var scroller = $( _div, { 'class': classes.sScrollWrapper } )
5086			.append(
5087				$(_div, { 'class': classes.sScrollHead } )
5088					.css( {
5089						overflow: 'hidden',
5090						position: 'relative',
5091						border: 0,
5092						width: scrollX ? size(scrollX) : '100%'
5093					} )
5094					.append(
5095						$(_div, { 'class': classes.sScrollHeadInner } )
5096							.css( {
5097								'box-sizing': 'content-box',
5098								width: scroll.sXInner || '100%'
5099							} )
5100							.append(
5101								headerClone
5102									.removeAttr('id')
5103									.css( 'margin-left', 0 )
5104									.append( captionSide === 'top' ? caption : null )
5105									.append(
5106										table.children('thead')
5107									)
5108							)
5109					)
5110			)
5111			.append(
5112				$(_div, { 'class': classes.sScrollBody } )
5113					.css( {
5114						position: 'relative',
5115						overflow: 'auto',
5116						width: size( scrollX )
5117					} )
5118					.append( table )
5119			);
5120	
5121		if ( footer ) {
5122			scroller.append(
5123				$(_div, { 'class': classes.sScrollFoot } )
5124					.css( {
5125						overflow: 'hidden',
5126						border: 0,
5127						width: scrollX ? size(scrollX) : '100%'
5128					} )
5129					.append(
5130						$(_div, { 'class': classes.sScrollFootInner } )
5131							.append(
5132								footerClone
5133									.removeAttr('id')
5134									.css( 'margin-left', 0 )
5135									.append( captionSide === 'bottom' ? caption : null )
5136									.append(
5137										table.children('tfoot')
5138									)
5139							)
5140					)
5141			);
5142		}
5143	
5144		var children = scroller.children();
5145		var scrollHead = children[0];
5146		var scrollBody = children[1];
5147		var scrollFoot = footer ? children[2] : null;
5148	
5149		// When the body is scrolled, then we also want to scroll the headers
5150		if ( scrollX ) {
5151			$(scrollBody).on( 'scroll.DT', function (e) {
5152				var scrollLeft = this.scrollLeft;
5153	
5154				scrollHead.scrollLeft = scrollLeft;
5155	
5156				if ( footer ) {
5157					scrollFoot.scrollLeft = scrollLeft;
5158				}
5159			} );
5160		}
5161	
5162		$(scrollBody).css(
5163			scrollY && scroll.bCollapse ? 'max-height' : 'height', 
5164			scrollY
5165		);
5166	
5167		settings.nScrollHead = scrollHead;
5168		settings.nScrollBody = scrollBody;
5169		settings.nScrollFoot = scrollFoot;
5170	
5171		// On redraw - align columns
5172		settings.aoDrawCallback.push( {
5173			"fn": _fnScrollDraw,
5174			"sName": "scrolling"
5175		} );
5176	
5177		return scroller[0];
5178	}
5179	
5180	
5181	
5182	/**
5183	 * Update the header, footer and body tables for resizing - i.e. column
5184	 * alignment.
5185	 *
5186	 * Welcome to the most horrible function DataTables. The process that this
5187	 * function follows is basically:
5188	 *   1. Re-create the table inside the scrolling div
5189	 *   2. Take live measurements from the DOM
5190	 *   3. Apply the measurements to align the columns
5191	 *   4. Clean up
5192	 *
5193	 *  @param {object} settings dataTables settings object
5194	 *  @memberof DataTable#oApi
5195	 */
5196	function _fnScrollDraw ( settings )
5197	{
5198		// Given that this is such a monster function, a lot of variables are use
5199		// to try and keep the minimised size as small as possible
5200		var
5201			scroll         = settings.oScroll,
5202			scrollX        = scroll.sX,
5203			scrollXInner   = scroll.sXInner,
5204			scrollY        = scroll.sY,
5205			barWidth       = scroll.iBarWidth,
5206			divHeader      = $(settings.nScrollHead),
5207			divHeaderStyle = divHeader[0].style,
5208			divHeaderInner = divHeader.children('div'),
5209			divHeaderInnerStyle = divHeaderInner[0].style,
5210			divHeaderTable = divHeaderInner.children('table'),
5211			divBodyEl      = settings.nScrollBody,
5212			divBody        = $(divBodyEl),
5213			divBodyStyle   = divBodyEl.style,
5214			divFooter      = $(settings.nScrollFoot),
5215			divFooterInner = divFooter.children('div'),
5216			divFooterTable = divFooterInner.children('table'),
5217			header         = $(settings.nTHead),
5218			table          = $(settings.nTable),
5219			tableEl        = table[0],
5220			tableStyle     = tableEl.style,
5221			footer         = settings.nTFoot ? $(settings.nTFoot) : null,
5222			browser        = settings.oBrowser,
5223			ie67           = browser.bScrollOversize,
5224			dtHeaderCells  = _pluck( settings.aoColumns, 'nTh' ),
5225			headerTrgEls, footerTrgEls,
5226			headerSrcEls, footerSrcEls,
5227			headerCopy, footerCopy,
5228			headerWidths=[], footerWidths=[],
5229			headerContent=[], footerContent=[],
5230			idx, correction, sanityWidth,
5231			zeroOut = function(nSizer) {
5232				var style = nSizer.style;
5233				style.paddingTop = "0";
5234				style.paddingBottom = "0";
5235				style.borderTopWidth = "0";
5236				style.borderBottomWidth = "0";
5237				style.height = 0;
5238			};
5239	
5240		// If the scrollbar visibility has changed from the last draw, we need to
5241		// adjust the column sizes as the table width will have changed to account
5242		// for the scrollbar
5243		var scrollBarVis = divBodyEl.scrollHeight > divBodyEl.clientHeight;
5244		
5245		if ( settings.scrollBarVis !== scrollBarVis && settings.scrollBarVis !== undefined ) {
5246			settings.scrollBarVis = scrollBarVis;
5247			_fnAdjustColumnSizing( settings );
5248			return; // adjust column sizing will call this function again
5249		}
5250		else {
5251			settings.scrollBarVis = scrollBarVis;
5252		}
5253	
5254		/*
5255		 * 1. Re-create the table inside the scrolling div
5256		 */
5257	
5258		// Remove the old minimised thead and tfoot elements in the inner table
5259		table.children('thead, tfoot').remove();
5260	
5261		if ( footer ) {
5262			footerCopy = footer.clone().prependTo( table );
5263			footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized
5264			footerSrcEls = footerCopy.find('tr');
5265		}
5266	
5267		// Clone the current header and footer elements and then place it into the inner table
5268		headerCopy = header.clone().prependTo( table );
5269		headerTrgEls = header.find('tr'); // original header is in its own table
5270		headerSrcEls = headerCopy.find('tr');
5271		headerCopy.find('th, td').removeAttr('tabindex');
5272	
5273	
5274		/*
5275		 * 2. Take live measurements from the DOM - do not alter the DOM itself!
5276		 */
5277	
5278		// Remove old sizing and apply the calculated column widths
5279		// Get the unique column headers in the newly created (cloned) header. We want to apply the
5280		// calculated sizes to this header
5281		if ( ! scrollX )
5282		{
5283			divBodyStyle.width = '100%';
5284			divHeader[0].style.width = '100%';
5285		}
5286	
5287		$.each( _fnGetUniqueThs( settings, headerCopy ), function ( i, el ) {
5288			idx = _fnVisibleToColumnIndex( settings, i );
5289			el.style.width = settings.aoColumns[idx].sWidth;
5290		} );
5291	
5292		if ( footer ) {
5293			_fnApplyToChildren( function(n) {
5294				n.style.width = "";
5295			}, footerSrcEls );
5296		}
5297	
5298		// Size the table as a whole
5299		sanityWidth = table.outerWidth();
5300		if ( scrollX === "" ) {
5301			// No x scrolling
5302			tableStyle.width = "100%";
5303	
5304			// IE7 will make the width of the table when 100% include the scrollbar
5305			// - which is shouldn't. When there is a scrollbar we need to take this
5306			// into account.
5307			if ( ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight ||
5308				divBody.css('overflow-y') == "scroll")
5309			) {
5310				tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth);
5311			}
5312	
5313			// Recalculate the sanity width
5314			sanityWidth = table.outerWidth();
5315		}
5316		else if ( scrollXInner !== "" ) {
5317			// legacy x scroll inner has been given - use it
5318			tableStyle.width = _fnStringToCss(scrollXInner);
5319	
5320			// Recalculate the sanity width
5321			sanityWidth = table.outerWidth();
5322		}
5323	
5324		// Hidden header should have zero height, so remove padding and borders. Then
5325		// set the width based on the real headers
5326	
5327		// Apply all styles in one pass
5328		_fnApplyToChildren( zeroOut, headerSrcEls );
5329	
5330		// Read all widths in next pass
5331		_fnApplyToChildren( function(nSizer) {
5332			headerContent.push( nSizer.innerHTML );
5333			headerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
5334		}, headerSrcEls );
5335	
5336		// Apply all widths in final pass
5337		_fnApplyToChildren( function(nToSize, i) {
5338			// Only apply widths to the DataTables detected header cells - this
5339			// prevents complex headers from having contradictory sizes applied
5340			if ( $.inArray( nToSize, dtHeaderCells ) !== -1 ) {
5341				nToSize.style.width = headerWidths[i];
5342			}
5343		}, headerTrgEls );
5344	
5345		$(headerSrcEls).height(0);
5346	
5347		/* Same again with the footer if we have one */
5348		if ( footer )
5349		{
5350			_fnApplyToChildren( zeroOut, footerSrcEls );
5351	
5352			_fnApplyToChildren( function(nSizer) {
5353				footerContent.push( nSizer.innerHTML );
5354				footerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
5355			}, footerSrcEls );
5356	
5357			_fnApplyToChildren( function(nToSize, i) {
5358				nToSize.style.width = footerWidths[i];
5359			}, footerTrgEls );
5360	
5361			$(footerSrcEls).height(0);
5362		}
5363	
5364	
5365		/*
5366		 * 3. Apply the measurements
5367		 */
5368	
5369		// "Hide" the header and footer that we used for the sizing. We need to keep
5370		// the content of the cell so that the width applied to the header and body
5371		// both match, but we want to hide it completely. We want to also fix their
5372		// width to what they currently are
5373		_fnApplyToChildren( function(nSizer, i) {
5374			nSizer.innerHTML = '<div class="dataTables_sizing">'+headerContent[i]+'</div>';
5375			nSizer.childNodes[0].style.height = "0";
5376			nSizer.childNodes[0].style.overflow = "hidden";
5377			nSizer.style.width = headerWidths[i];
5378		}, headerSrcEls );
5379	
5380		if ( footer )
5381		{
5382			_fnApplyToChildren( function(nSizer, i) {
5383				nSizer.innerHTML = '<div class="dataTables_sizing">'+footerContent[i]+'</div>';
5384				nSizer.childNodes[0].style.height = "0";
5385				nSizer.childNodes[0].style.overflow = "hidden";
5386				nSizer.style.width = footerWidths[i];
5387			}, footerSrcEls );
5388		}
5389	
5390		// Sanity check that the table is of a sensible width. If not then we are going to get
5391		// misalignment - try to prevent this by not allowing the table to shrink below its min width
5392		if ( table.outerWidth() < sanityWidth )
5393		{
5394			// The min width depends upon if we have a vertical scrollbar visible or not */
5395			correction = ((divBodyEl.scrollHeight > divBodyEl.offsetHeight ||
5396				divBody.css('overflow-y') == "scroll")) ?
5397					sanityWidth+barWidth :
5398					sanityWidth;
5399	
5400			// IE6/7 are a law unto themselves...
5401			if ( ie67 && (divBodyEl.scrollHeight >
5402				divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll")
5403			) {
5404				tableStyle.width = _fnStringToCss( correction-barWidth );
5405			}
5406	
5407			// And give the user a warning that we've stopped the table getting too small
5408			if ( scrollX === "" || scrollXInner !== "" ) {
5409				_fnLog( settings, 1, 'Possible column misalignment', 6 );
5410			}
5411		}
5412		else
5413		{
5414			correction = '100%';
5415		}
5416	
5417		// Apply to the container elements
5418		divBodyStyle.width = _fnStringToCss( correction );
5419		divHeaderStyle.width = _fnStringToCss( correction );
5420	
5421		if ( footer ) {
5422			settings.nScrollFoot.style.width = _fnStringToCss( correction );
5423		}
5424	
5425	
5426		/*
5427		 * 4. Clean up
5428		 */
5429		if ( ! scrollY ) {
5430			/* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
5431			 * the scrollbar height from the visible display, rather than adding it on. We need to
5432			 * set the height in order to sort this. Don't want to do it in any other browsers.
5433			 */
5434			if ( ie67 ) {
5435				divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+barWidth );
5436			}
5437		}
5438	
5439		/* Finally set the width's of the header and footer tables */
5440		var iOuterWidth = table.outerWidth();
5441		divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth );
5442		divHeaderInnerStyle.width = _fnStringToCss( iOuterWidth );
5443	
5444		// Figure out if there are scrollbar present - if so then we need a the header and footer to
5445		// provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
5446		var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll";
5447		var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' );
5448		divHeaderInnerStyle[ padding ] = bScrolling ? barWidth+"px" : "0px";
5449	
5450		if ( footer ) {
5451			divFooterTable[0].style.width = _fnStringToCss( iOuterWidth );
5452			divFooterInner[0].style.width = _fnStringToCss( iOuterWidth );
5453			divFooterInner[0].style[padding] = bScrolling ? barWidth+"px" : "0px";
5454		}
5455	
5456		// Correct DOM ordering for colgroup - comes before the thead
5457		table.children('colgroup').insertBefore( table.children('thead') );
5458	
5459		/* Adjust the position of the header in case we loose the y-scrollbar */
5460		divBody.scroll(
vendor: 11,594 bytes, lines 5460-5858
5460);
5461	
5462		// If sorting or filtering has occurred, jump the scrolling back to the top
5463		// only if we aren't holding the position
5464		if ( (settings.bSorted || settings.bFiltered) && ! settings._drawHold ) {
5465			divBodyEl.scrollTop = 0;
5466		}
5467	}
5468	
5469	
5470	
5471	/**
5472	 * Apply a given function to the display child nodes of an element array (typically
5473	 * TD children of TR rows
5474	 *  @param {function} fn Method to apply to the objects
5475	 *  @param array {nodes} an1 List of elements to look through for display children
5476	 *  @param array {nodes} an2 Another list (identical structure to the first) - optional
5477	 *  @memberof DataTable#oApi
5478	 */
5479	function _fnApplyToChildren( fn, an1, an2 )
5480	{
5481		var index=0, i=0, iLen=an1.length;
5482		var nNode1, nNode2;
5483	
5484		while ( i < iLen ) {
5485			nNode1 = an1[i].firstChild;
5486			nNode2 = an2 ? an2[i].firstChild : null;
5487	
5488			while ( nNode1 ) {
5489				if ( nNode1.nodeType === 1 ) {
5490					if ( an2 ) {
5491						fn( nNode1, nNode2, index );
5492					}
5493					else {
5494						fn( nNode1, index );
5495					}
5496	
5497					index++;
5498				}
5499	
5500				nNode1 = nNode1.nextSibling;
5501				nNode2 = an2 ? nNode2.nextSibling : null;
5502			}
5503	
5504			i++;
5505		}
5506	}
5507	
5508	
5509	
5510	var __re_html_remove = /<.*?>/g;
5511	
5512	
5513	/**
5514	 * Calculate the width of columns for the table
5515	 *  @param {object} oSettings dataTables settings object
5516	 *  @memberof DataTable#oApi
5517	 */
5518	function _fnCalculateColumnWidths ( oSettings )
5519	{
5520		var
5521			table = oSettings.nTable,
5522			columns = oSettings.aoColumns,
5523			scroll = oSettings.oScroll,
5524			scrollY = scroll.sY,
5525			scrollX = scroll.sX,
5526			scrollXInner = scroll.sXInner,
5527			columnCount = columns.length,
5528			visibleColumns = _fnGetColumns( oSettings, 'bVisible' ),
5529			headerCells = $('th', oSettings.nTHead),
5530			tableWidthAttr = table.getAttribute('width'), // from DOM element
5531			tableContainer = table.parentNode,
5532			userInputs = false,
5533			i, column, columnIdx, width, outerWidth,
5534			browser = oSettings.oBrowser,
5535			ie67 = browser.bScrollOversize;
5536	
5537		var styleWidth = table.style.width;
5538		if ( styleWidth && styleWidth.indexOf('%') !== -1 ) {
5539			tableWidthAttr = styleWidth;
5540		}
5541	
5542		/* Convert any user input sizes into pixel sizes */
5543		for ( i=0 ; i<visibleColumns.length ; i++ ) {
5544			column = columns[ visibleColumns[i] ];
5545	
5546			if ( column.sWidth !== null ) {
5547				column.sWidth = _fnConvertToWidth( column.sWidthOrig, tableContainer );
5548	
5549				userInputs = true;
5550			}
5551		}
5552	
5553		/* If the number of columns in the DOM equals the number that we have to
5554		 * process in DataTables, then we can use the offsets that are created by
5555		 * the web- browser. No custom sizes can be set in order for this to happen,
5556		 * nor scrolling used
5557		 */
5558		if ( ie67 || ! userInputs && ! scrollX && ! scrollY &&
5559		     columnCount == _fnVisbleColumns( oSettings ) &&
5560		     columnCount == headerCells.length
5561		) {
5562			for ( i=0 ; i<columnCount ; i++ ) {
5563				var colIdx = _fnVisibleToColumnIndex( oSettings, i );
5564	
5565				if ( colIdx !== null ) {
5566					columns[ colIdx ].sWidth = _fnStringToCss( headerCells.eq(i).width() );
5567				}
5568			}
5569		}
5570		else
5571		{
5572			// Otherwise construct a single row, worst case, table with the widest
5573			// node in the data, assign any user defined widths, then insert it into
5574			// the DOM and allow the browser to do all the hard work of calculating
5575			// table widths
5576			var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table
5577				.css( 'visibility', 'hidden' )
5578				.removeAttr( 'id' );
5579	
5580			// Clean up the table body
5581			tmpTable.find('tbody tr').remove();
5582			var tr = $('<tr/>').appendTo( tmpTable.find('tbody') );
5583	
5584			// Clone the table header and footer - we can't use the header / footer
5585			// from the cloned table, since if scrolling is active, the table's
5586			// real header and footer are contained in different table tags
5587			tmpTable.find('thead, tfoot').remove();
5588			tmpTable
5589				.append( $(oSettings.nTHead).clone() )
5590				.append( $(oSettings.nTFoot).clone() );
5591	
5592			// Remove any assigned widths from the footer (from scrolling)
5593			tmpTable.find('tfoot th, tfoot td').css('width', '');
5594	
5595			// Apply custom sizing to the cloned header
5596			headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] );
5597	
5598			for ( i=0 ; i<visibleColumns.length ; i++ ) {
5599				column = columns[ visibleColumns[i] ];
5600	
5601				headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ?
5602					_fnStringToCss( column.sWidthOrig ) :
5603					'';
5604	
5605				// For scrollX we need to force the column width otherwise the
5606				// browser will collapse it. If this width is smaller than the
5607				// width the column requires, then it will have no effect
5608				if ( column.sWidthOrig && scrollX ) {
5609					$( headerCells[i] ).append( $('<div/>').css( {
5610						width: column.sWidthOrig,
5611						margin: 0,
5612						padding: 0,
5613						border: 0,
5614						height: 1
5615					} ) );
5616				}
5617			}
5618	
5619			// Find the widest cell for each column and put it into the table
5620			if ( oSettings.aoData.length ) {
5621				for ( i=0 ; i<visibleColumns.length ; i++ ) {
5622					columnIdx = visibleColumns[i];
5623					column = columns[ columnIdx ];
5624	
5625					$( _fnGetWidestNode( oSettings, columnIdx ) )
5626						.clone( false )
5627						.append( column.sContentPadding )
5628						.appendTo( tr );
5629				}
5630			}
5631	
5632			// Tidy the temporary table - remove name attributes so there aren't
5633			// duplicated in the dom (radio elements for example)
5634			$('[name]', tmpTable).removeAttr('name');
5635	
5636			// Table has been built, attach to the document so we can work with it.
5637			// A holding element is used, positioned at the top of the container
5638			// with minimal height, so it has no effect on if the container scrolls
5639			// or not. Otherwise it might trigger scrolling when it actually isn't
5640			// needed
5641			var holder = $('<div/>').css( scrollX || scrollY ?
5642					{
5643						position: 'absolute',
5644						top: 0,
5645						left: 0,
5646						height: 1,
5647						right: 0,
5648						overflow: 'hidden'
5649					} :
5650					{}
5651				)
5652				.append( tmpTable )
5653				.appendTo( tableContainer );
5654	
5655			// When scrolling (X or Y) we want to set the width of the table as 
5656			// appropriate. However, when not scrolling leave the table width as it
5657			// is. This results in slightly different, but I think correct behaviour
5658			if ( scrollX && scrollXInner ) {
5659				tmpTable.width( scrollXInner );
5660			}
5661			else if ( scrollX ) {
5662				tmpTable.css( 'width', 'auto' );
5663				tmpTable.removeAttr('width');
5664	
5665				// If there is no width attribute or style, then allow the table to
5666				// collapse
5667				if ( tmpTable.width() < tableContainer.clientWidth && tableWidthAttr ) {
5668					tmpTable.width( tableContainer.clientWidth );
5669				}
5670			}
5671			else if ( scrollY ) {
5672				tmpTable.width( tableContainer.clientWidth );
5673			}
5674			else if ( tableWidthAttr ) {
5675				tmpTable.width( tableWidthAttr );
5676			}
5677	
5678			// Get the width of each column in the constructed table - we need to
5679			// know the inner width (so it can be assigned to the other table's
5680			// cells) and the outer width so we can calculate the full width of the
5681			// table. This is safe since DataTables requires a unique cell for each
5682			// column, but if ever a header can span multiple columns, this will
5683			// need to be modified.
5684			var total = 0;
5685			for ( i=0 ; i<visibleColumns.length ; i++ ) {
5686				var cell = $(headerCells[i]);
5687				var border = cell.outerWidth() - cell.width();
5688	
5689				// Use getBounding... where possible (not IE8-) because it can give
5690				// sub-pixel accuracy, which we then want to round up!
5691				var bounding = browser.bBounding ?
5692					Math.ceil( headerCells[i].getBoundingClientRect().width ) :
5693					cell.outerWidth();
5694	
5695				// Total is tracked to remove any sub-pixel errors as the outerWidth
5696				// of the table might not equal the total given here (IE!).
5697				total += bounding;
5698	
5699				// Width for each column to use
5700				columns[ visibleColumns[i] ].sWidth = _fnStringToCss( bounding - border );
5701			}
5702	
5703			table.style.width = _fnStringToCss( total );
5704	
5705			// Finished with the table - ditch it
5706			holder.remove();
5707		}
5708	
5709		// If there is a width attr, we want to attach an event listener which
5710		// allows the table sizing to automatically adjust when the window is
5711		// resized. Use the width attr rather than CSS, since we can't know if the
5712		// CSS is a relative value or absolute - DOM read is always px.
5713		if ( tableWidthAttr ) {
5714			table.style.width = _fnStringToCss( tableWidthAttr );
5715		}
5716	
5717		if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) {
5718			var bindResize = function () {
5719				$(window).on('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {
5720					_fnAdjustColumnSizing( oSettings );
5721				} ) );
5722			};
5723	
5724			// IE6/7 will crash if we bind a resize event handler on page load.
5725			// To be removed in 1.11 which drops IE6/7 support
5726			if ( ie67 ) {
5727				setTimeout( bindResize, 1000 );
5728			}
5729			else {
5730				bindResize();
5731			}
5732	
5733			oSettings._reszEvt = true;
5734		}
5735	}
5736	
5737	
5738	/**
5739	 * Throttle the calls to a function. Arguments and context are maintained for
5740	 * the throttled function
5741	 *  @param {function} fn Function to be called
5742	 *  @param {int} [freq=200] call frequency in mS
5743	 *  @returns {function} wrapped function
5744	 *  @memberof DataTable#oApi
5745	 */
5746	var _fnThrottle = DataTable.util.throttle;
5747	
5748	
5749	/**
5750	 * Convert a CSS unit width to pixels (e.g. 2em)
5751	 *  @param {string} width width to be converted
5752	 *  @param {node} parent parent to get the with for (required for relative widths) - optional
5753	 *  @returns {int} width in pixels
5754	 *  @memberof DataTable#oApi
5755	 */
5756	function _fnConvertToWidth ( width, parent )
5757	{
5758		if ( ! width ) {
5759			return 0;
5760		}
5761	
5762		var n = $('<div/>')
5763			.css( 'width', _fnStringToCss( width ) )
5764			.appendTo( parent || document.body );
5765	
5766		var val = n[0].offsetWidth;
5767		n.remove();
5768	
5769		return val;
5770	}
5771	
5772	
5773	/**
5774	 * Get the widest node
5775	 *  @param {object} settings dataTables settings object
5776	 *  @param {int} colIdx column of interest
5777	 *  @returns {node} widest table node
5778	 *  @memberof DataTable#oApi
5779	 */
5780	function _fnGetWidestNode( settings, colIdx )
5781	{
5782		var idx = _fnGetMaxLenString( settings, colIdx );
5783		if ( idx < 0 ) {
5784			return null;
5785		}
5786	
5787		var data = settings.aoData[ idx ];
5788		return ! data.nTr ? // Might not have been created when deferred rendering
5789			$('<td/>').html( _fnGetCellData( settings, idx, colIdx, 'display' ) )[0] :
5790			data.anCells[ colIdx ];
5791	}
5792	
5793	
5794	/**
5795	 * Get the maximum strlen for each data column
5796	 *  @param {object} settings dataTables settings object
5797	 *  @param {int} colIdx column of interest
5798	 *  @returns {string} max string length for each column
5799	 *  @memberof DataTable#oApi
5800	 */
5801	function _fnGetMaxLenString( settings, colIdx )
5802	{
5803		var s, max=-1, maxIdx = -1;
5804	
5805		for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
5806			s = _fnGetCellData( settings, i, colIdx, 'display' )+'';
5807			s = s.replace( __re_html_remove, '' );
5808			s = s.replace( /&nbsp;/g, ' ' );
5809	
5810			if ( s.length > max ) {
5811				max = s.length;
5812				maxIdx = i;
5813			}
5814		}
5815	
5816		return maxIdx;
5817	}
5818	
5819	
5820	/**
5821	 * Append a CSS unit (only if required) to a string
5822	 *  @param {string} value to css-ify
5823	 *  @returns {string} value with css unit
5824	 *  @memberof DataTable#oApi
5825	 */
5826	function _fnStringToCss( s )
5827	{
5828		if ( s === null ) {
5829			return '0px';
5830		}
5831	
5832		if ( typeof s == 'number' ) {
5833			return s < 0 ?
5834				'0px' :
5835				s+'px';
5836		}
5837	
5838		// Check it has a unit character already
5839		return s.match(/\d$/) ?
5840			s+'px' :
5841			s;
5842	}
5843	
5844	
5845	
5846	function _fnSortFlatten ( settings )
5847	{
5848		var
5849			i, iLen, k, kLen,
5850			aSort = [],
5851			aiOrig = [],
5852			aoColumns = settings.aoColumns,
5853			aDataSort, iCol, sType, srcCol,
5854			fixed = settings.aaSortingFixed,
5855			fixedObj = $.isPlainObject( fixed ),
5856			nestedSort = [],
5857			add = function ( a ) {
5858				if ( a.length && ! 
vendor: 39,758 bytes, lines 5858-7379
5858$.isArray( a[0] ) ) {
5859					// 1D array
5860					nestedSort.push( a );
5861				}
5862				else {
5863					// 2D array
5864					$.merge( nestedSort, a );
5865				}
5866			};
5867	
5868		// Build the sort array, with pre-fix and post-fix options if they have been
5869		// specified
5870		if ( $.isArray( fixed ) ) {
5871			add( fixed );
5872		}
5873	
5874		if ( fixedObj && fixed.pre ) {
5875			add( fixed.pre );
5876		}
5877	
5878		add( settings.aaSorting );
5879	
5880		if (fixedObj && fixed.post ) {
5881			add( fixed.post );
5882		}
5883	
5884		for ( i=0 ; i<nestedSort.length ; i++ )
5885		{
5886			srcCol = nestedSort[i][0];
5887			aDataSort = aoColumns[ srcCol ].aDataSort;
5888	
5889			for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ )
5890			{
5891				iCol = aDataSort[k];
5892				sType = aoColumns[ iCol ].sType || 'string';
5893	
5894				if ( nestedSort[i]._idx === undefined ) {
5895					nestedSort[i]._idx = $.inArray( nestedSort[i][1], aoColumns[iCol].asSorting );
5896				}
5897	
5898				aSort.push( {
5899					src:       srcCol,
5900					col:       iCol,
5901					dir:       nestedSort[i][1],
5902					index:     nestedSort[i]._idx,
5903					type:      sType,
5904					formatter: DataTable.ext.type.order[ sType+"-pre" ]
5905				} );
5906			}
5907		}
5908	
5909		return aSort;
5910	}
5911	
5912	/**
5913	 * Change the order of the table
5914	 *  @param {object} oSettings dataTables settings object
5915	 *  @memberof DataTable#oApi
5916	 *  @todo This really needs split up!
5917	 */
5918	function _fnSort ( oSettings )
5919	{
5920		var
5921			i, ien, iLen, j, jLen, k, kLen,
5922			sDataType, nTh,
5923			aiOrig = [],
5924			oExtSort = DataTable.ext.type.order,
5925			aoData = oSettings.aoData,
5926			aoColumns = oSettings.aoColumns,
5927			aDataSort, data, iCol, sType, oSort,
5928			formatters = 0,
5929			sortCol,
5930			displayMaster = oSettings.aiDisplayMaster,
5931			aSort;
5932	
5933		// Resolve any column types that are unknown due to addition or invalidation
5934		// @todo Can this be moved into a 'data-ready' handler which is called when
5935		//   data is going to be used in the table?
5936		_fnColumnTypes( oSettings );
5937	
5938		aSort = _fnSortFlatten( oSettings );
5939	
5940		for ( i=0, ien=aSort.length ; i<ien ; i++ ) {
5941			sortCol = aSort[i];
5942	
5943			// Track if we can use the fast sort algorithm
5944			if ( sortCol.formatter ) {
5945				formatters++;
5946			}
5947	
5948			// Load the data needed for the sort, for each cell
5949			_fnSortData( oSettings, sortCol.col );
5950		}
5951	
5952		/* No sorting required if server-side or no sorting array */
5953		if ( _fnDataSource( oSettings ) != 'ssp' && aSort.length !== 0 )
5954		{
5955			// Create a value - key array of the current row positions such that we can use their
5956			// current position during the sort, if values match, in order to perform stable sorting
5957			for ( i=0, iLen=displayMaster.length ; i<iLen ; i++ ) {
5958				aiOrig[ displayMaster[i] ] = i;
5959			}
5960	
5961			/* Do the sort - here we want multi-column sorting based on a given data source (column)
5962			 * and sorting function (from oSort) in a certain direction. It's reasonably complex to
5963			 * follow on it's own, but this is what we want (example two column sorting):
5964			 *  fnLocalSorting = function(a,b){
5965			 *    var iTest;
5966			 *    iTest = oSort['string-asc']('data11', 'data12');
5967			 *      if (iTest !== 0)
5968			 *        return iTest;
5969			 *    iTest = oSort['numeric-desc']('data21', 'data22');
5970			 *    if (iTest !== 0)
5971			 *      return iTest;
5972			 *    return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
5973			 *  }
5974			 * Basically we have a test for each sorting column, if the data in that column is equal,
5975			 * test the next column. If all columns match, then we use a numeric sort on the row
5976			 * positions in the original data array to provide a stable sort.
5977			 *
5978			 * Note - I know it seems excessive to have two sorting methods, but the first is around
5979			 * 15% faster, so the second is only maintained for backwards compatibility with sorting
5980			 * methods which do not have a pre-sort formatting function.
5981			 */
5982			if ( formatters === aSort.length ) {
5983				// All sort types have formatting functions
5984				displayMaster.sort( function ( a, b ) {
5985					var
5986						x, y, k, test, sort,
5987						len=aSort.length,
5988						dataA = aoData[a]._aSortData,
5989						dataB = aoData[b]._aSortData;
5990	
5991					for ( k=0 ; k<len ; k++ ) {
5992						sort = aSort[k];
5993	
5994						x = dataA[ sort.col ];
5995						y = dataB[ sort.col ];
5996	
5997						test = x<y ? -1 : x>y ? 1 : 0;
5998						if ( test !== 0 ) {
5999							return sort.dir === 'asc' ? test : -test;
6000						}
6001					}
6002	
6003					x = aiOrig[a];
6004					y = aiOrig[b];
6005					return x<y ? -1 : x>y ? 1 : 0;
6006				} );
6007			}
6008			else {
6009				// Depreciated - remove in 1.11 (providing a plug-in option)
6010				// Not all sort types have formatting methods, so we have to call their sorting
6011				// methods.
6012				displayMaster.sort( function ( a, b ) {
6013					var
6014						x, y, k, l, test, sort, fn,
6015						len=aSort.length,
6016						dataA = aoData[a]._aSortData,
6017						dataB = aoData[b]._aSortData;
6018	
6019					for ( k=0 ; k<len ; k++ ) {
6020						sort = aSort[k];
6021	
6022						x = dataA[ sort.col ];
6023						y = dataB[ sort.col ];
6024	
6025						fn = oExtSort[ sort.type+"-"+sort.dir ] || oExtSort[ "string-"+sort.dir ];
6026						test = fn( x, y );
6027						if ( test !== 0 ) {
6028							return test;
6029						}
6030					}
6031	
6032					x = aiOrig[a];
6033					y = aiOrig[b];
6034					return x<y ? -1 : x>y ? 1 : 0;
6035				} );
6036			}
6037		}
6038	
6039		/* Tell the draw function that we have sorted the data */
6040		oSettings.bSorted = true;
6041	}
6042	
6043	
6044	function _fnSortAria ( settings )
6045	{
6046		var label;
6047		var nextSort;
6048		var columns = settings.aoColumns;
6049		var aSort = _fnSortFlatten( settings );
6050		var oAria = settings.oLanguage.oAria;
6051	
6052		// ARIA attributes - need to loop all columns, to update all (removing old
6053		// attributes as needed)
6054		for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
6055		{
6056			var col = columns[i];
6057			var asSorting = col.asSorting;
6058			var sTitle = col.sTitle.replace( /<.*?>/g, "" );
6059			var th = col.nTh;
6060	
6061			// IE7 is throwing an error when setting these properties with jQuery's
6062			// attr() and removeAttr() methods...
6063			th.removeAttribute('aria-sort');
6064	
6065			/* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
6066			if ( col.bSortable ) {
6067				if ( aSort.length > 0 && aSort[0].col == i ) {
6068					th.setAttribute('aria-sort', aSort[0].dir=="asc" ? "ascending" : "descending" );
6069					nextSort = asSorting[ aSort[0].index+1 ] || asSorting[0];
6070				}
6071				else {
6072					nextSort = asSorting[0];
6073				}
6074	
6075				label = sTitle + ( nextSort === "asc" ?
6076					oAria.sSortAscending :
6077					oAria.sSortDescending
6078				);
6079			}
6080			else {
6081				label = sTitle;
6082			}
6083	
6084			th.setAttribute('aria-label', label);
6085		}
6086	}
6087	
6088	
6089	/**
6090	 * Function to run on user sort request
6091	 *  @param {object} settings dataTables settings object
6092	 *  @param {node} attachTo node to attach the handler to
6093	 *  @param {int} colIdx column sorting index
6094	 *  @param {boolean} [append=false] Append the requested sort to the existing
6095	 *    sort if true (i.e. multi-column sort)
6096	 *  @param {function} [callback] callback function
6097	 *  @memberof DataTable#oApi
6098	 */
6099	function _fnSortListener ( settings, colIdx, append, callback )
6100	{
6101		var col = settings.aoColumns[ colIdx ];
6102		var sorting = settings.aaSorting;
6103		var asSorting = col.asSorting;
6104		var nextSortIdx;
6105		var next = function ( a, overflow ) {
6106			var idx = a._idx;
6107			if ( idx === undefined ) {
6108				idx = $.inArray( a[1], asSorting );
6109			}
6110	
6111			return idx+1 < asSorting.length ?
6112				idx+1 :
6113				overflow ?
6114					null :
6115					0;
6116		};
6117	
6118		// Convert to 2D array if needed
6119		if ( typeof sorting[0] === 'number' ) {
6120			sorting = settings.aaSorting = [ sorting ];
6121		}
6122	
6123		// If appending the sort then we are multi-column sorting
6124		if ( append && settings.oFeatures.bSortMulti ) {
6125			// Are we already doing some kind of sort on this column?
6126			var sortIdx = $.inArray( colIdx, _pluck(sorting, '0') );
6127	
6128			if ( sortIdx !== -1 ) {
6129				// Yes, modify the sort
6130				nextSortIdx = next( sorting[sortIdx], true );
6131	
6132				if ( nextSortIdx === null && sorting.length === 1 ) {
6133					nextSortIdx = 0; // can't remove sorting completely
6134				}
6135	
6136				if ( nextSortIdx === null ) {
6137					sorting.splice( sortIdx, 1 );
6138				}
6139				else {
6140					sorting[sortIdx][1] = asSorting[ nextSortIdx ];
6141					sorting[sortIdx]._idx = nextSortIdx;
6142				}
6143			}
6144			else {
6145				// No sort on this column yet
6146				sorting.push( [ colIdx, asSorting[0], 0 ] );
6147				sorting[sorting.length-1]._idx = 0;
6148			}
6149		}
6150		else if ( sorting.length && sorting[0][0] == colIdx ) {
6151			// Single column - already sorting on this column, modify the sort
6152			nextSortIdx = next( sorting[0] );
6153	
6154			sorting.length = 1;
6155			sorting[0][1] = asSorting[ nextSortIdx ];
6156			sorting[0]._idx = nextSortIdx;
6157		}
6158		else {
6159			// Single column - sort only on this column
6160			sorting.length = 0;
6161			sorting.push( [ colIdx, asSorting[0] ] );
6162			sorting[0]._idx = 0;
6163		}
6164	
6165		// Run the sort by calling a full redraw
6166		_fnReDraw( settings );
6167	
6168		// callback used for async user interaction
6169		if ( typeof callback == 'function' ) {
6170			callback( settings );
6171		}
6172	}
6173	
6174	
6175	/**
6176	 * Attach a sort handler (click) to a node
6177	 *  @param {object} settings dataTables settings object
6178	 *  @param {node} attachTo node to attach the handler to
6179	 *  @param {int} colIdx column sorting index
6180	 *  @param {function} [callback] callback function
6181	 *  @memberof DataTable#oApi
6182	 */
6183	function _fnSortAttachListener ( settings, attachTo, colIdx, callback )
6184	{
6185		var col = settings.aoColumns[ colIdx ];
6186	
6187		_fnBindAction( attachTo, {}, function (e) {
6188			/* If the column is not sortable - don't to anything */
6189			if ( col.bSortable === false ) {
6190				return;
6191			}
6192	
6193			// If processing is enabled use a timeout to allow the processing
6194			// display to be shown - otherwise to it synchronously
6195			if ( settings.oFeatures.bProcessing ) {
6196				_fnProcessingDisplay( settings, true );
6197	
6198				setTimeout( function() {
6199					_fnSortListener( settings, colIdx, e.shiftKey, callback );
6200	
6201					// In server-side processing, the draw callback will remove the
6202					// processing display
6203					if ( _fnDataSource( settings ) !== 'ssp' ) {
6204						_fnProcessingDisplay( settings, false );
6205					}
6206				}, 0 );
6207			}
6208			else {
6209				_fnSortListener( settings, colIdx, e.shiftKey, callback );
6210			}
6211		} );
6212	}
6213	
6214	
6215	/**
6216	 * Set the sorting classes on table's body, Note: it is safe to call this function
6217	 * when bSort and bSortClasses are false
6218	 *  @param {object} oSettings dataTables settings object
6219	 *  @memberof DataTable#oApi
6220	 */
6221	function _fnSortingClasses( settings )
6222	{
6223		var oldSort = settings.aLastSort;
6224		var sortClass = settings.oClasses.sSortColumn;
6225		var sort = _fnSortFlatten( settings );
6226		var features = settings.oFeatures;
6227		var i, ien, colIdx;
6228	
6229		if ( features.bSort && features.bSortClasses ) {
6230			// Remove old sorting classes
6231			for ( i=0, ien=oldSort.length ; i<ien ; i++ ) {
6232				colIdx = oldSort[i].src;
6233	
6234				// Remove column sorting
6235				$( _pluck( settings.aoData, 'anCells', colIdx ) )
6236					.removeClass( sortClass + (i<2 ? i+1 : 3) );
6237			}
6238	
6239			// Add new column sorting
6240			for ( i=0, ien=sort.length ; i<ien ; i++ ) {
6241				colIdx = sort[i].src;
6242	
6243				$( _pluck( settings.aoData, 'anCells', colIdx ) )
6244					.addClass( sortClass + (i<2 ? i+1 : 3) );
6245			}
6246		}
6247	
6248		settings.aLastSort = sort;
6249	}
6250	
6251	
6252	// Get the data to sort a column, be it from cache, fresh (populating the
6253	// cache), or from a sort formatter
6254	function _fnSortData( settings, idx )
6255	{
6256		// Custom sorting function - provided by the sort data type
6257		var column = settings.aoColumns[ idx ];
6258		var customSort = DataTable.ext.order[ column.sSortDataType ];
6259		var customData;
6260	
6261		if ( customSort ) {
6262			customData = customSort.call( settings.oInstance, settings, idx,
6263				_fnColumnIndexToVisible( settings, idx )
6264			);
6265		}
6266	
6267		// Use / populate cache
6268		var row, cellData;
6269		var formatter = DataTable.ext.type.order[ column.sType+"-pre" ];
6270	
6271		for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
6272			row = settings.aoData[i];
6273	
6274			if ( ! row._aSortData ) {
6275				row._aSortData = [];
6276			}
6277	
6278			if ( ! row._aSortData[idx] || customSort ) {
6279				cellData = customSort ?
6280					customData[i] : // If there was a custom sort function, use data from there
6281					_fnGetCellData( settings, i, idx, 'sort' );
6282	
6283				row._aSortData[ idx ] = formatter ?
6284					formatter( cellData ) :
6285					cellData;
6286			}
6287		}
6288	}
6289	
6290	
6291	
6292	/**
6293	 * Save the state of a table
6294	 *  @param {object} oSettings dataTables settings object
6295	 *  @memberof DataTable#oApi
6296	 */
6297	function _fnSaveState ( settings )
6298	{
6299		if ( !settings.oFeatures.bStateSave || settings.bDestroying )
6300		{
6301			return;
6302		}
6303	
6304		/* Store the interesting variables */
6305		var state = {
6306			time:    +new Date(),
6307			start:   settings._iDisplayStart,
6308			length:  settings._iDisplayLength,
6309			order:   $.extend( true, [], settings.aaSorting ),
6310			search:  _fnSearchToCamel( settings.oPreviousSearch ),
6311			columns: $.map( settings.aoColumns, function ( col, i ) {
6312				return {
6313					visible: col.bVisible,
6314					search: _fnSearchToCamel( settings.aoPreSearchCols[i] )
6315				};
6316			} )
6317		};
6318	
6319		_fnCallbackFire( settings, "aoStateSaveParams", 'stateSaveParams', [settings, state] );
6320	
6321		settings.oSavedState = state;
6322		settings.fnStateSaveCallback.call( settings.oInstance, settings, state );
6323	}
6324	
6325	
6326	/**
6327	 * Attempt to load a saved table state
6328	 *  @param {object} oSettings dataTables settings object
6329	 *  @param {object} oInit DataTables init object so we can override settings
6330	 *  @param {function} callback Callback to execute when the state has been loaded
6331	 *  @memberof DataTable#oApi
6332	 */
6333	function _fnLoadState ( settings, oInit, callback )
6334	{
6335		var i, ien;
6336		var columns = settings.aoColumns;
6337		var loaded = function ( s ) {
6338			if ( ! s || ! s.time ) {
6339				callback();
6340				return;
6341			}
6342	
6343			// Allow custom and plug-in manipulation functions to alter the saved data set and
6344			// cancelling of loading by returning false
6345			var abStateLoad = _fnCallbackFire( settings, 'aoStateLoadParams', 'stateLoadParams', [settings, s] );
6346			if ( $.inArray( false, abStateLoad ) !== -1 ) {
6347				callback();
6348				return;
6349			}
6350	
6351			// Reject old data
6352			var duration = settings.iStateDuration;
6353			if ( duration > 0 && s.time < +new Date() - (duration*1000) ) {
6354				callback();
6355				return;
6356			}
6357	
6358			// Number of columns have changed - all bets are off, no restore of settings
6359			if ( s.columns && columns.length !== s.columns.length ) {
6360				callback();
6361				return;
6362			}
6363	
6364			// Store the saved state so it might be accessed at any time
6365			settings.oLoadedState = $.extend( true, {}, s );
6366	
6367			// Restore key features - todo - for 1.11 this needs to be done by
6368			// subscribed events
6369			if ( s.start !== undefined ) {
6370				settings._iDisplayStart    = s.start;
6371				settings.iInitDisplayStart = s.start;
6372			}
6373			if ( s.length !== undefined ) {
6374				settings._iDisplayLength   = s.length;
6375			}
6376	
6377			// Order
6378			if ( s.order !== undefined ) {
6379				settings.aaSorting = [];
6380				$.each( s.order, function ( i, col ) {
6381					settings.aaSorting.push( col[0] >= columns.length ?
6382						[ 0, col[1] ] :
6383						col
6384					);
6385				} );
6386			}
6387	
6388			// Search
6389			if ( s.search !== undefined ) {
6390				$.extend( settings.oPreviousSearch, _fnSearchToHung( s.search ) );
6391			}
6392	
6393			// Columns
6394			//
6395			if ( s.columns ) {
6396				for ( i=0, ien=s.columns.length ; i<ien ; i++ ) {
6397					var col = s.columns[i];
6398	
6399					// Visibility
6400					if ( col.visible !== undefined ) {
6401						columns[i].bVisible = col.visible;
6402					}
6403	
6404					// Search
6405					if ( col.search !== undefined ) {
6406						$.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) );
6407					}
6408				}
6409			}
6410	
6411			_fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, s] );
6412			callback();
6413		}
6414	
6415		if ( ! settings.oFeatures.bStateSave ) {
6416			callback();
6417			return;
6418		}
6419	
6420		var state = settings.fnStateLoadCallback.call( settings.oInstance, settings, loaded );
6421	
6422		if ( state !== undefined ) {
6423			loaded( state );
6424		}
6425		// otherwise, wait for the loaded callback to be executed
6426	}
6427	
6428	
6429	/**
6430	 * Return the settings object for a particular table
6431	 *  @param {node} table table we are using as a dataTable
6432	 *  @returns {object} Settings object - or null if not found
6433	 *  @memberof DataTable#oApi
6434	 */
6435	function _fnSettingsFromNode ( table )
6436	{
6437		var settings = DataTable.settings;
6438		var idx = $.inArray( table, _pluck( settings, 'nTable' ) );
6439	
6440		return idx !== -1 ?
6441			settings[ idx ] :
6442			null;
6443	}
6444	
6445	
6446	/**
6447	 * Log an error message
6448	 *  @param {object} settings dataTables settings object
6449	 *  @param {int} level log error messages, or display them to the user
6450	 *  @param {string} msg error message
6451	 *  @param {int} tn Technical note id to get more information about the error.
6452	 *  @memberof DataTable#oApi
6453	 */
6454	function _fnLog( settings, level, msg, tn )
6455	{
6456		msg = 'DataTables warning: '+
6457			(settings ? 'table id='+settings.sTableId+' - ' : '')+msg;
6458	
6459		if ( tn ) {
6460			msg += '. For more information about this error, please see '+
6461			'http://datatables.net/tn/'+tn;
6462		}
6463	
6464		if ( ! level  ) {
6465			// Backwards compatibility pre 1.10
6466			var ext = DataTable.ext;
6467			var type = ext.sErrMode || ext.errMode;
6468	
6469			if ( settings ) {
6470				_fnCallbackFire( settings, null, 'error', [ settings, tn, msg ] );
6471			}
6472	
6473			if ( type == 'alert' ) {
6474				alert( msg );
6475			}
6476			else if ( type == 'throw' ) {
6477				throw new Error(msg);
6478			}
6479			else if ( typeof type == 'function' ) {
6480				type( settings, tn, msg );
6481			}
6482		}
6483		else if ( window.console && console.log ) {
6484			console.log( msg );
6485		}
6486	}
6487	
6488	
6489	/**
6490	 * See if a property is defined on one object, if so assign it to the other object
6491	 *  @param {object} ret target object
6492	 *  @param {object} src source object
6493	 *  @param {string} name property
6494	 *  @param {string} [mappedName] name to map too - optional, name used if not given
6495	 *  @memberof DataTable#oApi
6496	 */
6497	function _fnMap( ret, src, name, mappedName )
6498	{
6499		if ( $.isArray( name ) ) {
6500			$.each( name, function (i, val) {
6501				if ( $.isArray( val ) ) {
6502					_fnMap( ret, src, val[0], val[1] );
6503				}
6504				else {
6505					_fnMap( ret, src, val );
6506				}
6507			} );
6508	
6509			return;
6510		}
6511	
6512		if ( mappedName === undefined ) {
6513			mappedName = name;
6514		}
6515	
6516		if ( src[name] !== undefined ) {
6517			ret[mappedName] = src[name];
6518		}
6519	}
6520	
6521	
6522	/**
6523	 * Extend objects - very similar to jQuery.extend, but deep copy objects, and
6524	 * shallow copy arrays. The reason we need to do this, is that we don't want to
6525	 * deep copy array init values (such as aaSorting) since the dev wouldn't be
6526	 * able to override them, but we do want to deep copy arrays.
6527	 *  @param {object} out Object to extend
6528	 *  @param {object} extender Object from which the properties will be applied to
6529	 *      out
6530	 *  @param {boolean} breakRefs If true, then arrays will be sliced to take an
6531	 *      independent copy with the exception of the `data` or `aaData` parameters
6532	 *      if they are present. This is so you can pass in a collection to
6533	 *      DataTables and have that used as your data source without breaking the
6534	 *      references
6535	 *  @returns {object} out Reference, just for convenience - out === the return.
6536	 *  @memberof DataTable#oApi
6537	 *  @todo This doesn't take account of arrays inside the deep copied objects.
6538	 */
6539	function _fnExtend( out, extender, breakRefs )
6540	{
6541		var val;
6542	
6543		for ( var prop in extender ) {
6544			if ( extender.hasOwnProperty(prop) ) {
6545				val = extender[prop];
6546	
6547				if ( $.isPlainObject( val ) ) {
6548					if ( ! $.isPlainObject( out[prop] ) ) {
6549						out[prop] = {};
6550					}
6551					$.extend( true, out[prop], val );
6552				}
6553				else if ( breakRefs && prop !== 'data' && prop !== 'aaData' && $.isArray(val) ) {
6554					out[prop] = val.slice();
6555				}
6556				else {
6557					out[prop] = val;
6558				}
6559			}
6560		}
6561	
6562		return out;
6563	}
6564	
6565	
6566	/**
6567	 * Bind an event handers to allow a click or return key to activate the callback.
6568	 * This is good for accessibility since a return on the keyboard will have the
6569	 * same effect as a click, if the element has focus.
6570	 *  @param {element} n Element to bind the action to
6571	 *  @param {object} oData Data object to pass to the triggered function
6572	 *  @param {function} fn Callback function for when the event is triggered
6573	 *  @memberof DataTable#oApi
6574	 */
6575	function _fnBindAction( n, oData, fn )
6576	{
6577		$(n)
6578			.on( 'click.DT', oData, function (e) {
6579					$(n).blur(); // Remove focus outline for mouse users
6580					fn(e);
6581				} )
6582			.on( 'keypress.DT', oData, function (e){
6583					if ( e.which === 13 ) {
6584						e.preventDefault();
6585						fn(e);
6586					}
6587				} )
6588			.on( 'selectstart.DT', function () {
6589					/* Take the brutal approach to cancelling text selection */
6590					return false;
6591				} );
6592	}
6593	
6594	
6595	/**
6596	 * Register a callback function. Easily allows a callback function to be added to
6597	 * an array store of callback functions that can then all be called together.
6598	 *  @param {object} oSettings dataTables settings object
6599	 *  @param {string} sStore Name of the array storage for the callbacks in oSettings
6600	 *  @param {function} fn Function to be called back
6601	 *  @param {string} sName Identifying name for the callback (i.e. a label)
6602	 *  @memberof DataTable#oApi
6603	 */
6604	function _fnCallbackReg( oSettings, sStore, fn, sName )
6605	{
6606		if ( fn )
6607		{
6608			oSettings[sStore].push( {
6609				"fn": fn,
6610				"sName": sName
6611			} );
6612		}
6613	}
6614	
6615	
6616	/**
6617	 * Fire callback functions and trigger events. Note that the loop over the
6618	 * callback array store is done backwards! Further note that you do not want to
6619	 * fire off triggers in time sensitive applications (for example cell creation)
6620	 * as its slow.
6621	 *  @param {object} settings dataTables settings object
6622	 *  @param {string} callbackArr Name of the array storage for the callbacks in
6623	 *      oSettings
6624	 *  @param {string} eventName Name of the jQuery custom event to trigger. If
6625	 *      null no trigger is fired
6626	 *  @param {array} args Array of arguments to pass to the callback function /
6627	 *      trigger
6628	 *  @memberof DataTable#oApi
6629	 */
6630	function _fnCallbackFire( settings, callbackArr, eventName, args )
6631	{
6632		var ret = [];
6633	
6634		if ( callbackArr ) {
6635			ret = $.map( settings[callbackArr].slice().reverse(), function (val, i) {
6636				return val.fn.apply( settings.oInstance, args );
6637			} );
6638		}
6639	
6640		if ( eventName !== null ) {
6641			var e = $.Event( eventName+'.dt' );
6642	
6643			$(settings.nTable).trigger( e, args );
6644	
6645			ret.push( e.result );
6646		}
6647	
6648		return ret;
6649	}
6650	
6651	
6652	function _fnLengthOverflow ( settings )
6653	{
6654		var
6655			start = settings._iDisplayStart,
6656			end = settings.fnDisplayEnd(),
6657			len = settings._iDisplayLength;
6658	
6659		/* If we have space to show extra rows (backing up from the end point - then do so */
6660		if ( start >= end )
6661		{
6662			start = end - len;
6663		}
6664	
6665		// Keep the start record on the current page
6666		start -= (start % len);
6667	
6668		if ( len === -1 || start < 0 )
6669		{
6670			start = 0;
6671		}
6672	
6673		settings._iDisplayStart = start;
6674	}
6675	
6676	
6677	function _fnRenderer( settings, type )
6678	{
6679		var renderer = settings.renderer;
6680		var host = DataTable.ext.renderer[type];
6681	
6682		if ( $.isPlainObject( renderer ) && renderer[type] ) {
6683			// Specific renderer for this type. If available use it, otherwise use
6684			// the default.
6685			return host[renderer[type]] || host._;
6686		}
6687		else if ( typeof renderer === 'string' ) {
6688			// Common renderer - if there is one available for this type use it,
6689			// otherwise use the default
6690			return host[renderer] || host._;
6691		}
6692	
6693		// Use the default
6694		return host._;
6695	}
6696	
6697	
6698	/**
6699	 * Detect the data source being used for the table. Used to simplify the code
6700	 * a little (ajax) and to make it compress a little smaller.
6701	 *
6702	 *  @param {object} settings dataTables settings object
6703	 *  @returns {string} Data source
6704	 *  @memberof DataTable#oApi
6705	 */
6706	function _fnDataSource ( settings )
6707	{
6708		if ( settings.oFeatures.bServerSide ) {
6709			return 'ssp';
6710		}
6711		else if ( settings.ajax || settings.sAjaxSource ) {
6712			return 'ajax';
6713		}
6714		return 'dom';
6715	}
6716	
6717
6718	
6719	
6720	/**
6721	 * Computed structure of the DataTables API, defined by the options passed to
6722	 * `DataTable.Api.register()` when building the API.
6723	 *
6724	 * The structure is built in order to speed creation and extension of the Api
6725	 * objects since the extensions are effectively pre-parsed.
6726	 *
6727	 * The array is an array of objects with the following structure, where this
6728	 * base array represents the Api prototype base:
6729	 *
6730	 *     [
6731	 *       {
6732	 *         name:      'data'                -- string   - Property name
6733	 *         val:       function () {},       -- function - Api method (or undefined if just an object
6734	 *         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
6735	 *         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
6736	 *       },
6737	 *       {
6738	 *         name:     'row'
6739	 *         val:       {},
6740	 *         methodExt: [ ... ],
6741	 *         propExt:   [
6742	 *           {
6743	 *             name:      'data'
6744	 *             val:       function () {},
6745	 *             methodExt: [ ... ],
6746	 *             propExt:   [ ... ]
6747	 *           },
6748	 *           ...
6749	 *         ]
6750	 *       }
6751	 *     ]
6752	 *
6753	 * @type {Array}
6754	 * @ignore
6755	 */
6756	var __apiStruct = [];
6757	
6758	
6759	/**
6760	 * `Array.prototype` reference.
6761	 *
6762	 * @type object
6763	 * @ignore
6764	 */
6765	var __arrayProto = Array.prototype;
6766	
6767	
6768	/**
6769	 * Abstraction for `context` parameter of the `Api` constructor to allow it to
6770	 * take several different forms for ease of use.
6771	 *
6772	 * Each of the input parameter types will be converted to a DataTables settings
6773	 * object where possible.
6774	 *
6775	 * @param  {string|node|jQuery|object} mixed DataTable identifier. Can be one
6776	 *   of:
6777	 *
6778	 *   * `string` - jQuery selector. Any DataTables' matching the given selector
6779	 *     with be found and used.
6780	 *   * `node` - `TABLE` node which has already been formed into a DataTable.
6781	 *   * `jQuery` - A jQuery object of `TABLE` nodes.
6782	 *   * `object` - DataTables settings object
6783	 *   * `DataTables.Api` - API instance
6784	 * @return {array|null} Matching DataTables settings objects. `null` or
6785	 *   `undefined` is returned if no matching DataTable is found.
6786	 * @ignore
6787	 */
6788	var _toSettings = function ( mixed )
6789	{
6790		var idx, jq;
6791		var settings = DataTable.settings;
6792		var tables = $.map( settings, function (el, i) {
6793			return el.nTable;
6794		} );
6795	
6796		if ( ! mixed ) {
6797			return [];
6798		}
6799		else if ( mixed.nTable && mixed.oApi ) {
6800			// DataTables settings object
6801			return [ mixed ];
6802		}
6803		else if ( mixed.nodeName && mixed.nodeName.toLowerCase() === 'table' ) {
6804			// Table node
6805			idx = $.inArray( mixed, tables );
6806			return idx !== -1 ? [ settings[idx] ] : null;
6807		}
6808		else if ( mixed && typeof mixed.settings === 'function' ) {
6809			return mixed.settings().toArray();
6810		}
6811		else if ( typeof mixed === 'string' ) {
6812			// jQuery selector
6813			jq = $(mixed);
6814		}
6815		else if ( mixed instanceof $ ) {
6816			// jQuery object (also DataTables instance)
6817			jq = mixed;
6818		}
6819	
6820		if ( jq ) {
6821			return jq.map( function(i) {
6822				idx = $.inArray( this, tables );
6823				return idx !== -1 ? settings[idx] : null;
6824			} ).toArray();
6825		}
6826	};
6827	
6828	
6829	/**
6830	 * DataTables API class - used to control and interface with  one or more
6831	 * DataTables enhanced tables.
6832	 *
6833	 * The API class is heavily based on jQuery, presenting a chainable interface
6834	 * that you can use to interact with tables. Each instance of the API class has
6835	 * a "context" - i.e. the tables that it will operate on. This could be a single
6836	 * table, all tables on a page or a sub-set thereof.
6837	 *
6838	 * Additionally the API is designed to allow you to easily work with the data in
6839	 * the tables, retrieving and manipulating it as required. This is done by
6840	 * presenting the API class as an array like interface. The contents of the
6841	 * array depend upon the actions requested by each method (for example
6842	 * `rows().nodes()` will return an array of nodes, while `rows().data()` will
6843	 * return an array of objects or arrays depending upon your table's
6844	 * configuration). The API object has a number of array like methods (`push`,
6845	 * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`,
6846	 * `unique` etc) to assist your working with the data held in a table.
6847	 *
6848	 * Most methods (those which return an Api instance) are chainable, which means
6849	 * the return from a method call also has all of the methods available that the
6850	 * top level object had. For example, these two calls are equivalent:
6851	 *
6852	 *     // Not chained
6853	 *     api.row.add( {...} );
6854	 *     api.draw();
6855	 *
6856	 *     // Chained
6857	 *     api.row.add( {...} ).draw();
6858	 *
6859	 * @class DataTable.Api
6860	 * @param {array|object|string|jQuery} context DataTable identifier. This is
6861	 *   used to define which DataTables enhanced tables this API will operate on.
6862	 *   Can be one of:
6863	 *
6864	 *   * `string` - jQuery selector. Any DataTables' matching the given selector
6865	 *     with be found and used.
6866	 *   * `node` - `TABLE` node which has already been formed into a DataTable.
6867	 *   * `jQuery` - A jQuery object of `TABLE` nodes.
6868	 *   * `object` - DataTables settings object
6869	 * @param {array} [data] Data to initialise the Api instance with.
6870	 *
6871	 * @example
6872	 *   // Direct initialisation during DataTables construction
6873	 *   var api = $('#example').DataTable();
6874	 *
6875	 * @example
6876	 *   // Initialisation using a DataTables jQuery object
6877	 *   var api = $('#example').dataTable().api();
6878	 *
6879	 * @example
6880	 *   // Initialisation as a constructor
6881	 *   var api = new $.fn.DataTable.Api( 'table.dataTable' );
6882	 */
6883	_Api = function ( context, data )
6884	{
6885		if ( ! (this instanceof _Api) ) {
6886			return new _Api( context, data );
6887		}
6888	
6889		var settings = [];
6890		var ctxSettings = function ( o ) {
6891			var a = _toSettings( o );
6892			if ( a ) {
6893				settings = settings.concat( a );
6894			}
6895		};
6896	
6897		if ( $.isArray( context ) ) {
6898			for ( var i=0, ien=context.length ; i<ien ; i++ ) {
6899				ctxSettings( context[i] );
6900			}
6901		}
6902		else {
6903			ctxSettings( context );
6904		}
6905	
6906		// Remove duplicates
6907		this.context = _unique( settings );
6908	
6909		// Initial data
6910		if ( data ) {
6911			$.merge( this, data );
6912		}
6913	
6914		// selector
6915		this.selector = {
6916			rows: null,
6917			cols: null,
6918			opts: null
6919		};
6920	
6921		_Api.extend( this, this, __apiStruct );
6922	};
6923	
6924	DataTable.Api = _Api;
6925	
6926	// Don't destroy the existing prototype, just extend it. Required for jQuery 2's
6927	// isPlainObject.
6928	$.extend( _Api.prototype, {
6929		any: function ()
6930		{
6931			return this.count() !== 0;
6932		},
6933	
6934	
6935		concat:  __arrayProto.concat,
6936	
6937	
6938		context: [], // array of table settings objects
6939	
6940	
6941		count: function ()
6942		{
6943			return this.flatten().length;
6944		},
6945	
6946	
6947		each: function ( fn )
6948		{
6949			for ( var i=0, ien=this.length ; i<ien; i++ ) {
6950				fn.call( this, this[i], i, this );
6951			}
6952	
6953			return this;
6954		},
6955	
6956	
6957		eq: function ( idx )
6958		{
6959			var ctx = this.context;
6960	
6961			return ctx.length > idx ?
6962				new _Api( ctx[idx], this[idx] ) :
6963				null;
6964		},
6965	
6966	
6967		filter: function ( fn )
6968		{
6969			var a = [];
6970	
6971			if ( __arrayProto.filter ) {
6972				a = __arrayProto.filter.call( this, fn, this );
6973			}
6974			else {
6975				// Compatibility for browsers without EMCA-252-5 (JS 1.6)
6976				for ( var i=0, ien=this.length ; i<ien ; i++ ) {
6977					if ( fn.call( this, this[i], i, this ) ) {
6978						a.push( this[i] );
6979					}
6980				}
6981			}
6982	
6983			return new _Api( this.context, a );
6984		},
6985	
6986	
6987		flatten: function ()
6988		{
6989			var a = [];
6990			return new _Api( this.context, a.concat.apply( a, this.toArray() ) );
6991		},
6992	
6993	
6994		join:    __arrayProto.join,
6995	
6996	
6997		indexOf: __arrayProto.indexOf || function (obj, start)
6998		{
6999			for ( var i=(start || 0), ien=this.length ; i<ien ; i++ ) {
7000				if ( this[i] === obj ) {
7001					return i;
7002				}
7003			}
7004			return -1;
7005		},
7006	
7007		iterator: function ( flatten, type, fn, alwaysNew ) {
7008			var
7009				a = [], ret,
7010				i, ien, j, jen,
7011				context = this.context,
7012				rows, items, item,
7013				selector = this.selector;
7014	
7015			// Argument shifting
7016			if ( typeof flatten === 'string' ) {
7017				alwaysNew = fn;
7018				fn = type;
7019				type = flatten;
7020				flatten = false;
7021			}
7022	
7023			for ( i=0, ien=context.length ; i<ien ; i++ ) {
7024				var apiInst = new _Api( context[i] );
7025	
7026				if ( type === 'table' ) {
7027					ret = fn.call( apiInst, context[i], i );
7028	
7029					if ( ret !== undefined ) {
7030						a.push( ret );
7031					}
7032				}
7033				else if ( type === 'columns' || type === 'rows' ) {
7034					// this has same length as context - one entry for each table
7035					ret = fn.call( apiInst, context[i], this[i], i );
7036	
7037					if ( ret !== undefined ) {
7038						a.push( ret );
7039					}
7040				}
7041				else if ( type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell' ) {
7042					// columns and rows share the same structure.
7043					// 'this' is an array of column indexes for each context
7044					items = this[i];
7045	
7046					if ( type === 'column-rows' ) {
7047						rows = _selector_row_indexes( context[i], selector.opts );
7048					}
7049	
7050					for ( j=0, jen=items.length ; j<jen ; j++ ) {
7051						item = items[j];
7052	
7053						if ( type === 'cell' ) {
7054							ret = fn.call( apiInst, context[i], item.row, item.column, i, j );
7055						}
7056						else {
7057							ret = fn.call( apiInst, context[i], item, i, j, rows );
7058						}
7059	
7060						if ( ret !== undefined ) {
7061							a.push( ret );
7062						}
7063					}
7064				}
7065			}
7066	
7067			if ( a.length || alwaysNew ) {
7068				var api = new _Api( context, flatten ? a.concat.apply( [], a ) : a );
7069				var apiSelector = api.selector;
7070				apiSelector.rows = selector.rows;
7071				apiSelector.cols = selector.cols;
7072				apiSelector.opts = selector.opts;
7073				return api;
7074			}
7075			return this;
7076		},
7077	
7078	
7079		lastIndexOf: __arrayProto.lastIndexOf || function (obj, start)
7080		{
7081			// Bit cheeky...
7082			return this.indexOf.apply( this.toArray.reverse(), arguments );
7083		},
7084	
7085	
7086		length:  0,
7087	
7088	
7089		map: function ( fn )
7090		{
7091			var a = [];
7092	
7093			if ( __arrayProto.map ) {
7094				a = __arrayProto.map.call( this, fn, this );
7095			}
7096			else {
7097				// Compatibility for browsers without EMCA-252-5 (JS 1.6)
7098				for ( var i=0, ien=this.length ; i<ien ; i++ ) {
7099					a.push( fn.call( this, this[i], i ) );
7100				}
7101			}
7102	
7103			return new _Api( this.context, a );
7104		},
7105	
7106	
7107		pluck: function ( prop )
7108		{
7109			return this.map( function ( el ) {
7110				return el[ prop ];
7111			} );
7112		},
7113	
7114		pop:     __arrayProto.pop,
7115	
7116	
7117		push:    __arrayProto.push,
7118	
7119	
7120		// Does not return an API instance
7121		reduce: __arrayProto.reduce || function ( fn, init )
7122		{
7123			return _fnReduce( this, fn, init, 0, this.length, 1 );
7124		},
7125	
7126	
7127		reduceRight: __arrayProto.reduceRight || function ( fn, init )
7128		{
7129			return _fnReduce( this, fn, init, this.length-1, -1, -1 );
7130		},
7131	
7132	
7133		reverse: __arrayProto.reverse,
7134	
7135	
7136		// Object with rows, columns and opts
7137		selector: null,
7138	
7139	
7140		shift:   __arrayProto.shift,
7141	
7142	
7143		slice: function () {
7144			return new _Api( this.context, this );
7145		},
7146	
7147	
7148		sort:    __arrayProto.sort, // ? name - order?
7149	
7150	
7151		splice:  __arrayProto.splice,
7152	
7153	
7154		toArray: function ()
7155		{
7156			return __arrayProto.slice.call( this );
7157		},
7158	
7159	
7160		to$: function ()
7161		{
7162			return $( this );
7163		},
7164	
7165	
7166		toJQuery: function ()
7167		{
7168			return $( this );
7169		},
7170	
7171	
7172		unique: function ()
7173		{
7174			return new _Api( this.context, _unique(this) );
7175		},
7176	
7177	
7178		unshift: __arrayProto.unshift
7179	} );
7180	
7181	
7182	_Api.extend = function ( scope, obj, ext )
7183	{
7184		// Only extend API instances and static properties of the API
7185		if ( ! ext.length || ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) {
7186			return;
7187		}
7188	
7189		var
7190			i, ien,
7191			j, jen,
7192			struct, inner,
7193			methodScoping = function ( scope, fn, struc ) {
7194				return function () {
7195					var ret = fn.apply( scope, arguments );
7196	
7197					// Method extension
7198					_Api.extend( ret, ret, struc.methodExt );
7199					return ret;
7200				};
7201			};
7202	
7203		for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7204			struct = ext[i];
7205	
7206			// Value
7207			obj[ struct.name ] = typeof struct.val === 'function' ?
7208				methodScoping( scope, struct.val, struct ) :
7209				$.isPlainObject( struct.val ) ?
7210					{} :
7211					struct.val;
7212	
7213			obj[ struct.name ].__dt_wrapper = true;
7214	
7215			// Property extension
7216			_Api.extend( scope, obj[ struct.name ], struct.propExt );
7217		}
7218	};
7219	
7220	
7221	// @todo - Is there need for an augment function?
7222	// _Api.augment = function ( inst, name )
7223	// {
7224	// 	// Find src object in the structure from the name
7225	// 	var parts = name.split('.');
7226	
7227	// 	_Api.extend( inst, obj );
7228	// };
7229	
7230	
7231	//     [
7232	//       {
7233	//         name:      'data'                -- string   - Property name
7234	//         val:       function () {},       -- function - Api method (or undefined if just an object
7235	//         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
7236	//         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
7237	//       },
7238	//       {
7239	//         name:     'row'
7240	//         val:       {},
7241	//         methodExt: [ ... ],
7242	//         propExt:   [
7243	//           {
7244	//             name:      'data'
7245	//             val:       function () {},
7246	//             methodExt: [ ... ],
7247	//             propExt:   [ ... ]
7248	//           },
7249	//           ...
7250	//         ]
7251	//       }
7252	//     ]
7253	
7254	_Api.register = _api_register = function ( name, val )
7255	{
7256		if ( $.isArray( name ) ) {
7257			for ( var j=0, jen=name.length ; j<jen ; j++ ) {
7258				_Api.register( name[j], val );
7259			}
7260			return;
7261		}
7262	
7263		var
7264			i, ien,
7265			heir = name.split('.'),
7266			struct = __apiStruct,
7267			key, method;
7268	
7269		var find = function ( src, name ) {
7270			for ( var i=0, ien=src.length ; i<ien ; i++ ) {
7271				if ( src[i].name === name ) {
7272					return src[i];
7273				}
7274			}
7275			return null;
7276		};
7277	
7278		for ( i=0, ien=heir.length ; i<ien ; i++ ) {
7279			method = heir[i].indexOf('()') !== -1;
7280			key = method ?
7281				heir[i].replace('()', '') :
7282				heir[i];
7283	
7284			var src = find( struct, key );
7285			if ( ! src ) {
7286				src = {
7287					name:      key,
7288					val:       {},
7289					methodExt: [],
7290					propExt:   []
7291				};
7292				struct.push( src );
7293			}
7294	
7295			if ( i === ien-1 ) {
7296				src.val = val;
7297			}
7298			else {
7299				struct = method ?
7300					src.methodExt :
7301					src.propExt;
7302			}
7303		}
7304	};
7305	
7306	
7307	_Api.registerPlural = _api_registerPlural = function ( pluralName, singularName, val ) {
7308		_Api.register( pluralName, val );
7309	
7310		_Api.register( singularName, function () {
7311			var ret = val.apply( this, arguments );
7312	
7313			if ( ret === this ) {
7314				// Returned item is the API instance that was passed in, return it
7315				return this;
7316			}
7317			else if ( ret instanceof _Api ) {
7318				// New API instance returned, want the value from the first item
7319				// in the returned array for the singular result.
7320				return ret.length ?
7321					$.isArray( ret[0] ) ?
7322						new _Api( ret.context, ret[0] ) : // Array results are 'enhanced'
7323						ret[0] :
7324					undefined;
7325			}
7326	
7327			// Non-API return - just fire it back
7328			return ret;
7329		} );
7330	};
7331	
7332	
7333	/**
7334	 * Selector for HTML tables. Apply the given selector to the give array of
7335	 * DataTables settings objects.
7336	 *
7337	 * @param {string|integer} [selector] jQuery selector string or integer
7338	 * @param  {array} Array of DataTables settings objects to be filtered
7339	 * @return {array}
7340	 * @ignore
7341	 */
7342	var __table_selector = function ( selector, a )
7343	{
7344		// Integer is used to pick out a table by index
7345		if ( typeof selector === 'number' ) {
7346			return [ a[ selector ] ];
7347		}
7348	
7349		// Perform a jQuery selector on the table nodes
7350		var nodes = $.map( a, function (el, i) {
7351			return el.nTable;
7352		} );
7353	
7354		return $(nodes)
7355			.filter( selector )
7356			.map( function (i) {
7357				// Need to translate back from the table node to the settings
7358				var idx = $.inArray( this, nodes );
7359				return a[ idx ];
7360			} )
7361			.toArray();
7362	};
7363	
7364	
7365	
7366	/**
7367	 * Context selector for the API's context (i.e. the tables the API instance
7368	 * refers to.
7369	 *
7370	 * @name    DataTable.Api#tables
7371	 * @param {string|integer} [selector] Selector to pick which tables the iterator
7372	 *   should operate on. If not given, all tables in the current context are
7373	 *   used. This can be given as a jQuery selector (for example `':gt(0)'`) to
7374	 *   select multiple tables or as an integer to select a single table.
7375	 * @returns {DataTable.Api} Returns a new API instance if a selector is given.
7376	 */
7377	_api_register( 'tables()', function ( selector ) {
7378		// A new instance is created if there was a selector specified
7379		return selector
vendor: 9,632 bytes, lines 7379-7727
7379 ?
7380			new _Api( __table_selector( selector, this.context ) ) :
7381			this;
7382	} );
7383	
7384	
7385	_api_register( 'table()', function ( selector ) {
7386		var tables = this.tables( selector );
7387		var ctx = tables.context;
7388	
7389		// Truncate to the first matched table
7390		return ctx.length ?
7391			new _Api( ctx[0] ) :
7392			tables;
7393	} );
7394	
7395	
7396	_api_registerPlural( 'tables().nodes()', 'table().node()' , function () {
7397		return this.iterator( 'table', function ( ctx ) {
7398			return ctx.nTable;
7399		}, 1 );
7400	} );
7401	
7402	
7403	_api_registerPlural( 'tables().body()', 'table().body()' , function () {
7404		return this.iterator( 'table', function ( ctx ) {
7405			return ctx.nTBody;
7406		}, 1 );
7407	} );
7408	
7409	
7410	_api_registerPlural( 'tables().header()', 'table().header()' , function () {
7411		return this.iterator( 'table', function ( ctx ) {
7412			return ctx.nTHead;
7413		}, 1 );
7414	} );
7415	
7416	
7417	_api_registerPlural( 'tables().footer()', 'table().footer()' , function () {
7418		return this.iterator( 'table', function ( ctx ) {
7419			return ctx.nTFoot;
7420		}, 1 );
7421	} );
7422	
7423	
7424	_api_registerPlural( 'tables().containers()', 'table().container()' , function () {
7425		return this.iterator( 'table', function ( ctx ) {
7426			return ctx.nTableWrapper;
7427		}, 1 );
7428	} );
7429	
7430	
7431	
7432	/**
7433	 * Redraw the tables in the current context.
7434	 */
7435	_api_register( 'draw()', function ( paging ) {
7436		return this.iterator( 'table', function ( settings ) {
7437			if ( paging === 'page' ) {
7438				_fnDraw( settings );
7439			}
7440			else {
7441				if ( typeof paging === 'string' ) {
7442					paging = paging === 'full-hold' ?
7443						false :
7444						true;
7445				}
7446	
7447				_fnReDraw( settings, paging===false );
7448			}
7449		} );
7450	} );
7451	
7452	
7453	
7454	/**
7455	 * Get the current page index.
7456	 *
7457	 * @return {integer} Current page index (zero based)
7458	 *//**
7459	 * Set the current page.
7460	 *
7461	 * Note that if you attempt to show a page which does not exist, DataTables will
7462	 * not throw an error, but rather reset the paging.
7463	 *
7464	 * @param {integer|string} action The paging action to take. This can be one of:
7465	 *  * `integer` - The page index to jump to
7466	 *  * `string` - An action to take:
7467	 *    * `first` - Jump to first page.
7468	 *    * `next` - Jump to the next page
7469	 *    * `previous` - Jump to previous page
7470	 *    * `last` - Jump to the last page.
7471	 * @returns {DataTables.Api} this
7472	 */
7473	_api_register( 'page()', function ( action ) {
7474		if ( action === undefined ) {
7475			return this.page.info().page; // not an expensive call
7476		}
7477	
7478		// else, have an action to take on all tables
7479		return this.iterator( 'table', function ( settings ) {
7480			_fnPageChange( settings, action );
7481		} );
7482	} );
7483	
7484	
7485	/**
7486	 * Paging information for the first table in the current context.
7487	 *
7488	 * If you require paging information for another table, use the `table()` method
7489	 * with a suitable selector.
7490	 *
7491	 * @return {object} Object with the following properties set:
7492	 *  * `page` - Current page index (zero based - i.e. the first page is `0`)
7493	 *  * `pages` - Total number of pages
7494	 *  * `start` - Display index for the first record shown on the current page
7495	 *  * `end` - Display index for the last record shown on the current page
7496	 *  * `length` - Display length (number of records). Note that generally `start
7497	 *    + length = end`, but this is not always true, for example if there are
7498	 *    only 2 records to show on the final page, with a length of 10.
7499	 *  * `recordsTotal` - Full data set length
7500	 *  * `recordsDisplay` - Data set length once the current filtering criterion
7501	 *    are applied.
7502	 */
7503	_api_register( 'page.info()', function ( action ) {
7504		if ( this.context.length === 0 ) {
7505			return undefined;
7506		}
7507	
7508		var
7509			settings   = this.context[0],
7510			start      = settings._iDisplayStart,
7511			len        = settings.oFeatures.bPaginate ? settings._iDisplayLength : -1,
7512			visRecords = settings.fnRecordsDisplay(),
7513			all        = len === -1;
7514	
7515		return {
7516			"page":           all ? 0 : Math.floor( start / len ),
7517			"pages":          all ? 1 : Math.ceil( visRecords / len ),
7518			"start":          start,
7519			"end":            settings.fnDisplayEnd(),
7520			"length":         len,
7521			"recordsTotal":   settings.fnRecordsTotal(),
7522			"recordsDisplay": visRecords,
7523			"serverSide":     _fnDataSource( settings ) === 'ssp'
7524		};
7525	} );
7526	
7527	
7528	/**
7529	 * Get the current page length.
7530	 *
7531	 * @return {integer} Current page length. Note `-1` indicates that all records
7532	 *   are to be shown.
7533	 *//**
7534	 * Set the current page length.
7535	 *
7536	 * @param {integer} Page length to set. Use `-1` to show all records.
7537	 * @returns {DataTables.Api} this
7538	 */
7539	_api_register( 'page.len()', function ( len ) {
7540		// Note that we can't call this function 'length()' because `length`
7541		// is a Javascript property of functions which defines how many arguments
7542		// the function expects.
7543		if ( len === undefined ) {
7544			return this.context.length !== 0 ?
7545				this.context[0]._iDisplayLength :
7546				undefined;
7547		}
7548	
7549		// else, set the page length
7550		return this.iterator( 'table', function ( settings ) {
7551			_fnLengthChange( settings, len );
7552		} );
7553	} );
7554	
7555	
7556	
7557	var __reload = function ( settings, holdPosition, callback ) {
7558		// Use the draw event to trigger a callback
7559		if ( callback ) {
7560			var api = new _Api( settings );
7561	
7562			api.one( 'draw', function () {
7563				callback( api.ajax.json() );
7564			} );
7565		}
7566	
7567		if ( _fnDataSource( settings ) == 'ssp' ) {
7568			_fnReDraw( settings, holdPosition );
7569		}
7570		else {
7571			_fnProcessingDisplay( settings, true );
7572	
7573			// Cancel an existing request
7574			var xhr = settings.jqXHR;
7575			if ( xhr && xhr.readyState !== 4 ) {
7576				xhr.abort();
7577			}
7578	
7579			// Trigger xhr
7580			_fnBuildAjax( settings, [], function( json ) {
7581				_fnClearTable( settings );
7582	
7583				var data = _fnAjaxDataSrc( settings, json );
7584				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7585					_fnAddData( settings, data[i] );
7586				}
7587	
7588				_fnReDraw( settings, holdPosition );
7589				_fnProcessingDisplay( settings, false );
7590			} );
7591		}
7592	};
7593	
7594	
7595	/**
7596	 * Get the JSON response from the last Ajax request that DataTables made to the
7597	 * server. Note that this returns the JSON from the first table in the current
7598	 * context.
7599	 *
7600	 * @return {object} JSON received from the server.
7601	 */
7602	_api_register( 'ajax.json()', function () {
7603		var ctx = this.context;
7604	
7605		if ( ctx.length > 0 ) {
7606			return ctx[0].json;
7607		}
7608	
7609		// else return undefined;
7610	} );
7611	
7612	
7613	/**
7614	 * Get the data submitted in the last Ajax request
7615	 */
7616	_api_register( 'ajax.params()', function () {
7617		var ctx = this.context;
7618	
7619		if ( ctx.length > 0 ) {
7620			return ctx[0].oAjaxData;
7621		}
7622	
7623		// else return undefined;
7624	} );
7625	
7626	
7627	/**
7628	 * Reload tables from the Ajax data source. Note that this function will
7629	 * automatically re-draw the table when the remote data has been loaded.
7630	 *
7631	 * @param {boolean} [reset=true] Reset (default) or hold the current paging
7632	 *   position. A full re-sort and re-filter is performed when this method is
7633	 *   called, which is why the pagination reset is the default action.
7634	 * @returns {DataTables.Api} this
7635	 */
7636	_api_register( 'ajax.reload()', function ( callback, resetPaging ) {
7637		return this.iterator( 'table', function (settings) {
7638			__reload( settings, resetPaging===false, callback );
7639		} );
7640	} );
7641	
7642	
7643	/**
7644	 * Get the current Ajax URL. Note that this returns the URL from the first
7645	 * table in the current context.
7646	 *
7647	 * @return {string} Current Ajax source URL
7648	 *//**
7649	 * Set the Ajax URL. Note that this will set the URL for all tables in the
7650	 * current context.
7651	 *
7652	 * @param {string} url URL to set.
7653	 * @returns {DataTables.Api} this
7654	 */
7655	_api_register( 'ajax.url()', function ( url ) {
7656		var ctx = this.context;
7657	
7658		if ( url === undefined ) {
7659			// get
7660			if ( ctx.length === 0 ) {
7661				return undefined;
7662			}
7663			ctx = ctx[0];
7664	
7665			return ctx.ajax ?
7666				$.isPlainObject( ctx.ajax ) ?
7667					ctx.ajax.url :
7668					ctx.ajax :
7669				ctx.sAjaxSource;
7670		}
7671	
7672		// set
7673		return this.iterator( 'table', function ( settings ) {
7674			if ( $.isPlainObject( settings.ajax ) ) {
7675				settings.ajax.url = url;
7676			}
7677			else {
7678				settings.ajax = url;
7679			}
7680			// No need to consider sAjaxSource here since DataTables gives priority
7681			// to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any
7682			// value of `sAjaxSource` redundant.
7683		} );
7684	} );
7685	
7686	
7687	/**
7688	 * Load data from the newly set Ajax URL. Note that this method is only
7689	 * available when `ajax.url()` is used to set a URL. Additionally, this method
7690	 * has the same effect as calling `ajax.reload()` but is provided for
7691	 * convenience when setting a new URL. Like `ajax.reload()` it will
7692	 * automatically redraw the table once the remote data has been loaded.
7693	 *
7694	 * @returns {DataTables.Api} this
7695	 */
7696	_api_register( 'ajax.url().load()', function ( callback, resetPaging ) {
7697		// Same as a reload, but makes sense to present it for easy access after a
7698		// url change
7699		return this.iterator( 'table', function ( ctx ) {
7700			__reload( ctx, resetPaging===false, callback );
7701		} );
7702	} );
7703	
7704	
7705	
7706	
7707	var _selector_run = function ( type, selector, selectFn, settings, opts )
7708	{
7709		var
7710			out = [], res,
7711			a, i, ien, j, jen,
7712			selectorType = typeof selector;
7713	
7714		// Can't just check for isArray here, as an API or jQuery instance might be
7715		// given with their array like look
7716		if ( ! selector || selectorType === 'string' || selectorType === 'function' || selector.length === undefined ) {
7717			selector = [ selector ];
7718		}
7719	
7720		for ( i=0, ien=selector.length ; i<ien ; i++ ) {
7721			// Only split on simple strings - complex expressions will be jQuery selectors
7722			a = selector[i] && selector[i].split && ! selector[i].match(/[\[\(:]/) ?
7723				selector[i].split(',') :
7724				[ selector[i] ];
7725	
7726			for ( j=0, jen=a.length ; j<jen ; j++ ) {
7727				res = selectFn( typeof a[j] === 'string' ? 
vendor: 47,870 bytes, lines 7727-9526
7727$.trim(a[j]) : a[j] );
7728	
7729				if ( res && res.length ) {
7730					out = out.concat( res );
7731				}
7732			}
7733		}
7734	
7735		// selector extensions
7736		var ext = _ext.selector[ type ];
7737		if ( ext.length ) {
7738			for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7739				out = ext[i]( settings, opts, out );
7740			}
7741		}
7742	
7743		return _unique( out );
7744	};
7745	
7746	
7747	var _selector_opts = function ( opts )
7748	{
7749		if ( ! opts ) {
7750			opts = {};
7751		}
7752	
7753		// Backwards compatibility for 1.9- which used the terminology filter rather
7754		// than search
7755		if ( opts.filter && opts.search === undefined ) {
7756			opts.search = opts.filter;
7757		}
7758	
7759		return $.extend( {
7760			search: 'none',
7761			order: 'current',
7762			page: 'all'
7763		}, opts );
7764	};
7765	
7766	
7767	var _selector_first = function ( inst )
7768	{
7769		// Reduce the API instance to the first item found
7770		for ( var i=0, ien=inst.length ; i<ien ; i++ ) {
7771			if ( inst[i].length > 0 ) {
7772				// Assign the first element to the first item in the instance
7773				// and truncate the instance and context
7774				inst[0] = inst[i];
7775				inst[0].length = 1;
7776				inst.length = 1;
7777				inst.context = [ inst.context[i] ];
7778	
7779				return inst;
7780			}
7781		}
7782	
7783		// Not found - return an empty instance
7784		inst.length = 0;
7785		return inst;
7786	};
7787	
7788	
7789	var _selector_row_indexes = function ( settings, opts )
7790	{
7791		var
7792			i, ien, tmp, a=[],
7793			displayFiltered = settings.aiDisplay,
7794			displayMaster = settings.aiDisplayMaster;
7795	
7796		var
7797			search = opts.search,  // none, applied, removed
7798			order  = opts.order,   // applied, current, index (original - compatibility with 1.9)
7799			page   = opts.page;    // all, current
7800	
7801		if ( _fnDataSource( settings ) == 'ssp' ) {
7802			// In server-side processing mode, most options are irrelevant since
7803			// rows not shown don't exist and the index order is the applied order
7804			// Removed is a special case - for consistency just return an empty
7805			// array
7806			return search === 'removed' ?
7807				[] :
7808				_range( 0, displayMaster.length );
7809		}
7810		else if ( page == 'current' ) {
7811			// Current page implies that order=current and fitler=applied, since it is
7812			// fairly senseless otherwise, regardless of what order and search actually
7813			// are
7814			for ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i<ien ; i++ ) {
7815				a.push( displayFiltered[i] );
7816			}
7817		}
7818		else if ( order == 'current' || order == 'applied' ) {
7819			if ( search == 'none') {
7820				a = displayMaster.slice();
7821			}
7822			else if ( search == 'applied' ) {
7823				a = displayFiltered.slice();
7824			}
7825			else if ( search == 'removed' ) {
7826				// O(n+m) solution by creating a hash map
7827				var displayFilteredMap = {};
7828	
7829				for ( var i=0, ien=displayFiltered.length ; i<ien ; i++ ) {
7830					displayFilteredMap[displayFiltered[i]] = null;
7831				}
7832	
7833				a = $.map( displayMaster, function (el) {
7834					return ! displayFilteredMap.hasOwnProperty(el) ?
7835						el :
7836						null;
7837				} );
7838			}
7839		}
7840		else if ( order == 'index' || order == 'original' ) {
7841			for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
7842				if ( search == 'none' ) {
7843					a.push( i );
7844				}
7845				else { // applied | removed
7846					tmp = $.inArray( i, displayFiltered );
7847	
7848					if ((tmp === -1 && search == 'removed') ||
7849						(tmp >= 0   && search == 'applied') )
7850					{
7851						a.push( i );
7852					}
7853				}
7854			}
7855		}
7856	
7857		return a;
7858	};
7859	
7860	
7861	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
7862	 * Rows
7863	 *
7864	 * {}          - no selector - use all available rows
7865	 * {integer}   - row aoData index
7866	 * {node}      - TR node
7867	 * {string}    - jQuery selector to apply to the TR elements
7868	 * {array}     - jQuery array of nodes, or simply an array of TR nodes
7869	 *
7870	 */
7871	var __row_selector = function ( settings, selector, opts )
7872	{
7873		var rows;
7874		var run = function ( sel ) {
7875			var selInt = _intVal( sel );
7876			var i, ien;
7877			var aoData = settings.aoData;
7878	
7879			// Short cut - selector is a number and no options provided (default is
7880			// all records, so no need to check if the index is in there, since it
7881			// must be - dev error if the index doesn't exist).
7882			if ( selInt !== null && ! opts ) {
7883				return [ selInt ];
7884			}
7885	
7886			if ( ! rows ) {
7887				rows = _selector_row_indexes( settings, opts );
7888			}
7889	
7890			if ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) {
7891				// Selector - integer
7892				return [ selInt ];
7893			}
7894			else if ( sel === null || sel === undefined || sel === '' ) {
7895				// Selector - none
7896				return rows;
7897			}
7898	
7899			// Selector - function
7900			if ( typeof sel === 'function' ) {
7901				return $.map( rows, function (idx) {
7902					var row = aoData[ idx ];
7903					return sel( idx, row._aData, row.nTr ) ? idx : null;
7904				} );
7905			}
7906	
7907			// Selector - node
7908			if ( sel.nodeName ) {
7909				var rowIdx = sel._DT_RowIndex;  // Property added by DT for fast lookup
7910				var cellIdx = sel._DT_CellIndex;
7911	
7912				if ( rowIdx !== undefined ) {
7913					// Make sure that the row is actually still present in the table
7914					return aoData[ rowIdx ] && aoData[ rowIdx ].nTr === sel ?
7915						[ rowIdx ] :
7916						[];
7917				}
7918				else if ( cellIdx ) {
7919					return aoData[ cellIdx.row ] && aoData[ cellIdx.row ].nTr === sel ?
7920						[ cellIdx.row ] :
7921						[];
7922				}
7923				else {
7924					var host = $(sel).closest('*[data-dt-row]');
7925					return host.length ?
7926						[ host.data('dt-row') ] :
7927						[];
7928				}
7929			}
7930	
7931			// ID selector. Want to always be able to select rows by id, regardless
7932			// of if the tr element has been created or not, so can't rely upon
7933			// jQuery here - hence a custom implementation. This does not match
7934			// Sizzle's fast selector or HTML4 - in HTML5 the ID can be anything,
7935			// but to select it using a CSS selector engine (like Sizzle or
7936			// querySelect) it would need to need to be escaped for some characters.
7937			// DataTables simplifies this for row selectors since you can select
7938			// only a row. A # indicates an id any anything that follows is the id -
7939			// unescaped.
7940			if ( typeof sel === 'string' && sel.charAt(0) === '#' ) {
7941				// get row index from id
7942				var rowObj = settings.aIds[ sel.replace( /^#/, '' ) ];
7943				if ( rowObj !== undefined ) {
7944					return [ rowObj.idx ];
7945				}
7946	
7947				// need to fall through to jQuery in case there is DOM id that
7948				// matches
7949			}
7950			
7951			// Get nodes in the order from the `rows` array with null values removed
7952			var nodes = _removeEmpty(
7953				_pluck_order( settings.aoData, rows, 'nTr' )
7954			);
7955	
7956			// Selector - jQuery selector string, array of nodes or jQuery object/
7957			// As jQuery's .filter() allows jQuery objects to be passed in filter,
7958			// it also allows arrays, so this will cope with all three options
7959			return $(nodes)
7960				.filter( sel )
7961				.map( function () {
7962					return this._DT_RowIndex;
7963				} )
7964				.toArray();
7965		};
7966	
7967		return _selector_run( 'row', selector, run, settings, opts );
7968	};
7969	
7970	
7971	_api_register( 'rows()', function ( selector, opts ) {
7972		// argument shifting
7973		if ( selector === undefined ) {
7974			selector = '';
7975		}
7976		else if ( $.isPlainObject( selector ) ) {
7977			opts = selector;
7978			selector = '';
7979		}
7980	
7981		opts = _selector_opts( opts );
7982	
7983		var inst = this.iterator( 'table', function ( settings ) {
7984			return __row_selector( settings, selector, opts );
7985		}, 1 );
7986	
7987		// Want argument shifting here and in __row_selector?
7988		inst.selector.rows = selector;
7989		inst.selector.opts = opts;
7990	
7991		return inst;
7992	} );
7993	
7994	_api_register( 'rows().nodes()', function () {
7995		return this.iterator( 'row', function ( settings, row ) {
7996			return settings.aoData[ row ].nTr || undefined;
7997		}, 1 );
7998	} );
7999	
8000	_api_register( 'rows().data()', function () {
8001		return this.iterator( true, 'rows', function ( settings, rows ) {
8002			return _pluck_order( settings.aoData, rows, '_aData' );
8003		}, 1 );
8004	} );
8005	
8006	_api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) {
8007		return this.iterator( 'row', function ( settings, row ) {
8008			var r = settings.aoData[ row ];
8009			return type === 'search' ? r._aFilterData : r._aSortData;
8010		}, 1 );
8011	} );
8012	
8013	_api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) {
8014		return this.iterator( 'row', function ( settings, row ) {
8015			_fnInvalidate( settings, row, src );
8016		} );
8017	} );
8018	
8019	_api_registerPlural( 'rows().indexes()', 'row().index()', function () {
8020		return this.iterator( 'row', function ( settings, row ) {
8021			return row;
8022		}, 1 );
8023	} );
8024	
8025	_api_registerPlural( 'rows().ids()', 'row().id()', function ( hash ) {
8026		var a = [];
8027		var context = this.context;
8028	
8029		// `iterator` will drop undefined values, but in this case we want them
8030		for ( var i=0, ien=context.length ; i<ien ; i++ ) {
8031			for ( var j=0, jen=this[i].length ; j<jen ; j++ ) {
8032				var id = context[i].rowIdFn( context[i].aoData[ this[i][j] ]._aData );
8033				a.push( (hash === true ? '#' : '' )+ id );
8034			}
8035		}
8036	
8037		return new _Api( context, a );
8038	} );
8039	
8040	_api_registerPlural( 'rows().remove()', 'row().remove()', function () {
8041		var that = this;
8042	
8043		this.iterator( 'row', function ( settings, row, thatIdx ) {
8044			var data = settings.aoData;
8045			var rowData = data[ row ];
8046			var i, ien, j, jen;
8047			var loopRow, loopCells;
8048	
8049			data.splice( row, 1 );
8050	
8051			// Update the cached indexes
8052			for ( i=0, ien=data.length ; i<ien ; i++ ) {
8053				loopRow = data[i];
8054				loopCells = loopRow.anCells;
8055	
8056				// Rows
8057				if ( loopRow.nTr !== null ) {
8058					loopRow.nTr._DT_RowIndex = i;
8059				}
8060	
8061				// Cells
8062				if ( loopCells !== null ) {
8063					for ( j=0, jen=loopCells.length ; j<jen ; j++ ) {
8064						loopCells[j]._DT_CellIndex.row = i;
8065					}
8066				}
8067			}
8068	
8069			// Delete from the display arrays
8070			_fnDeleteIndex( settings.aiDisplayMaster, row );
8071			_fnDeleteIndex( settings.aiDisplay, row );
8072			_fnDeleteIndex( that[ thatIdx ], row, false ); // maintain local indexes
8073	
8074			// For server-side processing tables - subtract the deleted row from the count
8075			if ( settings._iRecordsDisplay > 0 ) {
8076				settings._iRecordsDisplay--;
8077			}
8078	
8079			// Check for an 'overflow' they case for displaying the table
8080			_fnLengthOverflow( settings );
8081	
8082			// Remove the row's ID reference if there is one
8083			var id = settings.rowIdFn( rowData._aData );
8084			if ( id !== undefined ) {
8085				delete settings.aIds[ id ];
8086			}
8087		} );
8088	
8089		this.iterator( 'table', function ( settings ) {
8090			for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
8091				settings.aoData[i].idx = i;
8092			}
8093		} );
8094	
8095		return this;
8096	} );
8097	
8098	
8099	_api_register( 'rows.add()', function ( rows ) {
8100		var newRows = this.iterator( 'table', function ( settings ) {
8101				var row, i, ien;
8102				var out = [];
8103	
8104				for ( i=0, ien=rows.length ; i<ien ; i++ ) {
8105					row = rows[i];
8106	
8107					if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
8108						out.push( _fnAddTr( settings, row )[0] );
8109					}
8110					else {
8111						out.push( _fnAddData( settings, row ) );
8112					}
8113				}
8114	
8115				return out;
8116			}, 1 );
8117	
8118		// Return an Api.rows() extended instance, so rows().nodes() etc can be used
8119		var modRows = this.rows( -1 );
8120		modRows.pop();
8121		$.merge( modRows, newRows );
8122	
8123		return modRows;
8124	} );
8125	
8126	
8127	
8128	
8129	
8130	/**
8131	 *
8132	 */
8133	_api_register( 'row()', function ( selector, opts ) {
8134		return _selector_first( this.rows( selector, opts ) );
8135	} );
8136	
8137	
8138	_api_register( 'row().data()', function ( data ) {
8139		var ctx = this.context;
8140	
8141		if ( data === undefined ) {
8142			// Get
8143			return ctx.length && this.length ?
8144				ctx[0].aoData[ this[0] ]._aData :
8145				undefined;
8146		}
8147	
8148		// Set
8149		var row = ctx[0].aoData[ this[0] ];
8150		row._aData = data;
8151	
8152		// If the DOM has an id, and the data source is an array
8153		if ( $.isArray( data ) && row.nTr.id ) {
8154			_fnSetObjectDataFn( ctx[0].rowId )( data, row.nTr.id );
8155		}
8156	
8157		// Automatically invalidate
8158		_fnInvalidate( ctx[0], this[0], 'data' );
8159	
8160		return this;
8161	} );
8162	
8163	
8164	_api_register( 'row().node()', function () {
8165		var ctx = this.context;
8166	
8167		return ctx.length && this.length ?
8168			ctx[0].aoData[ this[0] ].nTr || null :
8169			null;
8170	} );
8171	
8172	
8173	_api_register( 'row.add()', function ( row ) {
8174		// Allow a jQuery object to be passed in - only a single row is added from
8175		// it though - the first element in the set
8176		if ( row instanceof $ && row.length ) {
8177			row = row[0];
8178		}
8179	
8180		var rows = this.iterator( 'table', function ( settings ) {
8181			if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
8182				return _fnAddTr( settings, row )[0];
8183			}
8184			return _fnAddData( settings, row );
8185		} );
8186	
8187		// Return an Api.rows() extended instance, with the newly added row selected
8188		return this.row( rows[0] );
8189	} );
8190	
8191	
8192	
8193	var __details_add = function ( ctx, row, data, klass )
8194	{
8195		// Convert to array of TR elements
8196		var rows = [];
8197		var addRow = function ( r, k ) {
8198			// Recursion to allow for arrays of jQuery objects
8199			if ( $.isArray( r ) || r instanceof $ ) {
8200				for ( var i=0, ien=r.length ; i<ien ; i++ ) {
8201					addRow( r[i], k );
8202				}
8203				return;
8204			}
8205	
8206			// If we get a TR element, then just add it directly - up to the dev
8207			// to add the correct number of columns etc
8208			if ( r.nodeName && r.nodeName.toLowerCase() === 'tr' ) {
8209				rows.push( r );
8210			}
8211			else {
8212				// Otherwise create a row with a wrapper
8213				var created = $('<tr><td/></tr>').addClass( k );
8214				$('td', created)
8215					.addClass( k )
8216					.html( r )
8217					[0].colSpan = _fnVisbleColumns( ctx );
8218	
8219				rows.push( created[0] );
8220			}
8221		};
8222	
8223		addRow( data, klass );
8224	
8225		if ( row._details ) {
8226			row._details.detach();
8227		}
8228	
8229		row._details = $(rows);
8230	
8231		// If the children were already shown, that state should be retained
8232		if ( row._detailsShow ) {
8233			row._details.insertAfter( row.nTr );
8234		}
8235	};
8236	
8237	
8238	var __details_remove = function ( api, idx )
8239	{
8240		var ctx = api.context;
8241	
8242		if ( ctx.length ) {
8243			var row = ctx[0].aoData[ idx !== undefined ? idx : api[0] ];
8244	
8245			if ( row && row._details ) {
8246				row._details.remove();
8247	
8248				row._detailsShow = undefined;
8249				row._details = undefined;
8250			}
8251		}
8252	};
8253	
8254	
8255	var __details_display = function ( api, show ) {
8256		var ctx = api.context;
8257	
8258		if ( ctx.length && api.length ) {
8259			var row = ctx[0].aoData[ api[0] ];
8260	
8261			if ( row._details ) {
8262				row._detailsShow = show;
8263	
8264				if ( show ) {
8265					row._details.insertAfter( row.nTr );
8266				}
8267				else {
8268					row._details.detach();
8269				}
8270	
8271				__details_events( ctx[0] );
8272			}
8273		}
8274	};
8275	
8276	
8277	var __details_events = function ( settings )
8278	{
8279		var api = new _Api( settings );
8280		var namespace = '.dt.DT_details';
8281		var drawEvent = 'draw'+namespace;
8282		var colvisEvent = 'column-visibility'+namespace;
8283		var destroyEvent = 'destroy'+namespace;
8284		var data = settings.aoData;
8285	
8286		api.off( drawEvent +' '+ colvisEvent +' '+ destroyEvent );
8287	
8288		if ( _pluck( data, '_details' ).length > 0 ) {
8289			// On each draw, insert the required elements into the document
8290			api.on( drawEvent, function ( e, ctx ) {
8291				if ( settings !== ctx ) {
8292					return;
8293				}
8294	
8295				api.rows( {page:'current'} ).eq(0).each( function (idx) {
8296					// Internal data grab
8297					var row = data[ idx ];
8298	
8299					if ( row._detailsShow ) {
8300						row._details.insertAfter( row.nTr );
8301					}
8302				} );
8303			} );
8304	
8305			// Column visibility change - update the colspan
8306			api.on( colvisEvent, function ( e, ctx, idx, vis ) {
8307				if ( settings !== ctx ) {
8308					return;
8309				}
8310	
8311				// Update the colspan for the details rows (note, only if it already has
8312				// a colspan)
8313				var row, visible = _fnVisbleColumns( ctx );
8314	
8315				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
8316					row = data[i];
8317	
8318					if ( row._details ) {
8319						row._details.children('td[colspan]').attr('colspan', visible );
8320					}
8321				}
8322			} );
8323	
8324			// Table destroyed - nuke any child rows
8325			api.on( destroyEvent, function ( e, ctx ) {
8326				if ( settings !== ctx ) {
8327					return;
8328				}
8329	
8330				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
8331					if ( data[i]._details ) {
8332						__details_remove( api, i );
8333					}
8334				}
8335			} );
8336		}
8337	};
8338	
8339	// Strings for the method names to help minification
8340	var _emp = '';
8341	var _child_obj = _emp+'row().child';
8342	var _child_mth = _child_obj+'()';
8343	
8344	// data can be:
8345	//  tr
8346	//  string
8347	//  jQuery or array of any of the above
8348	_api_register( _child_mth, function ( data, klass ) {
8349		var ctx = this.context;
8350	
8351		if ( data === undefined ) {
8352			// get
8353			return ctx.length && this.length ?
8354				ctx[0].aoData[ this[0] ]._details :
8355				undefined;
8356		}
8357		else if ( data === true ) {
8358			// show
8359			this.child.show();
8360		}
8361		else if ( data === false ) {
8362			// remove
8363			__details_remove( this );
8364		}
8365		else if ( ctx.length && this.length ) {
8366			// set
8367			__details_add( ctx[0], ctx[0].aoData[ this[0] ], data, klass );
8368		}
8369	
8370		return this;
8371	} );
8372	
8373	
8374	_api_register( [
8375		_child_obj+'.show()',
8376		_child_mth+'.show()' // only when `child()` was called with parameters (without
8377	], function ( show ) {   // it returns an object and this method is not executed)
8378		__details_display( this, true );
8379		return this;
8380	} );
8381	
8382	
8383	_api_register( [
8384		_child_obj+'.hide()',
8385		_child_mth+'.hide()' // only when `child()` was called with parameters (without
8386	], function () {         // it returns an object and this method is not executed)
8387		__details_display( this, false );
8388		return this;
8389	} );
8390	
8391	
8392	_api_register( [
8393		_child_obj+'.remove()',
8394		_child_mth+'.remove()' // only when `child()` was called with parameters (without
8395	], function () {           // it returns an object and this method is not executed)
8396		__details_remove( this );
8397		return this;
8398	} );
8399	
8400	
8401	_api_register( _child_obj+'.isShown()', function () {
8402		var ctx = this.context;
8403	
8404		if ( ctx.length && this.length ) {
8405			// _detailsShown as false or undefined will fall through to return false
8406			return ctx[0].aoData[ this[0] ]._detailsShow || false;
8407		}
8408		return false;
8409	} );
8410	
8411	
8412	
8413	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
8414	 * Columns
8415	 *
8416	 * {integer}           - column index (>=0 count from left, <0 count from right)
8417	 * "{integer}:visIdx"  - visible column index (i.e. translate to column index)  (>=0 count from left, <0 count from right)
8418	 * "{integer}:visible" - alias for {integer}:visIdx  (>=0 count from left, <0 count from right)
8419	 * "{string}:name"     - column name
8420	 * "{string}"          - jQuery selector on column header nodes
8421	 *
8422	 */
8423	
8424	// can be an array of these items, comma separated list, or an array of comma
8425	// separated lists
8426	
8427	var __re_column_selector = /^([^:]+):(name|visIdx|visible)$/;
8428	
8429	
8430	// r1 and r2 are redundant - but it means that the parameters match for the
8431	// iterator callback in columns().data()
8432	var __columnData = function ( settings, column, r1, r2, rows ) {
8433		var a = [];
8434		for ( var row=0, ien=rows.length ; row<ien ; row++ ) {
8435			a.push( _fnGetCellData( settings, rows[row], column ) );
8436		}
8437		return a;
8438	};
8439	
8440	
8441	var __column_selector = function ( settings, selector, opts )
8442	{
8443		var
8444			columns = settings.aoColumns,
8445			names = _pluck( columns, 'sName' ),
8446			nodes = _pluck( columns, 'nTh' );
8447	
8448		var run = function ( s ) {
8449			var selInt = _intVal( s );
8450	
8451			// Selector - all
8452			if ( s === '' ) {
8453				return _range( columns.length );
8454			}
8455	
8456			// Selector - index
8457			if ( selInt !== null ) {
8458				return [ selInt >= 0 ?
8459					selInt : // Count from left
8460					columns.length + selInt // Count from right (+ because its a negative value)
8461				];
8462			}
8463	
8464			// Selector = function
8465			if ( typeof s === 'function' ) {
8466				var rows = _selector_row_indexes( settings, opts );
8467	
8468				return $.map( columns, function (col, idx) {
8469					return s(
8470							idx,
8471							__columnData( settings, idx, 0, 0, rows ),
8472							nodes[ idx ]
8473						) ? idx : null;
8474				} );
8475			}
8476	
8477			// jQuery or string selector
8478			var match = typeof s === 'string' ?
8479				s.match( __re_column_selector ) :
8480				'';
8481	
8482			if ( match ) {
8483				switch( match[2] ) {
8484					case 'visIdx':
8485					case 'visible':
8486						var idx = parseInt( match[1], 10 );
8487						// Visible index given, convert to column index
8488						if ( idx < 0 ) {
8489							// Counting from the right
8490							var visColumns = $.map( columns, function (col,i) {
8491								return col.bVisible ? i : null;
8492							} );
8493							return [ visColumns[ visColumns.length + idx ] ];
8494						}
8495						// Counting from the left
8496						return [ _fnVisibleToColumnIndex( settings, idx ) ];
8497	
8498					case 'name':
8499						// match by name. `names` is column index complete and in order
8500						return $.map( names, function (name, i) {
8501							return name === match[1] ? i : null;
8502						} );
8503	
8504					default:
8505						return [];
8506				}
8507			}
8508	
8509			// Cell in the table body
8510			if ( s.nodeName && s._DT_CellIndex ) {
8511				return [ s._DT_CellIndex.column ];
8512			}
8513	
8514			// jQuery selector on the TH elements for the columns
8515			var jqResult = $( nodes )
8516				.filter( s )
8517				.map( function () {
8518					return $.inArray( this, nodes ); // `nodes` is column index complete and in order
8519				} )
8520				.toArray();
8521	
8522			if ( jqResult.length || ! s.nodeName ) {
8523				return jqResult;
8524			}
8525	
8526			// Otherwise a node which might have a `dt-column` data attribute, or be
8527			// a child or such an element
8528			var host = $(s).closest('*[data-dt-column]');
8529			return host.length ?
8530				[ host.data('dt-column') ] :
8531				[];
8532		};
8533	
8534		return _selector_run( 'column', selector, run, settings, opts );
8535	};
8536	
8537	
8538	var __setColumnVis = function ( settings, column, vis ) {
8539		var
8540			cols = settings.aoColumns,
8541			col  = cols[ column ],
8542			data = settings.aoData,
8543			row, cells, i, ien, tr;
8544	
8545		// Get
8546		if ( vis === undefined ) {
8547			return col.bVisible;
8548		}
8549	
8550		// Set
8551		// No change
8552		if ( col.bVisible === vis ) {
8553			return;
8554		}
8555	
8556		if ( vis ) {
8557			// Insert column
8558			// Need to decide if we should use appendChild or insertBefore
8559			var insertBefore = $.inArray( true, _pluck(cols, 'bVisible'), column+1 );
8560	
8561			for ( i=0, ien=data.length ; i<ien ; i++ ) {
8562				tr = data[i].nTr;
8563				cells = data[i].anCells;
8564	
8565				if ( tr ) {
8566					// insertBefore can act like appendChild if 2nd arg is null
8567					tr.insertBefore( cells[ column ], cells[ insertBefore ] || null );
8568				}
8569			}
8570		}
8571		else {
8572			// Remove column
8573			$( _pluck( settings.aoData, 'anCells', column ) ).detach();
8574		}
8575	
8576		// Common actions
8577		col.bVisible = vis;
8578		_fnDrawHead( settings, settings.aoHeader );
8579		_fnDrawHead( settings, settings.aoFooter );
8580	
8581		// Update colspan for no records display. Child rows and extensions will use their own
8582		// listeners to do this - only need to update the empty table item here
8583		if ( ! settings.aiDisplay.length ) {
8584			$(settings.nTBody).find('td[colspan]').attr('colspan', _fnVisbleColumns(settings));
8585		}
8586	
8587		_fnSaveState( settings );
8588	};
8589	
8590	
8591	_api_register( 'columns()', function ( selector, opts ) {
8592		// argument shifting
8593		if ( selector === undefined ) {
8594			selector = '';
8595		}
8596		else if ( $.isPlainObject( selector ) ) {
8597			opts = selector;
8598			selector = '';
8599		}
8600	
8601		opts = _selector_opts( opts );
8602	
8603		var inst = this.iterator( 'table', function ( settings ) {
8604			return __column_selector( settings, selector, opts );
8605		}, 1 );
8606	
8607		// Want argument shifting here and in _row_selector?
8608		inst.selector.cols = selector;
8609		inst.selector.opts = opts;
8610	
8611		return inst;
8612	} );
8613	
8614	_api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) {
8615		return this.iterator( 'column', function ( settings, column ) {
8616			return settings.aoColumns[column].nTh;
8617		}, 1 );
8618	} );
8619	
8620	_api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) {
8621		return this.iterator( 'column', function ( settings, column ) {
8622			return settings.aoColumns[column].nTf;
8623		}, 1 );
8624	} );
8625	
8626	_api_registerPlural( 'columns().data()', 'column().data()', function () {
8627		return this.iterator( 'column-rows', __columnData, 1 );
8628	} );
8629	
8630	_api_registerPlural( 'columns().dataSrc()', 'column().dataSrc()', function () {
8631		return this.iterator( 'column', function ( settings, column ) {
8632			return settings.aoColumns[column].mData;
8633		}, 1 );
8634	} );
8635	
8636	_api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) {
8637		return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8638			return _pluck_order( settings.aoData, rows,
8639				type === 'search' ? '_aFilterData' : '_aSortData', column
8640			);
8641		}, 1 );
8642	} );
8643	
8644	_api_registerPlural( 'columns().nodes()', 'column().nodes()', function () {
8645		return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8646			return _pluck_order( settings.aoData, rows, 'anCells', column ) ;
8647		}, 1 );
8648	} );
8649	
8650	_api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis, calc ) {
8651		var ret = this.iterator( 'column', function ( settings, column ) {
8652			if ( vis === undefined ) {
8653				return settings.aoColumns[ column ].bVisible;
8654			} // else
8655			__setColumnVis( settings, column, vis );
8656		} );
8657	
8658		// Group the column visibility changes
8659		if ( vis !== undefined ) {
8660			// Second loop once the first is done for events
8661			this.iterator( 'column', function ( settings, column ) {
8662				_fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis, calc] );
8663			} );
8664	
8665			if ( calc === undefined || calc ) {
8666				this.columns.adjust();
8667			}
8668		}
8669	
8670		return ret;
8671	} );
8672	
8673	_api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) {
8674		return this.iterator( 'column', function ( settings, column ) {
8675			return type === 'visible' ?
8676				_fnColumnIndexToVisible( settings, column ) :
8677				column;
8678		}, 1 );
8679	} );
8680	
8681	_api_register( 'columns.adjust()', function () {
8682		return this.iterator( 'table', function ( settings ) {
8683			_fnAdjustColumnSizing( settings );
8684		}, 1 );
8685	} );
8686	
8687	_api_register( 'column.index()', function ( type, idx ) {
8688		if ( this.context.length !== 0 ) {
8689			var ctx = this.context[0];
8690	
8691			if ( type === 'fromVisible' || type === 'toData' ) {
8692				return _fnVisibleToColumnIndex( ctx, idx );
8693			}
8694			else if ( type === 'fromData' || type === 'toVisible' ) {
8695				return _fnColumnIndexToVisible( ctx, idx );
8696			}
8697		}
8698	} );
8699	
8700	_api_register( 'column()', function ( selector, opts ) {
8701		return _selector_first( this.columns( selector, opts ) );
8702	} );
8703	
8704	
8705	
8706	var __cell_selector = function ( settings, selector, opts )
8707	{
8708		var data = settings.aoData;
8709		var rows = _selector_row_indexes( settings, opts );
8710		var cells = _removeEmpty( _pluck_order( data, rows, 'anCells' ) );
8711		var allCells = $( [].concat.apply([], cells) );
8712		var row;
8713		var columns = settings.aoColumns.length;
8714		var a, i, ien, j, o, host;
8715	
8716		var run = function ( s ) {
8717			var fnSelector = typeof s === 'function';
8718	
8719			if ( s === null || s === undefined || fnSelector ) {
8720				// All cells and function selectors
8721				a = [];
8722	
8723				for ( i=0, ien=rows.length ; i<ien ; i++ ) {
8724					row = rows[i];
8725	
8726					for ( j=0 ; j<columns ; j++ ) {
8727						o = {
8728							row: row,
8729							column: j
8730						};
8731	
8732						if ( fnSelector ) {
8733							// Selector - function
8734							host = data[ row ];
8735	
8736							if ( s( o, _fnGetCellData(settings, row, j), host.anCells ? host.anCells[j] : null ) ) {
8737								a.push( o );
8738							}
8739						}
8740						else {
8741							// Selector - all
8742							a.push( o );
8743						}
8744					}
8745				}
8746	
8747				return a;
8748			}
8749			
8750			// Selector - index
8751			if ( $.isPlainObject( s ) ) {
8752				// Valid cell index and its in the array of selectable rows
8753				return s.column !== undefined && s.row !== undefined && $.inArray( s.row, rows ) !== -1 ?
8754					[s] :
8755					[];
8756			}
8757	
8758			// Selector - jQuery filtered cells
8759			var jqResult = allCells
8760				.filter( s )
8761				.map( function (i, el) {
8762					return { // use a new object, in case someone changes the values
8763						row:    el._DT_CellIndex.row,
8764						column: el._DT_CellIndex.column
8765	 				};
8766				} )
8767				.toArray();
8768	
8769			if ( jqResult.length || ! s.nodeName ) {
8770				return jqResult;
8771			}
8772	
8773			// Otherwise the selector is a node, and there is one last option - the
8774			// element might be a child of an element which has dt-row and dt-column
8775			// data attributes
8776			host = $(s).closest('*[data-dt-row]');
8777			return host.length ?
8778				[ {
8779					row: host.data('dt-row'),
8780					column: host.data('dt-column')
8781				} ] :
8782				[];
8783		};
8784	
8785		return _selector_run( 'cell', selector, run, settings, opts );
8786	};
8787	
8788	
8789	
8790	
8791	_api_register( 'cells()', function ( rowSelector, columnSelector, opts ) {
8792		// Argument shifting
8793		if ( $.isPlainObject( rowSelector ) ) {
8794			// Indexes
8795			if ( rowSelector.row === undefined ) {
8796				// Selector options in first parameter
8797				opts = rowSelector;
8798				rowSelector = null;
8799			}
8800			else {
8801				// Cell index objects in first parameter
8802				opts = columnSelector;
8803				columnSelector = null;
8804			}
8805		}
8806		if ( $.isPlainObject( columnSelector ) ) {
8807			opts = columnSelector;
8808			columnSelector = null;
8809		}
8810	
8811		// Cell selector
8812		if ( columnSelector === null || columnSelector === undefined ) {
8813			return this.iterator( 'table', function ( settings ) {
8814				return __cell_selector( settings, rowSelector, _selector_opts( opts ) );
8815			} );
8816		}
8817	
8818		// Row + column selector
8819		var columns = this.columns( columnSelector );
8820		var rows = this.rows( rowSelector );
8821		var a, i, ien, j, jen;
8822	
8823		this.iterator( 'table', function ( settings, idx ) {
8824			a = [];
8825	
8826			for ( i=0, ien=rows[idx].length ; i<ien ; i++ ) {
8827				for ( j=0, jen=columns[idx].length ; j<jen ; j++ ) {
8828					a.push( {
8829						row:    rows[idx][i],
8830						column: columns[idx][j]
8831					} );
8832				}
8833			}
8834		}, 1 );
8835	
8836	    // Now pass through the cell selector for options
8837	    var cells = this.cells( a, opts );
8838	
8839		$.extend( cells.selector, {
8840			cols: columnSelector,
8841			rows: rowSelector,
8842			opts: opts
8843		} );
8844	
8845		return cells;
8846	} );
8847	
8848	
8849	_api_registerPlural( 'cells().nodes()', 'cell().node()', function () {
8850		return this.iterator( 'cell', function ( settings, row, column ) {
8851			var data = settings.aoData[ row ];
8852	
8853			return data && data.anCells ?
8854				data.anCells[ column ] :
8855				undefined;
8856		}, 1 );
8857	} );
8858	
8859	
8860	_api_register( 'cells().data()', function () {
8861		return this.iterator( 'cell', function ( settings, row, column ) {
8862			return _fnGetCellData( settings, row, column );
8863		}, 1 );
8864	} );
8865	
8866	
8867	_api_registerPlural( 'cells().cache()', 'cell().cache()', function ( type ) {
8868		type = type === 'search' ? '_aFilterData' : '_aSortData';
8869	
8870		return this.iterator( 'cell', function ( settings, row, column ) {
8871			return settings.aoData[ row ][ type ][ column ];
8872		}, 1 );
8873	} );
8874	
8875	
8876	_api_registerPlural( 'cells().render()', 'cell().render()', function ( type ) {
8877		return this.iterator( 'cell', function ( settings, row, column ) {
8878			return _fnGetCellData( settings, row, column, type );
8879		}, 1 );
8880	} );
8881	
8882	
8883	_api_registerPlural( 'cells().indexes()', 'cell().index()', function () {
8884		return this.iterator( 'cell', function ( settings, row, column ) {
8885			return {
8886				row: row,
8887				column: column,
8888				columnVisible: _fnColumnIndexToVisible( settings, column )
8889			};
8890		}, 1 );
8891	} );
8892	
8893	
8894	_api_registerPlural( 'cells().invalidate()', 'cell().invalidate()', function ( src ) {
8895		return this.iterator( 'cell', function ( settings, row, column ) {
8896			_fnInvalidate( settings, row, src, column );
8897		} );
8898	} );
8899	
8900	
8901	
8902	_api_register( 'cell()', function ( rowSelector, columnSelector, opts ) {
8903		return _selector_first( this.cells( rowSelector, columnSelector, opts ) );
8904	} );
8905	
8906	
8907	_api_register( 'cell().data()', function ( data ) {
8908		var ctx = this.context;
8909		var cell = this[0];
8910	
8911		if ( data === undefined ) {
8912			// Get
8913			return ctx.length && cell.length ?
8914				_fnGetCellData( ctx[0], cell[0].row, cell[0].column ) :
8915				undefined;
8916		}
8917	
8918		// Set
8919		_fnSetCellData( ctx[0], cell[0].row, cell[0].column, data );
8920		_fnInvalidate( ctx[0], cell[0].row, 'data', cell[0].column );
8921	
8922		return this;
8923	} );
8924	
8925	
8926	
8927	/**
8928	 * Get current ordering (sorting) that has been applied to the table.
8929	 *
8930	 * @returns {array} 2D array containing the sorting information for the first
8931	 *   table in the current context. Each element in the parent array represents
8932	 *   a column being sorted upon (i.e. multi-sorting with two columns would have
8933	 *   2 inner arrays). The inner arrays may have 2 or 3 elements. The first is
8934	 *   the column index that the sorting condition applies to, the second is the
8935	 *   direction of the sort (`desc` or `asc`) and, optionally, the third is the
8936	 *   index of the sorting order from the `column.sorting` initialisation array.
8937	 *//**
8938	 * Set the ordering for the table.
8939	 *
8940	 * @param {integer} order Column index to sort upon.
8941	 * @param {string} direction Direction of the sort to be applied (`asc` or `desc`)
8942	 * @returns {DataTables.Api} this
8943	 *//**
8944	 * Set the ordering for the table.
8945	 *
8946	 * @param {array} order 1D array of sorting information to be applied.
8947	 * @param {array} [...] Optional additional sorting conditions
8948	 * @returns {DataTables.Api} this
8949	 *//**
8950	 * Set the ordering for the table.
8951	 *
8952	 * @param {array} order 2D array of sorting information to be applied.
8953	 * @returns {DataTables.Api} this
8954	 */
8955	_api_register( 'order()', function ( order, dir ) {
8956		var ctx = this.context;
8957	
8958		if ( order === undefined ) {
8959			// get
8960			return ctx.length !== 0 ?
8961				ctx[0].aaSorting :
8962				undefined;
8963		}
8964	
8965		// set
8966		if ( typeof order === 'number' ) {
8967			// Simple column / direction passed in
8968			order = [ [ order, dir ] ];
8969		}
8970		else if ( order.length && ! $.isArray( order[0] ) ) {
8971			// Arguments passed in (list of 1D arrays)
8972			order = Array.prototype.slice.call( arguments );
8973		}
8974		// otherwise a 2D array was passed in
8975	
8976		return this.iterator( 'table', function ( settings ) {
8977			settings.aaSorting = order.slice();
8978		} );
8979	} );
8980	
8981	
8982	/**
8983	 * Attach a sort listener to an element for a given column
8984	 *
8985	 * @param {node|jQuery|string} node Identifier for the element(s) to attach the
8986	 *   listener to. This can take the form of a single DOM node, a jQuery
8987	 *   collection of nodes or a jQuery selector which will identify the node(s).
8988	 * @param {integer} column the column that a click on this node will sort on
8989	 * @param {function} [callback] callback function when sort is run
8990	 * @returns {DataTables.Api} this
8991	 */
8992	_api_register( 'order.listener()', function ( node, column, callback ) {
8993		return this.iterator( 'table', function ( settings ) {
8994			_fnSortAttachListener( settings, node, column, callback );
8995		} );
8996	} );
8997	
8998	
8999	_api_register( 'order.fixed()', function ( set ) {
9000		if ( ! set ) {
9001			var ctx = this.context;
9002			var fixed = ctx.length ?
9003				ctx[0].aaSortingFixed :
9004				undefined;
9005	
9006			return $.isArray( fixed ) ?
9007				{ pre: fixed } :
9008				fixed;
9009		}
9010	
9011		return this.iterator( 'table', function ( settings ) {
9012			settings.aaSortingFixed = $.extend( true, {}, set );
9013		} );
9014	} );
9015	
9016	
9017	// Order by the selected column(s)
9018	_api_register( [
9019		'columns().order()',
9020		'column().order()'
9021	], function ( dir ) {
9022		var that = this;
9023	
9024		return this.iterator( 'table', function ( settings, i ) {
9025			var sort = [];
9026	
9027			$.each( that[i], function (j, col) {
9028				sort.push( [ col, dir ] );
9029			} );
9030	
9031			settings.aaSorting = sort;
9032		} );
9033	} );
9034	
9035	
9036	
9037	_api_register( 'search()', function ( input, regex, smart, caseInsen ) {
9038		var ctx = this.context;
9039	
9040		if ( input === undefined ) {
9041			// get
9042			return ctx.length !== 0 ?
9043				ctx[0].oPreviousSearch.sSearch :
9044				undefined;
9045		}
9046	
9047		// set
9048		return this.iterator( 'table', function ( settings ) {
9049			if ( ! settings.oFeatures.bFilter ) {
9050				return;
9051			}
9052	
9053			_fnFilterComplete( settings, $.extend( {}, settings.oPreviousSearch, {
9054				"sSearch": input+"",
9055				"bRegex":  regex === null ? false : regex,
9056				"bSmart":  smart === null ? true  : smart,
9057				"bCaseInsensitive": caseInsen === null ? true : caseInsen
9058			} ), 1 );
9059		} );
9060	} );
9061	
9062	
9063	_api_registerPlural(
9064		'columns().search()',
9065		'column().search()',
9066		function ( input, regex, smart, caseInsen ) {
9067			return this.iterator( 'column', function ( settings, column ) {
9068				var preSearch = settings.aoPreSearchCols;
9069	
9070				if ( input === undefined ) {
9071					// get
9072					return preSearch[ column ].sSearch;
9073				}
9074	
9075				// set
9076				if ( ! settings.oFeatures.bFilter ) {
9077					return;
9078				}
9079	
9080				$.extend( preSearch[ column ], {
9081					"sSearch": input+"",
9082					"bRegex":  regex === null ? false : regex,
9083					"bSmart":  smart === null ? true  : smart,
9084					"bCaseInsensitive": caseInsen === null ? true : caseInsen
9085				} );
9086	
9087				_fnFilterComplete( settings, settings.oPreviousSearch, 1 );
9088			} );
9089		}
9090	);
9091	
9092	/*
9093	 * State API methods
9094	 */
9095	
9096	_api_register( 'state()', function () {
9097		return this.context.length ?
9098			this.context[0].oSavedState :
9099			null;
9100	} );
9101	
9102	
9103	_api_register( 'state.clear()', function () {
9104		return this.iterator( 'table', function ( settings ) {
9105			// Save an empty object
9106			settings.fnStateSaveCallback.call( settings.oInstance, settings, {} );
9107		} );
9108	} );
9109	
9110	
9111	_api_register( 'state.loaded()', function () {
9112		return this.context.length ?
9113			this.context[0].oLoadedState :
9114			null;
9115	} );
9116	
9117	
9118	_api_register( 'state.save()', function () {
9119		return this.iterator( 'table', function ( settings ) {
9120			_fnSaveState( settings );
9121		} );
9122	} );
9123	
9124	
9125	
9126	/**
9127	 * Provide a common method for plug-ins to check the version of DataTables being
9128	 * used, in order to ensure compatibility.
9129	 *
9130	 *  @param {string} version Version string to check for, in the format "X.Y.Z".
9131	 *    Note that the formats "X" and "X.Y" are also acceptable.
9132	 *  @returns {boolean} true if this version of DataTables is greater or equal to
9133	 *    the required version, or false if this version of DataTales is not
9134	 *    suitable
9135	 *  @static
9136	 *  @dtopt API-Static
9137	 *
9138	 *  @example
9139	 *    alert( $.fn.dataTable.versionCheck( '1.9.0' ) );
9140	 */
9141	DataTable.versionCheck = DataTable.fnVersionCheck = function( version )
9142	{
9143		var aThis = DataTable.version.split('.');
9144		var aThat = version.split('.');
9145		var iThis, iThat;
9146	
9147		for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) {
9148			iThis = parseInt( aThis[i], 10 ) || 0;
9149			iThat = parseInt( aThat[i], 10 ) || 0;
9150	
9151			// Parts are the same, keep comparing
9152			if (iThis === iThat) {
9153				continue;
9154			}
9155	
9156			// Parts are different, return immediately
9157			return iThis > iThat;
9158		}
9159	
9160		return true;
9161	};
9162	
9163	
9164	/**
9165	 * Check if a `<table>` node is a DataTable table already or not.
9166	 *
9167	 *  @param {node|jquery|string} table Table node, jQuery object or jQuery
9168	 *      selector for the table to test. Note that if more than more than one
9169	 *      table is passed on, only the first will be checked
9170	 *  @returns {boolean} true the table given is a DataTable, or false otherwise
9171	 *  @static
9172	 *  @dtopt API-Static
9173	 *
9174	 *  @example
9175	 *    if ( ! $.fn.DataTable.isDataTable( '#example' ) ) {
9176	 *      $('#example').dataTable();
9177	 *    }
9178	 */
9179	DataTable.isDataTable = DataTable.fnIsDataTable = function ( table )
9180	{
9181		var t = $(table).get(0);
9182		var is = false;
9183	
9184		if ( table instanceof DataTable.Api ) {
9185			return true;
9186		}
9187	
9188		$.each( DataTable.settings, function (i, o) {
9189			var head = o.nScrollHead ? $('table', o.nScrollHead)[0] : null;
9190			var foot = o.nScrollFoot ? $('table', o.nScrollFoot)[0] : null;
9191	
9192			if ( o.nTable === t || head === t || foot === t ) {
9193				is = true;
9194			}
9195		} );
9196	
9197		return is;
9198	};
9199	
9200	
9201	/**
9202	 * Get all DataTable tables that have been initialised - optionally you can
9203	 * select to get only currently visible tables.
9204	 *
9205	 *  @param {boolean} [visible=false] Flag to indicate if you want all (default)
9206	 *    or visible tables only.
9207	 *  @returns {array} Array of `table` nodes (not DataTable instances) which are
9208	 *    DataTables
9209	 *  @static
9210	 *  @dtopt API-Static
9211	 *
9212	 *  @example
9213	 *    $.each( $.fn.dataTable.tables(true), function () {
9214	 *      $(table).DataTable().columns.adjust();
9215	 *    } );
9216	 */
9217	DataTable.tables = DataTable.fnTables = function ( visible )
9218	{
9219		var api = false;
9220	
9221		if ( $.isPlainObject( visible ) ) {
9222			api = visible.api;
9223			visible = visible.visible;
9224		}
9225	
9226		var a = $.map( DataTable.settings, function (o) {
9227			if ( !visible || (visible && $(o.nTable).is(':visible')) ) {
9228				return o.nTable;
9229			}
9230		} );
9231	
9232		return api ?
9233			new _Api( a ) :
9234			a;
9235	};
9236	
9237	
9238	/**
9239	 * Convert from camel case parameters to Hungarian notation. This is made public
9240	 * for the extensions to provide the same ability as DataTables core to accept
9241	 * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase
9242	 * parameters.
9243	 *
9244	 *  @param {object} src The model object which holds all parameters that can be
9245	 *    mapped.
9246	 *  @param {object} user The object to convert from camel case to Hungarian.
9247	 *  @param {boolean} force When set to `true`, properties which already have a
9248	 *    Hungarian value in the `user` object will be overwritten. Otherwise they
9249	 *    won't be.
9250	 */
9251	DataTable.camelToHungarian = _fnCamelToHungarian;
9252	
9253	
9254	
9255	/**
9256	 *
9257	 */
9258	_api_register( '$()', function ( selector, opts ) {
9259		var
9260			rows   = this.rows( opts ).nodes(), // Get all rows
9261			jqRows = $(rows);
9262	
9263		return $( [].concat(
9264			jqRows.filter( selector ).toArray(),
9265			jqRows.find( selector ).toArray()
9266		) );
9267	} );
9268	
9269	
9270	// jQuery functions to operate on the tables
9271	$.each( [ 'on', 'one', 'off' ], function (i, key) {
9272		_api_register( key+'()', function ( /* event, handler */ ) {
9273			var args = Array.prototype.slice.call(arguments);
9274	
9275			// Add the `dt` namespace automatically if it isn't already present
9276			args[0] = $.map( args[0].split( /\s/ ), function ( e ) {
9277				return ! e.match(/\.dt\b/) ?
9278					e+'.dt' :
9279					e;
9280				} ).join( ' ' );
9281	
9282			var inst = $( this.tables().nodes() );
9283			inst[key].apply( inst, args );
9284			return this;
9285		} );
9286	} );
9287	
9288	
9289	_api_register( 'clear()', function () {
9290		return this.iterator( 'table', function ( settings ) {
9291			_fnClearTable( settings );
9292		} );
9293	} );
9294	
9295	
9296	_api_register( 'settings()', function () {
9297		return new _Api( this.context, this.context );
9298	} );
9299	
9300	
9301	_api_register( 'init()', function () {
9302		var ctx = this.context;
9303		return ctx.length ? ctx[0].oInit : null;
9304	} );
9305	
9306	
9307	_api_register( 'data()', function () {
9308		return this.iterator( 'table', function ( settings ) {
9309			return _pluck( settings.aoData, '_aData' );
9310		} ).flatten();
9311	} );
9312	
9313	
9314	_api_register( 'destroy()', function ( remove ) {
9315		remove = remove || false;
9316	
9317		return this.iterator( 'table', function ( settings ) {
9318			var orig      = settings.nTableWrapper.parentNode;
9319			var classes   = settings.oClasses;
9320			var table     = settings.nTable;
9321			var tbody     = settings.nTBody;
9322			var thead     = settings.nTHead;
9323			var tfoot     = settings.nTFoot;
9324			var jqTable   = $(table);
9325			var jqTbody   = $(tbody);
9326			var jqWrapper = $(settings.nTableWrapper);
9327			var rows      = $.map( settings.aoData, function (r) { return r.nTr; } );
9328			var i, ien;
9329	
9330			// Flag to note that the table is currently being destroyed - no action
9331			// should be taken
9332			settings.bDestroying = true;
9333	
9334			// Fire off the destroy callbacks for plug-ins etc
9335			_fnCallbackFire( settings, "aoDestroyCallback", "destroy", [settings] );
9336	
9337			// If not being removed from the document, make all columns visible
9338			if ( ! remove ) {
9339				new _Api( settings ).columns().visible( true );
9340			}
9341	
9342			// Blitz all `DT` namespaced events (these are internal events, the
9343			// lowercase, `dt` events are user subscribed and they are responsible
9344			// for removing them
9345			jqWrapper.off('.DT').find(':not(tbody *)').off('.DT');
9346			$(window).off('.DT-'+settings.sInstance);
9347	
9348			// When scrolling we had to break the table up - restore it
9349			if ( table != thead.parentNode ) {
9350				jqTable.children('thead').detach();
9351				jqTable.append( thead );
9352			}
9353	
9354			if ( tfoot && table != tfoot.parentNode ) {
9355				jqTable.children('tfoot').detach();
9356				jqTable.append( tfoot );
9357			}
9358	
9359			settings.aaSorting = [];
9360			settings.aaSortingFixed = [];
9361			_fnSortingClasses( settings );
9362	
9363			$( rows ).removeClass( settings.asStripeClasses.join(' ') );
9364	
9365			$('th, td', thead).removeClass( classes.sSortable+' '+
9366				classes.sSortableAsc+' '+classes.sSortableDesc+' '+classes.sSortableNone
9367			);
9368	
9369			// Add the TR elements back into the table in their original order
9370			jqTbody.children().detach();
9371			jqTbody.append( rows );
9372	
9373			// Remove the DataTables generated nodes, events and classes
9374			var removedMethod = remove ? 'remove' : 'detach';
9375			jqTable[ removedMethod ]();
9376			jqWrapper[ removedMethod ]();
9377	
9378			// If we need to reattach the table to the document
9379			if ( ! remove && orig ) {
9380				// insertBefore acts like appendChild if !arg[1]
9381				orig.insertBefore( table, settings.nTableReinsertBefore );
9382	
9383				// Restore the width of the original table - was read from the style property,
9384				// so we can restore directly to that
9385				jqTable
9386					.css( 'width', settings.sDestroyWidth )
9387					.removeClass( classes.sTable );
9388	
9389				// If the were originally stripe classes - then we add them back here.
9390				// Note this is not fool proof (for example if not all rows had stripe
9391				// classes - but it's a good effort without getting carried away
9392				ien = settings.asDestroyStripes.length;
9393	
9394				if ( ien ) {
9395					jqTbody.children().each( function (i) {
9396						$(this).addClass( settings.asDestroyStripes[i % ien] );
9397					} );
9398				}
9399			}
9400	
9401			/* Remove the settings object from the settings array */
9402			var idx = $.inArray( settings, DataTable.settings );
9403			if ( idx !== -1 ) {
9404				DataTable.settings.splice( idx, 1 );
9405			}
9406		} );
9407	} );
9408	
9409	
9410	// Add the `every()` method for rows, columns and cells in a compact form
9411	$.each( [ 'column', 'row', 'cell' ], function ( i, type ) {
9412		_api_register( type+'s().every()', function ( fn ) {
9413			var opts = this.selector.opts;
9414			var api = this;
9415	
9416			return this.iterator( type, function ( settings, arg1, arg2, arg3, arg4 ) {
9417				// Rows and columns:
9418				//  arg1 - index
9419				//  arg2 - table counter
9420				//  arg3 - loop counter
9421				//  arg4 - undefined
9422				// Cells:
9423				//  arg1 - row index
9424				//  arg2 - column index
9425				//  arg3 - table counter
9426				//  arg4 - loop counter
9427				fn.call(
9428					api[ type ](
9429						arg1,
9430						type==='cell' ? arg2 : opts,
9431						type==='cell' ? opts : undefined
9432					),
9433					arg1, arg2, arg3, arg4
9434				);
9435			} );
9436		} );
9437	} );
9438	
9439	
9440	// i18n method for extensions to be able to use the language object from the
9441	// DataTable
9442	_api_register( 'i18n()', function ( token, def, plural ) {
9443		var ctx = this.context[0];
9444		var resolved = _fnGetObjectDataFn( token )( ctx.oLanguage );
9445	
9446		if ( resolved === undefined ) {
9447			resolved = def;
9448		}
9449	
9450		if ( plural !== undefined && $.isPlainObject( resolved ) ) {
9451			resolved = resolved[ plural ] !== undefined ?
9452				resolved[ plural ] :
9453				resolved._;
9454		}
9455	
9456		return resolved.replace( '%d', plural ); // nb: plural might be undefined,
9457	} );
9458	/**
9459	 * Version string for plug-ins to check compatibility. Allowed format is
9460	 * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used
9461	 * only for non-release builds. See http://semver.org/ for more information.
9462	 *  @member
9463	 *  @type string
9464	 *  @default Version number
9465	 */
9466	DataTable.version = "1.10.19";
9467
9468	/**
9469	 * Private data store, containing all of the settings objects that are
9470	 * created for the tables on a given page.
9471	 *
9472	 * Note that the `DataTable.settings` object is aliased to
9473	 * `jQuery.fn.dataTableExt` through which it may be accessed and
9474	 * manipulated, or `jQuery.fn.dataTable.settings`.
9475	 *  @member
9476	 *  @type array
9477	 *  @default []
9478	 *  @private
9479	 */
9480	DataTable.settings = [];
9481
9482	/**
9483	 * Object models container, for the various models that DataTables has
9484	 * available to it. These models define the objects that are used to hold
9485	 * the active state and configuration of the table.
9486	 *  @namespace
9487	 */
9488	DataTable.models = {};
9489	
9490	
9491	
9492	/**
9493	 * Template object for the way in which DataTables holds information about
9494	 * search information for the global filter and individual column filters.
9495	 *  @namespace
9496	 */
9497	DataTable.models.oSearch = {
9498		/**
9499		 * Flag to indicate if the filtering should be case insensitive or not
9500		 *  @type boolean
9501		 *  @default true
9502		 */
9503		"bCaseInsensitive": true,
9504	
9505		/**
9506		 * Applied search term
9507		 *  @type string
9508		 *  @default <i>Empty string</i>
9509		 */
9510		"sSearch": "",
9511	
9512		/**
9513		 * Flag to indicate if the search term should be interpreted as a
9514		 * regular expression (true) or not (false) and therefore and special
9515		 * regex characters escaped.
9516		 *  @type boolean
9517		 *  @default false
9518		 */
9519		"bRegex": false,
9520	
9521		/**
9522		 * Flag to indicate if DataTables is to use its smart filtering or not.
9523		 *  @type boolean
9524		 *  @default true
9525		 */
9526		"bSmart": tru
vendor: 11,217 bytes, lines 9526-9884
9526e
9527	};
9528	
9529	
9530	
9531	
9532	/**
9533	 * Template object for the way in which DataTables holds information about
9534	 * each individual row. This is the object format used for the settings
9535	 * aoData array.
9536	 *  @namespace
9537	 */
9538	DataTable.models.oRow = {
9539		/**
9540		 * TR element for the row
9541		 *  @type node
9542		 *  @default null
9543		 */
9544		"nTr": null,
9545	
9546		/**
9547		 * Array of TD elements for each row. This is null until the row has been
9548		 * created.
9549		 *  @type array nodes
9550		 *  @default []
9551		 */
9552		"anCells": null,
9553	
9554		/**
9555		 * Data object from the original data source for the row. This is either
9556		 * an array if using the traditional form of DataTables, or an object if
9557		 * using mData options. The exact type will depend on the passed in
9558		 * data from the data source, or will be an array if using DOM a data
9559		 * source.
9560		 *  @type array|object
9561		 *  @default []
9562		 */
9563		"_aData": [],
9564	
9565		/**
9566		 * Sorting data cache - this array is ostensibly the same length as the
9567		 * number of columns (although each index is generated only as it is
9568		 * needed), and holds the data that is used for sorting each column in the
9569		 * row. We do this cache generation at the start of the sort in order that
9570		 * the formatting of the sort data need be done only once for each cell
9571		 * per sort. This array should not be read from or written to by anything
9572		 * other than the master sorting methods.
9573		 *  @type array
9574		 *  @default null
9575		 *  @private
9576		 */
9577		"_aSortData": null,
9578	
9579		/**
9580		 * Per cell filtering data cache. As per the sort data cache, used to
9581		 * increase the performance of the filtering in DataTables
9582		 *  @type array
9583		 *  @default null
9584		 *  @private
9585		 */
9586		"_aFilterData": null,
9587	
9588		/**
9589		 * Filtering data cache. This is the same as the cell filtering cache, but
9590		 * in this case a string rather than an array. This is easily computed with
9591		 * a join on `_aFilterData`, but is provided as a cache so the join isn't
9592		 * needed on every search (memory traded for performance)
9593		 *  @type array
9594		 *  @default null
9595		 *  @private
9596		 */
9597		"_sFilterRow": null,
9598	
9599		/**
9600		 * Cache of the class name that DataTables has applied to the row, so we
9601		 * can quickly look at this variable rather than needing to do a DOM check
9602		 * on className for the nTr property.
9603		 *  @type string
9604		 *  @default <i>Empty string</i>
9605		 *  @private
9606		 */
9607		"_sRowStripe": "",
9608	
9609		/**
9610		 * Denote if the original data source was from the DOM, or the data source
9611		 * object. This is used for invalidating data, so DataTables can
9612		 * automatically read data from the original source, unless uninstructed
9613		 * otherwise.
9614		 *  @type string
9615		 *  @default null
9616		 *  @private
9617		 */
9618		"src": null,
9619	
9620		/**
9621		 * Index in the aoData array. This saves an indexOf lookup when we have the
9622		 * object, but want to know the index
9623		 *  @type integer
9624		 *  @default -1
9625		 *  @private
9626		 */
9627		"idx": -1
9628	};
9629	
9630	
9631	/**
9632	 * Template object for the column information object in DataTables. This object
9633	 * is held in the settings aoColumns array and contains all the information that
9634	 * DataTables needs about each individual column.
9635	 *
9636	 * Note that this object is related to {@link DataTable.defaults.column}
9637	 * but this one is the internal data store for DataTables's cache of columns.
9638	 * It should NOT be manipulated outside of DataTables. Any configuration should
9639	 * be done through the initialisation options.
9640	 *  @namespace
9641	 */
9642	DataTable.models.oColumn = {
9643		/**
9644		 * Column index. This could be worked out on-the-fly with $.inArray, but it
9645		 * is faster to just hold it as a variable
9646		 *  @type integer
9647		 *  @default null
9648		 */
9649		"idx": null,
9650	
9651		/**
9652		 * A list of the columns that sorting should occur on when this column
9653		 * is sorted. That this property is an array allows multi-column sorting
9654		 * to be defined for a column (for example first name / last name columns
9655		 * would benefit from this). The values are integers pointing to the
9656		 * columns to be sorted on (typically it will be a single integer pointing
9657		 * at itself, but that doesn't need to be the case).
9658		 *  @type array
9659		 */
9660		"aDataSort": null,
9661	
9662		/**
9663		 * Define the sorting directions that are applied to the column, in sequence
9664		 * as the column is repeatedly sorted upon - i.e. the first value is used
9665		 * as the sorting direction when the column if first sorted (clicked on).
9666		 * Sort it again (click again) and it will move on to the next index.
9667		 * Repeat until loop.
9668		 *  @type array
9669		 */
9670		"asSorting": null,
9671	
9672		/**
9673		 * Flag to indicate if the column is searchable, and thus should be included
9674		 * in the filtering or not.
9675		 *  @type boolean
9676		 */
9677		"bSearchable": null,
9678	
9679		/**
9680		 * Flag to indicate if the column is sortable or not.
9681		 *  @type boolean
9682		 */
9683		"bSortable": null,
9684	
9685		/**
9686		 * Flag to indicate if the column is currently visible in the table or not
9687		 *  @type boolean
9688		 */
9689		"bVisible": null,
9690	
9691		/**
9692		 * Store for manual type assignment using the `column.type` option. This
9693		 * is held in store so we can manipulate the column's `sType` property.
9694		 *  @type string
9695		 *  @default null
9696		 *  @private
9697		 */
9698		"_sManualType": null,
9699	
9700		/**
9701		 * Flag to indicate if HTML5 data attributes should be used as the data
9702		 * source for filtering or sorting. True is either are.
9703		 *  @type boolean
9704		 *  @default false
9705		 *  @private
9706		 */
9707		"_bAttrSrc": false,
9708	
9709		/**
9710		 * Developer definable function that is called whenever a cell is created (Ajax source,
9711		 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
9712		 * allowing you to modify the DOM element (add background colour for example) when the
9713		 * element is available.
9714		 *  @type function
9715		 *  @param {element} nTd The TD node that has been created
9716		 *  @param {*} sData The Data for the cell
9717		 *  @param {array|object} oData The data for the whole row
9718		 *  @param {int} iRow The row index for the aoData data store
9719		 *  @default null
9720		 */
9721		"fnCreatedCell": null,
9722	
9723		/**
9724		 * Function to get data from a cell in a column. You should <b>never</b>
9725		 * access data directly through _aData internally in DataTables - always use
9726		 * the method attached to this property. It allows mData to function as
9727		 * required. This function is automatically assigned by the column
9728		 * initialisation method
9729		 *  @type function
9730		 *  @param {array|object} oData The data array/object for the array
9731		 *    (i.e. aoData[]._aData)
9732		 *  @param {string} sSpecific The specific data type you want to get -
9733		 *    'display', 'type' 'filter' 'sort'
9734		 *  @returns {*} The data for the cell from the given row's data
9735		 *  @default null
9736		 */
9737		"fnGetData": null,
9738	
9739		/**
9740		 * Function to set data for a cell in the column. You should <b>never</b>
9741		 * set the data directly to _aData internally in DataTables - always use
9742		 * this method. It allows mData to function as required. This function
9743		 * is automatically assigned by the column initialisation method
9744		 *  @type function
9745		 *  @param {array|object} oData The data array/object for the array
9746		 *    (i.e. aoData[]._aData)
9747		 *  @param {*} sValue Value to set
9748		 *  @default null
9749		 */
9750		"fnSetData": null,
9751	
9752		/**
9753		 * Property to read the value for the cells in the column from the data
9754		 * source array / object. If null, then the default content is used, if a
9755		 * function is given then the return from the function is used.
9756		 *  @type function|int|string|null
9757		 *  @default null
9758		 */
9759		"mData": null,
9760	
9761		/**
9762		 * Partner property to mData which is used (only when defined) to get
9763		 * the data - i.e. it is basically the same as mData, but without the
9764		 * 'set' option, and also the data fed to it is the result from mData.
9765		 * This is the rendering method to match the data method of mData.
9766		 *  @type function|int|string|null
9767		 *  @default null
9768		 */
9769		"mRender": null,
9770	
9771		/**
9772		 * Unique header TH/TD element for this column - this is what the sorting
9773		 * listener is attached to (if sorting is enabled.)
9774		 *  @type node
9775		 *  @default null
9776		 */
9777		"nTh": null,
9778	
9779		/**
9780		 * Unique footer TH/TD element for this column (if there is one). Not used
9781		 * in DataTables as such, but can be used for plug-ins to reference the
9782		 * footer for each column.
9783		 *  @type node
9784		 *  @default null
9785		 */
9786		"nTf": null,
9787	
9788		/**
9789		 * The class to apply to all TD elements in the table's TBODY for the column
9790		 *  @type string
9791		 *  @default null
9792		 */
9793		"sClass": null,
9794	
9795		/**
9796		 * When DataTables calculates the column widths to assign to each column,
9797		 * it finds the longest string in each column and then constructs a
9798		 * temporary table and reads the widths from that. The problem with this
9799		 * is that "mmm" is much wider then "iiii", but the latter is a longer
9800		 * string - thus the calculation can go wrong (doing it properly and putting
9801		 * it into an DOM object and measuring that is horribly(!) slow). Thus as
9802		 * a "work around" we provide this option. It will append its value to the
9803		 * text that is found to be the longest string for the column - i.e. padding.
9804		 *  @type string
9805		 */
9806		"sContentPadding": null,
9807	
9808		/**
9809		 * Allows a default value to be given for a column's data, and will be used
9810		 * whenever a null data source is encountered (this can be because mData
9811		 * is set to null, or because the data source itself is null).
9812		 *  @type string
9813		 *  @default null
9814		 */
9815		"sDefaultContent": null,
9816	
9817		/**
9818		 * Name for the column, allowing reference to the column by name as well as
9819		 * by index (needs a lookup to work by name).
9820		 *  @type string
9821		 */
9822		"sName": null,
9823	
9824		/**
9825		 * Custom sorting data type - defines which of the available plug-ins in
9826		 * afnSortData the custom sorting will use - if any is defined.
9827		 *  @type string
9828		 *  @default std
9829		 */
9830		"sSortDataType": 'std',
9831	
9832		/**
9833		 * Class to be applied to the header element when sorting on this column
9834		 *  @type string
9835		 *  @default null
9836		 */
9837		"sSortingClass": null,
9838	
9839		/**
9840		 * Class to be applied to the header element when sorting on this column -
9841		 * when jQuery UI theming is used.
9842		 *  @type string
9843		 *  @default null
9844		 */
9845		"sSortingClassJUI": null,
9846	
9847		/**
9848		 * Title of the column - what is seen in the TH element (nTh).
9849		 *  @type string
9850		 */
9851		"sTitle": null,
9852	
9853		/**
9854		 * Column sorting and filtering type
9855		 *  @type string
9856		 *  @default null
9857		 */
9858		"sType": null,
9859	
9860		/**
9861		 * Width of the column
9862		 *  @type string
9863		 *  @default null
9864		 */
9865		"sWidth": null,
9866	
9867		/**
9868		 * Width of the column when it was first "encountered"
9869		 *  @type string
9870		 *  @default null
9871		 */
9872		"sWidthOrig": null
9873	};
9874	
9875	
9876	/*
9877	 * Developer note: The properties of the object below are given in Hungarian
9878	 * notation, that was used as the interface for DataTables prior to v1.10, however
9879	 * from v1.10 onwards the primary interface is camel case. In order to avoid
9880	 * breaking backwards compatibility utterly with this change, the Hungarian
9881	 * version is still, internally the primary interface, but is is not documented
9882	 * - hence the @name tags in each doc comment. This allows a Javascript function
9883	 * to create a map from Hungarian notation to camel case (going the other direction
9884	 * would require each property to be listed, which would a
9884t around 3K to the size
9885	 * of DataTables, while this method is about a 0.5K hit
vendor: 57,087 bytes, lines 9885-11661
9885.
9886	 *
9887	 * Ultimately this does pave the way for Hungarian notation to be dropped
9888	 * completely, but that is a massive amount of work and will break current
9889	 * installs (therefore is on-hold until v2).
9890	 */
9891	
9892	/**
9893	 * Initialisation options that can be given to DataTables at initialisation
9894	 * time.
9895	 *  @namespace
9896	 */
9897	DataTable.defaults = {
9898		/**
9899		 * An array of data to use for the table, passed in at initialisation which
9900		 * will be used in preference to any data which is already in the DOM. This is
9901		 * particularly useful for constructing tables purely in Javascript, for
9902		 * example with a custom Ajax call.
9903		 *  @type array
9904		 *  @default null
9905		 *
9906		 *  @dtopt Option
9907		 *  @name DataTable.defaults.data
9908		 *
9909		 *  @example
9910		 *    // Using a 2D array data source
9911		 *    $(document).ready( function () {
9912		 *      $('#example').dataTable( {
9913		 *        "data": [
9914		 *          ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
9915		 *          ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
9916		 *        ],
9917		 *        "columns": [
9918		 *          { "title": "Engine" },
9919		 *          { "title": "Browser" },
9920		 *          { "title": "Platform" },
9921		 *          { "title": "Version" },
9922		 *          { "title": "Grade" }
9923		 *        ]
9924		 *      } );
9925		 *    } );
9926		 *
9927		 *  @example
9928		 *    // Using an array of objects as a data source (`data`)
9929		 *    $(document).ready( function () {
9930		 *      $('#example').dataTable( {
9931		 *        "data": [
9932		 *          {
9933		 *            "engine":   "Trident",
9934		 *            "browser":  "Internet Explorer 4.0",
9935		 *            "platform": "Win 95+",
9936		 *            "version":  4,
9937		 *            "grade":    "X"
9938		 *          },
9939		 *          {
9940		 *            "engine":   "Trident",
9941		 *            "browser":  "Internet Explorer 5.0",
9942		 *            "platform": "Win 95+",
9943		 *            "version":  5,
9944		 *            "grade":    "C"
9945		 *          }
9946		 *        ],
9947		 *        "columns": [
9948		 *          { "title": "Engine",   "data": "engine" },
9949		 *          { "title": "Browser",  "data": "browser" },
9950		 *          { "title": "Platform", "data": "platform" },
9951		 *          { "title": "Version",  "data": "version" },
9952		 *          { "title": "Grade",    "data": "grade" }
9953		 *        ]
9954		 *      } );
9955		 *    } );
9956		 */
9957		"aaData": null,
9958	
9959	
9960		/**
9961		 * If ordering is enabled, then DataTables will perform a first pass sort on
9962		 * initialisation. You can define which column(s) the sort is performed
9963		 * upon, and the sorting direction, with this variable. The `sorting` array
9964		 * should contain an array for each column to be sorted initially containing
9965		 * the column's index and a direction string ('asc' or 'desc').
9966		 *  @type array
9967		 *  @default [[0,'asc']]
9968		 *
9969		 *  @dtopt Option
9970		 *  @name DataTable.defaults.order
9971		 *
9972		 *  @example
9973		 *    // Sort by 3rd column first, and then 4th column
9974		 *    $(document).ready( function() {
9975		 *      $('#example').dataTable( {
9976		 *        "order": [[2,'asc'], [3,'desc']]
9977		 *      } );
9978		 *    } );
9979		 *
9980		 *    // No initial sorting
9981		 *    $(document).ready( function() {
9982		 *      $('#example').dataTable( {
9983		 *        "order": []
9984		 *      } );
9985		 *    } );
9986		 */
9987		"aaSorting": [[0,'asc']],
9988	
9989	
9990		/**
9991		 * This parameter is basically identical to the `sorting` parameter, but
9992		 * cannot be overridden by user interaction with the table. What this means
9993		 * is that you could have a column (visible or hidden) which the sorting
9994		 * will always be forced on first - any sorting after that (from the user)
9995		 * will then be performed as required. This can be useful for grouping rows
9996		 * together.
9997		 *  @type array
9998		 *  @default null
9999		 *
10000		 *  @dtopt Option
10001		 *  @name DataTable.defaults.orderFixed
10002		 *
10003		 *  @example
10004		 *    $(document).ready( function() {
10005		 *      $('#example').dataTable( {
10006		 *        "orderFixed": [[0,'asc']]
10007		 *      } );
10008		 *    } )
10009		 */
10010		"aaSortingFixed": [],
10011	
10012	
10013		/**
10014		 * DataTables can be instructed to load data to display in the table from a
10015		 * Ajax source. This option defines how that Ajax call is made and where to.
10016		 *
10017		 * The `ajax` property has three different modes of operation, depending on
10018		 * how it is defined. These are:
10019		 *
10020		 * * `string` - Set the URL from where the data should be loaded from.
10021		 * * `object` - Define properties for `jQuery.ajax`.
10022		 * * `function` - Custom data get function
10023		 *
10024		 * `string`
10025		 * --------
10026		 *
10027		 * As a string, the `ajax` property simply defines the URL from which
10028		 * DataTables will load data.
10029		 *
10030		 * `object`
10031		 * --------
10032		 *
10033		 * As an object, the parameters in the object are passed to
10034		 * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control
10035		 * of the Ajax request. DataTables has a number of default parameters which
10036		 * you can override using this option. Please refer to the jQuery
10037		 * documentation for a full description of the options available, although
10038		 * the following parameters provide additional options in DataTables or
10039		 * require special consideration:
10040		 *
10041		 * * `data` - As with jQuery, `data` can be provided as an object, but it
10042		 *   can also be used as a function to manipulate the data DataTables sends
10043		 *   to the server. The function takes a single parameter, an object of
10044		 *   parameters with the values that DataTables has readied for sending. An
10045		 *   object may be returned which will be merged into the DataTables
10046		 *   defaults, or you can add the items to the object that was passed in and
10047		 *   not return anything from the function. This supersedes `fnServerParams`
10048		 *   from DataTables 1.9-.
10049		 *
10050		 * * `dataSrc` - By default DataTables will look for the property `data` (or
10051		 *   `aaData` for compatibility with DataTables 1.9-) when obtaining data
10052		 *   from an Ajax source or for server-side processing - this parameter
10053		 *   allows that property to be changed. You can use Javascript dotted
10054		 *   object notation to get a data source for multiple levels of nesting, or
10055		 *   it my be used as a function. As a function it takes a single parameter,
10056		 *   the JSON returned from the server, which can be manipulated as
10057		 *   required, with the returned value being that used by DataTables as the
10058		 *   data source for the table. This supersedes `sAjaxDataProp` from
10059		 *   DataTables 1.9-.
10060		 *
10061		 * * `success` - Should not be overridden it is used internally in
10062		 *   DataTables. To manipulate / transform the data returned by the server
10063		 *   use `ajax.dataSrc`, or use `ajax` as a function (see below).
10064		 *
10065		 * `function`
10066		 * ----------
10067		 *
10068		 * As a function, making the Ajax call is left up to yourself allowing
10069		 * complete control of the Ajax request. Indeed, if desired, a method other
10070		 * than Ajax could be used to obtain the required data, such as Web storage
10071		 * or an AIR database.
10072		 *
10073		 * The function is given four parameters and no return is required. The
10074		 * parameters are:
10075		 *
10076		 * 1. _object_ - Data to send to the server
10077		 * 2. _function_ - Callback function that must be executed when the required
10078		 *    data has been obtained. That data should be passed into the callback
10079		 *    as the only parameter
10080		 * 3. _object_ - DataTables settings object for the table
10081		 *
10082		 * Note that this supersedes `fnServerData` from DataTables 1.9-.
10083		 *
10084		 *  @type string|object|function
10085		 *  @default null
10086		 *
10087		 *  @dtopt Option
10088		 *  @name DataTable.defaults.ajax
10089		 *  @since 1.10.0
10090		 *
10091		 * @example
10092		 *   // Get JSON data from a file via Ajax.
10093		 *   // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default).
10094		 *   $('#example').dataTable( {
10095		 *     "ajax": "data.json"
10096		 *   } );
10097		 *
10098		 * @example
10099		 *   // Get JSON data from a file via Ajax, using `dataSrc` to change
10100		 *   // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`)
10101		 *   $('#example').dataTable( {
10102		 *     "ajax": {
10103		 *       "url": "data.json",
10104		 *       "dataSrc": "tableData"
10105		 *     }
10106		 *   } );
10107		 *
10108		 * @example
10109		 *   // Get JSON data from a file via Ajax, using `dataSrc` to read data
10110		 *   // from a plain array rather than an array in an object
10111		 *   $('#example').dataTable( {
10112		 *     "ajax": {
10113		 *       "url": "data.json",
10114		 *       "dataSrc": ""
10115		 *     }
10116		 *   } );
10117		 *
10118		 * @example
10119		 *   // Manipulate the data returned from the server - add a link to data
10120		 *   // (note this can, should, be done using `render` for the column - this
10121		 *   // is just a simple example of how the data can be manipulated).
10122		 *   $('#example').dataTable( {
10123		 *     "ajax": {
10124		 *       "url": "data.json",
10125		 *       "dataSrc": function ( json ) {
10126		 *         for ( var i=0, ien=json.length ; i<ien ; i++ ) {
10127		 *           json[i][0] = '<a href="/message/'+json[i][0]+'>View message</a>';
10128		 *         }
10129		 *         return json;
10130		 *       }
10131		 *     }
10132		 *   } );
10133		 *
10134		 * @example
10135		 *   // Add data to the request
10136		 *   $('#example').dataTable( {
10137		 *     "ajax": {
10138		 *       "url": "data.json",
10139		 *       "data": function ( d ) {
10140		 *         return {
10141		 *           "extra_search": $('#extra').val()
10142		 *         };
10143		 *       }
10144		 *     }
10145		 *   } );
10146		 *
10147		 * @example
10148		 *   // Send request as POST
10149		 *   $('#example').dataTable( {
10150		 *     "ajax": {
10151		 *       "url": "data.json",
10152		 *       "type": "POST"
10153		 *     }
10154		 *   } );
10155		 *
10156		 * @example
10157		 *   // Get the data from localStorage (could interface with a form for
10158		 *   // adding, editing and removing rows).
10159		 *   $('#example').dataTable( {
10160		 *     "ajax": function (data, callback, settings) {
10161		 *       callback(
10162		 *         JSON.parse( localStorage.getItem('dataTablesData') )
10163		 *       );
10164		 *     }
10165		 *   } );
10166		 */
10167		"ajax": null,
10168	
10169	
10170		/**
10171		 * This parameter allows you to readily specify the entries in the length drop
10172		 * down menu that DataTables shows when pagination is enabled. It can be
10173		 * either a 1D array of options which will be used for both the displayed
10174		 * option and the value, or a 2D array which will use the array in the first
10175		 * position as the value, and the array in the second position as the
10176		 * displayed options (useful for language strings such as 'All').
10177		 *
10178		 * Note that the `pageLength` property will be automatically set to the
10179		 * first value given in this array, unless `pageLength` is also provided.
10180		 *  @type array
10181		 *  @default [ 10, 25, 50, 100 ]
10182		 *
10183		 *  @dtopt Option
10184		 *  @name DataTable.defaults.lengthMenu
10185		 *
10186		 *  @example
10187		 *    $(document).ready( function() {
10188		 *      $('#example').dataTable( {
10189		 *        "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
10190		 *      } );
10191		 *    } );
10192		 */
10193		"aLengthMenu": [ 10, 25, 50, 100 ],
10194	
10195	
10196		/**
10197		 * The `columns` option in the initialisation parameter allows you to define
10198		 * details about the way individual columns behave. For a full list of
10199		 * column options that can be set, please see
10200		 * {@link DataTable.defaults.column}. Note that if you use `columns` to
10201		 * define your columns, you must have an entry in the array for every single
10202		 * column that you have in your table (these can be null if you don't which
10203		 * to specify any options).
10204		 *  @member
10205		 *
10206		 *  @name DataTable.defaults.column
10207		 */
10208		"aoColumns": null,
10209	
10210		/**
10211		 * Very similar to `columns`, `columnDefs` allows you to target a specific
10212		 * column, multiple columns, or all columns, using the `targets` property of
10213		 * each object in the array. This allows great flexibility when creating
10214		 * tables, as the `columnDefs` arrays can be of any length, targeting the
10215		 * columns you specifically want. `columnDefs` may use any of the column
10216		 * options available: {@link DataTable.defaults.column}, but it _must_
10217		 * have `targets` defined in each object in the array. Values in the `targets`
10218		 * array may be:
10219		 *   <ul>
10220		 *     <li>a string - class name will be matched on the TH for the column</li>
10221		 *     <li>0 or a positive integer - column index counting from the left</li>
10222		 *     <li>a negative integer - column index counting from the right</li>
10223		 *     <li>the string "_all" - all columns (i.e. assign a default)</li>
10224		 *   </ul>
10225		 *  @member
10226		 *
10227		 *  @name DataTable.defaults.columnDefs
10228		 */
10229		"aoColumnDefs": null,
10230	
10231	
10232		/**
10233		 * Basically the same as `search`, this parameter defines the individual column
10234		 * filtering state at initialisation time. The array must be of the same size
10235		 * as the number of columns, and each element be an object with the parameters
10236		 * `search` and `escapeRegex` (the latter is optional). 'null' is also
10237		 * accepted and the default will be used.
10238		 *  @type array
10239		 *  @default []
10240		 *
10241		 *  @dtopt Option
10242		 *  @name DataTable.defaults.searchCols
10243		 *
10244		 *  @example
10245		 *    $(document).ready( function() {
10246		 *      $('#example').dataTable( {
10247		 *        "searchCols": [
10248		 *          null,
10249		 *          { "search": "My filter" },
10250		 *          null,
10251		 *          { "search": "^[0-9]", "escapeRegex": false }
10252		 *        ]
10253		 *      } );
10254		 *    } )
10255		 */
10256		"aoSearchCols": [],
10257	
10258	
10259		/**
10260		 * An array of CSS classes that should be applied to displayed rows. This
10261		 * array may be of any length, and DataTables will apply each class
10262		 * sequentially, looping when required.
10263		 *  @type array
10264		 *  @default null <i>Will take the values determined by the `oClasses.stripe*`
10265		 *    options</i>
10266		 *
10267		 *  @dtopt Option
10268		 *  @name DataTable.defaults.stripeClasses
10269		 *
10270		 *  @example
10271		 *    $(document).ready( function() {
10272		 *      $('#example').dataTable( {
10273		 *        "stripeClasses": [ 'strip1', 'strip2', 'strip3' ]
10274		 *      } );
10275		 *    } )
10276		 */
10277		"asStripeClasses": null,
10278	
10279	
10280		/**
10281		 * Enable or disable automatic column width calculation. This can be disabled
10282		 * as an optimisation (it takes some time to calculate the widths) if the
10283		 * tables widths are passed in using `columns`.
10284		 *  @type boolean
10285		 *  @default true
10286		 *
10287		 *  @dtopt Features
10288		 *  @name DataTable.defaults.autoWidth
10289		 *
10290		 *  @example
10291		 *    $(document).ready( function () {
10292		 *      $('#example').dataTable( {
10293		 *        "autoWidth": false
10294		 *      } );
10295		 *    } );
10296		 */
10297		"bAutoWidth": true,
10298	
10299	
10300		/**
10301		 * Deferred rendering can provide DataTables with a huge speed boost when you
10302		 * are using an Ajax or JS data source for the table. This option, when set to
10303		 * true, will cause DataTables to defer the creation of the table elements for
10304		 * each row until they are needed for a draw - saving a significant amount of
10305		 * time.
10306		 *  @type boolean
10307		 *  @default false
10308		 *
10309		 *  @dtopt Features
10310		 *  @name DataTable.defaults.deferRender
10311		 *
10312		 *  @example
10313		 *    $(document).ready( function() {
10314		 *      $('#example').dataTable( {
10315		 *        "ajax": "sources/arrays.txt",
10316		 *        "deferRender": true
10317		 *      } );
10318		 *    } );
10319		 */
10320		"bDeferRender": false,
10321	
10322	
10323		/**
10324		 * Replace a DataTable which matches the given selector and replace it with
10325		 * one which has the properties of the new initialisation object passed. If no
10326		 * table matches the selector, then the new DataTable will be constructed as
10327		 * per normal.
10328		 *  @type boolean
10329		 *  @default false
10330		 *
10331		 *  @dtopt Options
10332		 *  @name DataTable.defaults.destroy
10333		 *
10334		 *  @example
10335		 *    $(document).ready( function() {
10336		 *      $('#example').dataTable( {
10337		 *        "srollY": "200px",
10338		 *        "paginate": false
10339		 *      } );
10340		 *
10341		 *      // Some time later....
10342		 *      $('#example').dataTable( {
10343		 *        "filter": false,
10344		 *        "destroy": true
10345		 *      } );
10346		 *    } );
10347		 */
10348		"bDestroy": false,
10349	
10350	
10351		/**
10352		 * Enable or disable filtering of data. Filtering in DataTables is "smart" in
10353		 * that it allows the end user to input multiple words (space separated) and
10354		 * will match a row containing those words, even if not in the order that was
10355		 * specified (this allow matching across multiple columns). Note that if you
10356		 * wish to use filtering in DataTables this must remain 'true' - to remove the
10357		 * default filtering input box and retain filtering abilities, please use
10358		 * {@link DataTable.defaults.dom}.
10359		 *  @type boolean
10360		 *  @default true
10361		 *
10362		 *  @dtopt Features
10363		 *  @name DataTable.defaults.searching
10364		 *
10365		 *  @example
10366		 *    $(document).ready( function () {
10367		 *      $('#example').dataTable( {
10368		 *        "searching": false
10369		 *      } );
10370		 *    } );
10371		 */
10372		"bFilter": true,
10373	
10374	
10375		/**
10376		 * Enable or disable the table information display. This shows information
10377		 * about the data that is currently visible on the page, including information
10378		 * about filtered data if that action is being performed.
10379		 *  @type boolean
10380		 *  @default true
10381		 *
10382		 *  @dtopt Features
10383		 *  @name DataTable.defaults.info
10384		 *
10385		 *  @example
10386		 *    $(document).ready( function () {
10387		 *      $('#example').dataTable( {
10388		 *        "info": false
10389		 *      } );
10390		 *    } );
10391		 */
10392		"bInfo": true,
10393	
10394	
10395		/**
10396		 * Allows the end user to select the size of a formatted page from a select
10397		 * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`).
10398		 *  @type boolean
10399		 *  @default true
10400		 *
10401		 *  @dtopt Features
10402		 *  @name DataTable.defaults.lengthChange
10403		 *
10404		 *  @example
10405		 *    $(document).ready( function () {
10406		 *      $('#example').dataTable( {
10407		 *        "lengthChange": false
10408		 *      } );
10409		 *    } );
10410		 */
10411		"bLengthChange": true,
10412	
10413	
10414		/**
10415		 * Enable or disable pagination.
10416		 *  @type boolean
10417		 *  @default true
10418		 *
10419		 *  @dtopt Features
10420		 *  @name DataTable.defaults.paging
10421		 *
10422		 *  @example
10423		 *    $(document).ready( function () {
10424		 *      $('#example').dataTable( {
10425		 *        "paging": false
10426		 *      } );
10427		 *    } );
10428		 */
10429		"bPaginate": true,
10430	
10431	
10432		/**
10433		 * Enable or disable the display of a 'processing' indicator when the table is
10434		 * being processed (e.g. a sort). This is particularly useful for tables with
10435		 * large amounts of data where it can take a noticeable amount of time to sort
10436		 * the entries.
10437		 *  @type boolean
10438		 *  @default false
10439		 *
10440		 *  @dtopt Features
10441		 *  @name DataTable.defaults.processing
10442		 *
10443		 *  @example
10444		 *    $(document).ready( function () {
10445		 *      $('#example').dataTable( {
10446		 *        "processing": true
10447		 *      } );
10448		 *    } );
10449		 */
10450		"bProcessing": false,
10451	
10452	
10453		/**
10454		 * Retrieve the DataTables object for the given selector. Note that if the
10455		 * table has already been initialised, this parameter will cause DataTables
10456		 * to simply return the object that has already been set up - it will not take
10457		 * account of any changes you might have made to the initialisation object
10458		 * passed to DataTables (setting this parameter to true is an acknowledgement
10459		 * that you understand this). `destroy` can be used to reinitialise a table if
10460		 * you need.
10461		 *  @type boolean
10462		 *  @default false
10463		 *
10464		 *  @dtopt Options
10465		 *  @name DataTable.defaults.retrieve
10466		 *
10467		 *  @example
10468		 *    $(document).ready( function() {
10469		 *      initTable();
10470		 *      tableActions();
10471		 *    } );
10472		 *
10473		 *    function initTable ()
10474		 *    {
10475		 *      return $('#example').dataTable( {
10476		 *        "scrollY": "200px",
10477		 *        "paginate": false,
10478		 *        "retrieve": true
10479		 *      } );
10480		 *    }
10481		 *
10482		 *    function tableActions ()
10483		 *    {
10484		 *      var table = initTable();
10485		 *      // perform API operations with oTable
10486		 *    }
10487		 */
10488		"bRetrieve": false,
10489	
10490	
10491		/**
10492		 * When vertical (y) scrolling is enabled, DataTables will force the height of
10493		 * the table's viewport to the given height at all times (useful for layout).
10494		 * However, this can look odd when filtering data down to a small data set,
10495		 * and the footer is left "floating" further down. This parameter (when
10496		 * enabled) will cause DataTables to collapse the table's viewport down when
10497		 * the result set will fit within the given Y height.
10498		 *  @type boolean
10499		 *  @default false
10500		 *
10501		 *  @dtopt Options
10502		 *  @name DataTable.defaults.scrollCollapse
10503		 *
10504		 *  @example
10505		 *    $(document).ready( function() {
10506		 *      $('#example').dataTable( {
10507		 *        "scrollY": "200",
10508		 *        "scrollCollapse": true
10509		 *      } );
10510		 *    } );
10511		 */
10512		"bScrollCollapse": false,
10513	
10514	
10515		/**
10516		 * Configure DataTables to use server-side processing. Note that the
10517		 * `ajax` parameter must also be given in order to give DataTables a
10518		 * source to obtain the required data for each draw.
10519		 *  @type boolean
10520		 *  @default false
10521		 *
10522		 *  @dtopt Features
10523		 *  @dtopt Server-side
10524		 *  @name DataTable.defaults.serverSide
10525		 *
10526		 *  @example
10527		 *    $(document).ready( function () {
10528		 *      $('#example').dataTable( {
10529		 *        "serverSide": true,
10530		 *        "ajax": "xhr.php"
10531		 *      } );
10532		 *    } );
10533		 */
10534		"bServerSide": false,
10535	
10536	
10537		/**
10538		 * Enable or disable sorting of columns. Sorting of individual columns can be
10539		 * disabled by the `sortable` option for each column.
10540		 *  @type boolean
10541		 *  @default true
10542		 *
10543		 *  @dtopt Features
10544		 *  @name DataTable.defaults.ordering
10545		 *
10546		 *  @example
10547		 *    $(document).ready( function () {
10548		 *      $('#example').dataTable( {
10549		 *        "ordering": false
10550		 *      } );
10551		 *    } );
10552		 */
10553		"bSort": true,
10554	
10555	
10556		/**
10557		 * Enable or display DataTables' ability to sort multiple columns at the
10558		 * same time (activated by shift-click by the user).
10559		 *  @type boolean
10560		 *  @default true
10561		 *
10562		 *  @dtopt Options
10563		 *  @name DataTable.defaults.orderMulti
10564		 *
10565		 *  @example
10566		 *    // Disable multiple column sorting ability
10567		 *    $(document).ready( function () {
10568		 *      $('#example').dataTable( {
10569		 *        "orderMulti": false
10570		 *      } );
10571		 *    } );
10572		 */
10573		"bSortMulti": true,
10574	
10575	
10576		/**
10577		 * Allows control over whether DataTables should use the top (true) unique
10578		 * cell that is found for a single column, or the bottom (false - default).
10579		 * This is useful when using complex headers.
10580		 *  @type boolean
10581		 *  @default false
10582		 *
10583		 *  @dtopt Options
10584		 *  @name DataTable.defaults.orderCellsTop
10585		 *
10586		 *  @example
10587		 *    $(document).ready( function() {
10588		 *      $('#example').dataTable( {
10589		 *        "orderCellsTop": true
10590		 *      } );
10591		 *    } );
10592		 */
10593		"bSortCellsTop": false,
10594	
10595	
10596		/**
10597		 * Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and
10598		 * `sorting\_3` to the columns which are currently being sorted on. This is
10599		 * presented as a feature switch as it can increase processing time (while
10600		 * classes are removed and added) so for large data sets you might want to
10601		 * turn this off.
10602		 *  @type boolean
10603		 *  @default true
10604		 *
10605		 *  @dtopt Features
10606		 *  @name DataTable.defaults.orderClasses
10607		 *
10608		 *  @example
10609		 *    $(document).ready( function () {
10610		 *      $('#example').dataTable( {
10611		 *        "orderClasses": false
10612		 *      } );
10613		 *    } );
10614		 */
10615		"bSortClasses": true,
10616	
10617	
10618		/**
10619		 * Enable or disable state saving. When enabled HTML5 `localStorage` will be
10620		 * used to save table display information such as pagination information,
10621		 * display length, filtering and sorting. As such when the end user reloads
10622		 * the page the display display will match what thy had previously set up.
10623		 *
10624		 * Due to the use of `localStorage` the default state saving is not supported
10625		 * in IE6 or 7. If state saving is required in those browsers, use
10626		 * `stateSaveCallback` to provide a storage solution such as cookies.
10627		 *  @type boolean
10628		 *  @default false
10629		 *
10630		 *  @dtopt Features
10631		 *  @name DataTable.defaults.stateSave
10632		 *
10633		 *  @example
10634		 *    $(document).ready( function () {
10635		 *      $('#example').dataTable( {
10636		 *        "stateSave": true
10637		 *      } );
10638		 *    } );
10639		 */
10640		"bStateSave": false,
10641	
10642	
10643		/**
10644		 * This function is called when a TR element is created (and all TD child
10645		 * elements have been inserted), or registered if using a DOM source, allowing
10646		 * manipulation of the TR element (adding classes etc).
10647		 *  @type function
10648		 *  @param {node} row "TR" element for the current row
10649		 *  @param {array} data Raw data array for this row
10650		 *  @param {int} dataIndex The index of this row in the internal aoData array
10651		 *
10652		 *  @dtopt Callbacks
10653		 *  @name DataTable.defaults.createdRow
10654		 *
10655		 *  @example
10656		 *    $(document).ready( function() {
10657		 *      $('#example').dataTable( {
10658		 *        "createdRow": function( row, data, dataIndex ) {
10659		 *          // Bold the grade for all 'A' grade browsers
10660		 *          if ( data[4] == "A" )
10661		 *          {
10662		 *            $('td:eq(4)', row).html( '<b>A</b>' );
10663		 *          }
10664		 *        }
10665		 *      } );
10666		 *    } );
10667		 */
10668		"fnCreatedRow": null,
10669	
10670	
10671		/**
10672		 * This function is called on every 'draw' event, and allows you to
10673		 * dynamically modify any aspect you want about the created DOM.
10674		 *  @type function
10675		 *  @param {object} settings DataTables settings object
10676		 *
10677		 *  @dtopt Callbacks
10678		 *  @name DataTable.defaults.drawCallback
10679		 *
10680		 *  @example
10681		 *    $(document).ready( function() {
10682		 *      $('#example').dataTable( {
10683		 *        "drawCallback": function( settings ) {
10684		 *          alert( 'DataTables has redrawn the table' );
10685		 *        }
10686		 *      } );
10687		 *    } );
10688		 */
10689		"fnDrawCallback": null,
10690	
10691	
10692		/**
10693		 * Identical to fnHeaderCallback() but for the table footer this function
10694		 * allows you to modify the table footer on every 'draw' event.
10695		 *  @type function
10696		 *  @param {node} foot "TR" element for the footer
10697		 *  @param {array} data Full table data (as derived from the original HTML)
10698		 *  @param {int} start Index for the current display starting point in the
10699		 *    display array
10700		 *  @param {int} end Index for the current display ending point in the
10701		 *    display array
10702		 *  @param {array int} display Index array to translate the visual position
10703		 *    to the full data array
10704		 *
10705		 *  @dtopt Callbacks
10706		 *  @name DataTable.defaults.footerCallback
10707		 *
10708		 *  @example
10709		 *    $(document).ready( function() {
10710		 *      $('#example').dataTable( {
10711		 *        "footerCallback": function( tfoot, data, start, end, display ) {
10712		 *          tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start;
10713		 *        }
10714		 *      } );
10715		 *    } )
10716		 */
10717		"fnFooterCallback": null,
10718	
10719	
10720		/**
10721		 * When rendering large numbers in the information element for the table
10722		 * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
10723		 * to have a comma separator for the 'thousands' units (e.g. 1 million is
10724		 * rendered as "1,000,000") to help readability for the end user. This
10725		 * function will override the default method DataTables uses.
10726		 *  @type function
10727		 *  @member
10728		 *  @param {int} toFormat number to be formatted
10729		 *  @returns {string} formatted string for DataTables to show the number
10730		 *
10731		 *  @dtopt Callbacks
10732		 *  @name DataTable.defaults.formatNumber
10733		 *
10734		 *  @example
10735		 *    // Format a number using a single quote for the separator (note that
10736		 *    // this can also be done with the language.thousands option)
10737		 *    $(document).ready( function() {
10738		 *      $('#example').dataTable( {
10739		 *        "formatNumber": function ( toFormat ) {
10740		 *          return toFormat.toString().replace(
10741		 *            /\B(?=(\d{3})+(?!\d))/g, "'"
10742		 *          );
10743		 *        };
10744		 *      } );
10745		 *    } );
10746		 */
10747		"fnFormatNumber": function ( toFormat ) {
10748			return toFormat.toString().replace(
10749				/\B(?=(\d{3})+(?!\d))/g,
10750				this.oLanguage.sThousands
10751			);
10752		},
10753	
10754	
10755		/**
10756		 * This function is called on every 'draw' event, and allows you to
10757		 * dynamically modify the header row. This can be used to calculate and
10758		 * display useful information about the table.
10759		 *  @type function
10760		 *  @param {node} head "TR" element for the header
10761		 *  @param {array} data Full table data (as derived from the original HTML)
10762		 *  @param {int} start Index for the current display starting point in the
10763		 *    display array
10764		 *  @param {int} end Index for the current display ending point in the
10765		 *    display array
10766		 *  @param {array int} display Index array to translate the visual position
10767		 *    to the full data array
10768		 *
10769		 *  @dtopt Callbacks
10770		 *  @name DataTable.defaults.headerCallback
10771		 *
10772		 *  @example
10773		 *    $(document).ready( function() {
10774		 *      $('#example').dataTable( {
10775		 *        "fheaderCallback": function( head, data, start, end, display ) {
10776		 *          head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records";
10777		 *        }
10778		 *      } );
10779		 *    } )
10780		 */
10781		"fnHeaderCallback": null,
10782	
10783	
10784		/**
10785		 * The information element can be used to convey information about the current
10786		 * state of the table. Although the internationalisation options presented by
10787		 * DataTables are quite capable of dealing with most customisations, there may
10788		 * be times where you wish to customise the string further. This callback
10789		 * allows you to do exactly that.
10790		 *  @type function
10791		 *  @param {object} oSettings DataTables settings object
10792		 *  @param {int} start Starting position in data for the draw
10793		 *  @param {int} end End position in data for the draw
10794		 *  @param {int} max Total number of rows in the table (regardless of
10795		 *    filtering)
10796		 *  @param {int} total Total number of rows in the data set, after filtering
10797		 *  @param {string} pre The string that DataTables has formatted using it's
10798		 *    own rules
10799		 *  @returns {string} The string to be displayed in the information element.
10800		 *
10801		 *  @dtopt Callbacks
10802		 *  @name DataTable.defaults.infoCallback
10803		 *
10804		 *  @example
10805		 *    $('#example').dataTable( {
10806		 *      "infoCallback": function( settings, start, end, max, total, pre ) {
10807		 *        return start +" to "+ end;
10808		 *      }
10809		 *    } );
10810		 */
10811		"fnInfoCallback": null,
10812	
10813	
10814		/**
10815		 * Called when the table has been initialised. Normally DataTables will
10816		 * initialise sequentially and there will be no need for this function,
10817		 * however, this does not hold true when using external language information
10818		 * since that is obtained using an async XHR call.
10819		 *  @type function
10820		 *  @param {object} settings DataTables settings object
10821		 *  @param {object} json The JSON object request from the server - only
10822		 *    present if client-side Ajax sourced data is used
10823		 *
10824		 *  @dtopt Callbacks
10825		 *  @name DataTable.defaults.initComplete
10826		 *
10827		 *  @example
10828		 *    $(document).ready( function() {
10829		 *      $('#example').dataTable( {
10830		 *        "initComplete": function(settings, json) {
10831		 *          alert( 'DataTables has finished its initialisation.' );
10832		 *        }
10833		 *      } );
10834		 *    } )
10835		 */
10836		"fnInitComplete": null,
10837	
10838	
10839		/**
10840		 * Called at the very start of each table draw and can be used to cancel the
10841		 * draw by returning false, any other return (including undefined) results in
10842		 * the full draw occurring).
10843		 *  @type function
10844		 *  @param {object} settings DataTables settings object
10845		 *  @returns {boolean} False will cancel the draw, anything else (including no
10846		 *    return) will allow it to complete.
10847		 *
10848		 *  @dtopt Callbacks
10849		 *  @name DataTable.defaults.preDrawCallback
10850		 *
10851		 *  @example
10852		 *    $(document).ready( function() {
10853		 *      $('#example').dataTable( {
10854		 *        "preDrawCallback": function( settings ) {
10855		 *          if ( $('#test').val() == 1 ) {
10856		 *            return false;
10857		 *          }
10858		 *        }
10859		 *      } );
10860		 *    } );
10861		 */
10862		"fnPreDrawCallback": null,
10863	
10864	
10865		/**
10866		 * This function allows you to 'post process' each row after it have been
10867		 * generated for each table draw, but before it is rendered on screen. This
10868		 * function might be used for setting the row class name etc.
10869		 *  @type function
10870		 *  @param {node} row "TR" element for the current row
10871		 *  @param {array} data Raw data array for this row
10872		 *  @param {int} displayIndex The display index for the current table draw
10873		 *  @param {int} displayIndexFull The index of the data in the full list of
10874		 *    rows (after filtering)
10875		 *
10876		 *  @dtopt Callbacks
10877		 *  @name DataTable.defaults.rowCallback
10878		 *
10879		 *  @example
10880		 *    $(document).ready( function() {
10881		 *      $('#example').dataTable( {
10882		 *        "rowCallback": function( row, data, displayIndex, displayIndexFull ) {
10883		 *          // Bold the grade for all 'A' grade browsers
10884		 *          if ( data[4] == "A" ) {
10885		 *            $('td:eq(4)', row).html( '<b>A</b>' );
10886		 *          }
10887		 *        }
10888		 *      } );
10889		 *    } );
10890		 */
10891		"fnRowCallback": null,
10892	
10893	
10894		/**
10895		 * __Deprecated__ The functionality provided by this parameter has now been
10896		 * superseded by that provided through `ajax`, which should be used instead.
10897		 *
10898		 * This parameter allows you to override the default function which obtains
10899		 * the data from the server so something more suitable for your application.
10900		 * For example you could use POST data, or pull information from a Gears or
10901		 * AIR database.
10902		 *  @type function
10903		 *  @member
10904		 *  @param {string} source HTTP source to obtain the data from (`ajax`)
10905		 *  @param {array} data A key/value pair object containing the data to send
10906		 *    to the server
10907		 *  @param {function} callback to be called on completion of the data get
10908		 *    process that will draw the data on the page.
10909		 *  @param {object} settings DataTables settings object
10910		 *
10911		 *  @dtopt Callbacks
10912		 *  @dtopt Server-side
10913		 *  @name DataTable.defaults.serverData
10914		 *
10915		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
10916		 */
10917		"fnServerData": null,
10918	
10919	
10920		/**
10921		 * __Deprecated__ The functionality provided by this parameter has now been
10922		 * superseded by that provided through `ajax`, which should be used instead.
10923		 *
10924		 *  It is often useful to send extra data to the server when making an Ajax
10925		 * request - for example custom filtering information, and this callback
10926		 * function makes it trivial to send extra information to the server. The
10927		 * passed in parameter is the data set that has been constructed by
10928		 * DataTables, and you can add to this or modify it as you require.
10929		 *  @type function
10930		 *  @param {array} data Data array (array of objects which are name/value
10931		 *    pairs) that has been constructed by DataTables and will be sent to the
10932		 *    server. In the case of Ajax sourced data with server-side processing
10933		 *    this will be an empty array, for server-side processing there will be a
10934		 *    significant number of parameters!
10935		 *  @returns {undefined} Ensure that you modify the data array passed in,
10936		 *    as this is passed by reference.
10937		 *
10938		 *  @dtopt Callbacks
10939		 *  @dtopt Server-side
10940		 *  @name DataTable.defaults.serverParams
10941		 *
10942		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
10943		 */
10944		"fnServerParams": null,
10945	
10946	
10947		/**
10948		 * Load the table state. With this function you can define from where, and how, the
10949		 * state of a table is loaded. By default DataTables will load from `localStorage`
10950		 * but you might wish to use a server-side database or cookies.
10951		 *  @type function
10952		 *  @member
10953		 *  @param {object} settings DataTables settings object
10954		 *  @param {object} callback Callback that can be executed when done. It
10955		 *    should be passed the loaded state object.
10956		 *  @return {object} The DataTables state object to be loaded
10957		 *
10958		 *  @dtopt Callbacks
10959		 *  @name DataTable.defaults.stateLoadCallback
10960		 *
10961		 *  @example
10962		 *    $(document).ready( function() {
10963		 *      $('#example').dataTable( {
10964		 *        "stateSave": true,
10965		 *        "stateLoadCallback": function (settings, callback) {
10966		 *          $.ajax( {
10967		 *            "url": "/state_load",
10968		 *            "dataType": "json",
10969		 *            "success": function (json) {
10970		 *              callback( json );
10971		 *            }
10972		 *          } );
10973		 *        }
10974		 *      } );
10975		 *    } );
10976		 */
10977		"fnStateLoadCallback": function ( settings ) {
10978			try {
10979				return JSON.parse(
10980					(settings.iStateDuration === -1 ? sessionStorage : localStorage).getItem(
10981						'DataTables_'+settings.sInstance+'_'+location.pathname
10982					)
10983				);
10984			} catch (e) {}
10985		},
10986	
10987	
10988		/**
10989		 * Callback which allows modification of the saved state prior to loading that state.
10990		 * This callback is called when the table is loading state from the stored data, but
10991		 * prior to the settings object being modified by the saved state. Note that for
10992		 * plug-in authors, you should use the `stateLoadParams` event to load parameters for
10993		 * a plug-in.
10994		 *  @type function
10995		 *  @param {object} settings DataTables settings object
10996		 *  @param {object} data The state object that is to be loaded
10997		 *
10998		 *  @dtopt Callbacks
10999		 *  @name DataTable.defaults.stateLoadParams
11000		 *
11001		 *  @example
11002		 *    // Remove a saved filter, so filtering is never loaded
11003		 *    $(document).ready( function() {
11004		 *      $('#example').dataTable( {
11005		 *        "stateSave": true,
11006		 *        "stateLoadParams": function (settings, data) {
11007		 *          data.oSearch.sSearch = "";
11008		 *        }
11009		 *      } );
11010		 *    } );
11011		 *
11012		 *  @example
11013		 *    // Disallow state loading by returning false
11014		 *    $(document).ready( function() {
11015		 *      $('#example').dataTable( {
11016		 *        "stateSave": true,
11017		 *        "stateLoadParams": function (settings, data) {
11018		 *          return false;
11019		 *        }
11020		 *      } );
11021		 *    } );
11022		 */
11023		"fnStateLoadParams": null,
11024	
11025	
11026		/**
11027		 * Callback that is called when the state has been loaded from the state saving method
11028		 * and the DataTables settings object has been modified as a result of the loaded state.
11029		 *  @type function
11030		 *  @param {object} settings DataTables settings object
11031		 *  @param {object} data The state object that was loaded
11032		 *
11033		 *  @dtopt Callbacks
11034		 *  @name DataTable.defaults.stateLoaded
11035		 *
11036		 *  @example
11037		 *    // Show an alert with the filtering value that was saved
11038		 *    $(document).ready( function() {
11039		 *      $('#example').dataTable( {
11040		 *        "stateSave": true,
11041		 *        "stateLoaded": function (settings, data) {
11042		 *          alert( 'Saved filter was: '+data.oSearch.sSearch );
11043		 *        }
11044		 *      } );
11045		 *    } );
11046		 */
11047		"fnStateLoaded": null,
11048	
11049	
11050		/**
11051		 * Save the table state. This function allows you to define where and how the state
11052		 * information for the table is stored By default DataTables will use `localStorage`
11053		 * but you might wish to use a server-side database or cookies.
11054		 *  @type function
11055		 *  @member
11056		 *  @param {object} settings DataTables settings object
11057		 *  @param {object} data The state object to be saved
11058		 *
11059		 *  @dtopt Callbacks
11060		 *  @name DataTable.defaults.stateSaveCallback
11061		 *
11062		 *  @example
11063		 *    $(document).ready( function() {
11064		 *      $('#example').dataTable( {
11065		 *        "stateSave": true,
11066		 *        "stateSaveCallback": function (settings, data) {
11067		 *          // Send an Ajax request to the server with the state object
11068		 *          $.ajax( {
11069		 *            "url": "/state_save",
11070		 *            "data": data,
11071		 *            "dataType": "json",
11072		 *            "method": "POST"
11073		 *            "success": function () {}
11074		 *          } );
11075		 *        }
11076		 *      } );
11077		 *    } );
11078		 */
11079		"fnStateSaveCallback": function ( settings, data ) {
11080			try {
11081				(settings.iStateDuration === -1 ? sessionStorage : localStorage).setItem(
11082					'DataTables_'+settings.sInstance+'_'+location.pathname,
11083					JSON.stringify( data )
11084				);
11085			} catch (e) {}
11086		},
11087	
11088	
11089		/**
11090		 * Callback which allows modification of the state to be saved. Called when the table
11091		 * has changed state a new state save is required. This method allows modification of
11092		 * the state saving object prior to actually doing the save, including addition or
11093		 * other state properties or modification. Note that for plug-in authors, you should
11094		 * use the `stateSaveParams` event to save parameters for a plug-in.
11095		 *  @type function
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.stateSaveParams
11101		 *
11102		 *  @example
11103		 *    // Remove a saved filter, so filtering is never saved
11104		 *    $(document).ready( function() {
11105		 *      $('#example').dataTable( {
11106		 *        "stateSave": true,
11107		 *        "stateSaveParams": function (settings, data) {
11108		 *          data.oSearch.sSearch = "";
11109		 *        }
11110		 *      } );
11111		 *    } );
11112		 */
11113		"fnStateSaveParams": null,
11114	
11115	
11116		/**
11117		 * Duration for which the saved state information is considered valid. After this period
11118		 * has elapsed the state will be returned to the default.
11119		 * Value is given in seconds.
11120		 *  @type int
11121		 *  @default 7200 <i>(2 hours)</i>
11122		 *
11123		 *  @dtopt Options
11124		 *  @name DataTable.defaults.stateDuration
11125		 *
11126		 *  @example
11127		 *    $(document).ready( function() {
11128		 *      $('#example').dataTable( {
11129		 *        "stateDuration": 60*60*24; // 1 day
11130		 *      } );
11131		 *    } )
11132		 */
11133		"iStateDuration": 7200,
11134	
11135	
11136		/**
11137		 * When enabled DataTables will not make a request to the server for the first
11138		 * page draw - rather it will use the data already on the page (no sorting etc
11139		 * will be applied to it), thus saving on an XHR at load time. `deferLoading`
11140		 * is used to indicate that deferred loading is required, but it is also used
11141		 * to tell DataTables how many records there are in the full table (allowing
11142		 * the information element and pagination to be displayed correctly). In the case
11143		 * where a filtering is applied to the table on initial load, this can be
11144		 * indicated by giving the parameter as an array, where the first element is
11145		 * the number of records available after filtering and the second element is the
11146		 * number of records without filtering (allowing the table information element
11147		 * to be shown correctly).
11148		 *  @type int | array
11149		 *  @default null
11150		 *
11151		 *  @dtopt Options
11152		 *  @name DataTable.defaults.deferLoading
11153		 *
11154		 *  @example
11155		 *    // 57 records available in the table, no filtering applied
11156		 *    $(document).ready( function() {
11157		 *      $('#example').dataTable( {
11158		 *        "serverSide": true,
11159		 *        "ajax": "scripts/server_processing.php",
11160		 *        "deferLoading": 57
11161		 *      } );
11162		 *    } );
11163		 *
11164		 *  @example
11165		 *    // 57 records after filtering, 100 without filtering (an initial filter applied)
11166		 *    $(document).ready( function() {
11167		 *      $('#example').dataTable( {
11168		 *        "serverSide": true,
11169		 *        "ajax": "scripts/server_processing.php",
11170		 *        "deferLoading": [ 57, 100 ],
11171		 *        "search": {
11172		 *          "search": "my_filter"
11173		 *        }
11174		 *      } );
11175		 *    } );
11176		 */
11177		"iDeferLoading": null,
11178	
11179	
11180		/**
11181		 * Number of rows to display on a single page when using pagination. If
11182		 * feature enabled (`lengthChange`) then the end user will be able to override
11183		 * this to a custom setting using a pop-up menu.
11184		 *  @type int
11185		 *  @default 10
11186		 *
11187		 *  @dtopt Options
11188		 *  @name DataTable.defaults.pageLength
11189		 *
11190		 *  @example
11191		 *    $(document).ready( function() {
11192		 *      $('#example').dataTable( {
11193		 *        "pageLength": 50
11194		 *      } );
11195		 *    } )
11196		 */
11197		"iDisplayLength": 10,
11198	
11199	
11200		/**
11201		 * Define the starting point for data display when using DataTables with
11202		 * pagination. Note that this parameter is the number of records, rather than
11203		 * the page number, so if you have 10 records per page and want to start on
11204		 * the third page, it should be "20".
11205		 *  @type int
11206		 *  @default 0
11207		 *
11208		 *  @dtopt Options
11209		 *  @name DataTable.defaults.displayStart
11210		 *
11211		 *  @example
11212		 *    $(document).ready( function() {
11213		 *      $('#example').dataTable( {
11214		 *        "displayStart": 20
11215		 *      } );
11216		 *    } )
11217		 */
11218		"iDisplayStart": 0,
11219	
11220	
11221		/**
11222		 * By default DataTables allows keyboard navigation of the table (sorting, paging,
11223		 * and filtering) by adding a `tabindex` attribute to the required elements. This
11224		 * allows you to tab through the controls and press the enter key to activate them.
11225		 * The tabindex is default 0, meaning that the tab follows the flow of the document.
11226		 * You can overrule this using this parameter if you wish. Use a value of -1 to
11227		 * disable built-in keyboard navigation.
11228		 *  @type int
11229		 *  @default 0
11230		 *
11231		 *  @dtopt Options
11232		 *  @name DataTable.defaults.tabIndex
11233		 *
11234		 *  @example
11235		 *    $(document).ready( function() {
11236		 *      $('#example').dataTable( {
11237		 *        "tabIndex": 1
11238		 *      } );
11239		 *    } );
11240		 */
11241		"iTabIndex": 0,
11242	
11243	
11244		/**
11245		 * Classes that DataTables assigns to the various components and features
11246		 * that it adds to the HTML table. This allows classes to be configured
11247		 * during initialisation in addition to through the static
11248		 * {@link DataTable.ext.oStdClasses} object).
11249		 *  @namespace
11250		 *  @name DataTable.defaults.classes
11251		 */
11252		"oClasses": {},
11253	
11254	
11255		/**
11256		 * All strings that DataTables uses in the user interface that it creates
11257		 * are defined in this object, allowing you to modified them individually or
11258		 * completely replace them all as required.
11259		 *  @namespace
11260		 *  @name DataTable.defaults.language
11261		 */
11262		"oLanguage": {
11263			/**
11264			 * Strings that are used for WAI-ARIA labels and controls only (these are not
11265			 * actually visible on the page, but will be read by screenreaders, and thus
11266			 * must be internationalised as well).
11267			 *  @namespace
11268			 *  @name DataTable.defaults.language.aria
11269			 */
11270			"oAria": {
11271				/**
11272				 * ARIA label that is added to the table headers when the column may be
11273				 * sorted ascending by activing the column (click or return when focused).
11274				 * Note that the column header is prefixed to this string.
11275				 *  @type string
11276				 *  @default : activate to sort column ascending
11277				 *
11278				 *  @dtopt Language
11279				 *  @name DataTable.defaults.language.aria.sortAscending
11280				 *
11281				 *  @example
11282				 *    $(document).ready( function() {
11283				 *      $('#example').dataTable( {
11284				 *        "language": {
11285				 *          "aria": {
11286				 *            "sortAscending": " - click/return to sort ascending"
11287				 *          }
11288				 *        }
11289				 *      } );
11290				 *    } );
11291				 */
11292				"sSortAscending": ": activate to sort column ascending",
11293	
11294				/**
11295				 * ARIA label that is added to the table headers when the column may be
11296				 * sorted descending by activing the column (click or return when focused).
11297				 * Note that the column header is prefixed to this string.
11298				 *  @type string
11299				 *  @default : activate to sort column ascending
11300				 *
11301				 *  @dtopt Language
11302				 *  @name DataTable.defaults.language.aria.sortDescending
11303				 *
11304				 *  @example
11305				 *    $(document).ready( function() {
11306				 *      $('#example').dataTable( {
11307				 *        "language": {
11308				 *          "aria": {
11309				 *            "sortDescending": " - click/return to sort descending"
11310				 *          }
11311				 *        }
11312				 *      } );
11313				 *    } );
11314				 */
11315				"sSortDescending": ": activate to sort column descending"
11316			},
11317	
11318			/**
11319			 * Pagination string used by DataTables for the built-in pagination
11320			 * control types.
11321			 *  @namespace
11322			 *  @name DataTable.defaults.language.paginate
11323			 */
11324			"oPaginate": {
11325				/**
11326				 * Text to use when using the 'full_numbers' type of pagination for the
11327				 * button to take the user to the first page.
11328				 *  @type string
11329				 *  @default First
11330				 *
11331				 *  @dtopt Language
11332				 *  @name DataTable.defaults.language.paginate.first
11333				 *
11334				 *  @example
11335				 *    $(document).ready( function() {
11336				 *      $('#example').dataTable( {
11337				 *        "language": {
11338				 *          "paginate": {
11339				 *            "first": "First page"
11340				 *          }
11341				 *        }
11342				 *      } );
11343				 *    } );
11344				 */
11345				"sFirst": "First",
11346	
11347	
11348				/**
11349				 * Text to use when using the 'full_numbers' type of pagination for the
11350				 * button to take the user to the last page.
11351				 *  @type string
11352				 *  @default Last
11353				 *
11354				 *  @dtopt Language
11355				 *  @name DataTable.defaults.language.paginate.last
11356				 *
11357				 *  @example
11358				 *    $(document).ready( function() {
11359				 *      $('#example').dataTable( {
11360				 *        "language": {
11361				 *          "paginate": {
11362				 *            "last": "Last page"
11363				 *          }
11364				 *        }
11365				 *      } );
11366				 *    } );
11367				 */
11368				"sLast": "Last",
11369	
11370	
11371				/**
11372				 * Text to use for the 'next' pagination button (to take the user to the
11373				 * next page).
11374				 *  @type string
11375				 *  @default Next
11376				 *
11377				 *  @dtopt Language
11378				 *  @name DataTable.defaults.language.paginate.next
11379				 *
11380				 *  @example
11381				 *    $(document).ready( function() {
11382				 *      $('#example').dataTable( {
11383				 *        "language": {
11384				 *          "paginate": {
11385				 *            "next": "Next page"
11386				 *          }
11387				 *        }
11388				 *      } );
11389				 *    } );
11390				 */
11391				"sNext": "Next",
11392	
11393	
11394				/**
11395				 * Text to use for the 'previous' pagination button (to take the user to
11396				 * the previous page).
11397				 *  @type string
11398				 *  @default Previous
11399				 *
11400				 *  @dtopt Language
11401				 *  @name DataTable.defaults.language.paginate.previous
11402				 *
11403				 *  @example
11404				 *    $(document).ready( function() {
11405				 *      $('#example').dataTable( {
11406				 *        "language": {
11407				 *          "paginate": {
11408				 *            "previous": "Previous page"
11409				 *          }
11410				 *        }
11411				 *      } );
11412				 *    } );
11413				 */
11414				"sPrevious": "Previous"
11415			},
11416	
11417			/**
11418			 * This string is shown in preference to `zeroRecords` when the table is
11419			 * empty of data (regardless of filtering). Note that this is an optional
11420			 * parameter - if it is not given, the value of `zeroRecords` will be used
11421			 * instead (either the default or given value).
11422			 *  @type string
11423			 *  @default No data available in table
11424			 *
11425			 *  @dtopt Language
11426			 *  @name DataTable.defaults.language.emptyTable
11427			 *
11428			 *  @example
11429			 *    $(document).ready( function() {
11430			 *      $('#example').dataTable( {
11431			 *        "language": {
11432			 *          "emptyTable": "No data available in table"
11433			 *        }
11434			 *      } );
11435			 *    } );
11436			 */
11437			"sEmptyTable": "No data available in table",
11438	
11439	
11440			/**
11441			 * This string gives information to the end user about the information
11442			 * that is current on display on the page. The following tokens can be
11443			 * used in the string and will be dynamically replaced as the table
11444			 * display updates. This tokens can be placed anywhere in the string, or
11445			 * removed as needed by the language requires:
11446			 *
11447			 * * `\_START\_` - Display index of the first record on the current page
11448			 * * `\_END\_` - Display index of the last record on the current page
11449			 * * `\_TOTAL\_` - Number of records in the table after filtering
11450			 * * `\_MAX\_` - Number of records in the table without filtering
11451			 * * `\_PAGE\_` - Current page number
11452			 * * `\_PAGES\_` - Total number of pages of data in the table
11453			 *
11454			 *  @type string
11455			 *  @default Showing _START_ to _END_ of _TOTAL_ entries
11456			 *
11457			 *  @dtopt Language
11458			 *  @name DataTable.defaults.language.info
11459			 *
11460			 *  @example
11461			 *    $(document).ready( function() {
11462			 *      $('#example').dataTable( {
11463			 *        "language": {
11464			 *          "info": "Showing page _PAGE_ of _PAGES_"
11465			 *        }
11466			 *      } );
11467			 *    } );
11468			 */
11469			"sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
11470	
11471	
11472			/**
11473			 * Display information string for when the table is empty. Typically the
11474			 * format of this string should match `info`.
11475			 *  @type string
11476			 *  @default Showing 0 to 0 of 0 entries
11477			 *
11478			 *  @dtopt Language
11479			 *  @name DataTable.defaults.language.infoEmpty
11480			 *
11481			 *  @example
11482			 *    $(document).ready( function() {
11483			 *      $('#example').dataTable( {
11484			 *        "language": {
11485			 *          "infoEmpty": "No entries to show"
11486			 *        }
11487			 *      } );
11488			 *    } );
11489			 */
11490			"sInfoEmpty": "Showing 0 to 0 of 0 entries",
11491	
11492	
11493			/**
11494			 * When a user filters the information in a table, this string is appended
11495			 * to the information (`info`) to give an idea of how strong the filtering
11496			 * is. The variable _MAX_ is dynamically updated.
11497			 *  @type string
11498			 *  @default (filtered from _MAX_ total entries)
11499			 *
11500			 *  @dtopt Language
11501			 *  @name DataTable.defaults.language.infoFiltered
11502			 *
11503			 *  @example
11504			 *    $(document).ready( function() {
11505			 *      $('#example').dataTable( {
11506			 *        "language": {
11507			 *          "infoFiltered": " - filtering from _MAX_ records"
11508			 *        }
11509			 *      } );
11510			 *    } );
11511			 */
11512			"sInfoFiltered": "(filtered from _MAX_ total entries)",
11513	
11514	
11515			/**
11516			 * If can be useful to append extra information to the info string at times,
11517			 * and this variable does exactly that. This information will be appended to
11518			 * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are
11519			 * being used) at all times.
11520			 *  @type string
11521			 *  @default <i>Empty string</i>
11522			 *
11523			 *  @dtopt Language
11524			 *  @name DataTable.defaults.language.infoPostFix
11525			 *
11526			 *  @example
11527			 *    $(document).ready( function() {
11528			 *      $('#example').dataTable( {
11529			 *        "language": {
11530			 *          "infoPostFix": "All records shown are derived from real information."
11531			 *        }
11532			 *      } );
11533			 *    } );
11534			 */
11535			"sInfoPostFix": "",
11536	
11537	
11538			/**
11539			 * This decimal place operator is a little different from the other
11540			 * language options since DataTables doesn't output floating point
11541			 * numbers, so it won't ever use this for display of a number. Rather,
11542			 * what this parameter does is modify the sort methods of the table so
11543			 * that numbers which are in a format which has a character other than
11544			 * a period (`.`) as a decimal place will be sorted numerically.
11545			 *
11546			 * Note that numbers with different decimal places cannot be shown in
11547			 * the same table and still be sortable, the table must be consistent.
11548			 * However, multiple different tables on the page can use different
11549			 * decimal place characters.
11550			 *  @type string
11551			 *  @default 
11552			 *
11553			 *  @dtopt Language
11554			 *  @name DataTable.defaults.language.decimal
11555			 *
11556			 *  @example
11557			 *    $(document).ready( function() {
11558			 *      $('#example').dataTable( {
11559			 *        "language": {
11560			 *          "decimal": ","
11561			 *          "thousands": "."
11562			 *        }
11563			 *      } );
11564			 *    } );
11565			 */
11566			"sDecimal": "",
11567	
11568	
11569			/**
11570			 * DataTables has a build in number formatter (`formatNumber`) which is
11571			 * used to format large numbers that are used in the table information.
11572			 * By default a comma is used, but this can be trivially changed to any
11573			 * character you wish with this parameter.
11574			 *  @type string
11575			 *  @default ,
11576			 *
11577			 *  @dtopt Language
11578			 *  @name DataTable.defaults.language.thousands
11579			 *
11580			 *  @example
11581			 *    $(document).ready( function() {
11582			 *      $('#example').dataTable( {
11583			 *        "language": {
11584			 *          "thousands": "'"
11585			 *        }
11586			 *      } );
11587			 *    } );
11588			 */
11589			"sThousands": ",",
11590	
11591	
11592			/**
11593			 * Detail the action that will be taken when the drop down menu for the
11594			 * pagination length option is changed. The '_MENU_' variable is replaced
11595			 * with a default select list of 10, 25, 50 and 100, and can be replaced
11596			 * with a custom select box if required.
11597			 *  @type string
11598			 *  @default Show _MENU_ entries
11599			 *
11600			 *  @dtopt Language
11601			 *  @name DataTable.defaults.language.lengthMenu
11602			 *
11603			 *  @example
11604			 *    // Language change only
11605			 *    $(document).ready( function() {
11606			 *      $('#example').dataTable( {
11607			 *        "language": {
11608			 *          "lengthMenu": "Display _MENU_ records"
11609			 *        }
11610			 *      } );
11611			 *    } );
11612			 *
11613			 *  @example
11614			 *    // Language and options change
11615			 *    $(document).ready( function() {
11616			 *      $('#example').dataTable( {
11617			 *        "language": {
11618			 *          "lengthMenu": 'Display <select>'+
11619			 *            '<option value="10">10</option>'+
11620			 *            '<option value="20">20</option>'+
11621			 *            '<option value="30">30</option>'+
11622			 *            '<option value="40">40</option>'+
11623			 *            '<option value="50">50</option>'+
11624			 *            '<option value="-1">All</option>'+
11625			 *            '</select> records'
11626			 *        }
11627			 *      } );
11628			 *    } );
11629			 */
11630			"sLengthMenu": "Show _MENU_ entries",
11631	
11632	
11633			/**
11634			 * When using Ajax sourced data and during the first draw when DataTables is
11635			 * gathering the data, this message is shown in an empty row in the table to
11636			 * indicate to the end user the the data is being loaded. Note that this
11637			 * parameter is not used when loading data by server-side processing, just
11638			 * Ajax sourced data with client-side processing.
11639			 *  @type string
11640			 *  @default Loading...
11641			 *
11642			 *  @dtopt Language
11643			 *  @name DataTable.defaults.language.loadingRecords
11644			 *
11645			 *  @example
11646			 *    $(document).ready( function() {
11647			 *      $('#example').dataTable( {
11648			 *        "language": {
11649			 *          "loadingRecords": "Please wait - loading..."
11650			 *        }
11651			 *      } );
11652			 *    } );
11653			 */
11654			"sLoadingRecords": "Loading...",
11655	
11656	
11657			/**
11658			 * Text which is displayed when the table is processing a user action
11659			 * (usually a sort command or similar).
11660			 *  @type string
11661			 *
11661  @default Processing...
11662			 *
11663			 *  @dtopt Language
11664			 *  @name DataTable.defaults.language.processing
11665			 *
11666			 *  @example
11667			 *    $(document).ready( function() {
11668			 *      $('#example').dataTable( {
11669			 *        "language": {
11670			 *          "processing": "DataTables is currently busy"
11671			 *        }
11672			 *      } );
11673			 *    } );
11674			 */
11675			"sProcessing": "Processing...
vendor: 42,942 bytes, lines 11675-12969
11675",
11676	
11677	
11678			/**
11679			 * Details the actions that will be taken when the user types into the
11680			 * filtering input text box. The variable "_INPUT_", if used in the string,
11681			 * is replaced with the HTML text box for the filtering input allowing
11682			 * control over where it appears in the string. If "_INPUT_" is not given
11683			 * then the input box is appended to the string automatically.
11684			 *  @type string
11685			 *  @default Search:
11686			 *
11687			 *  @dtopt Language
11688			 *  @name DataTable.defaults.language.search
11689			 *
11690			 *  @example
11691			 *    // Input text box will be appended at the end automatically
11692			 *    $(document).ready( function() {
11693			 *      $('#example').dataTable( {
11694			 *        "language": {
11695			 *          "search": "Filter records:"
11696			 *        }
11697			 *      } );
11698			 *    } );
11699			 *
11700			 *  @example
11701			 *    // Specify where the filter should appear
11702			 *    $(document).ready( function() {
11703			 *      $('#example').dataTable( {
11704			 *        "language": {
11705			 *          "search": "Apply filter _INPUT_ to table"
11706			 *        }
11707			 *      } );
11708			 *    } );
11709			 */
11710			"sSearch": "Search:",
11711	
11712	
11713			/**
11714			 * Assign a `placeholder` attribute to the search `input` element
11715			 *  @type string
11716			 *  @default 
11717			 *
11718			 *  @dtopt Language
11719			 *  @name DataTable.defaults.language.searchPlaceholder
11720			 */
11721			"sSearchPlaceholder": "",
11722	
11723	
11724			/**
11725			 * All of the language information can be stored in a file on the
11726			 * server-side, which DataTables will look up if this parameter is passed.
11727			 * It must store the URL of the language file, which is in a JSON format,
11728			 * and the object has the same properties as the oLanguage object in the
11729			 * initialiser object (i.e. the above parameters). Please refer to one of
11730			 * the example language files to see how this works in action.
11731			 *  @type string
11732			 *  @default <i>Empty string - i.e. disabled</i>
11733			 *
11734			 *  @dtopt Language
11735			 *  @name DataTable.defaults.language.url
11736			 *
11737			 *  @example
11738			 *    $(document).ready( function() {
11739			 *      $('#example').dataTable( {
11740			 *        "language": {
11741			 *          "url": "http://www.sprymedia.co.uk/dataTables/lang.txt"
11742			 *        }
11743			 *      } );
11744			 *    } );
11745			 */
11746			"sUrl": "",
11747	
11748	
11749			/**
11750			 * Text shown inside the table records when the is no information to be
11751			 * displayed after filtering. `emptyTable` is shown when there is simply no
11752			 * information in the table at all (regardless of filtering).
11753			 *  @type string
11754			 *  @default No matching records found
11755			 *
11756			 *  @dtopt Language
11757			 *  @name DataTable.defaults.language.zeroRecords
11758			 *
11759			 *  @example
11760			 *    $(document).ready( function() {
11761			 *      $('#example').dataTable( {
11762			 *        "language": {
11763			 *          "zeroRecords": "No records to display"
11764			 *        }
11765			 *      } );
11766			 *    } );
11767			 */
11768			"sZeroRecords": "No matching records found"
11769		},
11770	
11771	
11772		/**
11773		 * This parameter allows you to have define the global filtering state at
11774		 * initialisation time. As an object the `search` parameter must be
11775		 * defined, but all other parameters are optional. When `regex` is true,
11776		 * the search string will be treated as a regular expression, when false
11777		 * (default) it will be treated as a straight string. When `smart`
11778		 * DataTables will use it's smart filtering methods (to word match at
11779		 * any point in the data), when false this will not be done.
11780		 *  @namespace
11781		 *  @extends DataTable.models.oSearch
11782		 *
11783		 *  @dtopt Options
11784		 *  @name DataTable.defaults.search
11785		 *
11786		 *  @example
11787		 *    $(document).ready( function() {
11788		 *      $('#example').dataTable( {
11789		 *        "search": {"search": "Initial search"}
11790		 *      } );
11791		 *    } )
11792		 */
11793		"oSearch": $.extend( {}, DataTable.models.oSearch ),
11794	
11795	
11796		/**
11797		 * __Deprecated__ The functionality provided by this parameter has now been
11798		 * superseded by that provided through `ajax`, which should be used instead.
11799		 *
11800		 * By default DataTables will look for the property `data` (or `aaData` for
11801		 * compatibility with DataTables 1.9-) when obtaining data from an Ajax
11802		 * source or for server-side processing - this parameter allows that
11803		 * property to be changed. You can use Javascript dotted object notation to
11804		 * get a data source for multiple levels of nesting.
11805		 *  @type string
11806		 *  @default data
11807		 *
11808		 *  @dtopt Options
11809		 *  @dtopt Server-side
11810		 *  @name DataTable.defaults.ajaxDataProp
11811		 *
11812		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11813		 */
11814		"sAjaxDataProp": "data",
11815	
11816	
11817		/**
11818		 * __Deprecated__ The functionality provided by this parameter has now been
11819		 * superseded by that provided through `ajax`, which should be used instead.
11820		 *
11821		 * You can instruct DataTables to load data from an external
11822		 * source using this parameter (use aData if you want to pass data in you
11823		 * already have). Simply provide a url a JSON object can be obtained from.
11824		 *  @type string
11825		 *  @default null
11826		 *
11827		 *  @dtopt Options
11828		 *  @dtopt Server-side
11829		 *  @name DataTable.defaults.ajaxSource
11830		 *
11831		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11832		 */
11833		"sAjaxSource": null,
11834	
11835	
11836		/**
11837		 * This initialisation variable allows you to specify exactly where in the
11838		 * DOM you want DataTables to inject the various controls it adds to the page
11839		 * (for example you might want the pagination controls at the top of the
11840		 * table). DIV elements (with or without a custom class) can also be added to
11841		 * aid styling. The follow syntax is used:
11842		 *   <ul>
11843		 *     <li>The following options are allowed:
11844		 *       <ul>
11845		 *         <li>'l' - Length changing</li>
11846		 *         <li>'f' - Filtering input</li>
11847		 *         <li>'t' - The table!</li>
11848		 *         <li>'i' - Information</li>
11849		 *         <li>'p' - Pagination</li>
11850		 *         <li>'r' - pRocessing</li>
11851		 *       </ul>
11852		 *     </li>
11853		 *     <li>The following constants are allowed:
11854		 *       <ul>
11855		 *         <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>
11856		 *         <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>
11857		 *       </ul>
11858		 *     </li>
11859		 *     <li>The following syntax is expected:
11860		 *       <ul>
11861		 *         <li>'&lt;' and '&gt;' - div elements</li>
11862		 *         <li>'&lt;"class" and '&gt;' - div with a class</li>
11863		 *         <li>'&lt;"#id" and '&gt;' - div with an ID</li>
11864		 *       </ul>
11865		 *     </li>
11866		 *     <li>Examples:
11867		 *       <ul>
11868		 *         <li>'&lt;"wrapper"flipt&gt;'</li>
11869		 *         <li>'&lt;lf&lt;t&gt;ip&gt;'</li>
11870		 *       </ul>
11871		 *     </li>
11872		 *   </ul>
11873		 *  @type string
11874		 *  @default lfrtip <i>(when `jQueryUI` is false)</i> <b>or</b>
11875		 *    <"H"lfr>t<"F"ip> <i>(when `jQueryUI` is true)</i>
11876		 *
11877		 *  @dtopt Options
11878		 *  @name DataTable.defaults.dom
11879		 *
11880		 *  @example
11881		 *    $(document).ready( function() {
11882		 *      $('#example').dataTable( {
11883		 *        "dom": '&lt;"top"i&gt;rt&lt;"bottom"flp&gt;&lt;"clear"&gt;'
11884		 *      } );
11885		 *    } );
11886		 */
11887		"sDom": "lfrtip",
11888	
11889	
11890		/**
11891		 * Search delay option. This will throttle full table searches that use the
11892		 * DataTables provided search input element (it does not effect calls to
11893		 * `dt-api search()`, providing a delay before the search is made.
11894		 *  @type integer
11895		 *  @default 0
11896		 *
11897		 *  @dtopt Options
11898		 *  @name DataTable.defaults.searchDelay
11899		 *
11900		 *  @example
11901		 *    $(document).ready( function() {
11902		 *      $('#example').dataTable( {
11903		 *        "searchDelay": 200
11904		 *      } );
11905		 *    } )
11906		 */
11907		"searchDelay": null,
11908	
11909	
11910		/**
11911		 * DataTables features six different built-in options for the buttons to
11912		 * display for pagination control:
11913		 *
11914		 * * `numbers` - Page number buttons only
11915		 * * `simple` - 'Previous' and 'Next' buttons only
11916		 * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers
11917		 * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons
11918		 * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus page numbers
11919		 * * `first_last_numbers` - 'First' and 'Last' buttons, plus page numbers
11920		 *  
11921		 * Further methods can be added using {@link DataTable.ext.oPagination}.
11922		 *  @type string
11923		 *  @default simple_numbers
11924		 *
11925		 *  @dtopt Options
11926		 *  @name DataTable.defaults.pagingType
11927		 *
11928		 *  @example
11929		 *    $(document).ready( function() {
11930		 *      $('#example').dataTable( {
11931		 *        "pagingType": "full_numbers"
11932		 *      } );
11933		 *    } )
11934		 */
11935		"sPaginationType": "simple_numbers",
11936	
11937	
11938		/**
11939		 * Enable horizontal scrolling. When a table is too wide to fit into a
11940		 * certain layout, or you have a large number of columns in the table, you
11941		 * can enable x-scrolling to show the table in a viewport, which can be
11942		 * scrolled. This property can be `true` which will allow the table to
11943		 * scroll horizontally when needed, or any CSS unit, or a number (in which
11944		 * case it will be treated as a pixel measurement). Setting as simply `true`
11945		 * is recommended.
11946		 *  @type boolean|string
11947		 *  @default <i>blank string - i.e. disabled</i>
11948		 *
11949		 *  @dtopt Features
11950		 *  @name DataTable.defaults.scrollX
11951		 *
11952		 *  @example
11953		 *    $(document).ready( function() {
11954		 *      $('#example').dataTable( {
11955		 *        "scrollX": true,
11956		 *        "scrollCollapse": true
11957		 *      } );
11958		 *    } );
11959		 */
11960		"sScrollX": "",
11961	
11962	
11963		/**
11964		 * This property can be used to force a DataTable to use more width than it
11965		 * might otherwise do when x-scrolling is enabled. For example if you have a
11966		 * table which requires to be well spaced, this parameter is useful for
11967		 * "over-sizing" the table, and thus forcing scrolling. This property can by
11968		 * any CSS unit, or a number (in which case it will be treated as a pixel
11969		 * measurement).
11970		 *  @type string
11971		 *  @default <i>blank string - i.e. disabled</i>
11972		 *
11973		 *  @dtopt Options
11974		 *  @name DataTable.defaults.scrollXInner
11975		 *
11976		 *  @example
11977		 *    $(document).ready( function() {
11978		 *      $('#example').dataTable( {
11979		 *        "scrollX": "100%",
11980		 *        "scrollXInner": "110%"
11981		 *      } );
11982		 *    } );
11983		 */
11984		"sScrollXInner": "",
11985	
11986	
11987		/**
11988		 * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
11989		 * to the given height, and enable scrolling for any data which overflows the
11990		 * current viewport. This can be used as an alternative to paging to display
11991		 * a lot of data in a small area (although paging and scrolling can both be
11992		 * enabled at the same time). This property can be any CSS unit, or a number
11993		 * (in which case it will be treated as a pixel measurement).
11994		 *  @type string
11995		 *  @default <i>blank string - i.e. disabled</i>
11996		 *
11997		 *  @dtopt Features
11998		 *  @name DataTable.defaults.scrollY
11999		 *
12000		 *  @example
12001		 *    $(document).ready( function() {
12002		 *      $('#example').dataTable( {
12003		 *        "scrollY": "200px",
12004		 *        "paginate": false
12005		 *      } );
12006		 *    } );
12007		 */
12008		"sScrollY": "",
12009	
12010	
12011		/**
12012		 * __Deprecated__ The functionality provided by this parameter has now been
12013		 * superseded by that provided through `ajax`, which should be used instead.
12014		 *
12015		 * Set the HTTP method that is used to make the Ajax call for server-side
12016		 * processing or Ajax sourced data.
12017		 *  @type string
12018		 *  @default GET
12019		 *
12020		 *  @dtopt Options
12021		 *  @dtopt Server-side
12022		 *  @name DataTable.defaults.serverMethod
12023		 *
12024		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
12025		 */
12026		"sServerMethod": "GET",
12027	
12028	
12029		/**
12030		 * DataTables makes use of renderers when displaying HTML elements for
12031		 * a table. These renderers can be added or modified by plug-ins to
12032		 * generate suitable mark-up for a site. For example the Bootstrap
12033		 * integration plug-in for DataTables uses a paging button renderer to
12034		 * display pagination buttons in the mark-up required by Bootstrap.
12035		 *
12036		 * For further information about the renderers available see
12037		 * DataTable.ext.renderer
12038		 *  @type string|object
12039		 *  @default null
12040		 *
12041		 *  @name DataTable.defaults.renderer
12042		 *
12043		 */
12044		"renderer": null,
12045	
12046	
12047		/**
12048		 * Set the data property name that DataTables should use to get a row's id
12049		 * to set as the `id` property in the node.
12050		 *  @type string
12051		 *  @default DT_RowId
12052		 *
12053		 *  @name DataTable.defaults.rowId
12054		 */
12055		"rowId": "DT_RowId"
12056	};
12057	
12058	_fnHungarianMap( DataTable.defaults );
12059	
12060	
12061	
12062	/*
12063	 * Developer note - See note in model.defaults.js about the use of Hungarian
12064	 * notation and camel case.
12065	 */
12066	
12067	/**
12068	 * Column options that can be given to DataTables at initialisation time.
12069	 *  @namespace
12070	 */
12071	DataTable.defaults.column = {
12072		/**
12073		 * Define which column(s) an order will occur on for this column. This
12074		 * allows a column's ordering to take multiple columns into account when
12075		 * doing a sort or use the data from a different column. For example first
12076		 * name / last name columns make sense to do a multi-column sort over the
12077		 * two columns.
12078		 *  @type array|int
12079		 *  @default null <i>Takes the value of the column index automatically</i>
12080		 *
12081		 *  @name DataTable.defaults.column.orderData
12082		 *  @dtopt Columns
12083		 *
12084		 *  @example
12085		 *    // Using `columnDefs`
12086		 *    $(document).ready( function() {
12087		 *      $('#example').dataTable( {
12088		 *        "columnDefs": [
12089		 *          { "orderData": [ 0, 1 ], "targets": [ 0 ] },
12090		 *          { "orderData": [ 1, 0 ], "targets": [ 1 ] },
12091		 *          { "orderData": 2, "targets": [ 2 ] }
12092		 *        ]
12093		 *      } );
12094		 *    } );
12095		 *
12096		 *  @example
12097		 *    // Using `columns`
12098		 *    $(document).ready( function() {
12099		 *      $('#example').dataTable( {
12100		 *        "columns": [
12101		 *          { "orderData": [ 0, 1 ] },
12102		 *          { "orderData": [ 1, 0 ] },
12103		 *          { "orderData": 2 },
12104		 *          null,
12105		 *          null
12106		 *        ]
12107		 *      } );
12108		 *    } );
12109		 */
12110		"aDataSort": null,
12111		"iDataSort": -1,
12112	
12113	
12114		/**
12115		 * You can control the default ordering direction, and even alter the
12116		 * behaviour of the sort handler (i.e. only allow ascending ordering etc)
12117		 * using this parameter.
12118		 *  @type array
12119		 *  @default [ 'asc', 'desc' ]
12120		 *
12121		 *  @name DataTable.defaults.column.orderSequence
12122		 *  @dtopt Columns
12123		 *
12124		 *  @example
12125		 *    // Using `columnDefs`
12126		 *    $(document).ready( function() {
12127		 *      $('#example').dataTable( {
12128		 *        "columnDefs": [
12129		 *          { "orderSequence": [ "asc" ], "targets": [ 1 ] },
12130		 *          { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] },
12131		 *          { "orderSequence": [ "desc" ], "targets": [ 3 ] }
12132		 *        ]
12133		 *      } );
12134		 *    } );
12135		 *
12136		 *  @example
12137		 *    // Using `columns`
12138		 *    $(document).ready( function() {
12139		 *      $('#example').dataTable( {
12140		 *        "columns": [
12141		 *          null,
12142		 *          { "orderSequence": [ "asc" ] },
12143		 *          { "orderSequence": [ "desc", "asc", "asc" ] },
12144		 *          { "orderSequence": [ "desc" ] },
12145		 *          null
12146		 *        ]
12147		 *      } );
12148		 *    } );
12149		 */
12150		"asSorting": [ 'asc', 'desc' ],
12151	
12152	
12153		/**
12154		 * Enable or disable filtering on the data in this column.
12155		 *  @type boolean
12156		 *  @default true
12157		 *
12158		 *  @name DataTable.defaults.column.searchable
12159		 *  @dtopt Columns
12160		 *
12161		 *  @example
12162		 *    // Using `columnDefs`
12163		 *    $(document).ready( function() {
12164		 *      $('#example').dataTable( {
12165		 *        "columnDefs": [
12166		 *          { "searchable": false, "targets": [ 0 ] }
12167		 *        ] } );
12168		 *    } );
12169		 *
12170		 *  @example
12171		 *    // Using `columns`
12172		 *    $(document).ready( function() {
12173		 *      $('#example').dataTable( {
12174		 *        "columns": [
12175		 *          { "searchable": false },
12176		 *          null,
12177		 *          null,
12178		 *          null,
12179		 *          null
12180		 *        ] } );
12181		 *    } );
12182		 */
12183		"bSearchable": true,
12184	
12185	
12186		/**
12187		 * Enable or disable ordering on this column.
12188		 *  @type boolean
12189		 *  @default true
12190		 *
12191		 *  @name DataTable.defaults.column.orderable
12192		 *  @dtopt Columns
12193		 *
12194		 *  @example
12195		 *    // Using `columnDefs`
12196		 *    $(document).ready( function() {
12197		 *      $('#example').dataTable( {
12198		 *        "columnDefs": [
12199		 *          { "orderable": false, "targets": [ 0 ] }
12200		 *        ] } );
12201		 *    } );
12202		 *
12203		 *  @example
12204		 *    // Using `columns`
12205		 *    $(document).ready( function() {
12206		 *      $('#example').dataTable( {
12207		 *        "columns": [
12208		 *          { "orderable": false },
12209		 *          null,
12210		 *          null,
12211		 *          null,
12212		 *          null
12213		 *        ] } );
12214		 *    } );
12215		 */
12216		"bSortable": true,
12217	
12218	
12219		/**
12220		 * Enable or disable the display of this column.
12221		 *  @type boolean
12222		 *  @default true
12223		 *
12224		 *  @name DataTable.defaults.column.visible
12225		 *  @dtopt Columns
12226		 *
12227		 *  @example
12228		 *    // Using `columnDefs`
12229		 *    $(document).ready( function() {
12230		 *      $('#example').dataTable( {
12231		 *        "columnDefs": [
12232		 *          { "visible": false, "targets": [ 0 ] }
12233		 *        ] } );
12234		 *    } );
12235		 *
12236		 *  @example
12237		 *    // Using `columns`
12238		 *    $(document).ready( function() {
12239		 *      $('#example').dataTable( {
12240		 *        "columns": [
12241		 *          { "visible": false },
12242		 *          null,
12243		 *          null,
12244		 *          null,
12245		 *          null
12246		 *        ] } );
12247		 *    } );
12248		 */
12249		"bVisible": true,
12250	
12251	
12252		/**
12253		 * Developer definable function that is called whenever a cell is created (Ajax source,
12254		 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
12255		 * allowing you to modify the DOM element (add background colour for example) when the
12256		 * element is available.
12257		 *  @type function
12258		 *  @param {element} td The TD node that has been created
12259		 *  @param {*} cellData The Data for the cell
12260		 *  @param {array|object} rowData The data for the whole row
12261		 *  @param {int} row The row index for the aoData data store
12262		 *  @param {int} col The column index for aoColumns
12263		 *
12264		 *  @name DataTable.defaults.column.createdCell
12265		 *  @dtopt Columns
12266		 *
12267		 *  @example
12268		 *    $(document).ready( function() {
12269		 *      $('#example').dataTable( {
12270		 *        "columnDefs": [ {
12271		 *          "targets": [3],
12272		 *          "createdCell": function (td, cellData, rowData, row, col) {
12273		 *            if ( cellData == "1.7" ) {
12274		 *              $(td).css('color', 'blue')
12275		 *            }
12276		 *          }
12277		 *        } ]
12278		 *      });
12279		 *    } );
12280		 */
12281		"fnCreatedCell": null,
12282	
12283	
12284		/**
12285		 * This parameter has been replaced by `data` in DataTables to ensure naming
12286		 * consistency. `dataProp` can still be used, as there is backwards
12287		 * compatibility in DataTables for this option, but it is strongly
12288		 * recommended that you use `data` in preference to `dataProp`.
12289		 *  @name DataTable.defaults.column.dataProp
12290		 */
12291	
12292	
12293		/**
12294		 * This property can be used to read data from any data source property,
12295		 * including deeply nested objects / properties. `data` can be given in a
12296		 * number of different ways which effect its behaviour:
12297		 *
12298		 * * `integer` - treated as an array index for the data source. This is the
12299		 *   default that DataTables uses (incrementally increased for each column).
12300		 * * `string` - read an object property from the data source. There are
12301		 *   three 'special' options that can be used in the string to alter how
12302		 *   DataTables reads the data from the source object:
12303		 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
12304		 *      Javascript to read from nested objects, so to can the options
12305		 *      specified in `data`. For example: `browser.version` or
12306		 *      `browser.name`. If your object parameter name contains a period, use
12307		 *      `\\` to escape it - i.e. `first\\.name`.
12308		 *    * `[]` - Array notation. DataTables can automatically combine data
12309		 *      from and array source, joining the data with the characters provided
12310		 *      between the two brackets. For example: `name[, ]` would provide a
12311		 *      comma-space separated list from the source array. If no characters
12312		 *      are provided between the brackets, the original array source is
12313		 *      returned.
12314		 *    * `()` - Function notation. Adding `()` to the end of a parameter will
12315		 *      execute a function of the name given. For example: `browser()` for a
12316		 *      simple function on the data source, `browser.version()` for a
12317		 *      function in a nested property or even `browser().version` to get an
12318		 *      object property if the function called returns an object. Note that
12319		 *      function notation is recommended for use in `render` rather than
12320		 *      `data` as it is much simpler to use as a renderer.
12321		 * * `null` - use the original data source for the row rather than plucking
12322		 *   data directly from it. This action has effects on two other
12323		 *   initialisation options:
12324		 *    * `defaultContent` - When null is given as the `data` option and
12325		 *      `defaultContent` is specified for the column, the value defined by
12326		 *      `defaultContent` will be used for the cell.
12327		 *    * `render` - When null is used for the `data` option and the `render`
12328		 *      option is specified for the column, the whole data source for the
12329		 *      row is used for the renderer.
12330		 * * `function` - the function given will be executed whenever DataTables
12331		 *   needs to set or get the data for a cell in the column. The function
12332		 *   takes three parameters:
12333		 *    * Parameters:
12334		 *      * `{array|object}` The data source for the row
12335		 *      * `{string}` The type call data requested - this will be 'set' when
12336		 *        setting data or 'filter', 'display', 'type', 'sort' or undefined
12337		 *        when gathering data. Note that when `undefined` is given for the
12338		 *        type DataTables expects to get the raw data for the object back<
12339		 *      * `{*}` Data to set when the second parameter is 'set'.
12340		 *    * Return:
12341		 *      * The return value from the function is not required when 'set' is
12342		 *        the type of call, but otherwise the return is what will be used
12343		 *        for the data requested.
12344		 *
12345		 * Note that `data` is a getter and setter option. If you just require
12346		 * formatting of data for output, you will likely want to use `render` which
12347		 * is simply a getter and thus simpler to use.
12348		 *
12349		 * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The
12350		 * name change reflects the flexibility of this property and is consistent
12351		 * with the naming of mRender. If 'mDataProp' is given, then it will still
12352		 * be used by DataTables, as it automatically maps the old name to the new
12353		 * if required.
12354		 *
12355		 *  @type string|int|function|null
12356		 *  @default null <i>Use automatically calculated column index</i>
12357		 *
12358		 *  @name DataTable.defaults.column.data
12359		 *  @dtopt Columns
12360		 *
12361		 *  @example
12362		 *    // Read table data from objects
12363		 *    // JSON structure for each row:
12364		 *    //   {
12365		 *    //      "engine": {value},
12366		 *    //      "browser": {value},
12367		 *    //      "platform": {value},
12368		 *    //      "version": {value},
12369		 *    //      "grade": {value}
12370		 *    //   }
12371		 *    $(document).ready( function() {
12372		 *      $('#example').dataTable( {
12373		 *        "ajaxSource": "sources/objects.txt",
12374		 *        "columns": [
12375		 *          { "data": "engine" },
12376		 *          { "data": "browser" },
12377		 *          { "data": "platform" },
12378		 *          { "data": "version" },
12379		 *          { "data": "grade" }
12380		 *        ]
12381		 *      } );
12382		 *    } );
12383		 *
12384		 *  @example
12385		 *    // Read information from deeply nested objects
12386		 *    // JSON structure for each row:
12387		 *    //   {
12388		 *    //      "engine": {value},
12389		 *    //      "browser": {value},
12390		 *    //      "platform": {
12391		 *    //         "inner": {value}
12392		 *    //      },
12393		 *    //      "details": [
12394		 *    //         {value}, {value}
12395		 *    //      ]
12396		 *    //   }
12397		 *    $(document).ready( function() {
12398		 *      $('#example').dataTable( {
12399		 *        "ajaxSource": "sources/deep.txt",
12400		 *        "columns": [
12401		 *          { "data": "engine" },
12402		 *          { "data": "browser" },
12403		 *          { "data": "platform.inner" },
12404		 *          { "data": "details.0" },
12405		 *          { "data": "details.1" }
12406		 *        ]
12407		 *      } );
12408		 *    } );
12409		 *
12410		 *  @example
12411		 *    // Using `data` as a function to provide different information for
12412		 *    // sorting, filtering and display. In this case, currency (price)
12413		 *    $(document).ready( function() {
12414		 *      $('#example').dataTable( {
12415		 *        "columnDefs": [ {
12416		 *          "targets": [ 0 ],
12417		 *          "data": function ( source, type, val ) {
12418		 *            if (type === 'set') {
12419		 *              source.price = val;
12420		 *              // Store the computed dislay and filter values for efficiency
12421		 *              source.price_display = val=="" ? "" : "$"+numberFormat(val);
12422		 *              source.price_filter  = val=="" ? "" : "$"+numberFormat(val)+" "+val;
12423		 *              return;
12424		 *            }
12425		 *            else if (type === 'display') {
12426		 *              return source.price_display;
12427		 *            }
12428		 *            else if (type === 'filter') {
12429		 *              return source.price_filter;
12430		 *            }
12431		 *            // 'sort', 'type' and undefined all just use the integer
12432		 *            return source.price;
12433		 *          }
12434		 *        } ]
12435		 *      } );
12436		 *    } );
12437		 *
12438		 *  @example
12439		 *    // Using default content
12440		 *    $(document).ready( function() {
12441		 *      $('#example').dataTable( {
12442		 *        "columnDefs": [ {
12443		 *          "targets": [ 0 ],
12444		 *          "data": null,
12445		 *          "defaultContent": "Click to edit"
12446		 *        } ]
12447		 *      } );
12448		 *    } );
12449		 *
12450		 *  @example
12451		 *    // Using array notation - outputting a list from an array
12452		 *    $(document).ready( function() {
12453		 *      $('#example').dataTable( {
12454		 *        "columnDefs": [ {
12455		 *          "targets": [ 0 ],
12456		 *          "data": "name[, ]"
12457		 *        } ]
12458		 *      } );
12459		 *    } );
12460		 *
12461		 */
12462		"mData": null,
12463	
12464	
12465		/**
12466		 * This property is the rendering partner to `data` and it is suggested that
12467		 * when you want to manipulate data for display (including filtering,
12468		 * sorting etc) without altering the underlying data for the table, use this
12469		 * property. `render` can be considered to be the the read only companion to
12470		 * `data` which is read / write (then as such more complex). Like `data`
12471		 * this option can be given in a number of different ways to effect its
12472		 * behaviour:
12473		 *
12474		 * * `integer` - treated as an array index for the data source. This is the
12475		 *   default that DataTables uses (incrementally increased for each column).
12476		 * * `string` - read an object property from the data source. There are
12477		 *   three 'special' options that can be used in the string to alter how
12478		 *   DataTables reads the data from the source object:
12479		 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
12480		 *      Javascript to read from nested objects, so to can the options
12481		 *      specified in `data`. For example: `browser.version` or
12482		 *      `browser.name`. If your object parameter name contains a period, use
12483		 *      `\\` to escape it - i.e. `first\\.name`.
12484		 *    * `[]` - Array notation. DataTables can automatically combine data
12485		 *      from and array source, joining the data with the characters provided
12486		 *      between the two brackets. For example: `name[, ]` would provide a
12487		 *      comma-space separated list from the source array. If no characters
12488		 *      are provided between the brackets, the original array source is
12489		 *      returned.
12490		 *    * `()` - Function notation. Adding `()` to the end of a parameter will
12491		 *      execute a function of the name given. For example: `browser()` for a
12492		 *      simple function on the data source, `browser.version()` for a
12493		 *      function in a nested property or even `browser().version` to get an
12494		 *      object property if the function called returns an object.
12495		 * * `object` - use different data for the different data types requested by
12496		 *   DataTables ('filter', 'display', 'type' or 'sort'). The property names
12497		 *   of the object is the data type the property refers to and the value can
12498		 *   defined using an integer, string or function using the same rules as
12499		 *   `render` normally does. Note that an `_` option _must_ be specified.
12500		 *   This is the default value to use if you haven't specified a value for
12501		 *   the data type requested by DataTables.
12502		 * * `function` - the function given will be executed whenever DataTables
12503		 *   needs to set or get the data for a cell in the column. The function
12504		 *   takes three parameters:
12505		 *    * Parameters:
12506		 *      * {array|object} The data source for the row (based on `data`)
12507		 *      * {string} The type call data requested - this will be 'filter',
12508		 *        'display', 'type' or 'sort'.
12509		 *      * {array|object} The full data source for the row (not based on
12510		 *        `data`)
12511		 *    * Return:
12512		 *      * The return value from the function is what will be used for the
12513		 *        data requested.
12514		 *
12515		 *  @type string|int|function|object|null
12516		 *  @default null Use the data source value.
12517		 *
12518		 *  @name DataTable.defaults.column.render
12519		 *  @dtopt Columns
12520		 *
12521		 *  @example
12522		 *    // Create a comma separated list from an array of objects
12523		 *    $(document).ready( function() {
12524		 *      $('#example').dataTable( {
12525		 *        "ajaxSource": "sources/deep.txt",
12526		 *        "columns": [
12527		 *          { "data": "engine" },
12528		 *          { "data": "browser" },
12529		 *          {
12530		 *            "data": "platform",
12531		 *            "render": "[, ].name"
12532		 *          }
12533		 *        ]
12534		 *      } );
12535		 *    } );
12536		 *
12537		 *  @example
12538		 *    // Execute a function to obtain data
12539		 *    $(document).ready( function() {
12540		 *      $('#example').dataTable( {
12541		 *        "columnDefs": [ {
12542		 *          "targets": [ 0 ],
12543		 *          "data": null, // Use the full data source object for the renderer's source
12544		 *          "render": "browserName()"
12545		 *        } ]
12546		 *      } );
12547		 *    } );
12548		 *
12549		 *  @example
12550		 *    // As an object, extracting different data for the different types
12551		 *    // This would be used with a data source such as:
12552		 *    //   { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" }
12553		 *    // Here the `phone` integer is used for sorting and type detection, while `phone_filter`
12554		 *    // (which has both forms) is used for filtering for if a user inputs either format, while
12555		 *    // the formatted phone number is the one that is shown in the table.
12556		 *    $(document).ready( function() {
12557		 *      $('#example').dataTable( {
12558		 *        "columnDefs": [ {
12559		 *          "targets": [ 0 ],
12560		 *          "data": null, // Use the full data source object for the renderer's source
12561		 *          "render": {
12562		 *            "_": "phone",
12563		 *            "filter": "phone_filter",
12564		 *            "display": "phone_display"
12565		 *          }
12566		 *        } ]
12567		 *      } );
12568		 *    } );
12569		 *
12570		 *  @example
12571		 *    // Use as a function to create a link from the data source
12572		 *    $(document).ready( function() {
12573		 *      $('#example').dataTable( {
12574		 *        "columnDefs": [ {
12575		 *          "targets": [ 0 ],
12576		 *          "data": "download_link",
12577		 *          "render": function ( data, type, full ) {
12578		 *            return '<a href="'+data+'">Download</a>';
12579		 *          }
12580		 *        } ]
12581		 *      } );
12582		 *    } );
12583		 */
12584		"mRender": null,
12585	
12586	
12587		/**
12588		 * Change the cell type created for the column - either TD cells or TH cells. This
12589		 * can be useful as TH cells have semantic meaning in the table body, allowing them
12590		 * to act as a header for a row (you may wish to add scope='row' to the TH elements).
12591		 *  @type string
12592		 *  @default td
12593		 *
12594		 *  @name DataTable.defaults.column.cellType
12595		 *  @dtopt Columns
12596		 *
12597		 *  @example
12598		 *    // Make the first column use TH cells
12599		 *    $(document).ready( function() {
12600		 *      $('#example').dataTable( {
12601		 *        "columnDefs": [ {
12602		 *          "targets": [ 0 ],
12603		 *          "cellType": "th"
12604		 *        } ]
12605		 *      } );
12606		 *    } );
12607		 */
12608		"sCellType": "td",
12609	
12610	
12611		/**
12612		 * Class to give to each cell in this column.
12613		 *  @type string
12614		 *  @default <i>Empty string</i>
12615		 *
12616		 *  @name DataTable.defaults.column.class
12617		 *  @dtopt Columns
12618		 *
12619		 *  @example
12620		 *    // Using `columnDefs`
12621		 *    $(document).ready( function() {
12622		 *      $('#example').dataTable( {
12623		 *        "columnDefs": [
12624		 *          { "class": "my_class", "targets": [ 0 ] }
12625		 *        ]
12626		 *      } );
12627		 *    } );
12628		 *
12629		 *  @example
12630		 *    // Using `columns`
12631		 *    $(document).ready( function() {
12632		 *      $('#example').dataTable( {
12633		 *        "columns": [
12634		 *          { "class": "my_class" },
12635		 *          null,
12636		 *          null,
12637		 *          null,
12638		 *          null
12639		 *        ]
12640		 *      } );
12641		 *    } );
12642		 */
12643		"sClass": "",
12644	
12645		/**
12646		 * When DataTables calculates the column widths to assign to each column,
12647		 * it finds the longest string in each column and then constructs a
12648		 * temporary table and reads the widths from that. The problem with this
12649		 * is that "mmm" is much wider then "iiii", but the latter is a longer
12650		 * string - thus the calculation can go wrong (doing it properly and putting
12651		 * it into an DOM object and measuring that is horribly(!) slow). Thus as
12652		 * a "work around" we provide this option. It will append its value to the
12653		 * text that is found to be the longest string for the column - i.e. padding.
12654		 * Generally you shouldn't need this!
12655		 *  @type string
12656		 *  @default <i>Empty string<i>
12657		 *
12658		 *  @name DataTable.defaults.column.contentPadding
12659		 *  @dtopt Columns
12660		 *
12661		 *  @example
12662		 *    // Using `columns`
12663		 *    $(document).ready( function() {
12664		 *      $('#example').dataTable( {
12665		 *        "columns": [
12666		 *          null,
12667		 *          null,
12668		 *          null,
12669		 *          {
12670		 *            "contentPadding": "mmm"
12671		 *          }
12672		 *        ]
12673		 *      } );
12674		 *    } );
12675		 */
12676		"sContentPadding": "",
12677	
12678	
12679		/**
12680		 * Allows a default value to be given for a column's data, and will be used
12681		 * whenever a null data source is encountered (this can be because `data`
12682		 * is set to null, or because the data source itself is null).
12683		 *  @type string
12684		 *  @default null
12685		 *
12686		 *  @name DataTable.defaults.column.defaultContent
12687		 *  @dtopt Columns
12688		 *
12689		 *  @example
12690		 *    // Using `columnDefs`
12691		 *    $(document).ready( function() {
12692		 *      $('#example').dataTable( {
12693		 *        "columnDefs": [
12694		 *          {
12695		 *            "data": null,
12696		 *            "defaultContent": "Edit",
12697		 *            "targets": [ -1 ]
12698		 *          }
12699		 *        ]
12700		 *      } );
12701		 *    } );
12702		 *
12703		 *  @example
12704		 *    // Using `columns`
12705		 *    $(document).ready( function() {
12706		 *      $('#example').dataTable( {
12707		 *        "columns": [
12708		 *          null,
12709		 *          null,
12710		 *          null,
12711		 *          {
12712		 *            "data": null,
12713		 *            "defaultContent": "Edit"
12714		 *          }
12715		 *        ]
12716		 *      } );
12717		 *    } );
12718		 */
12719		"sDefaultContent": null,
12720	
12721	
12722		/**
12723		 * This parameter is only used in DataTables' server-side processing. It can
12724		 * be exceptionally useful to know what columns are being displayed on the
12725		 * client side, and to map these to database fields. When defined, the names
12726		 * also allow DataTables to reorder information from the server if it comes
12727		 * back in an unexpected order (i.e. if you switch your columns around on the
12728		 * client-side, your server-side code does not also need updating).
12729		 *  @type string
12730		 *  @default <i>Empty string</i>
12731		 *
12732		 *  @name DataTable.defaults.column.name
12733		 *  @dtopt Columns
12734		 *
12735		 *  @example
12736		 *    // Using `columnDefs`
12737		 *    $(document).ready( function() {
12738		 *      $('#example').dataTable( {
12739		 *        "columnDefs": [
12740		 *          { "name": "engine", "targets": [ 0 ] },
12741		 *          { "name": "browser", "targets": [ 1 ] },
12742		 *          { "name": "platform", "targets": [ 2 ] },
12743		 *          { "name": "version", "targets": [ 3 ] },
12744		 *          { "name": "grade", "targets": [ 4 ] }
12745		 *        ]
12746		 *      } );
12747		 *    } );
12748		 *
12749		 *  @example
12750		 *    // Using `columns`
12751		 *    $(document).ready( function() {
12752		 *      $('#example').dataTable( {
12753		 *        "columns": [
12754		 *          { "name": "engine" },
12755		 *          { "name": "browser" },
12756		 *          { "name": "platform" },
12757		 *          { "name": "version" },
12758		 *          { "name": "grade" }
12759		 *        ]
12760		 *      } );
12761		 *    } );
12762		 */
12763		"sName": "",
12764	
12765	
12766		/**
12767		 * Defines a data source type for the ordering which can be used to read
12768		 * real-time information from the table (updating the internally cached
12769		 * version) prior to ordering. This allows ordering to occur on user
12770		 * editable elements such as form inputs.
12771		 *  @type string
12772		 *  @default std
12773		 *
12774		 *  @name DataTable.defaults.column.orderDataType
12775		 *  @dtopt Columns
12776		 *
12777		 *  @example
12778		 *    // Using `columnDefs`
12779		 *    $(document).ready( function() {
12780		 *      $('#example').dataTable( {
12781		 *        "columnDefs": [
12782		 *          { "orderDataType": "dom-text", "targets": [ 2, 3 ] },
12783		 *          { "type": "numeric", "targets": [ 3 ] },
12784		 *          { "orderDataType": "dom-select", "targets": [ 4 ] },
12785		 *          { "orderDataType": "dom-checkbox", "targets": [ 5 ] }
12786		 *        ]
12787		 *      } );
12788		 *    } );
12789		 *
12790		 *  @example
12791		 *    // Using `columns`
12792		 *    $(document).ready( function() {
12793		 *      $('#example').dataTable( {
12794		 *        "columns": [
12795		 *          null,
12796		 *          null,
12797		 *          { "orderDataType": "dom-text" },
12798		 *          { "orderDataType": "dom-text", "type": "numeric" },
12799		 *          { "orderDataType": "dom-select" },
12800		 *          { "orderDataType": "dom-checkbox" }
12801		 *        ]
12802		 *      } );
12803		 *    } );
12804		 */
12805		"sSortDataType": "std",
12806	
12807	
12808		/**
12809		 * The title of this column.
12810		 *  @type string
12811		 *  @default null <i>Derived from the 'TH' value for this column in the
12812		 *    original HTML table.</i>
12813		 *
12814		 *  @name DataTable.defaults.column.title
12815		 *  @dtopt Columns
12816		 *
12817		 *  @example
12818		 *    // Using `columnDefs`
12819		 *    $(document).ready( function() {
12820		 *      $('#example').dataTable( {
12821		 *        "columnDefs": [
12822		 *          { "title": "My column title", "targets": [ 0 ] }
12823		 *        ]
12824		 *      } );
12825		 *    } );
12826		 *
12827		 *  @example
12828		 *    // Using `columns`
12829		 *    $(document).ready( function() {
12830		 *      $('#example').dataTable( {
12831		 *        "columns": [
12832		 *          { "title": "My column title" },
12833		 *          null,
12834		 *          null,
12835		 *          null,
12836		 *          null
12837		 *        ]
12838		 *      } );
12839		 *    } );
12840		 */
12841		"sTitle": null,
12842	
12843	
12844		/**
12845		 * The type allows you to specify how the data for this column will be
12846		 * ordered. Four types (string, numeric, date and html (which will strip
12847		 * HTML tags before ordering)) are currently available. Note that only date
12848		 * formats understood by Javascript's Date() object will be accepted as type
12849		 * date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string',
12850		 * 'numeric', 'date' or 'html' (by default). Further types can be adding
12851		 * through plug-ins.
12852		 *  @type string
12853		 *  @default null <i>Auto-detected from raw data</i>
12854		 *
12855		 *  @name DataTable.defaults.column.type
12856		 *  @dtopt Columns
12857		 *
12858		 *  @example
12859		 *    // Using `columnDefs`
12860		 *    $(document).ready( function() {
12861		 *      $('#example').dataTable( {
12862		 *        "columnDefs": [
12863		 *          { "type": "html", "targets": [ 0 ] }
12864		 *        ]
12865		 *      } );
12866		 *    } );
12867		 *
12868		 *  @example
12869		 *    // Using `columns`
12870		 *    $(document).ready( function() {
12871		 *      $('#example').dataTable( {
12872		 *        "columns": [
12873		 *          { "type": "html" },
12874		 *          null,
12875		 *          null,
12876		 *          null,
12877		 *          null
12878		 *        ]
12879		 *      } );
12880		 *    } );
12881		 */
12882		"sType": null,
12883	
12884	
12885		/**
12886		 * Defining the width of the column, this parameter may take any CSS value
12887		 * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not
12888		 * been given a specific width through this interface ensuring that the table
12889		 * remains readable.
12890		 *  @type string
12891		 *  @default null <i>Automatic</i>
12892		 *
12893		 *  @name DataTable.defaults.column.width
12894		 *  @dtopt Columns
12895		 *
12896		 *  @example
12897		 *    // Using `columnDefs`
12898		 *    $(document).ready( function() {
12899		 *      $('#example').dataTable( {
12900		 *        "columnDefs": [
12901		 *          { "width": "20%", "targets": [ 0 ] }
12902		 *        ]
12903		 *      } );
12904		 *    } );
12905		 *
12906		 *  @example
12907		 *    // Using `columns`
12908		 *    $(document).ready( function() {
12909		 *      $('#example').dataTable( {
12910		 *        "columns": [
12911		 *          { "width": "20%" },
12912		 *          null,
12913		 *          null,
12914		 *          null,
12915		 *          null
12916		 *        ]
12917		 *      } );
12918		 *    } );
12919		 */
12920		"sWidth": null
12921	};
12922	
12923	_fnHungarianMap( DataTable.defaults.column );
12924	
12925	
12926	
12927	/**
12928	 * DataTables settings object - this holds all the information needed for a
12929	 * given table, including configuration, data and current application of the
12930	 * table options. DataTables does not have a single instance for each DataTable
12931	 * with the settings attached to that instance, but rather instances of the
12932	 * DataTable "class" are created on-the-fly as needed (typically by a
12933	 * $().dataTable() call) and the settings object is then applied to that
12934	 * instance.
12935	 *
12936	 * Note that this object is related to {@link DataTable.defaults} but this
12937	 * one is the internal data store for DataTables's cache of columns. It should
12938	 * NOT be manipulated outside of DataTables. Any configuration should be done
12939	 * through the initialisation options.
12940	 *  @namespace
12941	 *  @todo Really should attach the settings object to individual instances so we
12942	 *    don't need to create new instances on each $().dataTable() call (if the
12943	 *    table already exists). It would also save passing oSettings around and
12944	 *    into every single function. However, this is a very significant
12945	 *    architecture change for DataTables and will almost certainly break
12946	 *    backwards compatibility with older installations. This is something that
12947	 *    will be done in 2.0.
12948	 */
12949	DataTable.models.oSettings = {
12950		/**
12951		 * Primary features of DataTables and their enablement state.
12952		 *  @namespace
12953		 */
12954		"oFeatures": {
12955	
12956			/**
12957			 * Flag to say if DataTables should automatically try to calculate the
12958			 * optimum table and columns widths (true) or not (false).
12959			 * Note that this parameter will be set by the initialisation routine. To
12960			 * set a default use {@link DataTable.defaults}.
12961			 *  @type boolean
12962			 */
12963			"bAutoWidth": null,
12964	
12965			/**
12966			 * Delay the creation of TR and TD elements until they are actually
12967			 * needed by a driven page draw. This can give a significant speed
12968			 * increase for Ajax source and Javascript source data, but makes no
12969			 * difference at all f
12969ro
vendor: 14,836 bytes, lines 12969-13546
12969 DOM and server-side processing tables.
12970			 * Note that this parameter will be set by the initialisation routine. To
12971			 * set a default use {@link DataTable.defaults}.
12972			 *  @type boolean
12973			 */
12974			"bDeferRender": null,
12975	
12976			/**
12977			 * Enable filtering on the table or not. Note that if this is disabled
12978			 * then there is no filtering at all on the table, including fnFilter.
12979			 * To just remove the filtering input use sDom and remove the 'f' option.
12980			 * Note that this parameter will be set by the initialisation routine. To
12981			 * set a default use {@link DataTable.defaults}.
12982			 *  @type boolean
12983			 */
12984			"bFilter": null,
12985	
12986			/**
12987			 * Table information element (the 'Showing x of y records' div) enable
12988			 * flag.
12989			 * Note that this parameter will be set by the initialisation routine. To
12990			 * set a default use {@link DataTable.defaults}.
12991			 *  @type boolean
12992			 */
12993			"bInfo": null,
12994	
12995			/**
12996			 * Present a user control allowing the end user to change the page size
12997			 * when pagination is enabled.
12998			 * Note that this parameter will be set by the initialisation routine. To
12999			 * set a default use {@link DataTable.defaults}.
13000			 *  @type boolean
13001			 */
13002			"bLengthChange": null,
13003	
13004			/**
13005			 * Pagination enabled or not. Note that if this is disabled then length
13006			 * changing must also be disabled.
13007			 * Note that this parameter will be set by the initialisation routine. To
13008			 * set a default use {@link DataTable.defaults}.
13009			 *  @type boolean
13010			 */
13011			"bPaginate": null,
13012	
13013			/**
13014			 * Processing indicator enable flag whenever DataTables is enacting a
13015			 * user request - typically an Ajax request for server-side processing.
13016			 * Note that this parameter will be set by the initialisation routine. To
13017			 * set a default use {@link DataTable.defaults}.
13018			 *  @type boolean
13019			 */
13020			"bProcessing": null,
13021	
13022			/**
13023			 * Server-side processing enabled flag - when enabled DataTables will
13024			 * get all data from the server for every draw - there is no filtering,
13025			 * sorting or paging done on the client-side.
13026			 * Note that this parameter will be set by the initialisation routine. To
13027			 * set a default use {@link DataTable.defaults}.
13028			 *  @type boolean
13029			 */
13030			"bServerSide": null,
13031	
13032			/**
13033			 * Sorting enablement flag.
13034			 * Note that this parameter will be set by the initialisation routine. To
13035			 * set a default use {@link DataTable.defaults}.
13036			 *  @type boolean
13037			 */
13038			"bSort": null,
13039	
13040			/**
13041			 * Multi-column sorting
13042			 * Note that this parameter will be set by the initialisation routine. To
13043			 * set a default use {@link DataTable.defaults}.
13044			 *  @type boolean
13045			 */
13046			"bSortMulti": null,
13047	
13048			/**
13049			 * Apply a class to the columns which are being sorted to provide a
13050			 * visual highlight or not. This can slow things down when enabled since
13051			 * there is a lot of DOM interaction.
13052			 * Note that this parameter will be set by the initialisation routine. To
13053			 * set a default use {@link DataTable.defaults}.
13054			 *  @type boolean
13055			 */
13056			"bSortClasses": null,
13057	
13058			/**
13059			 * State saving enablement flag.
13060			 * Note that this parameter will be set by the initialisation routine. To
13061			 * set a default use {@link DataTable.defaults}.
13062			 *  @type boolean
13063			 */
13064			"bStateSave": null
13065		},
13066	
13067	
13068		/**
13069		 * Scrolling settings for a table.
13070		 *  @namespace
13071		 */
13072		"oScroll": {
13073			/**
13074			 * When the table is shorter in height than sScrollY, collapse the
13075			 * table container down to the height of the table (when true).
13076			 * Note that this parameter will be set by the initialisation routine. To
13077			 * set a default use {@link DataTable.defaults}.
13078			 *  @type boolean
13079			 */
13080			"bCollapse": null,
13081	
13082			/**
13083			 * Width of the scrollbar for the web-browser's platform. Calculated
13084			 * during table initialisation.
13085			 *  @type int
13086			 *  @default 0
13087			 */
13088			"iBarWidth": 0,
13089	
13090			/**
13091			 * Viewport width for horizontal scrolling. Horizontal scrolling is
13092			 * disabled if an empty string.
13093			 * Note that this parameter will be set by the initialisation routine. To
13094			 * set a default use {@link DataTable.defaults}.
13095			 *  @type string
13096			 */
13097			"sX": null,
13098	
13099			/**
13100			 * Width to expand the table to when using x-scrolling. Typically you
13101			 * should not need to use this.
13102			 * Note that this parameter will be set by the initialisation routine. To
13103			 * set a default use {@link DataTable.defaults}.
13104			 *  @type string
13105			 *  @deprecated
13106			 */
13107			"sXInner": null,
13108	
13109			/**
13110			 * Viewport height for vertical scrolling. Vertical scrolling is disabled
13111			 * if an empty string.
13112			 * Note that this parameter will be set by the initialisation routine. To
13113			 * set a default use {@link DataTable.defaults}.
13114			 *  @type string
13115			 */
13116			"sY": null
13117		},
13118	
13119		/**
13120		 * Language information for the table.
13121		 *  @namespace
13122		 *  @extends DataTable.defaults.oLanguage
13123		 */
13124		"oLanguage": {
13125			/**
13126			 * Information callback function. See
13127			 * {@link DataTable.defaults.fnInfoCallback}
13128			 *  @type function
13129			 *  @default null
13130			 */
13131			"fnInfoCallback": null
13132		},
13133	
13134		/**
13135		 * Browser support parameters
13136		 *  @namespace
13137		 */
13138		"oBrowser": {
13139			/**
13140			 * Indicate if the browser incorrectly calculates width:100% inside a
13141			 * scrolling element (IE6/7)
13142			 *  @type boolean
13143			 *  @default false
13144			 */
13145			"bScrollOversize": false,
13146	
13147			/**
13148			 * Determine if the vertical scrollbar is on the right or left of the
13149			 * scrolling container - needed for rtl language layout, although not
13150			 * all browsers move the scrollbar (Safari).
13151			 *  @type boolean
13152			 *  @default false
13153			 */
13154			"bScrollbarLeft": false,
13155	
13156			/**
13157			 * Flag for if `getBoundingClientRect` is fully supported or not
13158			 *  @type boolean
13159			 *  @default false
13160			 */
13161			"bBounding": false,
13162	
13163			/**
13164			 * Browser scrollbar width
13165			 *  @type integer
13166			 *  @default 0
13167			 */
13168			"barWidth": 0
13169		},
13170	
13171	
13172		"ajax": null,
13173	
13174	
13175		/**
13176		 * Array referencing the nodes which are used for the features. The
13177		 * parameters of this object match what is allowed by sDom - i.e.
13178		 *   <ul>
13179		 *     <li>'l' - Length changing</li>
13180		 *     <li>'f' - Filtering input</li>
13181		 *     <li>'t' - The table!</li>
13182		 *     <li>'i' - Information</li>
13183		 *     <li>'p' - Pagination</li>
13184		 *     <li>'r' - pRocessing</li>
13185		 *   </ul>
13186		 *  @type array
13187		 *  @default []
13188		 */
13189		"aanFeatures": [],
13190	
13191		/**
13192		 * Store data information - see {@link DataTable.models.oRow} for detailed
13193		 * information.
13194		 *  @type array
13195		 *  @default []
13196		 */
13197		"aoData": [],
13198	
13199		/**
13200		 * Array of indexes which are in the current display (after filtering etc)
13201		 *  @type array
13202		 *  @default []
13203		 */
13204		"aiDisplay": [],
13205	
13206		/**
13207		 * Array of indexes for display - no filtering
13208		 *  @type array
13209		 *  @default []
13210		 */
13211		"aiDisplayMaster": [],
13212	
13213		/**
13214		 * Map of row ids to data indexes
13215		 *  @type object
13216		 *  @default {}
13217		 */
13218		"aIds": {},
13219	
13220		/**
13221		 * Store information about each column that is in use
13222		 *  @type array
13223		 *  @default []
13224		 */
13225		"aoColumns": [],
13226	
13227		/**
13228		 * Store information about the table's header
13229		 *  @type array
13230		 *  @default []
13231		 */
13232		"aoHeader": [],
13233	
13234		/**
13235		 * Store information about the table's footer
13236		 *  @type array
13237		 *  @default []
13238		 */
13239		"aoFooter": [],
13240	
13241		/**
13242		 * Store the applied global search information in case we want to force a
13243		 * research or compare the old search to a new one.
13244		 * Note that this parameter will be set by the initialisation routine. To
13245		 * set a default use {@link DataTable.defaults}.
13246		 *  @namespace
13247		 *  @extends DataTable.models.oSearch
13248		 */
13249		"oPreviousSearch": {},
13250	
13251		/**
13252		 * Store the applied search for each column - see
13253		 * {@link DataTable.models.oSearch} for the format that is used for the
13254		 * filtering information for each column.
13255		 *  @type array
13256		 *  @default []
13257		 */
13258		"aoPreSearchCols": [],
13259	
13260		/**
13261		 * Sorting that is applied to the table. Note that the inner arrays are
13262		 * used in the following manner:
13263		 * <ul>
13264		 *   <li>Index 0 - column number</li>
13265		 *   <li>Index 1 - current sorting direction</li>
13266		 * </ul>
13267		 * Note that this parameter will be set by the initialisation routine. To
13268		 * set a default use {@link DataTable.defaults}.
13269		 *  @type array
13270		 *  @todo These inner arrays should really be objects
13271		 */
13272		"aaSorting": null,
13273	
13274		/**
13275		 * Sorting that is always applied to the table (i.e. prefixed in front of
13276		 * aaSorting).
13277		 * Note that this parameter will be set by the initialisation routine. To
13278		 * set a default use {@link DataTable.defaults}.
13279		 *  @type array
13280		 *  @default []
13281		 */
13282		"aaSortingFixed": [],
13283	
13284		/**
13285		 * Classes to use for the striping of a table.
13286		 * Note that this parameter will be set by the initialisation routine. To
13287		 * set a default use {@link DataTable.defaults}.
13288		 *  @type array
13289		 *  @default []
13290		 */
13291		"asStripeClasses": null,
13292	
13293		/**
13294		 * If restoring a table - we should restore its striping classes as well
13295		 *  @type array
13296		 *  @default []
13297		 */
13298		"asDestroyStripes": [],
13299	
13300		/**
13301		 * If restoring a table - we should restore its width
13302		 *  @type int
13303		 *  @default 0
13304		 */
13305		"sDestroyWidth": 0,
13306	
13307		/**
13308		 * Callback functions array for every time a row is inserted (i.e. on a draw).
13309		 *  @type array
13310		 *  @default []
13311		 */
13312		"aoRowCallback": [],
13313	
13314		/**
13315		 * Callback functions for the header on each draw.
13316		 *  @type array
13317		 *  @default []
13318		 */
13319		"aoHeaderCallback": [],
13320	
13321		/**
13322		 * Callback function for the footer on each draw.
13323		 *  @type array
13324		 *  @default []
13325		 */
13326		"aoFooterCallback": [],
13327	
13328		/**
13329		 * Array of callback functions for draw callback functions
13330		 *  @type array
13331		 *  @default []
13332		 */
13333		"aoDrawCallback": [],
13334	
13335		/**
13336		 * Array of callback functions for row created function
13337		 *  @type array
13338		 *  @default []
13339		 */
13340		"aoRowCreatedCallback": [],
13341	
13342		/**
13343		 * Callback functions for just before the table is redrawn. A return of
13344		 * false will be used to cancel the draw.
13345		 *  @type array
13346		 *  @default []
13347		 */
13348		"aoPreDrawCallback": [],
13349	
13350		/**
13351		 * Callback functions for when the table has been initialised.
13352		 *  @type array
13353		 *  @default []
13354		 */
13355		"aoInitComplete": [],
13356	
13357	
13358		/**
13359		 * Callbacks for modifying the settings to be stored for state saving, prior to
13360		 * saving state.
13361		 *  @type array
13362		 *  @default []
13363		 */
13364		"aoStateSaveParams": [],
13365	
13366		/**
13367		 * Callbacks for modifying the settings that have been stored for state saving
13368		 * prior to using the stored values to restore the state.
13369		 *  @type array
13370		 *  @default []
13371		 */
13372		"aoStateLoadParams": [],
13373	
13374		/**
13375		 * Callbacks for operating on the settings object once the saved state has been
13376		 * loaded
13377		 *  @type array
13378		 *  @default []
13379		 */
13380		"aoStateLoaded": [],
13381	
13382		/**
13383		 * Cache the table ID for quick access
13384		 *  @type string
13385		 *  @default <i>Empty string</i>
13386		 */
13387		"sTableId": "",
13388	
13389		/**
13390		 * The TABLE node for the main table
13391		 *  @type node
13392		 *  @default null
13393		 */
13394		"nTable": null,
13395	
13396		/**
13397		 * Permanent ref to the thead element
13398		 *  @type node
13399		 *  @default null
13400		 */
13401		"nTHead": null,
13402	
13403		/**
13404		 * Permanent ref to the tfoot element - if it exists
13405		 *  @type node
13406		 *  @default null
13407		 */
13408		"nTFoot": null,
13409	
13410		/**
13411		 * Permanent ref to the tbody element
13412		 *  @type node
13413		 *  @default null
13414		 */
13415		"nTBody": null,
13416	
13417		/**
13418		 * Cache the wrapper node (contains all DataTables controlled elements)
13419		 *  @type node
13420		 *  @default null
13421		 */
13422		"nTableWrapper": null,
13423	
13424		/**
13425		 * Indicate if when using server-side processing the loading of data
13426		 * should be deferred until the second draw.
13427		 * Note that this parameter will be set by the initialisation routine. To
13428		 * set a default use {@link DataTable.defaults}.
13429		 *  @type boolean
13430		 *  @default false
13431		 */
13432		"bDeferLoading": false,
13433	
13434		/**
13435		 * Indicate if all required information has been read in
13436		 *  @type boolean
13437		 *  @default false
13438		 */
13439		"bInitialised": false,
13440	
13441		/**
13442		 * Information about open rows. Each object in the array has the parameters
13443		 * 'nTr' and 'nParent'
13444		 *  @type array
13445		 *  @default []
13446		 */
13447		"aoOpenRows": [],
13448	
13449		/**
13450		 * Dictate the positioning of DataTables' control elements - see
13451		 * {@link DataTable.model.oInit.sDom}.
13452		 * Note that this parameter will be set by the initialisation routine. To
13453		 * set a default use {@link DataTable.defaults}.
13454		 *  @type string
13455		 *  @default null
13456		 */
13457		"sDom": null,
13458	
13459		/**
13460		 * Search delay (in mS)
13461		 *  @type integer
13462		 *  @default null
13463		 */
13464		"searchDelay": null,
13465	
13466		/**
13467		 * Which type of pagination should be used.
13468		 * Note that this parameter will be set by the initialisation routine. To
13469		 * set a default use {@link DataTable.defaults}.
13470		 *  @type string
13471		 *  @default two_button
13472		 */
13473		"sPaginationType": "two_button",
13474	
13475		/**
13476		 * The state duration (for `stateSave`) in seconds.
13477		 * Note that this parameter will be set by the initialisation routine. To
13478		 * set a default use {@link DataTable.defaults}.
13479		 *  @type int
13480		 *  @default 0
13481		 */
13482		"iStateDuration": 0,
13483	
13484		/**
13485		 * Array of callback functions for state saving. Each array element is an
13486		 * object with the following parameters:
13487		 *   <ul>
13488		 *     <li>function:fn - function to call. Takes two parameters, oSettings
13489		 *       and the JSON string to save that has been thus far created. Returns
13490		 *       a JSON string to be inserted into a json object
13491		 *       (i.e. '"param": [ 0, 1, 2]')</li>
13492		 *     <li>string:sName - name of callback</li>
13493		 *   </ul>
13494		 *  @type array
13495		 *  @default []
13496		 */
13497		"aoStateSave": [],
13498	
13499		/**
13500		 * Array of callback functions for state loading. Each array element is an
13501		 * object with the following parameters:
13502		 *   <ul>
13503		 *     <li>function:fn - function to call. Takes two parameters, oSettings
13504		 *       and the object stored. May return false to cancel state loading</li>
13505		 *     <li>string:sName - name of callback</li>
13506		 *   </ul>
13507		 *  @type array
13508		 *  @default []
13509		 */
13510		"aoStateLoad": [],
13511	
13512		/**
13513		 * State that was saved. Useful for back reference
13514		 *  @type object
13515		 *  @default null
13516		 */
13517		"oSavedState": null,
13518	
13519		/**
13520		 * State that was loaded. Useful for back reference
13521		 *  @type object
13522		 *  @default null
13523		 */
13524		"oLoadedState": null,
13525	
13526		/**
13527		 * Source url for AJAX data for the table.
13528		 * Note that this parameter will be set by the initialisation routine. To
13529		 * set a default use {@link DataTable.defaults}.
13530		 *  @type string
13531		 *  @default null
13532		 */
13533		"sAjaxSource": null,
13534	
13535		/**
13536		 * Property from a given object from which to read the table data from. This
13537		 * can be an empty string (when not server-side processing), in which case
13538		 * it is  assumed an an array is given directly.
13539		 * Note that this parameter will be set by the initialisation routine. To
13540		 * set a default use {@link DataTable.defaults}.
13541		 *  @type string
13542		 */
13543		"sAjaxDataProp": null,
13544	
13545		/**
13546		 * 
13546Note if draw should be blocked while getting data
13547		 *  @type boolean
13548		 *  @default true
13549		 */
13550		"bAjaxDataGet": true,
13551	
13552		/**
13553		 * The last jQuery XHR object that was used for server-side data gathering.
13554		 * This can be used for working with the XHR information in one of the
13555		 * callbacks
13556		 *  @type object
13557		 *  @default null
13558		 */
13559		"jqXHR": null,
13560	
13561		/**
13562		 * JSON returned from the server in the last Ajax request
13563		 *  @type object
13564		 *  @default undefined
13565		 */
13566		"json": undefined,
13567	
13568		/**
13569		 * Data submitted as part of the last Ajax request
13570		 *  @type object
13571		 *  @default undefined
13572		 */
13573		"oAjaxData": undefined,
13574	
13575		/**
13576		 * Function to get the server-side data.
13577		 * Note that this parameter will be set by the initialisation routine. To
13578		 * set a default use {@link DataTable.defaults}.
13579		 *  @type function
13580		 */
13581		"fnServerData": null,
13582	
13583		/**
13584		 * Functions which are called prior to sending an Ajax request so extra
13585		 * parameters can easily be sent to the server
13586		 *  @type array
13587		 *  @default []
13588		 */
13589		"aoServerParams": [],
13590	
13591		/**
13592		 * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
13593		 * required).
13594		 * Note that this parameter will be set by the initialisation routine. To
13595		 * set a default use {@link DataTable.defaults}.
13596		 *  @type string
13597		 */
13598		"sServerMethod": null,
13599	
13600		/**
13601		 * Format numbers for display.
13602		 * Note that this parameter will be set by the initialisation routine. To
13603		 * set a default use {@link DataTable.defaults}.
13604		 *  @type function
13605		 */
13606		"fnFormatNumber": null,
13607	
13608		/**
13609		 * List of options that can be used for the user selectable length menu.
13610		 * Note that this parameter will be set by the initialisation routine. To
13611		 * set a default use {@link DataTable.defaults}.
13612		 *  @type array
13613		 *  @default []
13614		 */
13615		"aLengthMenu": null,
13616	
13617		/**
13618		 * Counter for the draws that the table does. Also used as a tracker for
13619		 * server-side processing
13620		 *  @type int
13621		 *  @default 0
13622		 */
13623		"iDraw": 0,
13624	
13625		/**
13626		 * Indicate if a redraw is being done - useful for Ajax
13627		 *  @type boolean
13628		 *  @default false
13629		 */
13630		"bDrawing": false,
13631	
13632		/**
13633		 * Draw index (iDraw) of the last error when parsing the returned data
13634		 *  @type int
13635		 *  @default -1
13636		 */
13637		"iDrawError": -1,
13638	
13639		/**
13640		 * Paging display length
13641		 *  @type int
13642		 *  @default 10
13643		 */
13644		"_iDisplayLength": 10,
13645	
13646		/**
13647		 * Paging start point - aiDisplay index
13648		 *  @type int
13649		 *  @default 0
13650		 */
13651		"_iDisplayStart": 0,
13652	
13653		/**
13654		 * Server-side processing - number of records in the result set
13655		 * (i.e. before filtering), Use fnRecordsTotal rather than
13656		 * this property to get the value of the number of records, regardless of
13657		 * the server-side processing setting.
13658		 *  @type int
13659		 *  @default 0
13660		 *  @private
13661		 */
13662		"_iRecordsTotal": 0,
13663	
13664		/**
13665		 * Server-side processing - number of records in the current display set
13666		 * (i.e. after filtering). Use fnRecordsDisplay rather than
13667		 * this property to get the value of the number of records, regardless of
13668		 * the server-side processing setting.
13669		 *  @type boolean
13670		 *  @default 0
13671		 *  @private
13672		 */
13673		"_iRecordsDisplay": 0,
13674	
13675		/**
13676		 * The classes to use for the table
13677		 *  @type object
13678		 *  @default {}
13679		 */
vendor: 3,548 bytes, lines 13680-13835
13680		"oClasses": {},
13681	
13682		/**
13683		 * Flag attached to the settings object so you can check in the draw
13684		 * callback if filtering has been done in the draw. Deprecated in favour of
13685		 * events.
13686		 *  @type boolean
13687		 *  @default false
13688		 *  @deprecated
13689		 */
13690		"bFiltered": false,
13691	
13692		/**
13693		 * Flag attached to the settings object so you can check in the draw
13694		 * callback if sorting has been done in the draw. Deprecated in favour of
13695		 * events.
13696		 *  @type boolean
13697		 *  @default false
13698		 *  @deprecated
13699		 */
13700		"bSorted": false,
13701	
13702		/**
13703		 * Indicate that if multiple rows are in the header and there is more than
13704		 * one unique cell per column, if the top one (true) or bottom one (false)
13705		 * should be used for sorting / title by DataTables.
13706		 * Note that this parameter will be set by the initialisation routine. To
13707		 * set a default use {@link DataTable.defaults}.
13708		 *  @type boolean
13709		 */
13710		"bSortCellsTop": null,
13711	
13712		/**
13713		 * Initialisation object that is used for the table
13714		 *  @type object
13715		 *  @default null
13716		 */
13717		"oInit": null,
13718	
13719		/**
13720		 * Destroy callback functions - for plug-ins to attach themselves to the
13721		 * destroy so they can clean up markup and events.
13722		 *  @type array
13723		 *  @default []
13724		 */
13725		"aoDestroyCallback": [],
13726	
13727	
13728		/**
13729		 * Get the number of records in the current record set, before filtering
13730		 *  @type function
13731		 */
13732		"fnRecordsTotal": function ()
13733		{
13734			return _fnDataSource( this ) == 'ssp' ?
13735				this._iRecordsTotal * 1 :
13736				this.aiDisplayMaster.length;
13737		},
13738	
13739		/**
13740		 * Get the number of records in the current record set, after filtering
13741		 *  @type function
13742		 */
13743		"fnRecordsDisplay": function ()
13744		{
13745			return _fnDataSource( this ) == 'ssp' ?
13746				this._iRecordsDisplay * 1 :
13747				this.aiDisplay.length;
13748		},
13749	
13750		/**
13751		 * Get the display end point - aiDisplay index
13752		 *  @type function
13753		 */
13754		"fnDisplayEnd": function ()
13755		{
13756			var
13757				len      = this._iDisplayLength,
13758				start    = this._iDisplayStart,
13759				calc     = start + len,
13760				records  = this.aiDisplay.length,
13761				features = this.oFeatures,
13762				paginate = features.bPaginate;
13763	
13764			if ( features.bServerSide ) {
13765				return paginate === false || len === -1 ?
13766					start + records :
13767					Math.min( start+len, this._iRecordsDisplay );
13768			}
13769			else {
13770				return ! paginate || calc>records || len===-1 ?
13771					records :
13772					calc;
13773			}
13774		},
13775	
13776		/**
13777		 * The DataTables object for this table
13778		 *  @type object
13779		 *  @default null
13780		 */
13781		"oInstance": null,
13782	
13783		/**
13784		 * Unique identifier for each instance of the DataTables object. If there
13785		 * is an ID on the table node, then it takes that value, otherwise an
13786		 * incrementing internal counter is used.
13787		 *  @type string
13788		 *  @default null
13789		 */
13790		"sInstance": null,
13791	
13792		/**
13793		 * tabindex attribute value that is added to DataTables control elements, allowing
13794		 * keyboard navigation of the table and its controls.
13795		 */
13796		"iTabIndex": 0,
13797	
13798		/**
13799		 * DIV container for the footer scrolling table if scrolling
13800		 */
13801		"nScrollHead": null,
13802	
13803		/**
13804		 * DIV container for the footer scrolling table if scrolling
13805		 */
13806		"nScrollFoot": null,
13807	
13808		/**
13809		 * Last applied sort
13810		 *  @type array
13811		 *  @default []
13812		 */
13813		"aLastSort": [],
13814	
13815		/**
13816		 * Stored plug-in instances
13817		 *  @type object
13818		 *  @default {}
13819		 */
13820		"oPlugins": {},
13821	
13822		/**
13823		 * Function used to get a row's id from the row's data
13824		 *  @type function
13825		 *  @default null
13826		 */
13827		"rowIdFn": null,
13828	
13829		/**
13830		 * Data location where to store a row's id
13831		 *  @type string
13832		 *  @default null
13833		 */
13834		"rowId": null
13835	};
vendor: 16,410 bytes, lines 13836-14334
13836
13837	/**
13838	 * Extension object for DataTables that is used to provide all extension
13839	 * options.
13840	 *
13841	 * Note that the `DataTable.ext` object is available through
13842	 * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is
13843	 * also aliased to `jQuery.fn.dataTableExt` for historic reasons.
13844	 *  @namespace
13845	 *  @extends DataTable.models.ext
13846	 */
13847	
13848	
13849	/**
13850	 * DataTables extensions
13851	 * 
13852	 * This namespace acts as a collection area for plug-ins that can be used to
13853	 * extend DataTables capabilities. Indeed many of the build in methods
13854	 * use this method to provide their own capabilities (sorting methods for
13855	 * example).
13856	 *
13857	 * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy
13858	 * reasons
13859	 *
13860	 *  @namespace
13861	 */
13862	DataTable.ext = _ext = {
13863		/**
13864		 * Buttons. For use with the Buttons extension for DataTables. This is
13865		 * defined here so other extensions can define buttons regardless of load
13866		 * order. It is _not_ used by DataTables core.
13867		 *
13868		 *  @type object
13869		 *  @default {}
13870		 */
13871		buttons: {},
13872	
13873	
13874		/**
13875		 * Element class names
13876		 *
13877		 *  @type object
13878		 *  @default {}
13879		 */
13880		classes: {},
13881	
13882	
13883		/**
13884		 * DataTables build type (expanded by the download builder)
13885		 *
13886		 *  @type string
13887		 */
13888		builder: "-source-",
13889	
13890	
13891		/**
13892		 * Error reporting.
13893		 * 
13894		 * How should DataTables report an error. Can take the value 'alert',
13895		 * 'throw', 'none' or a function.
13896		 *
13897		 *  @type string|function
13898		 *  @default alert
13899		 */
13900		errMode: "alert",
13901	
13902	
13903		/**
13904		 * Feature plug-ins.
13905		 * 
13906		 * This is an array of objects which describe the feature plug-ins that are
13907		 * available to DataTables. These feature plug-ins are then available for
13908		 * use through the `dom` initialisation option.
13909		 * 
13910		 * Each feature plug-in is described by an object which must have the
13911		 * following properties:
13912		 * 
13913		 * * `fnInit` - function that is used to initialise the plug-in,
13914		 * * `cFeature` - a character so the feature can be enabled by the `dom`
13915		 *   instillation option. This is case sensitive.
13916		 *
13917		 * The `fnInit` function has the following input parameters:
13918		 *
13919		 * 1. `{object}` DataTables settings object: see
13920		 *    {@link DataTable.models.oSettings}
13921		 *
13922		 * And the following return is expected:
13923		 * 
13924		 * * {node|null} The element which contains your feature. Note that the
13925		 *   return may also be void if your plug-in does not require to inject any
13926		 *   DOM elements into DataTables control (`dom`) - for example this might
13927		 *   be useful when developing a plug-in which allows table control via
13928		 *   keyboard entry
13929		 *
13930		 *  @type array
13931		 *
13932		 *  @example
13933		 *    $.fn.dataTable.ext.features.push( {
13934		 *      "fnInit": function( oSettings ) {
13935		 *        return new TableTools( { "oDTSettings": oSettings } );
13936		 *      },
13937		 *      "cFeature": "T"
13938		 *    } );
13939		 */
13940		feature: [],
13941	
13942	
13943		/**
13944		 * Row searching.
13945		 * 
13946		 * This method of searching is complimentary to the default type based
13947		 * searching, and a lot more comprehensive as it allows you complete control
13948		 * over the searching logic. Each element in this array is a function
13949		 * (parameters described below) that is called for every row in the table,
13950		 * and your logic decides if it should be included in the searching data set
13951		 * or not.
13952		 *
13953		 * Searching functions have the following input parameters:
13954		 *
13955		 * 1. `{object}` DataTables settings object: see
13956		 *    {@link DataTable.models.oSettings}
13957		 * 2. `{array|object}` Data for the row to be processed (same as the
13958		 *    original format that was passed in as the data source, or an array
13959		 *    from a DOM data source
13960		 * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which
13961		 *    can be useful to retrieve the `TR` element if you need DOM interaction.
13962		 *
13963		 * And the following return is expected:
13964		 *
13965		 * * {boolean} Include the row in the searched result set (true) or not
13966		 *   (false)
13967		 *
13968		 * Note that as with the main search ability in DataTables, technically this
13969		 * is "filtering", since it is subtractive. However, for consistency in
13970		 * naming we call it searching here.
13971		 *
13972		 *  @type array
13973		 *  @default []
13974		 *
13975		 *  @example
13976		 *    // The following example shows custom search being applied to the
13977		 *    // fourth column (i.e. the data[3] index) based on two input values
13978		 *    // from the end-user, matching the data in a certain range.
13979		 *    $.fn.dataTable.ext.search.push(
13980		 *      function( settings, data, dataIndex ) {
13981		 *        var min = document.getElementById('min').value * 1;
13982		 *        var max = document.getElementById('max').value * 1;
13983		 *        var version = data[3] == "-" ? 0 : data[3]*1;
13984		 *
13985		 *        if ( min == "" && max == "" ) {
13986		 *          return true;
13987		 *        }
13988		 *        else if ( min == "" && version < max ) {
13989		 *          return true;
13990		 *        }
13991		 *        else if ( min < version && "" == max ) {
13992		 *          return true;
13993		 *        }
13994		 *        else if ( min < version && version < max ) {
13995		 *          return true;
13996		 *        }
13997		 *        return false;
13998		 *      }
13999		 *    );
14000		 */
14001		search: [],
14002	
14003	
14004		/**
14005		 * Selector extensions
14006		 *
14007		 * The `selector` option can be used to extend the options available for the
14008		 * selector modifier options (`selector-modifier` object data type) that
14009		 * each of the three built in selector types offer (row, column and cell +
14010		 * their plural counterparts). For example the Select extension uses this
14011		 * mechanism to provide an option to select only rows, columns and cells
14012		 * that have been marked as selected by the end user (`{selected: true}`),
14013		 * which can be used in conjunction with the existing built in selector
14014		 * options.
14015		 *
14016		 * Each property is an array to which functions can be pushed. The functions
14017		 * take three attributes:
14018		 *
14019		 * * Settings object for the host table
14020		 * * Options object (`selector-modifier` object type)
14021		 * * Array of selected item indexes
14022		 *
14023		 * The return is an array of the resulting item indexes after the custom
14024		 * selector has been applied.
14025		 *
14026		 *  @type object
14027		 */
14028		selector: {
14029			cell: [],
14030			column: [],
14031			row: []
14032		},
14033	
14034	
14035		/**
14036		 * Internal functions, exposed for used in plug-ins.
14037		 * 
14038		 * Please note that you should not need to use the internal methods for
14039		 * anything other than a plug-in (and even then, try to avoid if possible).
14040		 * The internal function may change between releases.
14041		 *
14042		 *  @type object
14043		 *  @default {}
14044		 */
14045		internal: {},
14046	
14047	
14048		/**
14049		 * Legacy configuration options. Enable and disable legacy options that
14050		 * are available in DataTables.
14051		 *
14052		 *  @type object
14053		 */
14054		legacy: {
14055			/**
14056			 * Enable / disable DataTables 1.9 compatible server-side processing
14057			 * requests
14058			 *
14059			 *  @type boolean
14060			 *  @default null
14061			 */
14062			ajax: null
14063		},
14064	
14065	
14066		/**
14067		 * Pagination plug-in methods.
14068		 * 
14069		 * Each entry in this object is a function and defines which buttons should
14070		 * be shown by the pagination rendering method that is used for the table:
14071		 * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the
14072		 * buttons are displayed in the document, while the functions here tell it
14073		 * what buttons to display. This is done by returning an array of button
14074		 * descriptions (what each button will do).
14075		 *
14076		 * Pagination types (the four built in options and any additional plug-in
14077		 * options defined here) can be used through the `paginationType`
14078		 * initialisation parameter.
14079		 *
14080		 * The functions defined take two parameters:
14081		 *
14082		 * 1. `{int} page` The current page index
14083		 * 2. `{int} pages` The number of pages in the table
14084		 *
14085		 * Each function is expected to return an array where each element of the
14086		 * array can be one of:
14087		 *
14088		 * * `first` - Jump to first page when activated
14089		 * * `last` - Jump to last page when activated
14090		 * * `previous` - Show previous page when activated
14091		 * * `next` - Show next page when activated
14092		 * * `{int}` - Show page of the index given
14093		 * * `{array}` - A nested array containing the above elements to add a
14094		 *   containing 'DIV' element (might be useful for styling).
14095		 *
14096		 * Note that DataTables v1.9- used this object slightly differently whereby
14097		 * an object with two functions would be defined for each plug-in. That
14098		 * ability is still supported by DataTables 1.10+ to provide backwards
14099		 * compatibility, but this option of use is now decremented and no longer
14100		 * documented in DataTables 1.10+.
14101		 *
14102		 *  @type object
14103		 *  @default {}
14104		 *
14105		 *  @example
14106		 *    // Show previous, next and current page buttons only
14107		 *    $.fn.dataTableExt.oPagination.current = function ( page, pages ) {
14108		 *      return [ 'previous', page, 'next' ];
14109		 *    };
14110		 */
14111		pager: {},
14112	
14113	
14114		renderer: {
14115			pageButton: {},
14116			header: {}
14117		},
14118	
14119	
14120		/**
14121		 * Ordering plug-ins - custom data source
14122		 * 
14123		 * The extension options for ordering of data available here is complimentary
14124		 * to the default type based ordering that DataTables typically uses. It
14125		 * allows much greater control over the the data that is being used to
14126		 * order a column, but is necessarily therefore more complex.
14127		 * 
14128		 * This type of ordering is useful if you want to do ordering based on data
14129		 * live from the DOM (for example the contents of an 'input' element) rather
14130		 * than just the static string that DataTables knows of.
14131		 * 
14132		 * The way these plug-ins work is that you create an array of the values you
14133		 * wish to be ordering for the column in question and then return that
14134		 * array. The data in the array much be in the index order of the rows in
14135		 * the table (not the currently ordering order!). Which order data gathering
14136		 * function is run here depends on the `dt-init columns.orderDataType`
14137		 * parameter that is used for the column (if any).
14138		 *
14139		 * The functions defined take two parameters:
14140		 *
14141		 * 1. `{object}` DataTables settings object: see
14142		 *    {@link DataTable.models.oSettings}
14143		 * 2. `{int}` Target column index
14144		 *
14145		 * Each function is expected to return an array:
14146		 *
14147		 * * `{array}` Data for the column to be ordering upon
14148		 *
14149		 *  @type array
14150		 *
14151		 *  @example
14152		 *    // Ordering using `input` node values
14153		 *    $.fn.dataTable.ext.order['dom-text'] = function  ( settings, col )
14154		 *    {
14155		 *      return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
14156		 *        return $('input', td).val();
14157		 *      } );
14158		 *    }
14159		 */
14160		order: {},
14161	
14162	
14163		/**
14164		 * Type based plug-ins.
14165		 *
14166		 * Each column in DataTables has a type assigned to it, either by automatic
14167		 * detection or by direct assignment using the `type` option for the column.
14168		 * The type of a column will effect how it is ordering and search (plug-ins
14169		 * can also make use of the column type if required).
14170		 *
14171		 * @namespace
14172		 */
14173		type: {
14174			/**
14175			 * Type detection functions.
14176			 *
14177			 * The functions defined in this object are used to automatically detect
14178			 * a column's type, making initialisation of DataTables super easy, even
14179			 * when complex data is in the table.
14180			 *
14181			 * The functions defined take two parameters:
14182			 *
14183		     *  1. `{*}` Data from the column cell to be analysed
14184		     *  2. `{settings}` DataTables settings object. This can be used to
14185		     *     perform context specific type detection - for example detection
14186		     *     based on language settings such as using a comma for a decimal
14187		     *     place. Generally speaking the options from the settings will not
14188		     *     be required
14189			 *
14190			 * Each function is expected to return:
14191			 *
14192			 * * `{string|null}` Data type detected, or null if unknown (and thus
14193			 *   pass it on to the other type detection functions.
14194			 *
14195			 *  @type array
14196			 *
14197			 *  @example
14198			 *    // Currency type detection plug-in:
14199			 *    $.fn.dataTable.ext.type.detect.push(
14200			 *      function ( data, settings ) {
14201			 *        // Check the numeric part
14202			 *        if ( ! data.substring(1).match(/[0-9]/) ) {
14203			 *          return null;
14204			 *        }
14205			 *
14206			 *        // Check prefixed by currency
14207			 *        if ( data.charAt(0) == '$' || data.charAt(0) == '&pound;' ) {
14208			 *          return 'currency';
14209			 *        }
14210			 *        return null;
14211			 *      }
14212			 *    );
14213			 */
14214			detect: [],
14215	
14216	
14217			/**
14218			 * Type based search formatting.
14219			 *
14220			 * The type based searching functions can be used to pre-format the
14221			 * data to be search on. For example, it can be used to strip HTML
14222			 * tags or to de-format telephone numbers for numeric only searching.
14223			 *
14224			 * Note that is a search is not defined for a column of a given type,
14225			 * no search formatting will be performed.
14226			 * 
14227			 * Pre-processing of searching data plug-ins - When you assign the sType
14228			 * for a column (or have it automatically detected for you by DataTables
14229			 * or a type detection plug-in), you will typically be using this for
14230			 * custom sorting, but it can also be used to provide custom searching
14231			 * by allowing you to pre-processing the data and returning the data in
14232			 * the format that should be searched upon. This is done by adding
14233			 * functions this object with a parameter name which matches the sType
14234			 * for that target column. This is the corollary of <i>afnSortData</i>
14235			 * for searching data.
14236			 *
14237			 * The functions defined take a single parameter:
14238			 *
14239		     *  1. `{*}` Data from the column cell to be prepared for searching
14240			 *
14241			 * Each function is expected to return:
14242			 *
14243			 * * `{string|null}` Formatted string that will be used for the searching.
14244			 *
14245			 *  @type object
14246			 *  @default {}
14247			 *
14248			 *  @example
14249			 *    $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) {
14250			 *      return d.replace(/\n/g," ").replace( /<.*?>/g, "" );
14251			 *    }
14252			 */
14253			search: {},
14254	
14255	
14256			/**
14257			 * Type based ordering.
14258			 *
14259			 * The column type tells DataTables what ordering to apply to the table
14260			 * when a column is sorted upon. The order for each type that is defined,
14261			 * is defined by the functions available in this object.
14262			 *
14263			 * Each ordering option can be described by three properties added to
14264			 * this object:
14265			 *
14266			 * * `{type}-pre` - Pre-formatting function
14267			 * * `{type}-asc` - Ascending order function
14268			 * * `{type}-desc` - Descending order function
14269			 *
14270			 * All three can be used together, only `{type}-pre` or only
14271			 * `{type}-asc` and `{type}-desc` together. It is generally recommended
14272			 * that only `{type}-pre` is used, as this provides the optimal
14273			 * implementation in terms of speed, although the others are provided
14274			 * for compatibility with existing Javascript sort functions.
14275			 *
14276			 * `{type}-pre`: Functions defined take a single parameter:
14277			 *
14278		     *  1. `{*}` Data from the column cell to be prepared for ordering
14279			 *
14280			 * And return:
14281			 *
14282			 * * `{*}` Data to be sorted upon
14283			 *
14284			 * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort
14285			 * functions, taking two parameters:
14286			 *
14287		     *  1. `{*}` Data to compare to the second parameter
14288		     *  2. `{*}` Data to compare to the first parameter
14289			 *
14290			 * And returning:
14291			 *
14292			 * * `{*}` Ordering match: <0 if first parameter should be sorted lower
14293			 *   than the second parameter, ===0 if the two parameters are equal and
14294			 *   >0 if the first parameter should be sorted height than the second
14295			 *   parameter.
14296			 * 
14297			 *  @type object
14298			 *  @default {}
14299			 *
14300			 *  @example
14301			 *    // Numeric ordering of formatted numbers with a pre-formatter
14302			 *    $.extend( $.fn.dataTable.ext.type.order, {
14303			 *      "string-pre": function(x) {
14304			 *        a = (a === "-" || a === "") ? 0 : a.replace( /[^\d\-\.]/g, "" );
14305			 *        return parseFloat( a );
14306			 *      }
14307			 *    } );
14308			 *
14309			 *  @example
14310			 *    // Case-sensitive string ordering, with no pre-formatting method
14311			 *    $.extend( $.fn.dataTable.ext.order, {
14312			 *      "string-case-asc": function(x,y) {
14313			 *        return ((x < y) ? -1 : ((x > y) ? 1 : 0));
14314			 *      },
14315			 *      "string-case-desc": function(x,y) {
14316			 *        return ((x < y) ? 1 : ((x > y) ? -1 : 0));
14317			 *      }
14318			 *    } );
14319			 */
14320			order: {}
14321		},
14322	
14323		/**
14324		 * Unique DataTables instance counter
14325		 *
14326		 * @type int
14327		 * @private
14328		 */
14329		_unique: 0,
14330	
14331	
14332		//
14333		// Depreciated
14334		// The following properties are retained for backwards compatib
vendor: 3,168 bytes, lines 14334-14471
14334lity only.
14335		// The should not be used in new projects and will be removed in a future
14336		// version
14337		//
14338	
14339		/**
14340		 * Version check function.
14341		 *  @type function
14342		 *  @depreciated Since 1.10
14343		 */
14344		fnVersionCheck: DataTable.fnVersionCheck,
14345	
14346	
14347		/**
14348		 * Index for what 'this' index API functions should use
14349		 *  @type int
14350		 *  @deprecated Since v1.10
14351		 */
14352		iApiIndex: 0,
14353	
14354	
14355		/**
14356		 * jQuery UI class container
14357		 *  @type object
14358		 *  @deprecated Since v1.10
14359		 */
14360		oJUIClasses: {},
14361	
14362	
14363		/**
14364		 * Software version
14365		 *  @type string
14366		 *  @deprecated Since v1.10
14367		 */
14368		sVersion: DataTable.version
14369	};
14370	
14371	
14372	//
14373	// Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts
14374	//
14375	$.extend( _ext, {
14376		afnFiltering: _ext.search,
14377		aTypes:       _ext.type.detect,
14378		ofnSearch:    _ext.type.search,
14379		oSort:        _ext.type.order,
14380		afnSortData:  _ext.order,
14381		aoFeatures:   _ext.feature,
14382		oApi:         _ext.internal,
14383		oStdClasses:  _ext.classes,
14384		oPagination:  _ext.pager
14385	} );
14386	
14387	
14388	$.extend( DataTable.ext.classes, {
14389		"sTable": "dataTable",
14390		"sNoFooter": "no-footer",
14391	
14392		/* Paging buttons */
14393		"sPageButton": "paginate_button",
14394		"sPageButtonActive": "current",
14395		"sPageButtonDisabled": "disabled",
14396	
14397		/* Striping classes */
14398		"sStripeOdd": "odd",
14399		"sStripeEven": "even",
14400	
14401		/* Empty row */
14402		"sRowEmpty": "dataTables_empty",
14403	
14404		/* Features */
14405		"sWrapper": "dataTables_wrapper",
14406		"sFilter": "dataTables_filter",
14407		"sInfo": "dataTables_info",
14408		"sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
14409		"sLength": "dataTables_length",
14410		"sProcessing": "dataTables_processing",
14411	
14412		/* Sorting */
14413		"sSortAsc": "sorting_asc",
14414		"sSortDesc": "sorting_desc",
14415		"sSortable": "sorting", /* Sortable in both directions */
14416		"sSortableAsc": "sorting_asc_disabled",
14417		"sSortableDesc": "sorting_desc_disabled",
14418		"sSortableNone": "sorting_disabled",
14419		"sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
14420	
14421		/* Filtering */
14422		"sFilterInput": "",
14423	
14424		/* Page length */
14425		"sLengthSelect": "",
14426	
14427		/* Scrolling */
14428		"sScrollWrapper": "dataTables_scroll",
14429		"sScrollHead": "dataTables_scrollHead",
14430		"sScrollHeadInner": "dataTables_scrollHeadInner",
14431		"sScrollBody": "dataTables_scrollBody",
14432		"sScrollFoot": "dataTables_scrollFoot",
14433		"sScrollFootInner": "dataTables_scrollFootInner",
14434	
14435		/* Misc */
14436		"sHeaderTH": "",
14437		"sFooterTH": "",
14438	
14439		// Deprecated
14440		"sSortJUIAsc": "",
14441		"sSortJUIDesc": "",
14442		"sSortJUI": "",
14443		"sSortJUIAscAllowed": "",
14444		"sSortJUIDescAllowed": "",
14445		"sSortJUIWrapper": "",
14446		"sSortIcon": "",
14447		"sJUIHeader": "",
14448		"sJUIFooter": ""
14449	} );
14450	
14451	
14452	var extPagination = DataTable.ext.pager;
14453	
14454	function _numbers ( page, pages ) {
14455		var
14456			numbers = [],
14457			buttons = extPagination.numbers_length,
14458			half = Math.floor( buttons / 2 ),
14459			i = 1;
14460	
14461		if ( pages <= buttons ) {
14462			numbers = _range( 0, pages );
14463		}
14464		else if ( page <= half ) {
14465			numbers = _range( 0, buttons-2 );
14466			numbers.push( 'ellipsis' );
14467			numbers.push( pages-1 );
14468		}
14469		else if ( page >= pages - 1 - half ) {
14470			numbers = _range( pages-(buttons-2), pages );
14471			numbers.splice( 0, 0, 'ellipsis' );
14471 // no unshift in ie6
14472			numbers.splice( 0, 0, 0 );
14473		}
14474		else {
14475			numbers = _range( page-half+2, page+half-1 );
14476			numbers.push( 'ellipsis' );
14477			numbers.push( pages-1 );
14478			numbers.splice( 0, 0, 'ellipsis' );
14479			numbers.splice( 0, 0, 0 );
14480		}
14481	
14482		numbers.DT_el = 'span';
14483		return numbers;
14484	}
14485	
14486	
14487	$.extend( extPagination, {
14488		simple: function ( page, pages ) {
14489			return [ 'previous', 'next' ];
14490		},
14491	
14492		full: function ( page, pages ) {
14493			return [  'first', 'previous', 'next', 'last' ];
14494		},
14495	
14496		numbers: function ( page, pages ) {
14497			return [ _numbers(page, pages) ];
14498		},
14499	
14500		simple_numbers: function ( page, pages ) {
14501			return [ 'previous', _numbers(page, pages), 'next' ];
14502		},
14503	
14504		full_numbers: function ( page, pages ) {
14505			return [ 'first', 'previous', _numbers(page, pages), 'next', 'last' ];
14506		},
14507		
14508		first_last_numbers: function (page, pages) {
14509	 		return ['first', _numbers(page, pages), 'last'];
14510	 	},
14511	
14512		// For testing and plug-ins to use
14513		_numbers: _numbers,
14514	
14515		// Number of number buttons (including ellipsis) to show. _Must be odd!_
14516		numbers_length: 7
14517	} );
14518	
14519	
14520	$.extend( true, DataTable.ext.renderer, {
14521		pageButton: {
14522			_: function ( settings, host, idx, buttons, page, pages ) {
14523				var classes = settings.oClasses;
14524				var lang = settings.oLanguage.oPaginate;
14525				var aria = settings.oLanguage.oAria.paginate || {};
14526				var btnDisplay, btnClass, counter=0;
14527	
14528				var attach = function( container, buttons ) {
14529					var i, ien, node, button;
14530					var clickHandler = function ( e ) {
14531						_fnPageChange( settings, e.data.action, true );
14532					};
14533	
14534					for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
14535						button = buttons[i];
14536	
14537						if ( $.isArray( button ) ) {
14538							var inner = $( '<'+(button.DT_el || 'div')+'/>' )
14539								.appendTo( container );
14540							attach( inner, button );
14541						}
14542						else {
14543							btnDisplay = null;
14544							btnClass = '';
14545	
14546							switch ( button ) {
14547								case 'ellipsis':
14548									container.append('<span class="ellipsis">&#x2026;</span>');
14549									break;
14550	
14551								case 'first':
14552									btnDisplay = lang.sFirst;
14553									btnClass = button + (page > 0 ?
14554										'' : ' '+classes.sPageButtonDisabled);
14555									break;
14556	
14557								case 'previous':
14558									btnDisplay = lang.sPrevious;
14559									btnClass = button + (page > 0 ?
14560										'' : ' '+classes.sPageButtonDisabled);
14561									break;
14562	
14563								case 'next':
14564									btnDisplay = lang.sNext;
14565									btnClass = button + (page < pages-1 ?
14566										'' : ' '+classes.sPageButtonDisabled);
14567									break;
14568	
14569								case 'last':
14570									btnDisplay = lang.sLast;
14571									btnClass = button + (page < pages-1 ?
14572										'' : ' '+classes.sPageButtonDisabled);
14573									break;
14574	
14575								default:
14576									btnDisplay = button + 1;
14577									btnClass = page === button ?
14578										classes.sPageButtonActive : '';
14579									break;
14580							}
14581	
14582							if ( btnDisplay !== null ) {
14583								node = $('<a>', {
14584										'class': classes.sPageButton+' '+btnClass,
14585										'aria-controls': settings.sTableId,
14586										'aria-label': aria[ button ],
14587										'data-dt-idx': counter,
14588										'tabindex': settings.iTabIndex,
14589										'id': idx === 0 && typeof button === 'string' ?
14590											settings.sTableId +'_'+ button :
14591											null
14592									} )
14593									.html( btnDisplay )
14594									.appendTo( container );
14595	
14596								_fnBindAction(
14597									node, {action: button}, clickHandler
14598								);
14599	
14600								counter++;
14601							}
14602						}
14603					}
14604				};
14605	
14606				// IE9 throws an 'unknown error' if document.activeElement is used
14607				// inside an iframe or frame. Try / catch the error. Not good for
14608				// accessibility, but neither are frames.
14609				var activeEl;
14610	
14611				try {
14612					// Because this approach is destroying and recreating the paging
14613					// elements, focus is lost on the select button which is bad for
14614					// accessibility. So we want to restore focus once the draw has
14615					// completed
14616					activeEl = $(host).find(document.activeElement).data('dt-idx');
14617				}
14618				catch (e) {}
14619	
14620				attach( $(host).empty(), buttons );
14621	
14622				if ( activeEl !== undefined ) {
14623					$(host).find( '[data-dt-idx='+activeEl+']' ).focus();
14624				}
14625			}
14626		}
14627	} );
14628	
14629	
14630	
14631	// Built in type detection. See model.ext.aTypes for information about
14632	// what is required from this methods.
14633	$.extend( DataTable.ext.type.detect, [
vendor: 18,244 bytes, lines 14634-15231
14634		// Plain numbers - first since V8 detects some plain numbers as dates
14635		// e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...).
14636		function ( d, settings )
14637		{
14638			var decimal = settings.oLanguage.sDecimal;
14639			return _isNumber( d, decimal ) ? 'num'+decimal : null;
14640		},
14641	
14642		// Dates (only those recognised by the browser's Date.parse)
14643		function ( d, settings )
14644		{
14645			// V8 tries _very_ hard to make a string passed into `Date.parse()`
14646			// valid, so we need to use a regex to restrict date formats. Use a
14647			// plug-in for anything other than ISO8601 style strings
14648			if ( d && !(d instanceof Date) && ! _re_date.test(d) ) {
14649				return null;
14650			}
14651			var parsed = Date.parse(d);
14652			return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null;
14653		},
14654	
14655		// Formatted numbers
14656		function ( d, settings )
14657		{
14658			var decimal = settings.oLanguage.sDecimal;
14659			return _isNumber( d, decimal, true ) ? 'num-fmt'+decimal : null;
14660		},
14661	
14662		// HTML numeric
14663		function ( d, settings )
14664		{
14665			var decimal = settings.oLanguage.sDecimal;
14666			return _htmlNumeric( d, decimal ) ? 'html-num'+decimal : null;
14667		},
14668	
14669		// HTML numeric, formatted
14670		function ( d, settings )
14671		{
14672			var decimal = settings.oLanguage.sDecimal;
14673			return _htmlNumeric( d, decimal, true ) ? 'html-num-fmt'+decimal : null;
14674		},
14675	
14676		// HTML (this is strict checking - there must be html)
14677		function ( d, settings )
14678		{
14679			return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ?
14680				'html' : null;
14681		}
14682	] );
14683	
14684	
14685	
14686	// Filter formatting functions. See model.ext.ofnSearch for information about
14687	// what is required from these methods.
14688	// 
14689	// Note that additional search methods are added for the html numbers and
14690	// html formatted numbers by `_addNumericSort()` when we know what the decimal
14691	// place is
14692	
14693	
14694	$.extend( DataTable.ext.type.search, {
14695		html: function ( data ) {
14696			return _empty(data) ?
14697				data :
14698				typeof data === 'string' ?
14699					data
14700						.replace( _re_new_lines, " " )
14701						.replace( _re_html, "" ) :
14702					'';
14703		},
14704	
14705		string: function ( data ) {
14706			return _empty(data) ?
14707				data :
14708				typeof data === 'string' ?
14709					data.replace( _re_new_lines, " " ) :
14710					data;
14711		}
14712	} );
14713	
14714	
14715	
14716	var __numericReplace = function ( d, decimalPlace, re1, re2 ) {
14717		if ( d !== 0 && (!d || d === '-') ) {
14718			return -Infinity;
14719		}
14720	
14721		// If a decimal place other than `.` is used, it needs to be given to the
14722		// function so we can detect it and replace with a `.` which is the only
14723		// decimal place Javascript recognises - it is not locale aware.
14724		if ( decimalPlace ) {
14725			d = _numToDecimal( d, decimalPlace );
14726		}
14727	
14728		if ( d.replace ) {
14729			if ( re1 ) {
14730				d = d.replace( re1, '' );
14731			}
14732	
14733			if ( re2 ) {
14734				d = d.replace( re2, '' );
14735			}
14736		}
14737	
14738		return d * 1;
14739	};
14740	
14741	
14742	// Add the numeric 'deformatting' functions for sorting and search. This is done
14743	// in a function to provide an easy ability for the language options to add
14744	// additional methods if a non-period decimal place is used.
14745	function _addNumericSort ( decimalPlace ) {
14746		$.each(
14747			{
14748				// Plain numbers
14749				"num": function ( d ) {
14750					return __numericReplace( d, decimalPlace );
14751				},
14752	
14753				// Formatted numbers
14754				"num-fmt": function ( d ) {
14755					return __numericReplace( d, decimalPlace, _re_formatted_numeric );
14756				},
14757	
14758				// HTML numeric
14759				"html-num": function ( d ) {
14760					return __numericReplace( d, decimalPlace, _re_html );
14761				},
14762	
14763				// HTML numeric, formatted
14764				"html-num-fmt": function ( d ) {
14765					return __numericReplace( d, decimalPlace, _re_html, _re_formatted_numeric );
14766				}
14767			},
14768			function ( key, fn ) {
14769				// Add the ordering method
14770				_ext.type.order[ key+decimalPlace+'-pre' ] = fn;
14771	
14772				// For HTML types add a search formatter that will strip the HTML
14773				if ( key.match(/^html\-/) ) {
14774					_ext.type.search[ key+decimalPlace ] = _ext.type.search.html;
14775				}
14776			}
14777		);
14778	}
14779	
14780	
14781	// Default sort methods
14782	$.extend( _ext.type.order, {
14783		// Dates
14784		"date-pre": function ( d ) {
14785			var ts = Date.parse( d );
14786			return isNaN(ts) ? -Infinity : ts;
14787		},
14788	
14789		// html
14790		"html-pre": function ( a ) {
14791			return _empty(a) ?
14792				'' :
14793				a.replace ?
14794					a.replace( /<.*?>/g, "" ).toLowerCase() :
14795					a+'';
14796		},
14797	
14798		// string
14799		"string-pre": function ( a ) {
14800			// This is a little complex, but faster than always calling toString,
14801			// http://jsperf.com/tostring-v-check
14802			return _empty(a) ?
14803				'' :
14804				typeof a === 'string' ?
14805					a.toLowerCase() :
14806					! a.toString ?
14807						'' :
14808						a.toString();
14809		},
14810	
14811		// string-asc and -desc are retained only for compatibility with the old
14812		// sort methods
14813		"string-asc": function ( x, y ) {
14814			return ((x < y) ? -1 : ((x > y) ? 1 : 0));
14815		},
14816	
14817		"string-desc": function ( x, y ) {
14818			return ((x < y) ? 1 : ((x > y) ? -1 : 0));
14819		}
14820	} );
14821	
14822	
14823	// Numeric sorting types - order doesn't matter here
14824	_addNumericSort( '' );
14825	
14826	
14827	$.extend( true, DataTable.ext.renderer, {
14828		header: {
14829			_: function ( settings, cell, column, classes ) {
14830				// No additional mark-up required
14831				// Attach a sort listener to update on sort - note that using the
14832				// `DT` namespace will allow the event to be removed automatically
14833				// on destroy, while the `dt` namespaced event is the one we are
14834				// listening for
14835				$(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
14836					if ( settings !== ctx ) { // need to check this this is the host
14837						return;               // table, not a nested one
14838					}
14839	
14840					var colIdx = column.idx;
14841	
14842					cell
14843						.removeClass(
14844							column.sSortingClass +' '+
14845							classes.sSortAsc +' '+
14846							classes.sSortDesc
14847						)
14848						.addClass( columns[ colIdx ] == 'asc' ?
14849							classes.sSortAsc : columns[ colIdx ] == 'desc' ?
14850								classes.sSortDesc :
14851								column.sSortingClass
14852						);
14853				} );
14854			},
14855	
14856			jqueryui: function ( settings, cell, column, classes ) {
14857				$('<div/>')
14858					.addClass( classes.sSortJUIWrapper )
14859					.append( cell.contents() )
14860					.append( $('<span/>')
14861						.addClass( classes.sSortIcon+' '+column.sSortingClassJUI )
14862					)
14863					.appendTo( cell );
14864	
14865				// Attach a sort listener to update on sort
14866				$(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
14867					if ( settings !== ctx ) {
14868						return;
14869					}
14870	
14871					var colIdx = column.idx;
14872	
14873					cell
14874						.removeClass( classes.sSortAsc +" "+classes.sSortDesc )
14875						.addClass( columns[ colIdx ] == 'asc' ?
14876							classes.sSortAsc : columns[ colIdx ] == 'desc' ?
14877								classes.sSortDesc :
14878								column.sSortingClass
14879						);
14880	
14881					cell
14882						.find( 'span.'+classes.sSortIcon )
14883						.removeClass(
14884							classes.sSortJUIAsc +" "+
14885							classes.sSortJUIDesc +" "+
14886							classes.sSortJUI +" "+
14887							classes.sSortJUIAscAllowed +" "+
14888							classes.sSortJUIDescAllowed
14889						)
14890						.addClass( columns[ colIdx ] == 'asc' ?
14891							classes.sSortJUIAsc : columns[ colIdx ] == 'desc' ?
14892								classes.sSortJUIDesc :
14893								column.sSortingClassJUI
14894						);
14895				} );
14896			}
14897		}
14898	} );
14899	
14900	/*
14901	 * Public helper functions. These aren't used internally by DataTables, or
14902	 * called by any of the options passed into DataTables, but they can be used
14903	 * externally by developers working with DataTables. They are helper functions
14904	 * to make working with DataTables a little bit easier.
14905	 */
14906	
14907	var __htmlEscapeEntities = function ( d ) {
14908		return typeof d === 'string' ?
14909			d.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;') :
14910			d;
14911	};
14912	
14913	/**
14914	 * Helpers for `columns.render`.
14915	 *
14916	 * The options defined here can be used with the `columns.render` initialisation
14917	 * option to provide a display renderer. The following functions are defined:
14918	 *
14919	 * * `number` - Will format numeric data (defined by `columns.data`) for
14920	 *   display, retaining the original unformatted data for sorting and filtering.
14921	 *   It takes 5 parameters:
14922	 *   * `string` - Thousands grouping separator
14923	 *   * `string` - Decimal point indicator
14924	 *   * `integer` - Number of decimal points to show
14925	 *   * `string` (optional) - Prefix.
14926	 *   * `string` (optional) - Postfix (/suffix).
14927	 * * `text` - Escape HTML to help prevent XSS attacks. It has no optional
14928	 *   parameters.
14929	 *
14930	 * @example
14931	 *   // Column definition using the number renderer
14932	 *   {
14933	 *     data: "salary",
14934	 *     render: $.fn.dataTable.render.number( '\'', '.', 0, '$' )
14935	 *   }
14936	 *
14937	 * @namespace
14938	 */
14939	DataTable.render = {
14940		number: function ( thousands, decimal, precision, prefix, postfix ) {
14941			return {
14942				display: function ( d ) {
14943					if ( typeof d !== 'number' && typeof d !== 'string' ) {
14944						return d;
14945					}
14946	
14947					var negative = d < 0 ? '-' : '';
14948					var flo = parseFloat( d );
14949	
14950					// If NaN then there isn't much formatting that we can do - just
14951					// return immediately, escaping any HTML (this was supposed to
14952					// be a number after all)
14953					if ( isNaN( flo ) ) {
14954						return __htmlEscapeEntities( d );
14955					}
14956	
14957					flo = flo.toFixed( precision );
14958					d = Math.abs( flo );
14959	
14960					var intPart = parseInt( d, 10 );
14961					var floatPart = precision ?
14962						decimal+(d - intPart).toFixed( precision ).substring( 2 ):
14963						'';
14964	
14965					return negative + (prefix||'') +
14966						intPart.toString().replace(
14967							/\B(?=(\d{3})+(?!\d))/g, thousands
14968						) +
14969						floatPart +
14970						(postfix||'');
14971				}
14972			};
14973		},
14974	
14975		text: function () {
14976			return {
14977				display: __htmlEscapeEntities,
14978				filter: __htmlEscapeEntities
14979			};
14980		}
14981	};
14982	
14983	
14984	/*
14985	 * This is really a good bit rubbish this method of exposing the internal methods
14986	 * publicly... - To be fixed in 2.0 using methods on the prototype
14987	 */
14988	
14989	
14990	/**
14991	 * Create a wrapper function for exporting an internal functions to an external API.
14992	 *  @param {string} fn API function name
14993	 *  @returns {function} wrapped function
14994	 *  @memberof DataTable#internal
14995	 */
14996	function _fnExternApiFunc (fn)
14997	{
14998		return function() {
14999			var args = [_fnSettingsFromNode( this[DataTable.ext.iApiIndex] )].concat(
15000				Array.prototype.slice.call(arguments)
15001			);
15002			return DataTable.ext.internal[fn].apply( this, args );
15003		};
15004	}
15005	
15006	
15007	/**
15008	 * Reference to internal functions for use by plug-in developers. Note that
15009	 * these methods are references to internal functions and are considered to be
15010	 * private. If you use these methods, be aware that they are liable to change
15011	 * between versions.
15012	 *  @namespace
15013	 */
15014	$.extend( DataTable.ext.internal, {
15015		_fnExternApiFunc: _fnExternApiFunc,
15016		_fnBuildAjax: _fnBuildAjax,
15017		_fnAjaxUpdate: _fnAjaxUpdate,
15018		_fnAjaxParameters: _fnAjaxParameters,
15019		_fnAjaxUpdateDraw: _fnAjaxUpdateDraw,
15020		_fnAjaxDataSrc: _fnAjaxDataSrc,
15021		_fnAddColumn: _fnAddColumn,
15022		_fnColumnOptions: _fnColumnOptions,
15023		_fnAdjustColumnSizing: _fnAdjustColumnSizing,
15024		_fnVisibleToColumnIndex: _fnVisibleToColumnIndex,
15025		_fnColumnIndexToVisible: _fnColumnIndexToVisible,
15026		_fnVisbleColumns: _fnVisbleColumns,
15027		_fnGetColumns: _fnGetColumns,
15028		_fnColumnTypes: _fnColumnTypes,
15029		_fnApplyColumnDefs: _fnApplyColumnDefs,
15030		_fnHungarianMap: _fnHungarianMap,
15031		_fnCamelToHungarian: _fnCamelToHungarian,
15032		_fnLanguageCompat: _fnLanguageCompat,
15033		_fnBrowserDetect: _fnBrowserDetect,
15034		_fnAddData: _fnAddData,
15035		_fnAddTr: _fnAddTr,
15036		_fnNodeToDataIndex: _fnNodeToDataIndex,
15037		_fnNodeToColumnIndex: _fnNodeToColumnIndex,
15038		_fnGetCellData: _fnGetCellData,
15039		_fnSetCellData: _fnSetCellData,
15040		_fnSplitObjNotation: _fnSplitObjNotation,
15041		_fnGetObjectDataFn: _fnGetObjectDataFn,
15042		_fnSetObjectDataFn: _fnSetObjectDataFn,
15043		_fnGetDataMaster: _fnGetDataMaster,
15044		_fnClearTable: _fnClearTable,
15045		_fnDeleteIndex: _fnDeleteIndex,
15046		_fnInvalidate: _fnInvalidate,
15047		_fnGetRowElements: _fnGetRowElements,
15048		_fnCreateTr: _fnCreateTr,
15049		_fnBuildHead: _fnBuildHead,
15050		_fnDrawHead: _fnDrawHead,
15051		_fnDraw: _fnDraw,
15052		_fnReDraw: _fnReDraw,
15053		_fnAddOptionsHtml: _fnAddOptionsHtml,
15054		_fnDetectHeader: _fnDetectHeader,
15055		_fnGetUniqueThs: _fnGetUniqueThs,
15056		_fnFeatureHtmlFilter: _fnFeatureHtmlFilter,
15057		_fnFilterComplete: _fnFilterComplete,
15058		_fnFilterCustom: _fnFilterCustom,
15059		_fnFilterColumn: _fnFilterColumn,
15060		_fnFilter: _fnFilter,
15061		_fnFilterCreateSearch: _fnFilterCreateSearch,
15062		_fnEscapeRegex: _fnEscapeRegex,
15063		_fnFilterData: _fnFilterData,
15064		_fnFeatureHtmlInfo: _fnFeatureHtmlInfo,
15065		_fnUpdateInfo: _fnUpdateInfo,
15066		_fnInfoMacros: _fnInfoMacros,
15067		_fnInitialise: _fnInitialise,
15068		_fnInitComplete: _fnInitComplete,
15069		_fnLengthChange: _fnLengthChange,
15070		_fnFeatureHtmlLength: _fnFeatureHtmlLength,
15071		_fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate,
15072		_fnPageChange: _fnPageChange,
15073		_fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing,
15074		_fnProcessingDisplay: _fnProcessingDisplay,
15075		_fnFeatureHtmlTable: _fnFeatureHtmlTable,
15076		_fnScrollDraw: _fnScrollDraw,
15077		_fnApplyToChildren: _fnApplyToChildren,
15078		_fnCalculateColumnWidths: _fnCalculateColumnWidths,
15079		_fnThrottle: _fnThrottle,
15080		_fnConvertToWidth: _fnConvertToWidth,
15081		_fnGetWidestNode: _fnGetWidestNode,
15082		_fnGetMaxLenString: _fnGetMaxLenString,
15083		_fnStringToCss: _fnStringToCss,
15084		_fnSortFlatten: _fnSortFlatten,
15085		_fnSort: _fnSort,
15086		_fnSortAria: _fnSortAria,
15087		_fnSortListener: _fnSortListener,
15088		_fnSortAttachListener: _fnSortAttachListener,
15089		_fnSortingClasses: _fnSortingClasses,
15090		_fnSortData: _fnSortData,
15091		_fnSaveState: _fnSaveState,
15092		_fnLoadState: _fnLoadState,
15093		_fnSettingsFromNode: _fnSettingsFromNode,
15094		_fnLog: _fnLog,
15095		_fnMap: _fnMap,
15096		_fnBindAction: _fnBindAction,
15097		_fnCallbackReg: _fnCallbackReg,
15098		_fnCallbackFire: _fnCallbackFire,
15099		_fnLengthOverflow: _fnLengthOverflow,
15100		_fnRenderer: _fnRenderer,
15101		_fnDataSource: _fnDataSource,
15102		_fnRowAttributes: _fnRowAttributes,
15103		_fnExtend: _fnExtend,
15104		_fnCalculateEnd: function () {} // Used by a lot of plug-ins, but redundant
15105		                                // in 1.10, so this dead-end function is
15106		                                // added to prevent errors
15107	} );
15108	
15109
15110	// jQuery access
15111	$.fn.dataTable = DataTable;
15112
15113	// Provide access to the host jQuery object (circular reference)
15114	DataTable.$ = $;
15115
15116	// Legacy aliases
15117	$.fn.dataTableSettings = DataTable.settings;
15118	$.fn.dataTableExt = DataTable.ext;
15119
15120	// With a capital `D` we return a DataTables API instance rather than a
15121	// jQuery object
15122	$.fn.DataTable = function ( opts ) {
15123		return $(this).dataTable( opts ).api();
15124	};
15125
15126	// All properties that are available to $.fn.dataTable should also be
15127	// available on $.fn.DataTable
15128	$.each( DataTable, function ( prop, val ) {
15129		$.fn.DataTable[ prop ] = val;
15130	} );
15131
15132
15133	// Information about events fired by DataTables - for documentation.
15134	/**
15135	 * Draw event, fired whenever the table is redrawn on the page, at the same
15136	 * point as fnDrawCallback. This may be useful for binding events or
15137	 * performing calculations when the table is altered at all.
15138	 *  @name DataTable#draw.dt
15139	 *  @event
15140	 *  @param {event} e jQuery event object
15141	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15142	 */
15143
15144	/**
15145	 * Search event, fired when the searching applied to the table (using the
15146	 * built-in global search, or column filters) is altered.
15147	 *  @name DataTable#search.dt
15148	 *  @event
15149	 *  @param {event} e jQuery event object
15150	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15151	 */
15152
15153	/**
15154	 * Page change event, fired when the paging of the table is altered.
15155	 *  @name DataTable#page.dt
15156	 *  @event
15157	 *  @param {event} e jQuery event object
15158	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15159	 */
15160
15161	/**
15162	 * Order event, fired when the ordering applied to the table is altered.
15163	 *  @name DataTable#order.dt
15164	 *  @event
15165	 *  @param {event} e jQuery event object
15166	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15167	 */
15168
15169	/**
15170	 * DataTables initialisation complete event, fired when the table is fully
15171	 * drawn, including Ajax data loaded, if Ajax data is required.
15172	 *  @name DataTable#init.dt
15173	 *  @event
15174	 *  @param {event} e jQuery event object
15175	 *  @param {object} oSettings DataTables settings object
15176	 *  @param {object} json The JSON object request from the server - only
15177	 *    present if client-side Ajax sourced data is used</li></ol>
15178	 */
15179
15180	/**
15181	 * State save event, fired when the table has changed state a new state save
15182	 * is required. This event allows modification of the state saving object
15183	 * prior to actually doing the save, including addition or other state
15184	 * properties (for plug-ins) or modification of a DataTables core property.
15185	 *  @name DataTable#stateSaveParams.dt
15186	 *  @event
15187	 *  @param {event} e jQuery event object
15188	 *  @param {object} oSettings DataTables settings object
15189	 *  @param {object} json The state information to be saved
15190	 */
15191
15192	/**
15193	 * State load event, fired when the table is loading state from the stored
15194	 * data, but prior to the settings object being modified by the saved state
15195	 * - allowing modification of the saved state is required or loading of
15196	 * state for a plug-in.
15197	 *  @name DataTable#stateLoadParams.dt
15198	 *  @event
15199	 *  @param {event} e jQuery event object
15200	 *  @param {object} oSettings DataTables settings object
15201	 *  @param {object} json The saved state information
15202	 */
15203
15204	/**
15205	 * State loaded event, fired when state has been loaded from stored data and
15206	 * the settings object has been modified by the loaded data.
15207	 *  @name DataTable#stateLoaded.dt
15208	 *  @event
15209	 *  @param {event} e jQuery event object
15210	 *  @param {object} oSettings DataTables settings object
15211	 *  @param {object} json The saved state information
15212	 */
15213
15214	/**
15215	 * Processing event, fired when DataTables is doing some kind of processing
15216	 * (be it, order, searcg or anything else). It can be used to indicate to
15217	 * the end user that there is something happening, or that something has
15218	 * finished.
15219	 *  @name DataTable#processing.dt
15220	 *  @event
15221	 *  @param {event} e jQuery event object
15222	 *  @param {object} oSettings DataTables settings object
15223	 *  @param {boolean} bShow Flag for if DataTables is doing processing or not
15224	 */
15225
15226	/**
15227	 * Ajax (XHR) event, fired whenever an Ajax request is completed from a
15228	 * request to made to the server for new data. This event is called before
15229	 * DataTables processed the returned data, so it can also be used to pre-
15230	 * process the data returned from the server, if needed.
15231	 *
15232	 * Note that this trigger is called in `fnServerData`, if you override
15233	 * `fnServerData` and which to use this event, you need to trigger it in you
15234	 * success function.
15235	 *  @name DataTable#xhr.dt
15236	 *  @event
15237	 *  @param {event} e jQuery event object
15238	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15239	 *  @param {object} json JSON returned from the server
15240	 *
15241	 *  @example
15242	 *     // Use a custom property returned from the server in another DOM element
15243	 *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
15244	 *       $('#status').html( json.status );
15245	 *     } );
15246	 *
15247	 *  @example
15248	 *     // Pre-process the data returned from the server
15249	 *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
15250	 *       for ( var i=0, ien=json.aaData.length ; i<ien ; i++ ) {
15251	 *         json.aaData[i].sum = json.aaData[i].one + json.aaData[i].two;
15252	 *       }
15253	 *       // Note no return - manipulate the data directly in the JSON object.
15254	 *     } );
15255	 */
15256
15257	/**
15258	 * Destroy event, fired when the DataTable is destroyed by calling fnDestroy
15259	 * or passing the bDestroy:true parameter in the initialisation object. This
15260	 * can be used to remove bound events, added DOM nodes, etc.
15261	 *  @name DataTable#destroy.dt
15262	 *  @event
15263	 *  @param {event} e jQuery event object
15264	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15265	 */
15266
15267	/**
15268	 * Page length change event, fired when number of records to show on each
15269	 * page (the length) is changed.
15270	 *  @name DataTable#length.dt
15271	 *  @event
15272	 *  @param {event} e jQuery event object
15273	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15274	 *  @param {integer} len New length
15275	 */
15276
15277	/**
15278	 * Column sizing has changed.
15279	 *  @name DataTable#column-sizing.dt
15280	 *  @event
15281	 *  @param {event} e jQuery event object
15282	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15283	 */
15284
15285	/**
15286	 * Column visibility has changed.
15287	 *  @name DataTable#column-visibility.dt
15288	 *  @event
15289	 *  @param {event} e jQuery event object
15290	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15291	 *  @param {int} column Column index
15292	 *  @param {bool} vis `false` if column now hidden, or `true` if visible
15293	 */
15294
15295	return $.fn.dataTable;
15296}));

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.