PageSourceSearch

https://ordering.bausch.ca/_ui/responsive/common/DataTables/datatables.js

js bausch.ca collected 2026-10-04 17:41:01 UTC 448,123 bytes, 15,313 lines download raw bytes

1/*
2 * This combined file was created by the DataTables downloader builder:
3 *   https://datatables.net/download
4 *
5 * To rebuild or modify this file with the latest versions of the included
6 * software please visit:
7 *   https://datatables.net/download/#dt/dt-1.10.18
8 *
9 * Included libraries:
10 *   DataTables 1.10.18
11 */
12
13/*! DataTables 1.10.18
14 * ©2008-2018 SpryMedia Ltd - datatables.net/license
15 */
16
17/**
18 * @summary     DataTables
19 * @description Paginate, search and order HTML tables
20 * @version     1.10.18
21 * @file        jquery.dataTables.js
22 * @author      SpryMedia Ltd
23 * @contact     www.datatables.net
24 * @copyright   Copyright 2008-2018 SpryMedia Ltd.
25 *
26 * This source file is free software, available under the following license:
27 *   MIT license - http://datatables.net/license
28 *
29 * This source file is distributed in the hope that it will be useful, but
30 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
31 * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
32 *
33 * For details please refer to: http://www.datatables.net
34 */
35
36/*jslint evil: true, undef: true, browser: true */
37/*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*/
38
39(function( factory ) {
40	"use strict";
41
42	if ( typeof define === 'function' && define.amd ) {
43		// AMD
44		define( ['jquery'], function ( $ ) {
45			return factory( $, window, document );
46		} );
47	}
48	else if ( typeof exports === 'object' ) {
49		// CommonJS
50		module.exports = function (root, $) {
51			if ( ! root ) {
52				// CommonJS environments without a window global must pass a
53				// root. This will give an error otherwise
54				root = window;
55			}
56
57			if ( ! $ ) {
58				$ = typeof window !== 'undefined' ? // jQuery's factory checks for a global window
59					require('jquery') :
60					require('jquery')( root );
61			}
62
63			return factory( $, root, root.document );
64		};
65	}
66	else {
67		// Browser
68		factory( jQuery, window, document );
69	}
70}
71(function( $, window, document, undefined ) {
72	"use strict";
73
74	/**
75	 * DataTables is a plug-in for the jQuery Javascript library. It is a highly
76	 * flexible tool, based upon the foundations of progressive enhancement,
77	 * which will add advanced interaction controls to any HTML table. For a
78	 * full list of features please refer to
79	 * [DataTables.net](href="http://datatables.net).
80	 *
81	 * Note that the `DataTable` object is not a global variable but is aliased
82	 * to `jQuery.fn.DataTable` and `jQuery.fn.dataTable` through which it may
83	 * be  accessed.
84	 *
85	 *  @class
86	 *  @param {object} [init={}] Configuration object for DataTables. Options
87	 *    are defined by {@link DataTable.defaults}
88	 *  @requires jQuery 1.7+
89	 *
90	 *  @example
91	 *    // Basic initialisation
92	 *    $(document).ready( function {
93	 *      $('#example').dataTable();
94	 *    } );
95	 *
96	 *  @example
97	 *    // Initialisation with configuration options - in this case, disable
98	 *    // pagination and sorting.
99	 *    $(document).ready( function {
100	 *      $('#example').dataTable( {
101	 *        "paginate": false,
102	 *        "sort": false
103	 *      } );
104	 *    } );
105	 */
106	var DataTable = function ( options )
107	{
vendor: 6,636 bytes, lines 107-266
107
108		/**
109		 * Perform a jQuery selector action on the table's TR elements (from the tbody) and
110		 * return the resulting jQuery object.
111		 *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
112		 *  @param {object} [oOpts] Optional parameters for modifying the rows to be included
113		 *  @param {string} [oOpts.filter=none] Select TR elements that meet the current filter
114		 *    criterion ("applied") or all TR elements (i.e. no filter).
115		 *  @param {string} [oOpts.order=current] Order of the TR elements in the processed array.
116		 *    Can be either 'current', whereby the current sorting of the table is used, or
117		 *    'original' whereby the original order the data was read into the table is used.
118		 *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
119		 *    ("current") or not ("all"). If 'current' is given, then order is assumed to be
120		 *    'current' and filter is 'applied', regardless of what they might be given as.
121		 *  @returns {object} jQuery object, filtered by the given selector.
122		 *  @dtopt API
123		 *  @deprecated Since v1.10
124		 *
125		 *  @example
126		 *    $(document).ready(function() {
127		 *      var oTable = $('#example').dataTable();
128		 *
129		 *      // Highlight every second row
130		 *      oTable.$('tr:odd').css('backgroundColor', 'blue');
131		 *    } );
132		 *
133		 *  @example
134		 *    $(document).ready(function() {
135		 *      var oTable = $('#example').dataTable();
136		 *
137		 *      // Filter to rows with 'Webkit' in them, add a background colour and then
138		 *      // remove the filter, thus highlighting the 'Webkit' rows only.
139		 *      oTable.fnFilter('Webkit');
140		 *      oTable.$('tr', {"search": "applied"}).css('backgroundColor', 'blue');
141		 *      oTable.fnFilter('');
142		 *    } );
143		 */
144		this.$ = function ( sSelector, oOpts )
145		{
146			return this.api(true).$( sSelector, oOpts );
147		};
148		
149		
150		/**
151		 * Almost identical to $ in operation, but in this case returns the data for the matched
152		 * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes
153		 * rather than any descendants, so the data can be obtained for the row/cell. If matching
154		 * rows are found, the data returned is the original data array/object that was used to
155		 * create the row (or a generated array if from a DOM source).
156		 *
157		 * This method is often useful in-combination with $ where both functions are given the
158		 * same parameters and the array indexes will match identically.
159		 *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
160		 *  @param {object} [oOpts] Optional parameters for modifying the rows to be included
161		 *  @param {string} [oOpts.filter=none] Select elements that meet the current filter
162		 *    criterion ("applied") or all elements (i.e. no filter).
163		 *  @param {string} [oOpts.order=current] Order of the data in the processed array.
164		 *    Can be either 'current', whereby the current sorting of the table is used, or
165		 *    'original' whereby the original order the data was read into the table is used.
166		 *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
167		 *    ("current") or not ("all"). If 'current' is given, then order is assumed to be
168		 *    'current' and filter is 'applied', regardless of what they might be given as.
169		 *  @returns {array} Data for the matched elements. If any elements, as a result of the
170		 *    selector, were not TR, TD or TH elements in the DataTable, they will have a null
171		 *    entry in the array.
172		 *  @dtopt API
173		 *  @deprecated Since v1.10
174		 *
175		 *  @example
176		 *    $(document).ready(function() {
177		 *      var oTable = $('#example').dataTable();
178		 *
179		 *      // Get the data from the first row in the table
180		 *      var data = oTable._('tr:first');
181		 *
182		 *      // Do something useful with the data
183		 *      alert( "First cell is: "+data[0] );
184		 *    } );
185		 *
186		 *  @example
187		 *    $(document).ready(function() {
188		 *      var oTable = $('#example').dataTable();
189		 *
190		 *      // Filter to 'Webkit' and get all data for
191		 *      oTable.fnFilter('Webkit');
192		 *      var data = oTable._('tr', {"search": "applied"});
193		 *
194		 *      // Do something with the data
195		 *      alert( data.length+" rows matched the search" );
196		 *    } );
197		 */
198		this._ = function ( sSelector, oOpts )
199		{
200			return this.api(true).rows( sSelector, oOpts ).data();
201		};
202		
203		
204		/**
205		 * Create a DataTables Api instance, with the currently selected tables for
206		 * the Api's context.
207		 * @param {boolean} [traditional=false] Set the API instance's context to be
208		 *   only the table referred to by the `DataTable.ext.iApiIndex` option, as was
209		 *   used in the API presented by DataTables 1.9- (i.e. the traditional mode),
210		 *   or if all tables captured in the jQuery object should be used.
211		 * @return {DataTables.Api}
212		 */
213		this.api = function ( traditional )
214		{
215			return traditional ?
216				new _Api(
217					_fnSettingsFromNode( this[ _ext.iApiIndex ] )
218				) :
219				new _Api( this );
220		};
221		
222		
223		/**
224		 * Add a single new row or multiple rows of data to the table. Please note
225		 * that this is suitable for client-side processing only - if you are using
226		 * server-side processing (i.e. "bServerSide": true), then to add data, you
227		 * must add it to the data source, i.e. the server-side, through an Ajax call.
228		 *  @param {array|object} data The data to be added to the table. This can be:
229		 *    <ul>
230		 *      <li>1D array of data - add a single row with the data provided</li>
231		 *      <li>2D array of arrays - add multiple rows in a single call</li>
232		 *      <li>object - data object when using <i>mData</i></li>
233		 *      <li>array of objects - multiple data objects when using <i>mData</i></li>
234		 *    </ul>
235		 *  @param {bool} [redraw=true] redraw the table or not
236		 *  @returns {array} An array of integers, representing the list of indexes in
237		 *    <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to
238		 *    the table.
239		 *  @dtopt API
240		 *  @deprecated Since v1.10
241		 *
242		 *  @example
243		 *    // Global var for counter
244		 *    var giCount = 2;
245		 *
246		 *    $(document).ready(function() {
247		 *      $('#example').dataTable();
248		 *    } );
249		 *
250		 *    function fnClickAddRow() {
251		 *      $('#example').dataTable().fnAddData( [
252		 *        giCount+".1",
253		 *        giCount+".2",
254		 *        giCount+".3",
255		 *        giCount+".4" ]
256		 *      );
257		 *
258		 *      giCount++;
259		 *    }
260		 */
261		this.fnAddData = function( data, redraw )
262		{
263			var api = this.api( true );
264		
265			/* Check if we want to add multiple rows or not */
266			var rows = 
266$.isArray(data) && ( $
vendor: 18,409 bytes, lines 266-862
266.isArray(data[0]) || $.isPlainObject(data[0]) ) ?
267				api.rows.add( data ) :
268				api.row.add( data );
269		
270			if ( redraw === undefined || redraw ) {
271				api.draw();
272			}
273		
274			return rows.flatten().toArray();
275		};
276		
277		
278		/**
279		 * This function will make DataTables recalculate the column sizes, based on the data
280		 * contained in the table and the sizes applied to the columns (in the DOM, CSS or
281		 * through the sWidth parameter). This can be useful when the width of the table's
282		 * parent element changes (for example a window resize).
283		 *  @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to
284		 *  @dtopt API
285		 *  @deprecated Since v1.10
286		 *
287		 *  @example
288		 *    $(document).ready(function() {
289		 *      var oTable = $('#example').dataTable( {
290		 *        "sScrollY": "200px",
291		 *        "bPaginate": false
292		 *      } );
293		 *
294		 *      $(window).on('resize', function () {
295		 *        oTable.fnAdjustColumnSizing();
296		 *      } );
297		 *    } );
298		 */
299		this.fnAdjustColumnSizing = function ( bRedraw )
300		{
301			var api = this.api( true ).columns.adjust();
302			var settings = api.settings()[0];
303			var scroll = settings.oScroll;
304		
305			if ( bRedraw === undefined || bRedraw ) {
306				api.draw( false );
307			}
308			else if ( scroll.sX !== "" || scroll.sY !== "" ) {
309				/* If not redrawing, but scrolling, we want to apply the new column sizes anyway */
310				_fnScrollDraw( settings );
311			}
312		};
313		
314		
315		/**
316		 * Quickly and simply clear a table
317		 *  @param {bool} [bRedraw=true] redraw the table or not
318		 *  @dtopt API
319		 *  @deprecated Since v1.10
320		 *
321		 *  @example
322		 *    $(document).ready(function() {
323		 *      var oTable = $('#example').dataTable();
324		 *
325		 *      // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...)
326		 *      oTable.fnClearTable();
327		 *    } );
328		 */
329		this.fnClearTable = function( bRedraw )
330		{
331			var api = this.api( true ).clear();
332		
333			if ( bRedraw === undefined || bRedraw ) {
334				api.draw();
335			}
336		};
337		
338		
339		/**
340		 * The exact opposite of 'opening' a row, this function will close any rows which
341		 * are currently 'open'.
342		 *  @param {node} nTr the table row to 'close'
343		 *  @returns {int} 0 on success, or 1 if failed (can't find the row)
344		 *  @dtopt API
345		 *  @deprecated Since v1.10
346		 *
347		 *  @example
348		 *    $(document).ready(function() {
349		 *      var oTable;
350		 *
351		 *      // 'open' an information row when a row is clicked on
352		 *      $('#example tbody tr').click( function () {
353		 *        if ( oTable.fnIsOpen(this) ) {
354		 *          oTable.fnClose( this );
355		 *        } else {
356		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
357		 *        }
358		 *      } );
359		 *
360		 *      oTable = $('#example').dataTable();
361		 *    } );
362		 */
363		this.fnClose = function( nTr )
364		{
365			this.api( true ).row( nTr ).child.hide();
366		};
367		
368		
369		/**
370		 * Remove a row for the table
371		 *  @param {mixed} target The index of the row from aoData to be deleted, or
372		 *    the TR element you want to delete
373		 *  @param {function|null} [callBack] Callback function
374		 *  @param {bool} [redraw=true] Redraw the table or not
375		 *  @returns {array} The row that was deleted
376		 *  @dtopt API
377		 *  @deprecated Since v1.10
378		 *
379		 *  @example
380		 *    $(document).ready(function() {
381		 *      var oTable = $('#example').dataTable();
382		 *
383		 *      // Immediately remove the first row
384		 *      oTable.fnDeleteRow( 0 );
385		 *    } );
386		 */
387		this.fnDeleteRow = function( target, callback, redraw )
388		{
389			var api = this.api( true );
390			var rows = api.rows( target );
391			var settings = rows.settings()[0];
392			var data = settings.aoData[ rows[0][0] ];
393		
394			rows.remove();
395		
396			if ( callback ) {
397				callback.call( this, settings, data );
398			}
399		
400			if ( redraw === undefined || redraw ) {
401				api.draw();
402			}
403		
404			return data;
405		};
406		
407		
408		/**
409		 * Restore the table to it's original state in the DOM by removing all of DataTables
410		 * enhancements, alterations to the DOM structure of the table and event listeners.
411		 *  @param {boolean} [remove=false] Completely remove the table from the DOM
412		 *  @dtopt API
413		 *  @deprecated Since v1.10
414		 *
415		 *  @example
416		 *    $(document).ready(function() {
417		 *      // This example is fairly pointless in reality, but shows how fnDestroy can be used
418		 *      var oTable = $('#example').dataTable();
419		 *      oTable.fnDestroy();
420		 *    } );
421		 */
422		this.fnDestroy = function ( remove )
423		{
424			this.api( true ).destroy( remove );
425		};
426		
427		
428		/**
429		 * Redraw the table
430		 *  @param {bool} [complete=true] Re-filter and resort (if enabled) the table before the draw.
431		 *  @dtopt API
432		 *  @deprecated Since v1.10
433		 *
434		 *  @example
435		 *    $(document).ready(function() {
436		 *      var oTable = $('#example').dataTable();
437		 *
438		 *      // Re-draw the table - you wouldn't want to do it here, but it's an example :-)
439		 *      oTable.fnDraw();
440		 *    } );
441		 */
442		this.fnDraw = function( complete )
443		{
444			// Note that this isn't an exact match to the old call to _fnDraw - it takes
445			// into account the new data, but can hold position.
446			this.api( true ).draw( complete );
447		};
448		
449		
450		/**
451		 * Filter the input based on data
452		 *  @param {string} sInput String to filter the table on
453		 *  @param {int|null} [iColumn] Column to limit filtering to
454		 *  @param {bool} [bRegex=false] Treat as regular expression or not
455		 *  @param {bool} [bSmart=true] Perform smart filtering or not
456		 *  @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es)
457		 *  @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false)
458		 *  @dtopt API
459		 *  @deprecated Since v1.10
460		 *
461		 *  @example
462		 *    $(document).ready(function() {
463		 *      var oTable = $('#example').dataTable();
464		 *
465		 *      // Sometime later - filter...
466		 *      oTable.fnFilter( 'test string' );
467		 *    } );
468		 */
469		this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive )
470		{
471			var api = this.api( true );
472		
473			if ( iColumn === null || iColumn === undefined ) {
474				api.search( sInput, bRegex, bSmart, bCaseInsensitive );
475			}
476			else {
477				api.column( iColumn ).search( sInput, bRegex, bSmart, bCaseInsensitive );
478			}
479		
480			api.draw();
481		};
482		
483		
484		/**
485		 * Get the data for the whole table, an individual row or an individual cell based on the
486		 * provided parameters.
487		 *  @param {int|node} [src] A TR row node, TD/TH cell node or an integer. If given as
488		 *    a TR node then the data source for the whole row will be returned. If given as a
489		 *    TD/TH cell node then iCol will be automatically calculated and the data for the
490		 *    cell returned. If given as an integer, then this is treated as the aoData internal
491		 *    data index for the row (see fnGetPosition) and the data for that row used.
492		 *  @param {int} [col] Optional column index that you want the data of.
493		 *  @returns {array|object|string} If mRow is undefined, then the data for all rows is
494		 *    returned. If mRow is defined, just data for that row, and is iCol is
495		 *    defined, only data for the designated cell is returned.
496		 *  @dtopt API
497		 *  @deprecated Since v1.10
498		 *
499		 *  @example
500		 *    // Row data
501		 *    $(document).ready(function() {
502		 *      oTable = $('#example').dataTable();
503		 *
504		 *      oTable.$('tr').click( function () {
505		 *        var data = oTable.fnGetData( this );
506		 *        // ... do something with the array / object of data for the row
507		 *      } );
508		 *    } );
509		 *
510		 *  @example
511		 *    // Individual cell data
512		 *    $(document).ready(function() {
513		 *      oTable = $('#example').dataTable();
514		 *
515		 *      oTable.$('td').click( function () {
516		 *        var sData = oTable.fnGetData( this );
517		 *        alert( 'The cell clicked on had the value of '+sData );
518		 *      } );
519		 *    } );
520		 */
521		this.fnGetData = function( src, col )
522		{
523			var api = this.api( true );
524		
525			if ( src !== undefined ) {
526				var type = src.nodeName ? src.nodeName.toLowerCase() : '';
527		
528				return col !== undefined || type == 'td' || type == 'th' ?
529					api.cell( src, col ).data() :
530					api.row( src ).data() || null;
531			}
532		
533			return api.data().toArray();
534		};
535		
536		
537		/**
538		 * Get an array of the TR nodes that are used in the table's body. Note that you will
539		 * typically want to use the '$' API method in preference to this as it is more
540		 * flexible.
541		 *  @param {int} [iRow] Optional row index for the TR element you want
542		 *  @returns {array|node} If iRow is undefined, returns an array of all TR elements
543		 *    in the table's body, or iRow is defined, just the TR element requested.
544		 *  @dtopt API
545		 *  @deprecated Since v1.10
546		 *
547		 *  @example
548		 *    $(document).ready(function() {
549		 *      var oTable = $('#example').dataTable();
550		 *
551		 *      // Get the nodes from the table
552		 *      var nNodes = oTable.fnGetNodes( );
553		 *    } );
554		 */
555		this.fnGetNodes = function( iRow )
556		{
557			var api = this.api( true );
558		
559			return iRow !== undefined ?
560				api.row( iRow ).node() :
561				api.rows().nodes().flatten().toArray();
562		};
563		
564		
565		/**
566		 * Get the array indexes of a particular cell from it's DOM element
567		 * and column index including hidden columns
568		 *  @param {node} node this can either be a TR, TD or TH in the table's body
569		 *  @returns {int} If nNode is given as a TR, then a single index is returned, or
570		 *    if given as a cell, an array of [row index, column index (visible),
571		 *    column index (all)] is given.
572		 *  @dtopt API
573		 *  @deprecated Since v1.10
574		 *
575		 *  @example
576		 *    $(document).ready(function() {
577		 *      $('#example tbody td').click( function () {
578		 *        // Get the position of the current data from the node
579		 *        var aPos = oTable.fnGetPosition( this );
580		 *
581		 *        // Get the data array for this row
582		 *        var aData = oTable.fnGetData( aPos[0] );
583		 *
584		 *        // Update the data array and return the value
585		 *        aData[ aPos[1] ] = 'clicked';
586		 *        this.innerHTML = 'clicked';
587		 *      } );
588		 *
589		 *      // Init DataTables
590		 *      oTable = $('#example').dataTable();
591		 *    } );
592		 */
593		this.fnGetPosition = function( node )
594		{
595			var api = this.api( true );
596			var nodeName = node.nodeName.toUpperCase();
597		
598			if ( nodeName == 'TR' ) {
599				return api.row( node ).index();
600			}
601			else if ( nodeName == 'TD' || nodeName == 'TH' ) {
602				var cell = api.cell( node ).index();
603		
604				return [
605					cell.row,
606					cell.columnVisible,
607					cell.column
608				];
609			}
610			return null;
611		};
612		
613		
614		/**
615		 * Check to see if a row is 'open' or not.
616		 *  @param {node} nTr the table row to check
617		 *  @returns {boolean} true if the row is currently open, false otherwise
618		 *  @dtopt API
619		 *  @deprecated Since v1.10
620		 *
621		 *  @example
622		 *    $(document).ready(function() {
623		 *      var oTable;
624		 *
625		 *      // 'open' an information row when a row is clicked on
626		 *      $('#example tbody tr').click( function () {
627		 *        if ( oTable.fnIsOpen(this) ) {
628		 *          oTable.fnClose( this );
629		 *        } else {
630		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
631		 *        }
632		 *      } );
633		 *
634		 *      oTable = $('#example').dataTable();
635		 *    } );
636		 */
637		this.fnIsOpen = function( nTr )
638		{
639			return this.api( true ).row( nTr ).child.isShown();
640		};
641		
642		
643		/**
644		 * This function will place a new row directly after a row which is currently
645		 * on display on the page, with the HTML contents that is passed into the
646		 * function. This can be used, for example, to ask for confirmation that a
647		 * particular record should be deleted.
648		 *  @param {node} nTr The table row to 'open'
649		 *  @param {string|node|jQuery} mHtml The HTML to put into the row
650		 *  @param {string} sClass Class to give the new TD cell
651		 *  @returns {node} The row opened. Note that if the table row passed in as the
652		 *    first parameter, is not found in the table, this method will silently
653		 *    return.
654		 *  @dtopt API
655		 *  @deprecated Since v1.10
656		 *
657		 *  @example
658		 *    $(document).ready(function() {
659		 *      var oTable;
660		 *
661		 *      // 'open' an information row when a row is clicked on
662		 *      $('#example tbody tr').click( function () {
663		 *        if ( oTable.fnIsOpen(this) ) {
664		 *          oTable.fnClose( this );
665		 *        } else {
666		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
667		 *        }
668		 *      } );
669		 *
670		 *      oTable = $('#example').dataTable();
671		 *    } );
672		 */
673		this.fnOpen = function( nTr, mHtml, sClass )
674		{
675			return this.api( true )
676				.row( nTr )
677				.child( mHtml, sClass )
678				.show()
679				.child()[0];
680		};
681		
682		
683		/**
684		 * Change the pagination - provides the internal logic for pagination in a simple API
685		 * function. With this function you can have a DataTables table go to the next,
686		 * previous, first or last pages.
687		 *  @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
688		 *    or page number to jump to (integer), note that page 0 is the first page.
689		 *  @param {bool} [bRedraw=true] Redraw the table or not
690		 *  @dtopt API
691		 *  @deprecated Since v1.10
692		 *
693		 *  @example
694		 *    $(document).ready(function() {
695		 *      var oTable = $('#example').dataTable();
696		 *      oTable.fnPageChange( 'next' );
697		 *    } );
698		 */
699		this.fnPageChange = function ( mAction, bRedraw )
700		{
701			var api = this.api( true ).page( mAction );
702		
703			if ( bRedraw === undefined || bRedraw ) {
704				api.draw(false);
705			}
706		};
707		
708		
709		/**
710		 * Show a particular column
711		 *  @param {int} iCol The column whose display should be changed
712		 *  @param {bool} bShow Show (true) or hide (false) the column
713		 *  @param {bool} [bRedraw=true] Redraw the table or not
714		 *  @dtopt API
715		 *  @deprecated Since v1.10
716		 *
717		 *  @example
718		 *    $(document).ready(function() {
719		 *      var oTable = $('#example').dataTable();
720		 *
721		 *      // Hide the second column after initialisation
722		 *      oTable.fnSetColumnVis( 1, false );
723		 *    } );
724		 */
725		this.fnSetColumnVis = function ( iCol, bShow, bRedraw )
726		{
727			var api = this.api( true ).column( iCol ).visible( bShow );
728		
729			if ( bRedraw === undefined || bRedraw ) {
730				api.columns.adjust().draw();
731			}
732		};
733		
734		
735		/**
736		 * Get the settings for a particular table for external manipulation
737		 *  @returns {object} DataTables settings object. See
738		 *    {@link DataTable.models.oSettings}
739		 *  @dtopt API
740		 *  @deprecated Since v1.10
741		 *
742		 *  @example
743		 *    $(document).ready(function() {
744		 *      var oTable = $('#example').dataTable();
745		 *      var oSettings = oTable.fnSettings();
746		 *
747		 *      // Show an example parameter from the settings
748		 *      alert( oSettings._iDisplayStart );
749		 *    } );
750		 */
751		this.fnSettings = function()
752		{
753			return _fnSettingsFromNode( this[_ext.iApiIndex] );
754		};
755		
756		
757		/**
758		 * Sort the table by a particular column
759		 *  @param {int} iCol the data index to sort on. Note that this will not match the
760		 *    'display index' if you have hidden data entries
761		 *  @dtopt API
762		 *  @deprecated Since v1.10
763		 *
764		 *  @example
765		 *    $(document).ready(function() {
766		 *      var oTable = $('#example').dataTable();
767		 *
768		 *      // Sort immediately with columns 0 and 1
769		 *      oTable.fnSort( [ [0,'asc'], [1,'asc'] ] );
770		 *    } );
771		 */
772		this.fnSort = function( aaSort )
773		{
774			this.api( true ).order( aaSort ).draw();
775		};
776		
777		
778		/**
779		 * Attach a sort listener to an element for a given column
780		 *  @param {node} nNode the element to attach the sort listener to
781		 *  @param {int} iColumn the column that a click on this node will sort on
782		 *  @param {function} [fnCallback] callback function when sort is run
783		 *  @dtopt API
784		 *  @deprecated Since v1.10
785		 *
786		 *  @example
787		 *    $(document).ready(function() {
788		 *      var oTable = $('#example').dataTable();
789		 *
790		 *      // Sort on column 1, when 'sorter' is clicked on
791		 *      oTable.fnSortListener( document.getElementById('sorter'), 1 );
792		 *    } );
793		 */
794		this.fnSortListener = function( nNode, iColumn, fnCallback )
795		{
796			this.api( true ).order.listener( nNode, iColumn, fnCallback );
797		};
798		
799		
800		/**
801		 * Update a table cell or row - this method will accept either a single value to
802		 * update the cell with, an array of values with one element for each column or
803		 * an object in the same format as the original data source. The function is
804		 * self-referencing in order to make the multi column updates easier.
805		 *  @param {object|array|string} mData Data to update the cell/row with
806		 *  @param {node|int} mRow TR element you want to update or the aoData index
807		 *  @param {int} [iColumn] The column to update, give as null or undefined to
808		 *    update a whole row.
809		 *  @param {bool} [bRedraw=true] Redraw the table or not
810		 *  @param {bool} [bAction=true] Perform pre-draw actions or not
811		 *  @returns {int} 0 on success, 1 on error
812		 *  @dtopt API
813		 *  @deprecated Since v1.10
814		 *
815		 *  @example
816		 *    $(document).ready(function() {
817		 *      var oTable = $('#example').dataTable();
818		 *      oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell
819		 *      oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], $('tbody tr')[0] ); // Row
820		 *    } );
821		 */
822		this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction )
823		{
824			var api = this.api( true );
825		
826			if ( iColumn === undefined || iColumn === null ) {
827				api.row( mRow ).data( mData );
828			}
829			else {
830				api.cell( mRow, iColumn ).data( mData );
831			}
832		
833			if ( bAction === undefined || bAction ) {
834				api.columns.adjust();
835			}
836		
837			if ( bRedraw === undefined || bRedraw ) {
838				api.draw();
839			}
840			return 0;
841		};
842		
843		
844		/**
845		 * Provide a common method for plug-ins to check the version of DataTables being used, in order
846		 * to ensure compatibility.
847		 *  @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the
848		 *    formats "X" and "X.Y" are also acceptable.
849		 *  @returns {boolean} true if this version of DataTables is greater or equal to the required
850		 *    version, or false if this version of DataTales is not suitable
851		 *  @method
852		 *  @dtopt API
853		 *  @deprecated Since v1.10
854		 *
855		 *  @example
856		 *    $(document).ready(function() {
857		 *      var oTable = $('#example').dataTable();
858		 *      alert( oTable.fnVersionCheck( '1.9.0' ) );
859		 *    } );
860		 */
861		this.fnVersionCheck = _ext.fnVersionCheck;
862		
vendor: 57,803 bytes, lines 863-2883
863
864		var _that = this;
865		var emptyInit = options === undefined;
866		var len = this.length;
867
868		if ( emptyInit ) {
869			options = {};
870		}
871
872		this.oApi = this.internal = _ext.internal;
873
874		// Extend with old style plug-in API methods
875		for ( var fn in DataTable.ext.internal ) {
876			if ( fn ) {
877				this[fn] = _fnExternApiFunc(fn);
878			}
879		}
880
881		this.each(function() {
882			// For each initialisation we want to give it a clean initialisation
883			// object that can be bashed around
884			var o = {};
885			var oInit = len > 1 ? // optimisation for single table case
886				_fnExtend( o, options, true ) :
887				options;
888
889			/*global oInit,_that,emptyInit*/
890			var i=0, iLen, j, jLen, k, kLen;
891			var sId = this.getAttribute( 'id' );
892			var bInitHandedOff = false;
893			var defaults = DataTable.defaults;
894			var $this = $(this);
895			
896			
897			/* Sanity check */
898			if ( this.nodeName.toLowerCase() != 'table' )
899			{
900				_fnLog( null, 0, 'Non-table node initialisation ('+this.nodeName+')', 2 );
901				return;
902			}
903			
904			/* Backwards compatibility for the defaults */
905			_fnCompatOpts( defaults );
906			_fnCompatCols( defaults.column );
907			
908			/* Convert the camel-case defaults to Hungarian */
909			_fnCamelToHungarian( defaults, defaults, true );
910			_fnCamelToHungarian( defaults.column, defaults.column, true );
911			
912			/* Setting up the initialisation object */
913			_fnCamelToHungarian( defaults, $.extend( oInit, $this.data() ) );
914			
915			
916			
917			/* Check to see if we are re-initialising a table */
918			var allSettings = DataTable.settings;
919			for ( i=0, iLen=allSettings.length ; i<iLen ; i++ )
920			{
921				var s = allSettings[i];
922			
923				/* Base check on table node */
924				if (
925					s.nTable == this ||
926					(s.nTHead && s.nTHead.parentNode == this) ||
927					(s.nTFoot && s.nTFoot.parentNode == this)
928				) {
929					var bRetrieve = oInit.bRetrieve !== undefined ? oInit.bRetrieve : defaults.bRetrieve;
930					var bDestroy = oInit.bDestroy !== undefined ? oInit.bDestroy : defaults.bDestroy;
931			
932					if ( emptyInit || bRetrieve )
933					{
934						return s.oInstance;
935					}
936					else if ( bDestroy )
937					{
938						s.oInstance.fnDestroy();
939						break;
940					}
941					else
942					{
943						_fnLog( s, 0, 'Cannot reinitialise DataTable', 3 );
944						return;
945					}
946				}
947			
948				/* If the element we are initialising has the same ID as a table which was previously
949				 * initialised, but the table nodes don't match (from before) then we destroy the old
950				 * instance by simply deleting it. This is under the assumption that the table has been
951				 * destroyed by other methods. Anyone using non-id selectors will need to do this manually
952				 */
953				if ( s.sTableId == this.id )
954				{
955					allSettings.splice( i, 1 );
956					break;
957				}
958			}
959			
960			/* Ensure the table has an ID - required for accessibility */
961			if ( sId === null || sId === "" )
962			{
963				sId = "DataTables_Table_"+(DataTable.ext._unique++);
964				this.id = sId;
965			}
966			
967			/* Create the settings object for this table and set some of the default parameters */
968			var oSettings = $.extend( true, {}, DataTable.models.oSettings, {
969				"sDestroyWidth": $this[0].style.width,
970				"sInstance":     sId,
971				"sTableId":      sId
972			} );
973			oSettings.nTable = this;
974			oSettings.oApi   = _that.internal;
975			oSettings.oInit  = oInit;
976			
977			allSettings.push( oSettings );
978			
979			// Need to add the instance after the instance after the settings object has been added
980			// to the settings array, so we can self reference the table instance if more than one
981			oSettings.oInstance = (_that.length===1) ? _that : $this.dataTable();
982			
983			// Backwards compatibility, before we apply all the defaults
984			_fnCompatOpts( oInit );
985			_fnLanguageCompat( oInit.oLanguage );
986			
987			// If the length menu is given, but the init display length is not, use the length menu
988			if ( oInit.aLengthMenu && ! oInit.iDisplayLength )
989			{
990				oInit.iDisplayLength = $.isArray( oInit.aLengthMenu[0] ) ?
991					oInit.aLengthMenu[0][0] : oInit.aLengthMenu[0];
992			}
993			
994			// Apply the defaults and init options to make a single init object will all
995			// options defined from defaults and instance options.
996			oInit = _fnExtend( $.extend( true, {}, defaults ), oInit );
997			
998			
999			// Map the initialisation options onto the settings object
1000			_fnMap( oSettings.oFeatures, oInit, [
1001				"bPaginate",
1002				"bLengthChange",
1003				"bFilter",
1004				"bSort",
1005				"bSortMulti",
1006				"bInfo",
1007				"bProcessing",
1008				"bAutoWidth",
1009				"bSortClasses",
1010				"bServerSide",
1011				"bDeferRender"
1012			] );
1013			_fnMap( oSettings, oInit, [
1014				"asStripeClasses",
1015				"ajax",
1016				"fnServerData",
1017				"fnFormatNumber",
1018				"sServerMethod",
1019				"aaSorting",
1020				"aaSortingFixed",
1021				"aLengthMenu",
1022				"sPaginationType",
1023				"sAjaxSource",
1024				"sAjaxDataProp",
1025				"iStateDuration",
1026				"sDom",
1027				"bSortCellsTop",
1028				"iTabIndex",
1029				"fnStateLoadCallback",
1030				"fnStateSaveCallback",
1031				"renderer",
1032				"searchDelay",
1033				"rowId",
1034				[ "iCookieDuration", "iStateDuration" ], // backwards compat
1035				[ "oSearch", "oPreviousSearch" ],
1036				[ "aoSearchCols", "aoPreSearchCols" ],
1037				[ "iDisplayLength", "_iDisplayLength" ]
1038			] );
1039			_fnMap( oSettings.oScroll, oInit, [
1040				[ "sScrollX", "sX" ],
1041				[ "sScrollXInner", "sXInner" ],
1042				[ "sScrollY", "sY" ],
1043				[ "bScrollCollapse", "bCollapse" ]
1044			] );
1045			_fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" );
1046			
1047			/* Callback functions which are array driven */
1048			_fnCallbackReg( oSettings, 'aoDrawCallback',       oInit.fnDrawCallback,      'user' );
1049			_fnCallbackReg( oSettings, 'aoServerParams',       oInit.fnServerParams,      'user' );
1050			_fnCallbackReg( oSettings, 'aoStateSaveParams',    oInit.fnStateSaveParams,   'user' );
1051			_fnCallbackReg( oSettings, 'aoStateLoadParams',    oInit.fnStateLoadParams,   'user' );
1052			_fnCallbackReg( oSettings, 'aoStateLoaded',        oInit.fnStateLoaded,       'user' );
1053			_fnCallbackReg( oSettings, 'aoRowCallback',        oInit.fnRowCallback,       'user' );
1054			_fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow,        'user' );
1055			_fnCallbackReg( oSettings, 'aoHeaderCallback',     oInit.fnHeaderCallback,    'user' );
1056			_fnCallbackReg( oSettings, 'aoFooterCallback',     oInit.fnFooterCallback,    'user' );
1057			_fnCallbackReg( oSettings, 'aoInitComplete',       oInit.fnInitComplete,      'user' );
1058			_fnCallbackReg( oSettings, 'aoPreDrawCallback',    oInit.fnPreDrawCallback,   'user' );
1059			
1060			oSettings.rowIdFn = _fnGetObjectDataFn( oInit.rowId );
1061			
1062			/* Browser support detection */
1063			_fnBrowserDetect( oSettings );
1064			
1065			var oClasses = oSettings.oClasses;
1066			
1067			$.extend( oClasses, DataTable.ext.classes, oInit.oClasses );
1068			$this.addClass( oClasses.sTable );
1069			
1070			
1071			if ( oSettings.iInitDisplayStart === undefined )
1072			{
1073				/* Display start point, taking into account the save saving */
1074				oSettings.iInitDisplayStart = oInit.iDisplayStart;
1075				oSettings._iDisplayStart = oInit.iDisplayStart;
1076			}
1077			
1078			if ( oInit.iDeferLoading !== null )
1079			{
1080				oSettings.bDeferLoading = true;
1081				var tmp = $.isArray( oInit.iDeferLoading );
1082				oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading;
1083				oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading;
1084			}
1085			
1086			/* Language definitions */
1087			var oLanguage = oSettings.oLanguage;
1088			$.extend( true, oLanguage, oInit.oLanguage );
1089			
1090			if ( oLanguage.sUrl )
1091			{
1092				/* Get the language definitions from a file - because this Ajax call makes the language
1093				 * get async to the remainder of this function we use bInitHandedOff to indicate that
1094				 * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor
1095				 */
1096				$.ajax( {
1097					dataType: 'json',
1098					url: oLanguage.sUrl,
1099					success: function ( json ) {
1100						_fnLanguageCompat( json );
1101						_fnCamelToHungarian( defaults.oLanguage, json );
1102						$.extend( true, oLanguage, json );
1103						_fnInitialise( oSettings );
1104					},
1105					error: function () {
1106						// Error occurred loading language file, continue on as best we can
1107						_fnInitialise( oSettings );
1108					}
1109				} );
1110				bInitHandedOff = true;
1111			}
1112			
1113			/*
1114			 * Stripes
1115			 */
1116			if ( oInit.asStripeClasses === null )
1117			{
1118				oSettings.asStripeClasses =[
1119					oClasses.sStripeOdd,
1120					oClasses.sStripeEven
1121				];
1122			}
1123			
1124			/* Remove row stripe classes if they are already on the table row */
1125			var stripeClasses = oSettings.asStripeClasses;
1126			var rowOne = $this.children('tbody').find('tr').eq(0);
1127			if ( $.inArray( true, $.map( stripeClasses, function(el, i) {
1128				return rowOne.hasClass(el);
1129			} ) ) !== -1 ) {
1130				$('tbody tr', this).removeClass( stripeClasses.join(' ') );
1131				oSettings.asDestroyStripes = stripeClasses.slice();
1132			}
1133			
1134			/*
1135			 * Columns
1136			 * See if we should load columns automatically or use defined ones
1137			 */
1138			var anThs = [];
1139			var aoColumnsInit;
1140			var nThead = this.getElementsByTagName('thead');
1141			if ( nThead.length !== 0 )
1142			{
1143				_fnDetectHeader( oSettings.aoHeader, nThead[0] );
1144				anThs = _fnGetUniqueThs( oSettings );
1145			}
1146			
1147			/* If not given a column array, generate one with nulls */
1148			if ( oInit.aoColumns === null )
1149			{
1150				aoColumnsInit = [];
1151				for ( i=0, iLen=anThs.length ; i<iLen ; i++ )
1152				{
1153					aoColumnsInit.push( null );
1154				}
1155			}
1156			else
1157			{
1158				aoColumnsInit = oInit.aoColumns;
1159			}
1160			
1161			/* Add the columns */
1162			for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ )
1163			{
1164				_fnAddColumn( oSettings, anThs ? anThs[i] : null );
1165			}
1166			
1167			/* Apply the column definitions */
1168			_fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) {
1169				_fnColumnOptions( oSettings, iCol, oDef );
1170			} );
1171			
1172			/* HTML5 attribute detection - build an mData object automatically if the
1173			 * attributes are found
1174			 */
1175			if ( rowOne.length ) {
1176				var a = function ( cell, name ) {
1177					return cell.getAttribute( 'data-'+name ) !== null ? name : null;
1178				};
1179			
1180				$( rowOne[0] ).children('th, td').each( function (i, cell) {
1181					var col = oSettings.aoColumns[i];
1182			
1183					if ( col.mData === i ) {
1184						var sort = a( cell, 'sort' ) || a( cell, 'order' );
1185						var filter = a( cell, 'filter' ) || a( cell, 'search' );
1186			
1187						if ( sort !== null || filter !== null ) {
1188							col.mData = {
1189								_:      i+'.display',
1190								sort:   sort !== null   ? i+'.@data-'+sort   : undefined,
1191								type:   sort !== null   ? i+'.@data-'+sort   : undefined,
1192								filter: filter !== null ? i+'.@data-'+filter : undefined
1193							};
1194			
1195							_fnColumnOptions( oSettings, i );
1196						}
1197					}
1198				} );
1199			}
1200			
1201			var features = oSettings.oFeatures;
1202			var loadedInit = function () {
1203				/*
1204				 * Sorting
1205				 * @todo For modularisation (1.11) this needs to do into a sort start up handler
1206				 */
1207			
1208				// If aaSorting is not defined, then we use the first indicator in asSorting
1209				// in case that has been altered, so the default sort reflects that option
1210				if ( oInit.aaSorting === undefined ) {
1211					var sorting = oSettings.aaSorting;
1212					for ( i=0, iLen=sorting.length ; i<iLen ; i++ ) {
1213						sorting[i][1] = oSettings.aoColumns[ i ].asSorting[0];
1214					}
1215				}
1216			
1217				/* Do a first pass on the sorting classes (allows any size changes to be taken into
1218				 * account, and also will apply sorting disabled classes if disabled
1219				 */
1220				_fnSortingClasses( oSettings );
1221			
1222				if ( features.bSort ) {
1223					_fnCallbackReg( oSettings, 'aoDrawCallback', function () {
1224						if ( oSettings.bSorted ) {
1225							var aSort = _fnSortFlatten( oSettings );
1226							var sortedColumns = {};
1227			
1228							$.each( aSort, function (i, val) {
1229								sortedColumns[ val.src ] = val.dir;
1230							} );
1231			
1232							_fnCallbackFire( oSettings, null, 'order', [oSettings, aSort, sortedColumns] );
1233							_fnSortAria( oSettings );
1234						}
1235					} );
1236				}
1237			
1238				_fnCallbackReg( oSettings, 'aoDrawCallback', function () {
1239					if ( oSettings.bSorted || _fnDataSource( oSettings ) === 'ssp' || features.bDeferRender ) {
1240						_fnSortingClasses( oSettings );
1241					}
1242				}, 'sc' );
1243			
1244			
1245				/*
1246				 * Final init
1247				 * Cache the header, body and footer as required, creating them if needed
1248				 */
1249			
1250				// Work around for Webkit bug 83867 - store the caption-side before removing from doc
1251				var captions = $this.children('caption').each( function () {
1252					this._captionSide = $(this).css('caption-side');
1253				} );
1254			
1255				var thead = $this.children('thead');
1256				if ( thead.length === 0 ) {
1257					thead = $('<thead/>').appendTo($this);
1258				}
1259				oSettings.nTHead = thead[0];
1260			
1261				var tbody = $this.children('tbody');
1262				if ( tbody.length === 0 ) {
1263					tbody = $('<tbody/>').appendTo($this);
1264				}
1265				oSettings.nTBody = tbody[0];
1266			
1267				var tfoot = $this.children('tfoot');
1268				if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") ) {
1269					// If we are a scrolling table, and no footer has been given, then we need to create
1270					// a tfoot element for the caption element to be appended to
1271					tfoot = $('<tfoot/>').appendTo($this);
1272				}
1273			
1274				if ( tfoot.length === 0 || tfoot.children().length === 0 ) {
1275					$this.addClass( oClasses.sNoFooter );
1276				}
1277				else if ( tfoot.length > 0 ) {
1278					oSettings.nTFoot = tfoot[0];
1279					_fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );
1280				}
1281			
1282				/* Check if there is data passing into the constructor */
1283				if ( oInit.aaData ) {
1284					for ( i=0 ; i<oInit.aaData.length ; i++ ) {
1285						_fnAddData( oSettings, oInit.aaData[ i ] );
1286					}
1287				}
1288				else if ( oSettings.bDeferLoading || _fnDataSource( oSettings ) == 'dom' ) {
1289					/* Grab the data from the page - only do this when deferred loading or no Ajax
1290					 * source since there is no point in reading the DOM data if we are then going
1291					 * to replace it with Ajax data
1292					 */
1293					_fnAddTr( oSettings, $(oSettings.nTBody).children('tr') );
1294				}
1295			
1296				/* Copy the data index array */
1297				oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
1298			
1299				/* Initialisation complete - table can be drawn */
1300				oSettings.bInitialised = true;
1301			
1302				/* Check if we need to initialise the table (it might not have been handed off to the
1303				 * language processor)
1304				 */
1305				if ( bInitHandedOff === false ) {
1306					_fnInitialise( oSettings );
1307				}
1308			};
1309			
1310			/* Must be done after everything which can be overridden by the state saving! */
1311			if ( oInit.bStateSave )
1312			{
1313				features.bStateSave = true;
1314				_fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' );
1315				_fnLoadState( oSettings, oInit, loadedInit );
1316			}
1317			else {
1318				loadedInit();
1319			}
1320			
1321		} );
1322		_that = null;
1323		return this;
1324	};
1325
1326	
1327	/*
1328	 * It is useful to have variables which are scoped locally so only the
1329	 * DataTables functions can access them and they don't leak into global space.
1330	 * At the same time these functions are often useful over multiple files in the
1331	 * core and API, so we list, or at least document, all variables which are used
1332	 * by DataTables as private variables here. This also ensures that there is no
1333	 * clashing of variable names and that they can easily referenced for reuse.
1334	 */
1335	
1336	
1337	// Defined else where
1338	//  _selector_run
1339	//  _selector_opts
1340	//  _selector_first
1341	//  _selector_row_indexes
1342	
1343	var _ext; // DataTable.ext
1344	var _Api; // DataTable.Api
1345	var _api_register; // DataTable.Api.register
1346	var _api_registerPlural; // DataTable.Api.registerPlural
1347	
1348	var _re_dic = {};
1349	var _re_new_lines = /[\r\n]/g;
1350	var _re_html = /<.*?>/g;
1351	
1352	// This is not strict ISO8601 - Date.parse() is quite lax, although
1353	// implementations differ between browsers.
1354	var _re_date = /^\d{2,4}[\.\/\-]\d{1,2}[\.\/\-]\d{1,2}([T ]{1}\d{1,2}[:\.]\d{2}([\.:]\d{2})?)?$/;
1355	
1356	// Escape regular expression special characters
1357	var _re_escape_regex = new RegExp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' );
1358	
1359	// http://en.wikipedia.org/wiki/Foreign_exchange_market
1360	// - \u20BD - Russian ruble.
1361	// - \u20a9 - South Korean Won
1362	// - \u20BA - Turkish Lira
1363	// - \u20B9 - Indian Rupee
1364	// - R - Brazil (R$) and South Africa
1365	// - fr - Swiss Franc
1366	// - kr - Swedish krona, Norwegian krone and Danish krone
1367	// - \u2009 is thin space and \u202F is narrow no-break space, both used in many
1368	// - Ƀ - Bitcoin
1369	// - Ξ - Ethereum
1370	//   standards as thousands separators.
1371	var _re_formatted_numeric = /[',$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfkɃΞ]/gi;
1372	
1373	
1374	var _empty = function ( d ) {
1375		return !d || d === true || d === '-' ? true : false;
1376	};
1377	
1378	
1379	var _intVal = function ( s ) {
1380		var integer = parseInt( s, 10 );
1381		return !isNaN(integer) && isFinite(s) ? integer : null;
1382	};
1383	
1384	// Convert from a formatted number with characters other than `.` as the
1385	// decimal place, to a Javascript number
1386	var _numToDecimal = function ( num, decimalPoint ) {
1387		// Cache created regular expressions for speed as this function is called often
1388		if ( ! _re_dic[ decimalPoint ] ) {
1389			_re_dic[ decimalPoint ] = new RegExp( _fnEscapeRegex( decimalPoint ), 'g' );
1390		}
1391		return typeof num === 'string' && decimalPoint !== '.' ?
1392			num.replace( /\./g, '' ).replace( _re_dic[ decimalPoint ], '.' ) :
1393			num;
1394	};
1395	
1396	
1397	var _isNumber = function ( d, decimalPoint, formatted ) {
1398		var strType = typeof d === 'string';
1399	
1400		// If empty return immediately so there must be a number if it is a
1401		// formatted string (this stops the string "k", or "kr", etc being detected
1402		// as a formatted number for currency
1403		if ( _empty( d ) ) {
1404			return true;
1405		}
1406	
1407		if ( decimalPoint && strType ) {
1408			d = _numToDecimal( d, decimalPoint );
1409		}
1410	
1411		if ( formatted && strType ) {
1412			d = d.replace( _re_formatted_numeric, '' );
1413		}
1414	
1415		return !isNaN( parseFloat(d) ) && isFinite( d );
1416	};
1417	
1418	
1419	// A string without HTML in it can be considered to be HTML still
1420	var _isHtml = function ( d ) {
1421		return _empty( d ) || typeof d === 'string';
1422	};
1423	
1424	
1425	var _htmlNumeric = function ( d, decimalPoint, formatted ) {
1426		if ( _empty( d ) ) {
1427			return true;
1428		}
1429	
1430		var html = _isHtml( d );
1431		return ! html ?
1432			null :
1433			_isNumber( _stripHtml( d ), decimalPoint, formatted ) ?
1434				true :
1435				null;
1436	};
1437	
1438	
1439	var _pluck = function ( a, prop, prop2 ) {
1440		var out = [];
1441		var i=0, ien=a.length;
1442	
1443		// Could have the test in the loop for slightly smaller code, but speed
1444		// is essential here
1445		if ( prop2 !== undefined ) {
1446			for ( ; i<ien ; i++ ) {
1447				if ( a[i] && a[i][ prop ] ) {
1448					out.push( a[i][ prop ][ prop2 ] );
1449				}
1450			}
1451		}
1452		else {
1453			for ( ; i<ien ; i++ ) {
1454				if ( a[i] ) {
1455					out.push( a[i][ prop ] );
1456				}
1457			}
1458		}
1459	
1460		return out;
1461	};
1462	
1463	
1464	// Basically the same as _pluck, but rather than looping over `a` we use `order`
1465	// as the indexes to pick from `a`
1466	var _pluck_order = function ( a, order, prop, prop2 )
1467	{
1468		var out = [];
1469		var i=0, ien=order.length;
1470	
1471		// Could have the test in the loop for slightly smaller code, but speed
1472		// is essential here
1473		if ( prop2 !== undefined ) {
1474			for ( ; i<ien ; i++ ) {
1475				if ( a[ order[i] ][ prop ] ) {
1476					out.push( a[ order[i] ][ prop ][ prop2 ] );
1477				}
1478			}
1479		}
1480		else {
1481			for ( ; i<ien ; i++ ) {
1482				out.push( a[ order[i] ][ prop ] );
1483			}
1484		}
1485	
1486		return out;
1487	};
1488	
1489	
1490	var _range = function ( len, start )
1491	{
1492		var out = [];
1493		var end;
1494	
1495		if ( start === undefined ) {
1496			start = 0;
1497			end = len;
1498		}
1499		else {
1500			end = start;
1501			start = len;
1502		}
1503	
1504		for ( var i=start ; i<end ; i++ ) {
1505			out.push( i );
1506		}
1507	
1508		return out;
1509	};
1510	
1511	
1512	var _removeEmpty = function ( a )
1513	{
1514		var out = [];
1515	
1516		for ( var i=0, ien=a.length ; i<ien ; i++ ) {
1517			if ( a[i] ) { // careful - will remove all falsy values!
1518				out.push( a[i] );
1519			}
1520		}
1521	
1522		return out;
1523	};
1524	
1525	
1526	var _stripHtml = function ( d ) {
1527		return d.replace( _re_html, '' );
1528	};
1529	
1530	
1531	/**
1532	 * Determine if all values in the array are unique. This means we can short
1533	 * cut the _unique method at the cost of a single loop. A sorted array is used
1534	 * to easily check the values.
1535	 *
1536	 * @param  {array} src Source array
1537	 * @return {boolean} true if all unique, false otherwise
1538	 * @ignore
1539	 */
1540	var _areAllUnique = function ( src ) {
1541		if ( src.length < 2 ) {
1542			return true;
1543		}
1544	
1545		var sorted = src.slice().sort();
1546		var last = sorted[0];
1547	
1548		for ( var i=1, ien=sorted.length ; i<ien ; i++ ) {
1549			if ( sorted[i] === last ) {
1550				return false;
1551			}
1552	
1553			last = sorted[i];
1554		}
1555	
1556		return true;
1557	};
1558	
1559	
1560	/**
1561	 * Find the unique elements in a source array.
1562	 *
1563	 * @param  {array} src Source array
1564	 * @return {array} Array of unique items
1565	 * @ignore
1566	 */
1567	var _unique = function ( src )
1568	{
1569		if ( _areAllUnique( src ) ) {
1570			return src.slice();
1571		}
1572	
1573		// A faster unique method is to use object keys to identify used values,
1574		// but this doesn't work with arrays or objects, which we must also
1575		// consider. See jsperf.com/compare-array-unique-versions/4 for more
1576		// information.
1577		var
1578			out = [],
1579			val,
1580			i, ien=src.length,
1581			j, k=0;
1582	
1583		again: for ( i=0 ; i<ien ; i++ ) {
1584			val = src[i];
1585	
1586			for ( j=0 ; j<k ; j++ ) {
1587				if ( out[j] === val ) {
1588					continue again;
1589				}
1590			}
1591	
1592			out.push( val );
1593			k++;
1594		}
1595	
1596		return out;
1597	};
1598	
1599	
1600	/**
1601	 * DataTables utility methods
1602	 * 
1603	 * This namespace provides helper methods that DataTables uses internally to
1604	 * create a DataTable, but which are not exclusively used only for DataTables.
1605	 * These methods can be used by extension authors to save the duplication of
1606	 * code.
1607	 *
1608	 *  @namespace
1609	 */
1610	DataTable.util = {
1611		/**
1612		 * Throttle the calls to a function. Arguments and context are maintained
1613		 * for the throttled function.
1614		 *
1615		 * @param {function} fn Function to be called
1616		 * @param {integer} freq Call frequency in mS
1617		 * @return {function} Wrapped function
1618		 */
1619		throttle: function ( fn, freq ) {
1620			var
1621				frequency = freq !== undefined ? freq : 200,
1622				last,
1623				timer;
1624	
1625			return function () {
1626				var
1627					that = this,
1628					now  = +new Date(),
1629					args = arguments;
1630	
1631				if ( last && now < last + frequency ) {
1632					clearTimeout( timer );
1633	
1634					timer = setTimeout( function () {
1635						last = undefined;
1636						fn.apply( that, args );
1637					}, frequency );
1638				}
1639				else {
1640					last = now;
1641					fn.apply( that, args );
1642				}
1643			};
1644		},
1645	
1646	
1647		/**
1648		 * Escape a string such that it can be used in a regular expression
1649		 *
1650		 *  @param {string} val string to escape
1651		 *  @returns {string} escaped string
1652		 */
1653		escapeRegex: function ( val ) {
1654			return val.replace( _re_escape_regex, '\\$1' );
1655		}
1656	};
1657	
1658	
1659	
1660	/**
1661	 * Create a mapping object that allows camel case parameters to be looked up
1662	 * for their Hungarian counterparts. The mapping is stored in a private
1663	 * parameter called `_hungarianMap` which can be accessed on the source object.
1664	 *  @param {object} o
1665	 *  @memberof DataTable#oApi
1666	 */
1667	function _fnHungarianMap ( o )
1668	{
1669		var
1670			hungarian = 'a aa ai ao as b fn i m o s ',
1671			match,
1672			newKey,
1673			map = {};
1674	
1675		$.each( o, function (key, val) {
1676			match = key.match(/^([^A-Z]+?)([A-Z])/);
1677	
1678			if ( match && hungarian.indexOf(match[1]+' ') !== -1 )
1679			{
1680				newKey = key.replace( match[0], match[2].toLowerCase() );
1681				map[ newKey ] = key;
1682	
1683				if ( match[1] === 'o' )
1684				{
1685					_fnHungarianMap( o[key] );
1686				}
1687			}
1688		} );
1689	
1690		o._hungarianMap = map;
1691	}
1692	
1693	
1694	/**
1695	 * Convert from camel case parameters to Hungarian, based on a Hungarian map
1696	 * created by _fnHungarianMap.
1697	 *  @param {object} src The model object which holds all parameters that can be
1698	 *    mapped.
1699	 *  @param {object} user The object to convert from camel case to Hungarian.
1700	 *  @param {boolean} force When set to `true`, properties which already have a
1701	 *    Hungarian value in the `user` object will be overwritten. Otherwise they
1702	 *    won't be.
1703	 *  @memberof DataTable#oApi
1704	 */
1705	function _fnCamelToHungarian ( src, user, force )
1706	{
1707		if ( ! src._hungarianMap ) {
1708			_fnHungarianMap( src );
1709		}
1710	
1711		var hungarianKey;
1712	
1713		$.each( user, function (key, val) {
1714			hungarianKey = src._hungarianMap[ key ];
1715	
1716			if ( hungarianKey !== undefined && (force || user[hungarianKey] === undefined) )
1717			{
1718				// For objects, we need to buzz down into the object to copy parameters
1719				if ( hungarianKey.charAt(0) === 'o' )
1720				{
1721					// Copy the camelCase options over to the hungarian
1722					if ( ! user[ hungarianKey ] ) {
1723						user[ hungarianKey ] = {};
1724					}
1725					$.extend( true, user[hungarianKey], user[key] );
1726	
1727					_fnCamelToHungarian( src[hungarianKey], user[hungarianKey], force );
1728				}
1729				else {
1730					user[hungarianKey] = user[ key ];
1731				}
1732			}
1733		} );
1734	}
1735	
1736	
1737	/**
1738	 * Language compatibility - when certain options are given, and others aren't, we
1739	 * need to duplicate the values over, in order to provide backwards compatibility
1740	 * with older language files.
1741	 *  @param {object} oSettings dataTables settings object
1742	 *  @memberof DataTable#oApi
1743	 */
1744	function _fnLanguageCompat( lang )
1745	{
1746		// Note the use of the Hungarian notation for the parameters in this method as
1747		// this is called after the mapping of camelCase to Hungarian
1748		var defaults = DataTable.defaults.oLanguage;
1749	
1750		// Default mapping
1751		var defaultDecimal = defaults.sDecimal;
1752		if ( defaultDecimal ) {
1753			_addNumericSort( defaultDecimal );
1754		}
1755	
1756		if ( lang ) {
1757			var zeroRecords = lang.sZeroRecords;
1758	
1759			// Backwards compatibility - if there is no sEmptyTable given, then use the same as
1760			// sZeroRecords - assuming that is given.
1761			if ( ! lang.sEmptyTable && zeroRecords &&
1762				defaults.sEmptyTable === "No data available in table" )
1763			{
1764				_fnMap( lang, lang, 'sZeroRecords', 'sEmptyTable' );
1765			}
1766	
1767			// Likewise with loading records
1768			if ( ! lang.sLoadingRecords && zeroRecords &&
1769				defaults.sLoadingRecords === "Loading..." )
1770			{
1771				_fnMap( lang, lang, 'sZeroRecords', 'sLoadingRecords' );
1772			}
1773	
1774			// Old parameter name of the thousands separator mapped onto the new
1775			if ( lang.sInfoThousands ) {
1776				lang.sThousands = lang.sInfoThousands;
1777			}
1778	
1779			var decimal = lang.sDecimal;
1780			if ( decimal && defaultDecimal !== decimal ) {
1781				_addNumericSort( decimal );
1782			}
1783		}
1784	}
1785	
1786	
1787	/**
1788	 * Map one parameter onto another
1789	 *  @param {object} o Object to map
1790	 *  @param {*} knew The new parameter name
1791	 *  @param {*} old The old parameter name
1792	 */
1793	var _fnCompatMap = function ( o, knew, old ) {
1794		if ( o[ knew ] !== undefined ) {
1795			o[ old ] = o[ knew ];
1796		}
1797	};
1798	
1799	
1800	/**
1801	 * Provide backwards compatibility for the main DT options. Note that the new
1802	 * options are mapped onto the old parameters, so this is an external interface
1803	 * change only.
1804	 *  @param {object} init Object to map
1805	 */
1806	function _fnCompatOpts ( init )
1807	{
1808		_fnCompatMap( init, 'ordering',      'bSort' );
1809		_fnCompatMap( init, 'orderMulti',    'bSortMulti' );
1810		_fnCompatMap( init, 'orderClasses',  'bSortClasses' );
1811		_fnCompatMap( init, 'orderCellsTop', 'bSortCellsTop' );
1812		_fnCompatMap( init, 'order',         'aaSorting' );
1813		_fnCompatMap( init, 'orderFixed',    'aaSortingFixed' );
1814		_fnCompatMap( init, 'paging',        'bPaginate' );
1815		_fnCompatMap( init, 'pagingType',    'sPaginationType' );
1816		_fnCompatMap( init, 'pageLength',    'iDisplayLength' );
1817		_fnCompatMap( init, 'searching',     'bFilter' );
1818	
1819		// Boolean initialisation of x-scrolling
1820		if ( typeof init.sScrollX === 'boolean' ) {
1821			init.sScrollX = init.sScrollX ? '100%' : '';
1822		}
1823		if ( typeof init.scrollX === 'boolean' ) {
1824			init.scrollX = init.scrollX ? '100%' : '';
1825		}
1826	
1827		// Column search objects are in an array, so it needs to be converted
1828		// element by element
1829		var searchCols = init.aoSearchCols;
1830	
1831		if ( searchCols ) {
1832			for ( var i=0, ien=searchCols.length ; i<ien ; i++ ) {
1833				if ( searchCols[i] ) {
1834					_fnCamelToHungarian( DataTable.models.oSearch, searchCols[i] );
1835				}
1836			}
1837		}
1838	}
1839	
1840	
1841	/**
1842	 * Provide backwards compatibility for column options. Note that the new options
1843	 * are mapped onto the old parameters, so this is an external interface change
1844	 * only.
1845	 *  @param {object} init Object to map
1846	 */
1847	function _fnCompatCols ( init )
1848	{
1849		_fnCompatMap( init, 'orderable',     'bSortable' );
1850		_fnCompatMap( init, 'orderData',     'aDataSort' );
1851		_fnCompatMap( init, 'orderSequence', 'asSorting' );
1852		_fnCompatMap( init, 'orderDataType', 'sortDataType' );
1853	
1854		// orderData can be given as an integer
1855		var dataSort = init.aDataSort;
1856		if ( typeof dataSort === 'number' && ! $.isArray( dataSort ) ) {
1857			init.aDataSort = [ dataSort ];
1858		}
1859	}
1860	
1861	
1862	/**
1863	 * Browser feature detection for capabilities, quirks
1864	 *  @param {object} settings dataTables settings object
1865	 *  @memberof DataTable#oApi
1866	 */
1867	function _fnBrowserDetect( settings )
1868	{
1869		// We don't need to do this every time DataTables is constructed, the values
1870		// calculated are specific to the browser and OS configuration which we
1871		// don't expect to change between initialisations
1872		if ( ! DataTable.__browser ) {
1873			var browser = {};
1874			DataTable.__browser = browser;
1875	
1876			// Scrolling feature / quirks detection
1877			var n = $('<div/>')
1878				.css( {
1879					position: 'fixed',
1880					top: 0,
1881					left: $(window).scrollLeft()*-1, // allow for scrolling
1882					height: 1,
1883					width: 1,
1884					overflow: 'hidden'
1885				} )
1886				.append(
1887					$('<div/>')
1888						.css( {
1889							position: 'absolute',
1890							top: 1,
1891							left: 1,
1892							width: 100,
1893							overflow: 'scroll'
1894						} )
1895						.append(
1896							$('<div/>')
1897								.css( {
1898									width: '100%',
1899									height: 10
1900								} )
1901						)
1902				)
1903				.appendTo( 'body' );
1904	
1905			var outer = n.children();
1906			var inner = outer.children();
1907	
1908			// Numbers below, in order, are:
1909			// inner.offsetWidth, inner.clientWidth, outer.offsetWidth, outer.clientWidth
1910			//
1911			// IE6 XP:                           100 100 100  83
1912			// IE7 Vista:                        100 100 100  83
1913			// IE 8+ Windows:                     83  83 100  83
1914			// Evergreen Windows:                 83  83 100  83
1915			// Evergreen Mac with scrollbars:     85  85 100  85
1916			// Evergreen Mac without scrollbars: 100 100 100 100
1917	
1918			// Get scrollbar width
1919			browser.barWidth = outer[0].offsetWidth - outer[0].clientWidth;
1920	
1921			// IE6/7 will oversize a width 100% element inside a scrolling element, to
1922			// include the width of the scrollbar, while other browsers ensure the inner
1923			// element is contained without forcing scrolling
1924			browser.bScrollOversize = inner[0].offsetWidth === 100 && outer[0].clientWidth !== 100;
1925	
1926			// In rtl text layout, some browsers (most, but not all) will place the
1927			// scrollbar on the left, rather than the right.
1928			browser.bScrollbarLeft = Math.round( inner.offset().left ) !== 1;
1929	
1930			// IE8- don't provide height and width for getBoundingClientRect
1931			browser.bBounding = n[0].getBoundingClientRect().width ? true : false;
1932	
1933			n.remove();
1934		}
1935	
1936		$.extend( settings.oBrowser, DataTable.__browser );
1937		settings.oScroll.iBarWidth = DataTable.__browser.barWidth;
1938	}
1939	
1940	
1941	/**
1942	 * Array.prototype reduce[Right] method, used for browsers which don't support
1943	 * JS 1.6. Done this way to reduce code size, since we iterate either way
1944	 *  @param {object} settings dataTables settings object
1945	 *  @memberof DataTable#oApi
1946	 */
1947	function _fnReduce ( that, fn, init, start, end, inc )
1948	{
1949		var
1950			i = start,
1951			value,
1952			isSet = false;
1953	
1954		if ( init !== undefined ) {
1955			value = init;
1956			isSet = true;
1957		}
1958	
1959		while ( i !== end ) {
1960			if ( ! that.hasOwnProperty(i) ) {
1961				continue;
1962			}
1963	
1964			value = isSet ?
1965				fn( value, that[i], i, that ) :
1966				that[i];
1967	
1968			isSet = true;
1969			i += inc;
1970		}
1971	
1972		return value;
1973	}
1974	
1975	/**
1976	 * Add a column to the list used for the table with default values
1977	 *  @param {object} oSettings dataTables settings object
1978	 *  @param {node} nTh The th element for this column
1979	 *  @memberof DataTable#oApi
1980	 */
1981	function _fnAddColumn( oSettings, nTh )
1982	{
1983		// Add column to aoColumns array
1984		var oDefaults = DataTable.defaults.column;
1985		var iCol = oSettings.aoColumns.length;
1986		var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {
1987			"nTh": nTh ? nTh : document.createElement('th'),
1988			"sTitle":    oDefaults.sTitle    ? oDefaults.sTitle    : nTh ? nTh.innerHTML : '',
1989			"aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],
1990			"mData": oDefaults.mData ? oDefaults.mData : iCol,
1991			idx: iCol
1992		} );
1993		oSettings.aoColumns.push( oCol );
1994	
1995		// Add search object for column specific search. Note that the `searchCols[ iCol ]`
1996		// passed into extend can be undefined. This allows the user to give a default
1997		// with only some of the parameters defined, and also not give a default
1998		var searchCols = oSettings.aoPreSearchCols;
1999		searchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] );
2000	
2001		// Use the default column options function to initialise classes etc
2002		_fnColumnOptions( oSettings, iCol, $(nTh).data() );
2003	}
2004	
2005	
2006	/**
2007	 * Apply options for a column
2008	 *  @param {object} oSettings dataTables settings object
2009	 *  @param {int} iCol column index to consider
2010	 *  @param {object} oOptions object with sType, bVisible and bSearchable etc
2011	 *  @memberof DataTable#oApi
2012	 */
2013	function _fnColumnOptions( oSettings, iCol, oOptions )
2014	{
2015		var oCol = oSettings.aoColumns[ iCol ];
2016		var oClasses = oSettings.oClasses;
2017		var th = $(oCol.nTh);
2018	
2019		// Try to get width information from the DOM. We can't get it from CSS
2020		// as we'd need to parse the CSS stylesheet. `width` option can override
2021		if ( ! oCol.sWidthOrig ) {
2022			// Width attribute
2023			oCol.sWidthOrig = th.attr('width') || null;
2024	
2025			// Style attribute
2026			var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/);
2027			if ( t ) {
2028				oCol.sWidthOrig = t[1];
2029			}
2030		}
2031	
2032		/* User specified column options */
2033		if ( oOptions !== undefined && oOptions !== null )
2034		{
2035			// Backwards compatibility
2036			_fnCompatCols( oOptions );
2037	
2038			// Map camel case parameters to their Hungarian counterparts
2039			_fnCamelToHungarian( DataTable.defaults.column, oOptions );
2040	
2041			/* Backwards compatibility for mDataProp */
2042			if ( oOptions.mDataProp !== undefined && !oOptions.mData )
2043			{
2044				oOptions.mData = oOptions.mDataProp;
2045			}
2046	
2047			if ( oOptions.sType )
2048			{
2049				oCol._sManualType = oOptions.sType;
2050			}
2051	
2052			// `class` is a reserved word in Javascript, so we need to provide
2053			// the ability to use a valid name for the camel case input
2054			if ( oOptions.className && ! oOptions.sClass )
2055			{
2056				oOptions.sClass = oOptions.className;
2057			}
2058			if ( oOptions.sClass ) {
2059				th.addClass( oOptions.sClass );
2060			}
2061	
2062			$.extend( oCol, oOptions );
2063			_fnMap( oCol, oOptions, "sWidth", "sWidthOrig" );
2064	
2065			/* iDataSort to be applied (backwards compatibility), but aDataSort will take
2066			 * priority if defined
2067			 */
2068			if ( oOptions.iDataSort !== undefined )
2069			{
2070				oCol.aDataSort = [ oOptions.iDataSort ];
2071			}
2072			_fnMap( oCol, oOptions, "aDataSort" );
2073		}
2074	
2075		/* Cache the data get and set functions for speed */
2076		var mDataSrc = oCol.mData;
2077		var mData = _fnGetObjectDataFn( mDataSrc );
2078		var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null;
2079	
2080		var attrTest = function( src ) {
2081			return typeof src === 'string' && src.indexOf('@') !== -1;
2082		};
2083		oCol._bAttrSrc = $.isPlainObject( mDataSrc ) && (
2084			attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter)
2085		);
2086		oCol._setter = null;
2087	
2088		oCol.fnGetData = function (rowData, type, meta) {
2089			var innerData = mData( rowData, type, undefined, meta );
2090	
2091			return mRender && type ?
2092				mRender( innerData, type, rowData, meta ) :
2093				innerData;
2094		};
2095		oCol.fnSetData = function ( rowData, val, meta ) {
2096			return _fnSetObjectDataFn( mDataSrc )( rowData, val, meta );
2097		};
2098	
2099		// Indicate if DataTables should read DOM data as an object or array
2100		// Used in _fnGetRowElements
2101		if ( typeof mDataSrc !== 'number' ) {
2102			oSettings._rowReadObject = true;
2103		}
2104	
2105		/* Feature sorting overrides column specific when off */
2106		if ( !oSettings.oFeatures.bSort )
2107		{
2108			oCol.bSortable = false;
2109			th.addClass( oClasses.sSortableNone ); // Have to add class here as order event isn't called
2110		}
2111	
2112		/* Check that the class assignment is correct for sorting */
2113		var bAsc = $.inArray('asc', oCol.asSorting) !== -1;
2114		var bDesc = $.inArray('desc', oCol.asSorting) !== -1;
2115		if ( !oCol.bSortable || (!bAsc && !bDesc) )
2116		{
2117			oCol.sSortingClass = oClasses.sSortableNone;
2118			oCol.sSortingClassJUI = "";
2119		}
2120		else if ( bAsc && !bDesc )
2121		{
2122			oCol.sSortingClass = oClasses.sSortableAsc;
2123			oCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed;
2124		}
2125		else if ( !bAsc && bDesc )
2126		{
2127			oCol.sSortingClass = oClasses.sSortableDesc;
2128			oCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed;
2129		}
2130		else
2131		{
2132			oCol.sSortingClass = oClasses.sSortable;
2133			oCol.sSortingClassJUI = oClasses.sSortJUI;
2134		}
2135	}
2136	
2137	
2138	/**
2139	 * Adjust the table column widths for new data. Note: you would probably want to
2140	 * do a redraw after calling this function!
2141	 *  @param {object} settings dataTables settings object
2142	 *  @memberof DataTable#oApi
2143	 */
2144	function _fnAdjustColumnSizing ( settings )
2145	{
2146		/* Not interested in doing column width calculation if auto-width is disabled */
2147		if ( settings.oFeatures.bAutoWidth !== false )
2148		{
2149			var columns = settings.aoColumns;
2150	
2151			_fnCalculateColumnWidths( settings );
2152			for ( var i=0 , iLen=columns.length ; i<iLen ; i++ )
2153			{
2154				columns[i].nTh.style.width = columns[i].sWidth;
2155			}
2156		}
2157	
2158		var scroll = settings.oScroll;
2159		if ( scroll.sY !== '' || scroll.sX !== '')
2160		{
2161			_fnScrollDraw( settings );
2162		}
2163	
2164		_fnCallbackFire( settings, null, 'column-sizing', [settings] );
2165	}
2166	
2167	
2168	/**
2169	 * Covert the index of a visible column to the index in the data array (take account
2170	 * of hidden columns)
2171	 *  @param {object} oSettings dataTables settings object
2172	 *  @param {int} iMatch Visible column index to lookup
2173	 *  @returns {int} i the data index
2174	 *  @memberof DataTable#oApi
2175	 */
2176	function _fnVisibleToColumnIndex( oSettings, iMatch )
2177	{
2178		var aiVis = _fnGetColumns( oSettings, 'bVisible' );
2179	
2180		return typeof aiVis[iMatch] === 'number' ?
2181			aiVis[iMatch] :
2182			null;
2183	}
2184	
2185	
2186	/**
2187	 * Covert the index of an index in the data array and convert it to the visible
2188	 *   column index (take account of hidden columns)
2189	 *  @param {int} iMatch Column index to lookup
2190	 *  @param {object} oSettings dataTables settings object
2191	 *  @returns {int} i the data index
2192	 *  @memberof DataTable#oApi
2193	 */
2194	function _fnColumnIndexToVisible( oSettings, iMatch )
2195	{
2196		var aiVis = _fnGetColumns( oSettings, 'bVisible' );
2197		var iPos = $.inArray( iMatch, aiVis );
2198	
2199		return iPos !== -1 ? iPos : null;
2200	}
2201	
2202	
2203	/**
2204	 * Get the number of visible columns
2205	 *  @param {object} oSettings dataTables settings object
2206	 *  @returns {int} i the number of visible columns
2207	 *  @memberof DataTable#oApi
2208	 */
2209	function _fnVisbleColumns( oSettings )
2210	{
2211		var vis = 0;
2212	
2213		// No reduce in IE8, use a loop for now
2214		$.each( oSettings.aoColumns, function ( i, col ) {
2215			if ( col.bVisible && $(col.nTh).css('display') !== 'none' ) {
2216				vis++;
2217			}
2218		} );
2219	
2220		return vis;
2221	}
2222	
2223	
2224	/**
2225	 * Get an array of column indexes that match a given property
2226	 *  @param {object} oSettings dataTables settings object
2227	 *  @param {string} sParam Parameter in aoColumns to look for - typically
2228	 *    bVisible or bSearchable
2229	 *  @returns {array} Array of indexes with matched properties
2230	 *  @memberof DataTable#oApi
2231	 */
2232	function _fnGetColumns( oSettings, sParam )
2233	{
2234		var a = [];
2235	
2236		$.map( oSettings.aoColumns, function(val, i) {
2237			if ( val[sParam] ) {
2238				a.push( i );
2239			}
2240		} );
2241	
2242		return a;
2243	}
2244	
2245	
2246	/**
2247	 * Calculate the 'type' of a column
2248	 *  @param {object} settings dataTables settings object
2249	 *  @memberof DataTable#oApi
2250	 */
2251	function _fnColumnTypes ( settings )
2252	{
2253		var columns = settings.aoColumns;
2254		var data = settings.aoData;
2255		var types = DataTable.ext.type.detect;
2256		var i, ien, j, jen, k, ken;
2257		var col, cell, detectedType, cache;
2258	
2259		// For each column, spin over the 
2260		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
2261			col = columns[i];
2262			cache = [];
2263	
2264			if ( ! col.sType && col._sManualType ) {
2265				col.sType = col._sManualType;
2266			}
2267			else if ( ! col.sType ) {
2268				for ( j=0, jen=types.length ; j<jen ; j++ ) {
2269					for ( k=0, ken=data.length ; k<ken ; k++ ) {
2270						// Use a cache array so we only need to get the type data
2271						// from the formatter once (when using multiple detectors)
2272						if ( cache[k] === undefined ) {
2273							cache[k] = _fnGetCellData( settings, k, i, 'type' );
2274						}
2275	
2276						detectedType = types[j]( cache[k], settings );
2277	
2278						// If null, then this type can't apply to this column, so
2279						// rather than testing all cells, break out. There is an
2280						// exception for the last type which is `html`. We need to
2281						// scan all rows since it is possible to mix string and HTML
2282						// types
2283						if ( ! detectedType && j !== types.length-1 ) {
2284							break;
2285						}
2286	
2287						// Only a single match is needed for html type since it is
2288						// bottom of the pile and very similar to string
2289						if ( detectedType === 'html' ) {
2290							break;
2291						}
2292					}
2293	
2294					// Type is valid for all data points in the column - use this
2295					// type
2296					if ( detectedType ) {
2297						col.sType = detectedType;
2298						break;
2299					}
2300				}
2301	
2302				// Fall back - if no type was detected, always use string
2303				if ( ! col.sType ) {
2304					col.sType = 'string';
2305				}
2306			}
2307		}
2308	}
2309	
2310	
2311	/**
2312	 * Take the column definitions and static columns arrays and calculate how
2313	 * they relate to column indexes. The callback function will then apply the
2314	 * definition found for a column to a suitable configuration object.
2315	 *  @param {object} oSettings dataTables settings object
2316	 *  @param {array} aoColDefs The aoColumnDefs array that is to be applied
2317	 *  @param {array} aoCols The aoColumns array that defines columns individually
2318	 *  @param {function} fn Callback function - takes two parameters, the calculated
2319	 *    column index and the definition for that column.
2320	 *  @memberof DataTable#oApi
2321	 */
2322	function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )
2323	{
2324		var i, iLen, j, jLen, k, kLen, def;
2325		var columns = oSettings.aoColumns;
2326	
2327		// Column definitions with aTargets
2328		if ( aoColDefs )
2329		{
2330			/* Loop over the definitions array - loop in reverse so first instance has priority */
2331			for ( i=aoColDefs.length-1 ; i>=0 ; i-- )
2332			{
2333				def = aoColDefs[i];
2334	
2335				/* Each definition can target multiple columns, as it is an array */
2336				var aTargets = def.targets !== undefined ?
2337					def.targets :
2338					def.aTargets;
2339	
2340				if ( ! $.isArray( aTargets ) )
2341				{
2342					aTargets = [ aTargets ];
2343				}
2344	
2345				for ( j=0, jLen=aTargets.length ; j<jLen ; j++ )
2346				{
2347					if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 )
2348					{
2349						/* Add columns that we don't yet know about */
2350						while( columns.length <= aTargets[j] )
2351						{
2352							_fnAddColumn( oSettings );
2353						}
2354	
2355						/* Integer, basic index */
2356						fn( aTargets[j], def );
2357					}
2358					else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 )
2359					{
2360						/* Negative integer, right to left column counting */
2361						fn( columns.length+aTargets[j], def );
2362					}
2363					else if ( typeof aTargets[j] === 'string' )
2364					{
2365						/* Class name matching on TH element */
2366						for ( k=0, kLen=columns.length ; k<kLen ; k++ )
2367						{
2368							if ( aTargets[j] == "_all" ||
2369							     $(columns[k].nTh).hasClass( aTargets[j] ) )
2370							{
2371								fn( k, def );
2372							}
2373						}
2374					}
2375				}
2376			}
2377		}
2378	
2379		// Statically defined columns array
2380		if ( aoCols )
2381		{
2382			for ( i=0, iLen=aoCols.length ; i<iLen ; i++ )
2383			{
2384				fn( i, aoCols[i] );
2385			}
2386		}
2387	}
2388	
2389	/**
2390	 * Add a data array to the table, creating DOM node etc. This is the parallel to
2391	 * _fnGatherData, but for adding rows from a Javascript source, rather than a
2392	 * DOM source.
2393	 *  @param {object} oSettings dataTables settings object
2394	 *  @param {array} aData data array to be added
2395	 *  @param {node} [nTr] TR element to add to the table - optional. If not given,
2396	 *    DataTables will create a row automatically
2397	 *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
2398	 *    if nTr is.
2399	 *  @returns {int} >=0 if successful (index of new aoData entry), -1 if failed
2400	 *  @memberof DataTable#oApi
2401	 */
2402	function _fnAddData ( oSettings, aDataIn, nTr, anTds )
2403	{
2404		/* Create the object for storing information about this new row */
2405		var iRow = oSettings.aoData.length;
2406		var oData = $.extend( true, {}, DataTable.models.oRow, {
2407			src: nTr ? 'dom' : 'data',
2408			idx: iRow
2409		} );
2410	
2411		oData._aData = aDataIn;
2412		oSettings.aoData.push( oData );
2413	
2414		/* Create the cells */
2415		var nTd, sThisType;
2416		var columns = oSettings.aoColumns;
2417	
2418		// Invalidate the column types as the new data needs to be revalidated
2419		for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
2420		{
2421			columns[i].sType = null;
2422		}
2423	
2424		/* Add to the display array */
2425		oSettings.aiDisplayMaster.push( iRow );
2426	
2427		var id = oSettings.rowIdFn( aDataIn );
2428		if ( id !== undefined ) {
2429			oSettings.aIds[ id ] = oData;
2430		}
2431	
2432		/* Create the DOM information, or register it if already present */
2433		if ( nTr || ! oSettings.oFeatures.bDeferRender )
2434		{
2435			_fnCreateTr( oSettings, iRow, nTr, anTds );
2436		}
2437	
2438		return iRow;
2439	}
2440	
2441	
2442	/**
2443	 * Add one or more TR elements to the table. Generally we'd expect to
2444	 * use this for reading data from a DOM sourced table, but it could be
2445	 * used for an TR element. Note that if a TR is given, it is used (i.e.
2446	 * it is not cloned).
2447	 *  @param {object} settings dataTables settings object
2448	 *  @param {array|node|jQuery} trs The TR element(s) to add to the table
2449	 *  @returns {array} Array of indexes for the added rows
2450	 *  @memberof DataTable#oApi
2451	 */
2452	function _fnAddTr( settings, trs )
2453	{
2454		var row;
2455	
2456		// Allow an individual node to be passed in
2457		if ( ! (trs instanceof $) ) {
2458			trs = $(trs);
2459		}
2460	
2461		return trs.map( function (i, el) {
2462			row = _fnGetRowElements( settings, el );
2463			return _fnAddData( settings, row.data, el, row.cells );
2464		} );
2465	}
2466	
2467	
2468	/**
2469	 * Take a TR element and convert it to an index in aoData
2470	 *  @param {object} oSettings dataTables settings object
2471	 *  @param {node} n the TR element to find
2472	 *  @returns {int} index if the node is found, null if not
2473	 *  @memberof DataTable#oApi
2474	 */
2475	function _fnNodeToDataIndex( oSettings, n )
2476	{
2477		return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null;
2478	}
2479	
2480	
2481	/**
2482	 * Take a TD element and convert it into a column data index (not the visible index)
2483	 *  @param {object} oSettings dataTables settings object
2484	 *  @param {int} iRow The row number the TD/TH can be found in
2485	 *  @param {node} n The TD/TH element to find
2486	 *  @returns {int} index if the node is found, -1 if not
2487	 *  @memberof DataTable#oApi
2488	 */
2489	function _fnNodeToColumnIndex( oSettings, iRow, n )
2490	{
2491		return $.inArray( n, oSettings.aoData[ iRow ].anCells );
2492	}
2493	
2494	
2495	/**
2496	 * Get the data for a given cell from the internal cache, taking into account data mapping
2497	 *  @param {object} settings dataTables settings object
2498	 *  @param {int} rowIdx aoData row id
2499	 *  @param {int} colIdx Column index
2500	 *  @param {string} type data get type ('display', 'type' 'filter' 'sort')
2501	 *  @returns {*} Cell data
2502	 *  @memberof DataTable#oApi
2503	 */
2504	function _fnGetCellData( settings, rowIdx, colIdx, type )
2505	{
2506		var draw           = settings.iDraw;
2507		var col            = settings.aoColumns[colIdx];
2508		var rowData        = settings.aoData[rowIdx]._aData;
2509		var defaultContent = col.sDefaultContent;
2510		var cellData       = col.fnGetData( rowData, type, {
2511			settings: settings,
2512			row:      rowIdx,
2513			col:      colIdx
2514		} );
2515	
2516		if ( cellData === undefined ) {
2517			if ( settings.iDrawError != draw && defaultContent === null ) {
2518				_fnLog( settings, 0, "Requested unknown parameter "+
2519					(typeof col.mData=='function' ? '{function}' : "'"+col.mData+"'")+
2520					" for row "+rowIdx+", column "+colIdx, 4 );
2521				settings.iDrawError = draw;
2522			}
2523			return defaultContent;
2524		}
2525	
2526		// When the data source is null and a specific data type is requested (i.e.
2527		// not the original data), we can use default column data
2528		if ( (cellData === rowData || cellData === null) && defaultContent !== null && type !== undefined ) {
2529			cellData = defaultContent;
2530		}
2531		else if ( typeof cellData === 'function' ) {
2532			// If the data source is a function, then we run it and use the return,
2533			// executing in the scope of the data object (for instances)
2534			return cellData.call( rowData );
2535		}
2536	
2537		if ( cellData === null && type == 'display' ) {
2538			return '';
2539		}
2540		return cellData;
2541	}
2542	
2543	
2544	/**
2545	 * Set the value for a specific cell, into the internal data cache
2546	 *  @param {object} settings dataTables settings object
2547	 *  @param {int} rowIdx aoData row id
2548	 *  @param {int} colIdx Column index
2549	 *  @param {*} val Value to set
2550	 *  @memberof DataTable#oApi
2551	 */
2552	function _fnSetCellData( settings, rowIdx, colIdx, val )
2553	{
2554		var col     = settings.aoColumns[colIdx];
2555		var rowData = settings.aoData[rowIdx]._aData;
2556	
2557		col.fnSetData( rowData, val, {
2558			settings: settings,
2559			row:      rowIdx,
2560			col:      colIdx
2561		}  );
2562	}
2563	
2564	
2565	// Private variable that is used to match action syntax in the data property object
2566	var __reArray = /\[.*?\]$/;
2567	var __reFn = /\(\)$/;
2568	
2569	/**
2570	 * Split string on periods, taking into account escaped periods
2571	 * @param  {string} str String to split
2572	 * @return {array} Split string
2573	 */
2574	function _fnSplitObjNotation( str )
2575	{
2576		return $.map( str.match(/(\\.|[^\.])+/g) || [''], function ( s ) {
2577			return s.replace(/\\\./g, '.');
2578		} );
2579	}
2580	
2581	
2582	/**
2583	 * Return a function that can be used to get data from a source object, taking
2584	 * into account the ability to use nested objects as a source
2585	 *  @param {string|int|function} mSource The data source for the object
2586	 *  @returns {function} Data get function
2587	 *  @memberof DataTable#oApi
2588	 */
2589	function _fnGetObjectDataFn( mSource )
2590	{
2591		if ( $.isPlainObject( mSource ) )
2592		{
2593			/* Build an object of get functions, and wrap them in a single call */
2594			var o = {};
2595			$.each( mSource, function (key, val) {
2596				if ( val ) {
2597					o[key] = _fnGetObjectDataFn( val );
2598				}
2599			} );
2600	
2601			return function (data, type, row, meta) {
2602				var t = o[type] || o._;
2603				return t !== undefined ?
2604					t(data, type, row, meta) :
2605					data;
2606			};
2607		}
2608		else if ( mSource === null )
2609		{
2610			/* Give an empty string for rendering / sorting etc */
2611			return function (data) { // type, row and meta also passed, but not used
2612				return data;
2613			};
2614		}
2615		else if ( typeof mSource === 'function' )
2616		{
2617			return function (data, type, row, meta) {
2618				return mSource( data, type, row, meta );
2619			};
2620		}
2621		else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
2622			      mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
2623		{
2624			/* If there is a . in the source string then the data source is in a
2625			 * nested object so we loop over the data for each level to get the next
2626			 * level down. On each loop we test for undefined, and if found immediately
2627			 * return. This allows entire objects to be missing and sDefaultContent to
2628			 * be used if defined, rather than throwing an error
2629			 */
2630			var fetchData = function (data, type, src) {
2631				var arrayNotation, funcNotation, out, innerSrc;
2632	
2633				if ( src !== "" )
2634				{
2635					var a = _fnSplitObjNotation( src );
2636	
2637					for ( var i=0, iLen=a.length ; i<iLen ; i++ )
2638					{
2639						// Check if we are dealing with special notation
2640						arrayNotation = a[i].match(__reArray);
2641						funcNotation = a[i].match(__reFn);
2642	
2643						if ( arrayNotation )
2644						{
2645							// Array notation
2646							a[i] = a[i].replace(__reArray, '');
2647	
2648							// Condition allows simply [] to be passed in
2649							if ( a[i] !== "" ) {
2650								data = data[ a[i] ];
2651							}
2652							out = [];
2653	
2654							// Get the remainder of the nested object to get
2655							a.splice( 0, i+1 );
2656							innerSrc = a.join('.');
2657	
2658							// Traverse each entry in the array getting the properties requested
2659							if ( $.isArray( data ) ) {
2660								for ( var j=0, jLen=data.length ; j<jLen ; j++ ) {
2661									out.push( fetchData( data[j], type, innerSrc ) );
2662								}
2663							}
2664	
2665							// If a string is given in between the array notation indicators, that
2666							// is used to join the strings together, otherwise an array is returned
2667							var join = arrayNotation[0].substring(1, arrayNotation[0].length-1);
2668							data = (join==="") ? out : out.join(join);
2669	
2670							// The inner call to fetchData has already traversed through the remainder
2671							// of the source requested, so we exit from the loop
2672							break;
2673						}
2674						else if ( funcNotation )
2675						{
2676							// Function call
2677							a[i] = a[i].replace(__reFn, '');
2678							data = data[ a[i] ]();
2679							continue;
2680						}
2681	
2682						if ( data === null || data[ a[i] ] === undefined )
2683						{
2684							return undefined;
2685						}
2686						data = data[ a[i] ];
2687					}
2688				}
2689	
2690				return data;
2691			};
2692	
2693			return function (data, type) { // row and meta also passed, but not used
2694				return fetchData( data, type, mSource );
2695			};
2696		}
2697		else
2698		{
2699			/* Array or flat object mapping */
2700			return function (data, type) { // row and meta also passed, but not used
2701				return data[mSource];
2702			};
2703		}
2704	}
2705	
2706	
2707	/**
2708	 * Return a function that can be used to set data from a source object, taking
2709	 * into account the ability to use nested objects as a source
2710	 *  @param {string|int|function} mSource The data source for the object
2711	 *  @returns {function} Data set function
2712	 *  @memberof DataTable#oApi
2713	 */
2714	function _fnSetObjectDataFn( mSource )
2715	{
2716		if ( $.isPlainObject( mSource ) )
2717		{
2718			/* Unlike get, only the underscore (global) option is used for for
2719			 * setting data since we don't know the type here. This is why an object
2720			 * option is not documented for `mData` (which is read/write), but it is
2721			 * for `mRender` which is read only.
2722			 */
2723			return _fnSetObjectDataFn( mSource._ );
2724		}
2725		else if ( mSource === null )
2726		{
2727			/* Nothing to do when the data source is null */
2728			return function () {};
2729		}
2730		else if ( typeof mSource === 'function' )
2731		{
2732			return function (data, val, meta) {
2733				mSource( data, 'set', val, meta );
2734			};
2735		}
2736		else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
2737			      mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
2738		{
2739			/* Like the get, we need to get data from a nested object */
2740			var setData = function (data, val, src) {
2741				var a = _fnSplitObjNotation( src ), b;
2742				var aLast = a[a.length-1];
2743				var arrayNotation, funcNotation, o, innerSrc;
2744	
2745				for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ )
2746				{
2747					// Check if we are dealing with an array notation request
2748					arrayNotation = a[i].match(__reArray);
2749					funcNotation = a[i].match(__reFn);
2750	
2751					if ( arrayNotation )
2752					{
2753						a[i] = a[i].replace(__reArray, '');
2754						data[ a[i] ] = [];
2755	
2756						// Get the remainder of the nested object to set so we can recurse
2757						b = a.slice();
2758						b.splice( 0, i+1 );
2759						innerSrc = b.join('.');
2760	
2761						// Traverse each entry in the array setting the properties requested
2762						if ( $.isArray( val ) )
2763						{
2764							for ( var j=0, jLen=val.length ; j<jLen ; j++ )
2765							{
2766								o = {};
2767								setData( o, val[j], innerSrc );
2768								data[ a[i] ].push( o );
2769							}
2770						}
2771						else
2772						{
2773							// We've been asked to save data to an array, but it
2774							// isn't array data to be saved. Best that can be done
2775							// is to just save the value.
2776							data[ a[i] ] = val;
2777						}
2778	
2779						// The inner call to setData has already traversed through the remainder
2780						// of the source and has set the data, thus we can exit here
2781						return;
2782					}
2783					else if ( funcNotation )
2784					{
2785						// Function call
2786						a[i] = a[i].replace(__reFn, '');
2787						data = data[ a[i] ]( val );
2788					}
2789	
2790					// If the nested object doesn't currently exist - since we are
2791					// trying to set the value - create it
2792					if ( data[ a[i] ] === null || data[ a[i] ] === undefined )
2793					{
2794						data[ a[i] ] = {};
2795					}
2796					data = data[ a[i] ];
2797				}
2798	
2799				// Last item in the input - i.e, the actual set
2800				if ( aLast.match(__reFn ) )
2801				{
2802					// Function call
2803					data = data[ aLast.replace(__reFn, '') ]( val );
2804				}
2805				else
2806				{
2807					// If array notation is used, we just want to strip it and use the property name
2808					// and assign the value. If it isn't used, then we get the result we want anyway
2809					data[ aLast.replace(__reArray, '') ] = val;
2810				}
2811			};
2812	
2813			return function (data, val) { // meta is also passed in, but not used
2814				return setData( data, val, mSource );
2815			};
2816		}
2817		else
2818		{
2819			/* Array or flat object mapping */
2820			return function (data, val) { // meta is also passed in, but not used
2821				data[mSource] = val;
2822			};
2823		}
2824	}
2825	
2826	
2827	/**
2828	 * Return an array with the full table data
2829	 *  @param {object} oSettings dataTables settings object
2830	 *  @returns array {array} aData Master data array
2831	 *  @memberof DataTable#oApi
2832	 */
2833	function _fnGetDataMaster ( settings )
2834	{
2835		return _pluck( settings.aoData, '_aData' );
2836	}
2837	
2838	
2839	/**
2840	 * Nuke the table
2841	 *  @param {object} oSettings dataTables settings object
2842	 *  @memberof DataTable#oApi
2843	 */
2844	function _fnClearTable( settings )
2845	{
2846		settings.aoData.length = 0;
2847		settings.aiDisplayMaster.length = 0;
2848		settings.aiDisplay.length = 0;
2849		settings.aIds = {};
2850	}
2851	
2852	
2853	 /**
2854	 * Take an array of integers (index array) and remove a target integer (value - not
2855	 * the key!)
2856	 *  @param {array} a Index array to target
2857	 *  @param {int} iTarget value to find
2858	 *  @memberof DataTable#oApi
2859	 */
2860	function _fnDeleteIndex( a, iTarget, splice )
2861	{
2862		var iTargetIndex = -1;
2863	
2864		for ( var i=0, iLen=a.length ; i<iLen ; i++ )
2865		{
2866			if ( a[i] == iTarget )
2867			{
2868				iTargetIndex = i;
2869			}
2870			else if ( a[i] > iTarget )
2871			{
2872				a[i]--;
2873			}
2874		}
2875	
2876		if ( iTargetIndex != -1 && splice === undefined )
2877		{
2878			a.splice( iTargetIndex, 1 );
2879		}
2880	}
2881	
2882	
2883	/**
2884	 * Mark cached data as invalid such that a re-read of the data will occur when
2885	 * the cached data is next requested. Also update from the data source object.
2886	 *
2887	 * @param {object} settings DataTables settings object
2888	 * @param {int}    rowIdx   Row index to invalidate
2889	 * @param {string} [src]    Source to invalidate from: undefined, 'auto', 'dom'
2890	 *     or 'data'
2891	 * @param {int}    [colIdx] Column index to invalidate. If undefined the whole
2892	 *     row will be invalidated
2893	 * @memberof DataTable#oApi
2894	 *
2895	 * @todo For the modularisation of v1.11 this will need to become a callback, so
2896	 *   the sort and filter methods can subscribe to it. That will required
2897	 *   initialisation options for sorting, which is why it is not already baked in
2898	 */
2899	function _fnInvalidate( settings, rowIdx, src, colIdx )
2900	{
2901		var row = settings.aoData[ rowIdx ];
2902		var i, ien;
2903		var cellWrite = function ( cell, col ) {
2904			// This is very frustrating, but in IE if you just write directly
2905			// to innerHTML, and elements that are overwritten are GC'ed,
2906			// even if there is a reference to them elsewhere
2907			while ( cell.childNodes.length ) {
2908				cell.removeChild( cell.firstChild );
2909			}
2910	
2911			cell.innerHTML = _fnGetCellData( settings, rowIdx, col, 'display' );
2912		};
2913	
2914		// Are we reading last data from DOM or the data object?
2915		if ( src === 'dom' || ((! src || src === 'auto') && row.src === 'dom') ) {
2916			// Read the data from the DOM
2917			row._aData = _fnGetRowElements(
2918					settings, row, colIdx, colIdx === undefined ? undefined : row._aData
2919				)
2920				.data;
2921		}
2922		else {
2923			// Reading from data object, update the DOM
2924			var cells = row.anCells;
2925	
2926			if ( cells ) {
2927				if ( colIdx !== undefined ) {
2928					cellWrite( cells[colIdx], colIdx );
2929				}
2930				else {
2931					for ( i=0, ien=cells.length ; i<ien ; i++ ) {
2932						cellWrite( cells[i], i );
2933					}
2934				}
2935			}
2936		}
2937	
2938		// For both row and cell invalidation, the cached data for sorting and
2939		// filtering is nulled out
2940		row._aSortData = null;
2941		row._aFilterData = null;
2942	
2943		// Invalidate the type for a specific column (if given) or all columns since
2944		// the data might have changed
2945		var cols = settings.aoColumns;
2946		if ( colIdx !== undefined ) {
2947			cols[ colIdx ].sType = null;
2948		}
2949		else {
2950			for ( i=0, ien=cols.length ; i<ien ; i++ ) {
2951				cols[i].sType = null;
2952			}
2953	
2954			// Update DataTables special `DT_*` attributes for the row
2955			_fnRowAttributes( settings, row );
2956		}
2957	}
2958	
2959	
2960	/**
2961	 * Build a data source object from an HTML row, reading the contents of the
2962	 * cells that are in the row.
2963	 *
2964	 * @param {object} settings DataTables settings object
2965	 * @param {node|object} TR element from which to read data or existing row
2966	 *   object from which to re-read the data from the cells
2967	 * @param {int} [colIdx] Optional column index
2968	 * @param {array|object} [d] Data source object. If `colIdx` is given then this
2969	 *   parameter should also be given and will be used to write the data into.
2970	 *   Only the column in question will be written
2971	 * @returns {object} Object with two parameters: `data` the data read, in
2972	 *   document order, and `cells` and array of nodes (they can be useful to the
2973	 *   caller, so rather than needing a second traversal to get them, just return
2974	 *   them from here).
2975	 * @memberof DataTable#oApi
2976	 */
2977	function _fnGetRowElements( settings, row, colIdx, d )
2978	{
2979		var
2980			tds = [],
2981			td = row.firstChild,
2982			name, col, o, i=0, contents,
2983			columns = settings.aoColumns,
2984			objectRead = settings._rowReadObject;
2985	
2986		// Allow the data object to be passed in, or construct
2987		d = d !== undefined ?
2988			d :
2989			objectRead ?
2990				{} :
2991				[];
2992	
2993		var attr = function ( str, td  ) {
2994			if ( typeof str === 'string' ) {
2995				var idx = str.indexOf('@');
2996	
2997				if ( idx !== -1 ) {
2998					var attr = str.substring( idx+1 );
2999					var setter = _fnSetObjectDataFn( str );
3000					setter( d, td.getAttribute( attr ) );
3001				}
3002			}
3003		};
3004	
3005		// Read data from a cell and store into the data object
3006		var cellProcess = function ( cell ) {
3007			if ( colIdx === undefined || colIdx === i ) {
3008				col = columns[i];
3009				contents = $.trim(cell.innerHTML);
3010	
3011				if ( col && col._bAttrSrc ) {
3012					var setter = _fnSetObjectDataFn( col.mData._ );
3013					setter( d, contents );
3014	
3015					attr( col.mData.sort, cell );
3016					attr( col.mData.type, cell );
3017					attr( col.mData.filter, cell );
3018				}
3019				else {
3020					// Depending on the `data` option for the columns the data can
3021					// be read to either an object or an array.
vendor: 10,997 bytes, lines 3022-3444
3022					if ( objectRead ) {
3023						if ( ! col._setter ) {
3024							// Cache the setter function
3025							col._setter = _fnSetObjectDataFn( col.mData );
3026						}
3027						col._setter( d, contents );
3028					}
3029					else {
3030						d[i] = contents;
3031					}
3032				}
3033			}
3034	
3035			i++;
3036		};
3037	
3038		if ( td ) {
3039			// `tr` element was passed in
3040			while ( td ) {
3041				name = td.nodeName.toUpperCase();
3042	
3043				if ( name == "TD" || name == "TH" ) {
3044					cellProcess( td );
3045					tds.push( td );
3046				}
3047	
3048				td = td.nextSibling;
3049			}
3050		}
3051		else {
3052			// Existing row object passed in
3053			tds = row.anCells;
3054	
3055			for ( var j=0, jen=tds.length ; j<jen ; j++ ) {
3056				cellProcess( tds[j] );
3057			}
3058		}
3059	
3060		// Read the ID from the DOM if present
3061		var rowNode = row.firstChild ? row : row.nTr;
3062	
3063		if ( rowNode ) {
3064			var id = rowNode.getAttribute( 'id' );
3065	
3066			if ( id ) {
3067				_fnSetObjectDataFn( settings.rowId )( d, id );
3068			}
3069		}
3070	
3071		return {
3072			data: d,
3073			cells: tds
3074		};
3075	}
3076	/**
3077	 * Create a new TR element (and it's TD children) for a row
3078	 *  @param {object} oSettings dataTables settings object
3079	 *  @param {int} iRow Row to consider
3080	 *  @param {node} [nTrIn] TR element to add to the table - optional. If not given,
3081	 *    DataTables will create a row automatically
3082	 *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
3083	 *    if nTr is.
3084	 *  @memberof DataTable#oApi
3085	 */
3086	function _fnCreateTr ( oSettings, iRow, nTrIn, anTds )
3087	{
3088		var
3089			row = oSettings.aoData[iRow],
3090			rowData = row._aData,
3091			cells = [],
3092			nTr, nTd, oCol,
3093			i, iLen;
3094	
3095		if ( row.nTr === null )
3096		{
3097			nTr = nTrIn || document.createElement('tr');
3098	
3099			row.nTr = nTr;
3100			row.anCells = cells;
3101	
3102			/* Use a private property on the node to allow reserve mapping from the node
3103			 * to the aoData array for fast look up
3104			 */
3105			nTr._DT_RowIndex = iRow;
3106	
3107			/* Special parameters can be given by the data source to be used on the row */
3108			_fnRowAttributes( oSettings, row );
3109	
3110			/* Process each column */
3111			for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
3112			{
3113				oCol = oSettings.aoColumns[i];
3114	
3115				nTd = nTrIn ? anTds[i] : document.createElement( oCol.sCellType );
3116				nTd._DT_CellIndex = {
3117					row: iRow,
3118					column: i
3119				};
3120				
3121				cells.push( nTd );
3122	
3123				// Need to create the HTML if new, or if a rendering function is defined
3124				if ( (!nTrIn || oCol.mRender || oCol.mData !== i) &&
3125					 (!$.isPlainObject(oCol.mData) || oCol.mData._ !== i+'.display')
3126				) {
3127					nTd.innerHTML = _fnGetCellData( oSettings, iRow, i, 'display' );
3128				}
3129	
3130				/* Add user defined class */
3131				if ( oCol.sClass )
3132				{
3133					nTd.className += ' '+oCol.sClass;
3134				}
3135	
3136				// Visibility - add or remove as required
3137				if ( oCol.bVisible && ! nTrIn )
3138				{
3139					nTr.appendChild( nTd );
3140				}
3141				else if ( ! oCol.bVisible && nTrIn )
3142				{
3143					nTd.parentNode.removeChild( nTd );
3144				}
3145	
3146				if ( oCol.fnCreatedCell )
3147				{
3148					oCol.fnCreatedCell.call( oSettings.oInstance,
3149						nTd, _fnGetCellData( oSettings, iRow, i ), rowData, iRow, i
3150					);
3151				}
3152			}
3153	
3154			_fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow, cells] );
3155		}
3156	
3157		// Remove once webkit bug 131819 and Chromium bug 365619 have been resolved
3158		// and deployed
3159		row.nTr.setAttribute( 'role', 'row' );
3160	}
3161	
3162	
3163	/**
3164	 * Add attributes to a row based on the special `DT_*` parameters in a data
3165	 * source object.
3166	 *  @param {object} settings DataTables settings object
3167	 *  @param {object} DataTables row object for the row to be modified
3168	 *  @memberof DataTable#oApi
3169	 */
3170	function _fnRowAttributes( settings, row )
3171	{
3172		var tr = row.nTr;
3173		var data = row._aData;
3174	
3175		if ( tr ) {
3176			var id = settings.rowIdFn( data );
3177	
3178			if ( id ) {
3179				tr.id = id;
3180			}
3181	
3182			if ( data.DT_RowClass ) {
3183				// Remove any classes added by DT_RowClass before
3184				var a = data.DT_RowClass.split(' ');
3185				row.__rowc = row.__rowc ?
3186					_unique( row.__rowc.concat( a ) ) :
3187					a;
3188	
3189				$(tr)
3190					.removeClass( row.__rowc.join(' ') )
3191					.addClass( data.DT_RowClass );
3192			}
3193	
3194			if ( data.DT_RowAttr ) {
3195				$(tr).attr( data.DT_RowAttr );
3196			}
3197	
3198			if ( data.DT_RowData ) {
3199				$(tr).data( data.DT_RowData );
3200			}
3201		}
3202	}
3203	
3204	
3205	/**
3206	 * Create the HTML header for the table
3207	 *  @param {object} oSettings dataTables settings object
3208	 *  @memberof DataTable#oApi
3209	 */
3210	function _fnBuildHead( oSettings )
3211	{
3212		var i, ien, cell, row, column;
3213		var thead = oSettings.nTHead;
3214		var tfoot = oSettings.nTFoot;
3215		var createHeader = $('th, td', thead).length === 0;
3216		var classes = oSettings.oClasses;
3217		var columns = oSettings.aoColumns;
3218	
3219		if ( createHeader ) {
3220			row = $('<tr/>').appendTo( thead );
3221		}
3222	
3223		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
3224			column = columns[i];
3225			cell = $( column.nTh ).addClass( column.sClass );
3226	
3227			if ( createHeader ) {
3228				cell.appendTo( row );
3229			}
3230	
3231			// 1.11 move into sorting
3232			if ( oSettings.oFeatures.bSort ) {
3233				cell.addClass( column.sSortingClass );
3234	
3235				if ( column.bSortable !== false ) {
3236					cell
3237						.attr( 'tabindex', oSettings.iTabIndex )
3238						.attr( 'aria-controls', oSettings.sTableId );
3239	
3240					_fnSortAttachListener( oSettings, column.nTh, i );
3241				}
3242			}
3243	
3244			if ( column.sTitle != cell[0].innerHTML ) {
3245				cell.html( column.sTitle );
3246			}
3247	
3248			_fnRenderer( oSettings, 'header' )(
3249				oSettings, cell, column, classes
3250			);
3251		}
3252	
3253		if ( createHeader ) {
3254			_fnDetectHeader( oSettings.aoHeader, thead );
3255		}
3256		
3257		/* ARIA role for the rows */
3258	 	$(thead).find('>tr').attr('role', 'row');
3259	
3260		/* Deal with the footer - add classes if required */
3261		$(thead).find('>tr>th, >tr>td').addClass( classes.sHeaderTH );
3262		$(tfoot).find('>tr>th, >tr>td').addClass( classes.sFooterTH );
3263	
3264		// Cache the footer cells. Note that we only take the cells from the first
3265		// row in the footer. If there is more than one row the user wants to
3266		// interact with, they need to use the table().foot() method. Note also this
3267		// allows cells to be used for multiple columns using colspan
3268		if ( tfoot !== null ) {
3269			var cells = oSettings.aoFooter[0];
3270	
3271			for ( i=0, ien=cells.length ; i<ien ; i++ ) {
3272				column = columns[i];
3273				column.nTf = cells[i].cell;
3274	
3275				if ( column.sClass ) {
3276					$(column.nTf).addClass( column.sClass );
3277				}
3278			}
3279		}
3280	}
3281	
3282	
3283	/**
3284	 * Draw the header (or footer) element based on the column visibility states. The
3285	 * methodology here is to use the layout array from _fnDetectHeader, modified for
3286	 * the instantaneous column visibility, to construct the new layout. The grid is
3287	 * traversed over cell at a time in a rows x columns grid fashion, although each
3288	 * cell insert can cover multiple elements in the grid - which is tracks using the
3289	 * aApplied array. Cell inserts in the grid will only occur where there isn't
3290	 * already a cell in that position.
3291	 *  @param {object} oSettings dataTables settings object
3292	 *  @param array {objects} aoSource Layout array from _fnDetectHeader
3293	 *  @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,
3294	 *  @memberof DataTable#oApi
3295	 */
3296	function _fnDrawHead( oSettings, aoSource, bIncludeHidden )
3297	{
3298		var i, iLen, j, jLen, k, kLen, n, nLocalTr;
3299		var aoLocal = [];
3300		var aApplied = [];
3301		var iColumns = oSettings.aoColumns.length;
3302		var iRowspan, iColspan;
3303	
3304		if ( ! aoSource )
3305		{
3306			return;
3307		}
3308	
3309		if (  bIncludeHidden === undefined )
3310		{
3311			bIncludeHidden = false;
3312		}
3313	
3314		/* Make a copy of the master layout array, but without the visible columns in it */
3315		for ( i=0, iLen=aoSource.length ; i<iLen ; i++ )
3316		{
3317			aoLocal[i] = aoSource[i].slice();
3318			aoLocal[i].nTr = aoSource[i].nTr;
3319	
3320			/* Remove any columns which are currently hidden */
3321			for ( j=iColumns-1 ; j>=0 ; j-- )
3322			{
3323				if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden )
3324				{
3325					aoLocal[i].splice( j, 1 );
3326				}
3327			}
3328	
3329			/* Prep the applied array - it needs an element for each row */
3330			aApplied.push( [] );
3331		}
3332	
3333		for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ )
3334		{
3335			nLocalTr = aoLocal[i].nTr;
3336	
3337			/* All cells are going to be replaced, so empty out the row */
3338			if ( nLocalTr )
3339			{
3340				while( (n = nLocalTr.firstChild) )
3341				{
3342					nLocalTr.removeChild( n );
3343				}
3344			}
3345	
3346			for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ )
3347			{
3348				iRowspan = 1;
3349				iColspan = 1;
3350	
3351				/* Check to see if there is already a cell (row/colspan) covering our target
3352				 * insert point. If there is, then there is nothing to do.
3353				 */
3354				if ( aApplied[i][j] === undefined )
3355				{
3356					nLocalTr.appendChild( aoLocal[i][j].cell );
3357					aApplied[i][j] = 1;
3358	
3359					/* Expand the cell to cover as many rows as needed */
3360					while ( aoLocal[i+iRowspan] !== undefined &&
3361					        aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell )
3362					{
3363						aApplied[i+iRowspan][j] = 1;
3364						iRowspan++;
3365					}
3366	
3367					/* Expand the cell to cover as many columns as needed */
3368					while ( aoLocal[i][j+iColspan] !== undefined &&
3369					        aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell )
3370					{
3371						/* Must update the applied array over the rows for the columns */
3372						for ( k=0 ; k<iRowspan ; k++ )
3373						{
3374							aApplied[i+k][j+iColspan] = 1;
3375						}
3376						iColspan++;
3377					}
3378	
3379					/* Do the actual expansion in the DOM */
3380					$(aoLocal[i][j].cell)
3381						.attr('rowspan', iRowspan)
3382						.attr('colspan', iColspan);
3383				}
3384			}
3385		}
3386	}
3387	
3388	
3389	/**
3390	 * Insert the required TR nodes into the table for display
3391	 *  @param {object} oSettings dataTables settings object
3392	 *  @memberof DataTable#oApi
3393	 */
3394	function _fnDraw( oSettings )
3395	{
3396		/* Provide a pre-callback function which can be used to cancel the draw is false is returned */
3397		var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] );
3398		if ( $.inArray( false, aPreDraw ) !== -1 )
3399		{
3400			_fnProcessingDisplay( oSettings, false );
3401			return;
3402		}
3403	
3404		var i, iLen, n;
3405		var anRows = [];
3406		var iRowCount = 0;
3407		var asStripeClasses = oSettings.asStripeClasses;
3408		var iStripes = asStripeClasses.length;
3409		var iOpenRows = oSettings.aoOpenRows.length;
3410		var oLang = oSettings.oLanguage;
3411		var iInitDisplayStart = oSettings.iInitDisplayStart;
3412		var bServerSide = _fnDataSource( oSettings ) == 'ssp';
3413		var aiDisplay = oSettings.aiDisplay;
3414	
3415		oSettings.bDrawing = true;
3416	
3417		/* Check and see if we have an initial draw position from state saving */
3418		if ( iInitDisplayStart !== undefined && iInitDisplayStart !== -1 )
3419		{
3420			oSettings._iDisplayStart = bServerSide ?
3421				iInitDisplayStart :
3422				iInitDisplayStart >= oSettings.fnRecordsDisplay() ?
3423					0 :
3424					iInitDisplayStart;
3425	
3426			oSettings.iInitDisplayStart = -1;
3427		}
3428	
3429		var iDisplayStart = oSettings._iDisplayStart;
3430		var iDisplayEnd = oSettings.fnDisplayEnd();
3431	
3432		/* Server-side processing draw intercept */
3433		if ( oSettings.bDeferLoading )
3434		{
3435			oSettings.bDeferLoading = false;
3436			oSettings.iDraw++;
3437			_fnProcessingDisplay( oSettings, false );
3438		}
3439		else if ( !bServerSide )
3440		{
3441			oSettings.iDraw++;
3442		}
3443		else if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) )
3444		{
vendor: 10,503 bytes, lines 3444-3833
3444
3445			return;
3446		}
3447	
3448		if ( aiDisplay.length !== 0 )
3449		{
3450			var iStart = bServerSide ? 0 : iDisplayStart;
3451			var iEnd = bServerSide ? oSettings.aoData.length : iDisplayEnd;
3452	
3453			for ( var j=iStart ; j<iEnd ; j++ )
3454			{
3455				var iDataIndex = aiDisplay[j];
3456				var aoData = oSettings.aoData[ iDataIndex ];
3457				if ( aoData.nTr === null )
3458				{
3459					_fnCreateTr( oSettings, iDataIndex );
3460				}
3461	
3462				var nRow = aoData.nTr;
3463	
3464				/* Remove the old striping classes and then add the new one */
3465				if ( iStripes !== 0 )
3466				{
3467					var sStripe = asStripeClasses[ iRowCount % iStripes ];
3468					if ( aoData._sRowStripe != sStripe )
3469					{
3470						$(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe );
3471						aoData._sRowStripe = sStripe;
3472					}
3473				}
3474	
3475				// Row callback functions - might want to manipulate the row
3476				// iRowCount and j are not currently documented. Are they at all
3477				// useful?
3478				_fnCallbackFire( oSettings, 'aoRowCallback', null,
3479					[nRow, aoData._aData, iRowCount, j, iDataIndex] );
3480	
3481				anRows.push( nRow );
3482				iRowCount++;
3483			}
3484		}
3485		else
3486		{
3487			/* Table is empty - create a row with an empty message in it */
3488			var sZero = oLang.sZeroRecords;
3489			if ( oSettings.iDraw == 1 &&  _fnDataSource( oSettings ) == 'ajax' )
3490			{
3491				sZero = oLang.sLoadingRecords;
3492			}
3493			else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 )
3494			{
3495				sZero = oLang.sEmptyTable;
3496			}
3497	
3498			anRows[ 0 ] = $( '<tr/>', { 'class': iStripes ? asStripeClasses[0] : '' } )
3499				.append( $('<td />', {
3500					'valign':  'top',
3501					'colSpan': _fnVisbleColumns( oSettings ),
3502					'class':   oSettings.oClasses.sRowEmpty
3503				} ).html( sZero ) )[0];
3504		}
3505	
3506		/* Header and footer callbacks */
3507		_fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0],
3508			_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
3509	
3510		_fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0],
3511			_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
3512	
3513		var body = $(oSettings.nTBody);
3514	
3515		body.children().detach();
3516		body.append( $(anRows) );
3517	
3518		/* Call all required callback functions for the end of a draw */
3519		_fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] );
3520	
3521		/* Draw is complete, sorting and filtering must be as well */
3522		oSettings.bSorted = false;
3523		oSettings.bFiltered = false;
3524		oSettings.bDrawing = false;
3525	}
3526	
3527	
3528	/**
3529	 * Redraw the table - taking account of the various features which are enabled
3530	 *  @param {object} oSettings dataTables settings object
3531	 *  @param {boolean} [holdPosition] Keep the current paging position. By default
3532	 *    the paging is reset to the first page
3533	 *  @memberof DataTable#oApi
3534	 */
3535	function _fnReDraw( settings, holdPosition )
3536	{
3537		var
3538			features = settings.oFeatures,
3539			sort     = features.bSort,
3540			filter   = features.bFilter;
3541	
3542		if ( sort ) {
3543			_fnSort( settings );
3544		}
3545	
3546		if ( filter ) {
3547			_fnFilterComplete( settings, settings.oPreviousSearch );
3548		}
3549		else {
3550			// No filtering, so we want to just use the display master
3551			settings.aiDisplay = settings.aiDisplayMaster.slice();
3552		}
3553	
3554		if ( holdPosition !== true ) {
3555			settings._iDisplayStart = 0;
3556		}
3557	
3558		// Let any modules know about the draw hold position state (used by
3559		// scrolling internally)
3560		settings._drawHold = holdPosition;
3561	
3562		_fnDraw( settings );
3563	
3564		settings._drawHold = false;
3565	}
3566	
3567	
3568	/**
3569	 * Add the options to the page HTML for the table
3570	 *  @param {object} oSettings dataTables settings object
3571	 *  @memberof DataTable#oApi
3572	 */
3573	function _fnAddOptionsHtml ( oSettings )
3574	{
3575		var classes = oSettings.oClasses;
3576		var table = $(oSettings.nTable);
3577		var holding = $('<div/>').insertBefore( table ); // Holding element for speed
3578		var features = oSettings.oFeatures;
3579	
3580		// All DataTables are wrapped in a div
3581		var insert = $('<div/>', {
3582			id:      oSettings.sTableId+'_wrapper',
3583			'class': classes.sWrapper + (oSettings.nTFoot ? '' : ' '+classes.sNoFooter)
3584		} );
3585	
3586		oSettings.nHolding = holding[0];
3587		oSettings.nTableWrapper = insert[0];
3588		oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;
3589	
3590		/* Loop over the user set positioning and place the elements as needed */
3591		var aDom = oSettings.sDom.split('');
3592		var featureNode, cOption, nNewNode, cNext, sAttr, j;
3593		for ( var i=0 ; i<aDom.length ; i++ )
3594		{
3595			featureNode = null;
3596			cOption = aDom[i];
3597	
3598			if ( cOption == '<' )
3599			{
3600				/* New container div */
3601				nNewNode = $('<div/>')[0];
3602	
3603				/* Check to see if we should append an id and/or a class name to the container */
3604				cNext = aDom[i+1];
3605				if ( cNext == "'" || cNext == '"' )
3606				{
3607					sAttr = "";
3608					j = 2;
3609					while ( aDom[i+j] != cNext )
3610					{
3611						sAttr += aDom[i+j];
3612						j++;
3613					}
3614	
3615					/* Replace jQuery UI constants @todo depreciated */
3616					if ( sAttr == "H" )
3617					{
3618						sAttr = classes.sJUIHeader;
3619					}
3620					else if ( sAttr == "F" )
3621					{
3622						sAttr = classes.sJUIFooter;
3623					}
3624	
3625					/* The attribute can be in the format of "#id.class", "#id" or "class" This logic
3626					 * breaks the string into parts and applies them as needed
3627					 */
3628					if ( sAttr.indexOf('.') != -1 )
3629					{
3630						var aSplit = sAttr.split('.');
3631						nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);
3632						nNewNode.className = aSplit[1];
3633					}
3634					else if ( sAttr.charAt(0) == "#" )
3635					{
3636						nNewNode.id = sAttr.substr(1, sAttr.length-1);
3637					}
3638					else
3639					{
3640						nNewNode.className = sAttr;
3641					}
3642	
3643					i += j; /* Move along the position array */
3644				}
3645	
3646				insert.append( nNewNode );
3647				insert = $(nNewNode);
3648			}
3649			else if ( cOption == '>' )
3650			{
3651				/* End container div */
3652				insert = insert.parent();
3653			}
3654			// @todo Move options into their own plugins?
3655			else if ( cOption == 'l' && features.bPaginate && features.bLengthChange )
3656			{
3657				/* Length */
3658				featureNode = _fnFeatureHtmlLength( oSettings );
3659			}
3660			else if ( cOption == 'f' && features.bFilter )
3661			{
3662				/* Filter */
3663				featureNode = _fnFeatureHtmlFilter( oSettings );
3664			}
3665			else if ( cOption == 'r' && features.bProcessing )
3666			{
3667				/* pRocessing */
3668				featureNode = _fnFeatureHtmlProcessing( oSettings );
3669			}
3670			else if ( cOption == 't' )
3671			{
3672				/* Table */
3673				featureNode = _fnFeatureHtmlTable( oSettings );
3674			}
3675			else if ( cOption ==  'i' && features.bInfo )
3676			{
3677				/* Info */
3678				featureNode = _fnFeatureHtmlInfo( oSettings );
3679			}
3680			else if ( cOption == 'p' && features.bPaginate )
3681			{
3682				/* Pagination */
3683				featureNode = _fnFeatureHtmlPaginate( oSettings );
3684			}
3685			else if ( DataTable.ext.feature.length !== 0 )
3686			{
3687				/* Plug-in features */
3688				var aoFeatures = DataTable.ext.feature;
3689				for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )
3690				{
3691					if ( cOption == aoFeatures[k].cFeature )
3692					{
3693						featureNode = aoFeatures[k].fnInit( oSettings );
3694						break;
3695					}
3696				}
3697			}
3698	
3699			/* Add to the 2D features array */
3700			if ( featureNode )
3701			{
3702				var aanFeatures = oSettings.aanFeatures;
3703	
3704				if ( ! aanFeatures[cOption] )
3705				{
3706					aanFeatures[cOption] = [];
3707				}
3708	
3709				aanFeatures[cOption].push( featureNode );
3710				insert.append( featureNode );
3711			}
3712		}
3713	
3714		/* Built our DOM structure - replace the holding div with what we want */
3715		holding.replaceWith( insert );
3716		oSettings.nHolding = null;
3717	}
3718	
3719	
3720	/**
3721	 * Use the DOM source to create up an array of header cells. The idea here is to
3722	 * create a layout grid (array) of rows x columns, which contains a reference
3723	 * to the cell that that point in the grid (regardless of col/rowspan), such that
3724	 * any column / row could be removed and the new grid constructed
3725	 *  @param array {object} aLayout Array to store the calculated layout in
3726	 *  @param {node} nThead The header/footer element for the table
3727	 *  @memberof DataTable#oApi
3728	 */
3729	function _fnDetectHeader ( aLayout, nThead )
3730	{
3731		var nTrs = $(nThead).children('tr');
3732		var nTr, nCell;
3733		var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan;
3734		var bUnique;
3735		var fnShiftCol = function ( a, i, j ) {
3736			var k = a[i];
3737	                while ( k[j] ) {
3738				j++;
3739			}
3740			return j;
3741		};
3742	
3743		aLayout.splice( 0, aLayout.length );
3744	
3745		/* We know how many rows there are in the layout - so prep it */
3746		for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
3747		{
3748			aLayout.push( [] );
3749		}
3750	
3751		/* Calculate a layout array */
3752		for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
3753		{
3754			nTr = nTrs[i];
3755			iColumn = 0;
3756	
3757			/* For every cell in the row... */
3758			nCell = nTr.firstChild;
3759			while ( nCell ) {
3760				if ( nCell.nodeName.toUpperCase() == "TD" ||
3761				     nCell.nodeName.toUpperCase() == "TH" )
3762				{
3763					/* Get the col and rowspan attributes from the DOM and sanitise them */
3764					iColspan = nCell.getAttribute('colspan') * 1;
3765					iRowspan = nCell.getAttribute('rowspan') * 1;
3766					iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan;
3767					iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan;
3768	
3769					/* There might be colspan cells already in this row, so shift our target
3770					 * accordingly
3771					 */
3772					iColShifted = fnShiftCol( aLayout, i, iColumn );
3773	
3774					/* Cache calculation for unique columns */
3775					bUnique = iColspan === 1 ? true : false;
3776	
3777					/* If there is col / rowspan, copy the information into the layout grid */
3778					for ( l=0 ; l<iColspan ; l++ )
3779					{
3780						for ( k=0 ; k<iRowspan ; k++ )
3781						{
3782							aLayout[i+k][iColShifted+l] = {
3783								"cell": nCell,
3784								"unique": bUnique
3785							};
3786							aLayout[i+k].nTr = nTr;
3787						}
3788					}
3789				}
3790				nCell = nCell.nextSibling;
3791			}
3792		}
3793	}
3794	
3795	
3796	/**
3797	 * Get an array of unique th elements, one for each column
3798	 *  @param {object} oSettings dataTables settings object
3799	 *  @param {node} nHeader automatically detect the layout from this node - optional
3800	 *  @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional
3801	 *  @returns array {node} aReturn list of unique th's
3802	 *  @memberof DataTable#oApi
3803	 */
3804	function _fnGetUniqueThs ( oSettings, nHeader, aLayout )
3805	{
3806		var aReturn = [];
3807		if ( !aLayout )
3808		{
3809			aLayout = oSettings.aoHeader;
3810			if ( nHeader )
3811			{
3812				aLayout = [];
3813				_fnDetectHeader( aLayout, nHeader );
3814			}
3815		}
3816	
3817		for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ )
3818		{
3819			for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ )
3820			{
3821				if ( aLayout[i][j].unique &&
3822					 (!aReturn[j] || !oSettings.bSortCellsTop) )
3823				{
3824					aReturn[j] = aLayout[i][j].cell;
3825				}
3826			}
3827		}
3828	
3829		return aReturn;
3830	}
3831	
3832	/**
3833	 * 
vendor: 47,598 bytes, lines 3833-5472
3833Create an Ajax call based on the table's settings, taking into account that
3834	 * parameters can have multiple forms, and backwards compatibility.
3835	 *
3836	 * @param {object} oSettings dataTables settings object
3837	 * @param {array} data Data to send to the server, required by
3838	 *     DataTables - may be augmented by developer callbacks
3839	 * @param {function} fn Callback function to run when data is obtained
3840	 */
3841	function _fnBuildAjax( oSettings, data, fn )
3842	{
3843		// Compatibility with 1.9-, allow fnServerData and event to manipulate
3844		_fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [data] );
3845	
3846		// Convert to object based for 1.10+ if using the old array scheme which can
3847		// come from server-side processing or serverParams
3848		if ( data && $.isArray(data) ) {
3849			var tmp = {};
3850			var rbracket = /(.*?)\[\]$/;
3851	
3852			$.each( data, function (key, val) {
3853				var match = val.name.match(rbracket);
3854	
3855				if ( match ) {
3856					// Support for arrays
3857					var name = match[0];
3858	
3859					if ( ! tmp[ name ] ) {
3860						tmp[ name ] = [];
3861					}
3862					tmp[ name ].push( val.value );
3863				}
3864				else {
3865					tmp[val.name] = val.value;
3866				}
3867			} );
3868			data = tmp;
3869		}
3870	
3871		var ajaxData;
3872		var ajax = oSettings.ajax;
3873		var instance = oSettings.oInstance;
3874		var callback = function ( json ) {
3875			_fnCallbackFire( oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR] );
3876			fn( json );
3877		};
3878	
3879		if ( $.isPlainObject( ajax ) && ajax.data )
3880		{
3881			ajaxData = ajax.data;
3882	
3883			var newData = typeof ajaxData === 'function' ?
3884				ajaxData( data, oSettings ) :  // fn can manipulate data or return
3885				ajaxData;                      // an object object or array to merge
3886	
3887			// If the function returned something, use that alone
3888			data = typeof ajaxData === 'function' && newData ?
3889				newData :
3890				$.extend( true, data, newData );
3891	
3892			// Remove the data property as we've resolved it already and don't want
3893			// jQuery to do it again (it is restored at the end of the function)
3894			delete ajax.data;
3895		}
3896	
3897		var baseAjax = {
3898			"data": data,
3899			"success": function (json) {
3900				var error = json.error || json.sError;
3901				if ( error ) {
3902					_fnLog( oSettings, 0, error );
3903				}
3904	
3905				oSettings.json = json;
3906				callback( json );
3907			},
3908			"dataType": "json",
3909			"cache": false,
3910			"type": oSettings.sServerMethod,
3911			"error": function (xhr, error, thrown) {
3912				var ret = _fnCallbackFire( oSettings, null, 'xhr', [oSettings, null, oSettings.jqXHR] );
3913	
3914				if ( $.inArray( true, ret ) === -1 ) {
3915					if ( error == "parsererror" ) {
3916						_fnLog( oSettings, 0, 'Invalid JSON response', 1 );
3917					}
3918					else if ( xhr.readyState === 4 ) {
3919						_fnLog( oSettings, 0, 'Ajax error', 7 );
3920					}
3921				}
3922	
3923				_fnProcessingDisplay( oSettings, false );
3924			}
3925		};
3926	
3927		// Store the data submitted for the API
3928		oSettings.oAjaxData = data;
3929	
3930		// Allow plug-ins and external processes to modify the data
3931		_fnCallbackFire( oSettings, null, 'preXhr', [oSettings, data] );
3932	
3933		if ( oSettings.fnServerData )
3934		{
3935			// DataTables 1.9- compatibility
3936			oSettings.fnServerData.call( instance,
3937				oSettings.sAjaxSource,
3938				$.map( data, function (val, key) { // Need to convert back to 1.9 trad format
3939					return { name: key, value: val };
3940				} ),
3941				callback,
3942				oSettings
3943			);
3944		}
3945		else if ( oSettings.sAjaxSource || typeof ajax === 'string' )
3946		{
3947			// DataTables 1.9- compatibility
3948			oSettings.jqXHR = $.ajax( $.extend( baseAjax, {
3949				url: ajax || oSettings.sAjaxSource
3950			} ) );
3951		}
3952		else if ( typeof ajax === 'function' )
3953		{
3954			// Is a function - let the caller define what needs to be done
3955			oSettings.jqXHR = ajax.call( instance, data, callback, oSettings );
3956		}
3957		else
3958		{
3959			// Object to extend the base settings
3960			oSettings.jqXHR = $.ajax( $.extend( baseAjax, ajax ) );
3961	
3962			// Restore for next time around
3963			ajax.data = ajaxData;
3964		}
3965	}
3966	
3967	
3968	/**
3969	 * Update the table using an Ajax call
3970	 *  @param {object} settings dataTables settings object
3971	 *  @returns {boolean} Block the table drawing or not
3972	 *  @memberof DataTable#oApi
3973	 */
3974	function _fnAjaxUpdate( settings )
3975	{
3976		if ( settings.bAjaxDataGet ) {
3977			settings.iDraw++;
3978			_fnProcessingDisplay( settings, true );
3979	
3980			_fnBuildAjax(
3981				settings,
3982				_fnAjaxParameters( settings ),
3983				function(json) {
3984					_fnAjaxUpdateDraw( settings, json );
3985				}
3986			);
3987	
3988			return false;
3989		}
3990		return true;
3991	}
3992	
3993	
3994	/**
3995	 * Build up the parameters in an object needed for a server-side processing
3996	 * request. Note that this is basically done twice, is different ways - a modern
3997	 * method which is used by default in DataTables 1.10 which uses objects and
3998	 * arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if
3999	 * the sAjaxSource option is used in the initialisation, or the legacyAjax
4000	 * option is set.
4001	 *  @param {object} oSettings dataTables settings object
4002	 *  @returns {bool} block the table drawing or not
4003	 *  @memberof DataTable#oApi
4004	 */
4005	function _fnAjaxParameters( settings )
4006	{
4007		var
4008			columns = settings.aoColumns,
4009			columnCount = columns.length,
4010			features = settings.oFeatures,
4011			preSearch = settings.oPreviousSearch,
4012			preColSearch = settings.aoPreSearchCols,
4013			i, data = [], dataProp, column, columnSearch,
4014			sort = _fnSortFlatten( settings ),
4015			displayStart = settings._iDisplayStart,
4016			displayLength = features.bPaginate !== false ?
4017				settings._iDisplayLength :
4018				-1;
4019	
4020		var param = function ( name, value ) {
4021			data.push( { 'name': name, 'value': value } );
4022		};
4023	
4024		// DataTables 1.9- compatible method
4025		param( 'sEcho',          settings.iDraw );
4026		param( 'iColumns',       columnCount );
4027		param( 'sColumns',       _pluck( columns, 'sName' ).join(',') );
4028		param( 'iDisplayStart',  displayStart );
4029		param( 'iDisplayLength', displayLength );
4030	
4031		// DataTables 1.10+ method
4032		var d = {
4033			draw:    settings.iDraw,
4034			columns: [],
4035			order:   [],
4036			start:   displayStart,
4037			length:  displayLength,
4038			search:  {
4039				value: preSearch.sSearch,
4040				regex: preSearch.bRegex
4041			}
4042		};
4043	
4044		for ( i=0 ; i<columnCount ; i++ ) {
4045			column = columns[i];
4046			columnSearch = preColSearch[i];
4047			dataProp = typeof column.mData=="function" ? 'function' : column.mData ;
4048	
4049			d.columns.push( {
4050				data:       dataProp,
4051				name:       column.sName,
4052				searchable: column.bSearchable,
4053				orderable:  column.bSortable,
4054				search:     {
4055					value: columnSearch.sSearch,
4056					regex: columnSearch.bRegex
4057				}
4058			} );
4059	
4060			param( "mDataProp_"+i, dataProp );
4061	
4062			if ( features.bFilter ) {
4063				param( 'sSearch_'+i,     columnSearch.sSearch );
4064				param( 'bRegex_'+i,      columnSearch.bRegex );
4065				param( 'bSearchable_'+i, column.bSearchable );
4066			}
4067	
4068			if ( features.bSort ) {
4069				param( 'bSortable_'+i, column.bSortable );
4070			}
4071		}
4072	
4073		if ( features.bFilter ) {
4074			param( 'sSearch', preSearch.sSearch );
4075			param( 'bRegex', preSearch.bRegex );
4076		}
4077	
4078		if ( features.bSort ) {
4079			$.each( sort, function ( i, val ) {
4080				d.order.push( { column: val.col, dir: val.dir } );
4081	
4082				param( 'iSortCol_'+i, val.col );
4083				param( 'sSortDir_'+i, val.dir );
4084			} );
4085	
4086			param( 'iSortingCols', sort.length );
4087		}
4088	
4089		// If the legacy.ajax parameter is null, then we automatically decide which
4090		// form to use, based on sAjaxSource
4091		var legacy = DataTable.ext.legacy.ajax;
4092		if ( legacy === null ) {
4093			return settings.sAjaxSource ? data : d;
4094		}
4095	
4096		// Otherwise, if legacy has been specified then we use that to decide on the
4097		// form
4098		return legacy ? data : d;
4099	}
4100	
4101	
4102	/**
4103	 * Data the data from the server (nuking the old) and redraw the table
4104	 *  @param {object} oSettings dataTables settings object
4105	 *  @param {object} json json data return from the server.
4106	 *  @param {string} json.sEcho Tracking flag for DataTables to match requests
4107	 *  @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering
4108	 *  @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering
4109	 *  @param {array} json.aaData The data to display on this page
4110	 *  @param {string} [json.sColumns] Column ordering (sName, comma separated)
4111	 *  @memberof DataTable#oApi
4112	 */
4113	function _fnAjaxUpdateDraw ( settings, json )
4114	{
4115		// v1.10 uses camelCase variables, while 1.9 uses Hungarian notation.
4116		// Support both
4117		var compat = function ( old, modern ) {
4118			return json[old] !== undefined ? json[old] : json[modern];
4119		};
4120	
4121		var data = _fnAjaxDataSrc( settings, json );
4122		var draw            = compat( 'sEcho',                'draw' );
4123		var recordsTotal    = compat( 'iTotalRecords',        'recordsTotal' );
4124		var recordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' );
4125	
4126		if ( draw ) {
4127			// Protect against out of sequence returns
4128			if ( draw*1 < settings.iDraw ) {
4129				return;
4130			}
4131			settings.iDraw = draw * 1;
4132		}
4133	
4134		_fnClearTable( settings );
4135		settings._iRecordsTotal   = parseInt(recordsTotal, 10);
4136		settings._iRecordsDisplay = parseInt(recordsFiltered, 10);
4137	
4138		for ( var i=0, ien=data.length ; i<ien ; i++ ) {
4139			_fnAddData( settings, data[i] );
4140		}
4141		settings.aiDisplay = settings.aiDisplayMaster.slice();
4142	
4143		settings.bAjaxDataGet = false;
4144		_fnDraw( settings );
4145	
4146		if ( ! settings._bInitComplete ) {
4147			_fnInitComplete( settings, json );
4148		}
4149	
4150		settings.bAjaxDataGet = true;
4151		_fnProcessingDisplay( settings, false );
4152	}
4153	
4154	
4155	/**
4156	 * Get the data from the JSON data source to use for drawing a table. Using
4157	 * `_fnGetObjectDataFn` allows the data to be sourced from a property of the
4158	 * source object, or from a processing function.
4159	 *  @param {object} oSettings dataTables settings object
4160	 *  @param  {object} json Data source object / array from the server
4161	 *  @return {array} Array of data to use
4162	 */
4163	function _fnAjaxDataSrc ( oSettings, json )
4164	{
4165		var dataSrc = $.isPlainObject( oSettings.ajax ) && oSettings.ajax.dataSrc !== undefined ?
4166			oSettings.ajax.dataSrc :
4167			oSettings.sAjaxDataProp; // Compatibility with 1.9-.
4168	
4169		// Compatibility with 1.9-. In order to read from aaData, check if the
4170		// default has been changed, if not, check for aaData
4171		if ( dataSrc === 'data' ) {
4172			return json.aaData || json[dataSrc];
4173		}
4174	
4175		return dataSrc !== "" ?
4176			_fnGetObjectDataFn( dataSrc )( json ) :
4177			json;
4178	}
4179	
4180	/**
4181	 * Generate the node required for filtering text
4182	 *  @returns {node} Filter control element
4183	 *  @param {object} oSettings dataTables settings object
4184	 *  @memberof DataTable#oApi
4185	 */
4186	function _fnFeatureHtmlFilter ( settings )
4187	{
4188		var classes = settings.oClasses;
4189		var tableId = settings.sTableId;
4190		var language = settings.oLanguage;
4191		var previousSearch = settings.oPreviousSearch;
4192		var features = settings.aanFeatures;
4193		var input = '<input type="search" class="'+classes.sFilterInput+'"/>';
4194	
4195		var str = language.sSearch;
4196		str = str.match(/_INPUT_/) ?
4197			str.replace('_INPUT_', input) :
4198			str+input;
4199	
4200		var filter = $('<div/>', {
4201				'id': ! features.f ? tableId+'_filter' : null,
4202				'class': classes.sFilter
4203			} )
4204			.append( $('<label/>' ).append( str ) );
4205	
4206		var searchFn = function() {
4207			/* Update all other filter input elements for the new display */
4208			var n = features.f;
4209			var val = !this.value ? "" : this.value; // mental IE8 fix :-(
4210	
4211			/* Now do the filter */
4212			if ( val != previousSearch.sSearch ) {
4213				_fnFilterComplete( settings, {
4214					"sSearch": val,
4215					"bRegex": previousSearch.bRegex,
4216					"bSmart": previousSearch.bSmart ,
4217					"bCaseInsensitive": previousSearch.bCaseInsensitive
4218				} );
4219	
4220				// Need to redraw, without resorting
4221				settings._iDisplayStart = 0;
4222				_fnDraw( settings );
4223			}
4224		};
4225	
4226		var searchDelay = settings.searchDelay !== null ?
4227			settings.searchDelay :
4228			_fnDataSource( settings ) === 'ssp' ?
4229				400 :
4230				0;
4231	
4232		var jqFilter = $('input', filter)
4233			.val( previousSearch.sSearch )
4234			.attr( 'placeholder', language.sSearchPlaceholder )
4235			.on(
4236				'keyup.DT search.DT input.DT paste.DT cut.DT',
4237				searchDelay ?
4238					_fnThrottle( searchFn, searchDelay ) :
4239					searchFn
4240			)
4241			.on( 'keypress.DT', function(e) {
4242				/* Prevent form submission */
4243				if ( e.keyCode == 13 ) {
4244					return false;
4245				}
4246			} )
4247			.attr('aria-controls', tableId);
4248	
4249		// Update the input elements whenever the table is filtered
4250		$(settings.nTable).on( 'search.dt.DT', function ( ev, s ) {
4251			if ( settings === s ) {
4252				// IE9 throws an 'unknown error' if document.activeElement is used
4253				// inside an iframe or frame...
4254				try {
4255					if ( jqFilter[0] !== document.activeElement ) {
4256						jqFilter.val( previousSearch.sSearch );
4257					}
4258				}
4259				catch ( e ) {}
4260			}
4261		} );
4262	
4263		return filter[0];
4264	}
4265	
4266	
4267	/**
4268	 * Filter the table using both the global filter and column based filtering
4269	 *  @param {object} oSettings dataTables settings object
4270	 *  @param {object} oSearch search information
4271	 *  @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)
4272	 *  @memberof DataTable#oApi
4273	 */
4274	function _fnFilterComplete ( oSettings, oInput, iForce )
4275	{
4276		var oPrevSearch = oSettings.oPreviousSearch;
4277		var aoPrevSearch = oSettings.aoPreSearchCols;
4278		var fnSaveFilter = function ( oFilter ) {
4279			/* Save the filtering values */
4280			oPrevSearch.sSearch = oFilter.sSearch;
4281			oPrevSearch.bRegex = oFilter.bRegex;
4282			oPrevSearch.bSmart = oFilter.bSmart;
4283			oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive;
4284		};
4285		var fnRegex = function ( o ) {
4286			// Backwards compatibility with the bEscapeRegex option
4287			return o.bEscapeRegex !== undefined ? !o.bEscapeRegex : o.bRegex;
4288		};
4289	
4290		// Resolve any column types that are unknown due to addition or invalidation
4291		// @todo As per sort - can this be moved into an event handler?
4292		_fnColumnTypes( oSettings );
4293	
4294		/* In server-side processing all filtering is done by the server, so no point hanging around here */
4295		if ( _fnDataSource( oSettings ) != 'ssp' )
4296		{
4297			/* Global filter */
4298			_fnFilter( oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive );
4299			fnSaveFilter( oInput );
4300	
4301			/* Now do the individual column filter */
4302			for ( var i=0 ; i<aoPrevSearch.length ; i++ )
4303			{
4304				_fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, fnRegex(aoPrevSearch[i]),
4305					aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive );
4306			}
4307	
4308			/* Custom filtering */
4309			_fnFilterCustom( oSettings );
4310		}
4311		else
4312		{
4313			fnSaveFilter( oInput );
4314		}
4315	
4316		/* Tell the draw function we have been filtering */
4317		oSettings.bFiltered = true;
4318		_fnCallbackFire( oSettings, null, 'search', [oSettings] );
4319	}
4320	
4321	
4322	/**
4323	 * Apply custom filtering functions
4324	 *  @param {object} oSettings dataTables settings object
4325	 *  @memberof DataTable#oApi
4326	 */
4327	function _fnFilterCustom( settings )
4328	{
4329		var filters = DataTable.ext.search;
4330		var displayRows = settings.aiDisplay;
4331		var row, rowIdx;
4332	
4333		for ( var i=0, ien=filters.length ; i<ien ; i++ ) {
4334			var rows = [];
4335	
4336			// Loop over each row and see if it should be included
4337			for ( var j=0, jen=displayRows.length ; j<jen ; j++ ) {
4338				rowIdx = displayRows[ j ];
4339				row = settings.aoData[ rowIdx ];
4340	
4341				if ( filters[i]( settings, row._aFilterData, rowIdx, row._aData, j ) ) {
4342					rows.push( rowIdx );
4343				}
4344			}
4345	
4346			// So the array reference doesn't break set the results into the
4347			// existing array
4348			displayRows.length = 0;
4349			$.merge( displayRows, rows );
4350		}
4351	}
4352	
4353	
4354	/**
4355	 * Filter the table on a per-column basis
4356	 *  @param {object} oSettings dataTables settings object
4357	 *  @param {string} sInput string to filter on
4358	 *  @param {int} iColumn column to filter
4359	 *  @param {bool} bRegex treat search string as a regular expression or not
4360	 *  @param {bool} bSmart use smart filtering or not
4361	 *  @param {bool} bCaseInsensitive Do case insenstive matching or not
4362	 *  @memberof DataTable#oApi
4363	 */
4364	function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, caseInsensitive )
4365	{
4366		if ( searchStr === '' ) {
4367			return;
4368		}
4369	
4370		var data;
4371		var out = [];
4372		var display = settings.aiDisplay;
4373		var rpSearch = _fnFilterCreateSearch( searchStr, regex, smart, caseInsensitive );
4374	
4375		for ( var i=0 ; i<display.length ; i++ ) {
4376			data = settings.aoData[ display[i] ]._aFilterData[ colIdx ];
4377	
4378			if ( rpSearch.test( data ) ) {
4379				out.push( display[i] );
4380			}
4381		}
4382	
4383		settings.aiDisplay = out;
4384	}
4385	
4386	
4387	/**
4388	 * Filter the data table based on user input and draw the table
4389	 *  @param {object} settings dataTables settings object
4390	 *  @param {string} input string to filter on
4391	 *  @param {int} force optional - force a research of the master array (1) or not (undefined or 0)
4392	 *  @param {bool} regex treat as a regular expression or not
4393	 *  @param {bool} smart perform smart filtering or not
4394	 *  @param {bool} caseInsensitive Do case insenstive matching or not
4395	 *  @memberof DataTable#oApi
4396	 */
4397	function _fnFilter( settings, input, force, regex, smart, caseInsensitive )
4398	{
4399		var rpSearch = _fnFilterCreateSearch( input, regex, smart, caseInsensitive );
4400		var prevSearch = settings.oPreviousSearch.sSearch;
4401		var displayMaster = settings.aiDisplayMaster;
4402		var display, invalidated, i;
4403		var filtered = [];
4404	
4405		// Need to take account of custom filtering functions - always filter
4406		if ( DataTable.ext.search.length !== 0 ) {
4407			force = true;
4408		}
4409	
4410		// Check if any of the rows were invalidated
4411		invalidated = _fnFilterData( settings );
4412	
4413		// If the input is blank - we just want the full data set
4414		if ( input.length <= 0 ) {
4415			settings.aiDisplay = displayMaster.slice();
4416		}
4417		else {
4418			// New search - start from the master array
4419			if ( invalidated ||
4420				 force ||
4421				 prevSearch.length > input.length ||
4422				 input.indexOf(prevSearch) !== 0 ||
4423				 settings.bSorted // On resort, the display master needs to be
4424				                  // re-filtered since indexes will have changed
4425			) {
4426				settings.aiDisplay = displayMaster.slice();
4427			}
4428	
4429			// Search the display array
4430			display = settings.aiDisplay;
4431	
4432			for ( i=0 ; i<display.length ; i++ ) {
4433				if ( rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) {
4434					filtered.push( display[i] );
4435				}
4436			}
4437	
4438			settings.aiDisplay = filtered;
4439		}
4440	}
4441	
4442	
4443	/**
4444	 * Build a regular expression object suitable for searching a table
4445	 *  @param {string} sSearch string to search for
4446	 *  @param {bool} bRegex treat as a regular expression or not
4447	 *  @param {bool} bSmart perform smart filtering or not
4448	 *  @param {bool} bCaseInsensitive Do case insensitive matching or not
4449	 *  @returns {RegExp} constructed object
4450	 *  @memberof DataTable#oApi
4451	 */
4452	function _fnFilterCreateSearch( search, regex, smart, caseInsensitive )
4453	{
4454		search = regex ?
4455			search :
4456			_fnEscapeRegex( search );
4457		
4458		if ( smart ) {
4459			/* For smart filtering we want to allow the search to work regardless of
4460			 * word order. We also want double quoted text to be preserved, so word
4461			 * order is important - a la google. So this is what we want to
4462			 * generate:
4463			 * 
4464			 * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$
4465			 */
4466			var a = $.map( search.match( /"[^"]+"|[^ ]+/g ) || [''], function ( word ) {
4467				if ( word.charAt(0) === '"' ) {
4468					var m = word.match( /^"(.*)"$/ );
4469					word = m ? m[1] : word;
4470				}
4471	
4472				return word.replace('"', '');
4473			} );
4474	
4475			search = '^(?=.*?'+a.join( ')(?=.*?' )+').*$';
4476		}
4477	
4478		return new RegExp( search, caseInsensitive ? 'i' : '' );
4479	}
4480	
4481	
4482	/**
4483	 * Escape a string such that it can be used in a regular expression
4484	 *  @param {string} sVal string to escape
4485	 *  @returns {string} escaped string
4486	 *  @memberof DataTable#oApi
4487	 */
4488	var _fnEscapeRegex = DataTable.util.escapeRegex;
4489	
4490	var __filter_div = $('<div>')[0];
4491	var __filter_div_textContent = __filter_div.textContent !== undefined;
4492	
4493	// Update the filtering data for each row if needed (by invalidation or first run)
4494	function _fnFilterData ( settings )
4495	{
4496		var columns = settings.aoColumns;
4497		var column;
4498		var i, j, ien, jen, filterData, cellData, row;
4499		var fomatters = DataTable.ext.type.search;
4500		var wasInvalidated = false;
4501	
4502		for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
4503			row = settings.aoData[i];
4504	
4505			if ( ! row._aFilterData ) {
4506				filterData = [];
4507	
4508				for ( j=0, jen=columns.length ; j<jen ; j++ ) {
4509					column = columns[j];
4510	
4511					if ( column.bSearchable ) {
4512						cellData = _fnGetCellData( settings, i, j, 'filter' );
4513	
4514						if ( fomatters[ column.sType ] ) {
4515							cellData = fomatters[ column.sType ]( cellData );
4516						}
4517	
4518						// Search in DataTables 1.10 is string based. In 1.11 this
4519						// should be altered to also allow strict type checking.
4520						if ( cellData === null ) {
4521							cellData = '';
4522						}
4523	
4524						if ( typeof cellData !== 'string' && cellData.toString ) {
4525							cellData = cellData.toString();
4526						}
4527					}
4528					else {
4529						cellData = '';
4530					}
4531	
4532					// If it looks like there is an HTML entity in the string,
4533					// attempt to decode it so sorting works as expected. Note that
4534					// we could use a single line of jQuery to do this, but the DOM
4535					// method used here is much faster http://jsperf.com/html-decode
4536					if ( cellData.indexOf && cellData.indexOf('&') !== -1 ) {
4537						__filter_div.innerHTML = cellData;
4538						cellData = __filter_div_textContent ?
4539							__filter_div.textContent :
4540							__filter_div.innerText;
4541					}
4542	
4543					if ( cellData.replace ) {
4544						cellData = cellData.replace(/[\r\n]/g, '');
4545					}
4546	
4547					filterData.push( cellData );
4548				}
4549	
4550				row._aFilterData = filterData;
4551				row._sFilterRow = filterData.join('  ');
4552				wasInvalidated = true;
4553			}
4554		}
4555	
4556		return wasInvalidated;
4557	}
4558	
4559	
4560	/**
4561	 * Convert from the internal Hungarian notation to camelCase for external
4562	 * interaction
4563	 *  @param {object} obj Object to convert
4564	 *  @returns {object} Inverted object
4565	 *  @memberof DataTable#oApi
4566	 */
4567	function _fnSearchToCamel ( obj )
4568	{
4569		return {
4570			search:          obj.sSearch,
4571			smart:           obj.bSmart,
4572			regex:           obj.bRegex,
4573			caseInsensitive: obj.bCaseInsensitive
4574		};
4575	}
4576	
4577	
4578	
4579	/**
4580	 * Convert from camelCase notation to the internal Hungarian. We could use the
4581	 * Hungarian convert function here, but this is cleaner
4582	 *  @param {object} obj Object to convert
4583	 *  @returns {object} Inverted object
4584	 *  @memberof DataTable#oApi
4585	 */
4586	function _fnSearchToHung ( obj )
4587	{
4588		return {
4589			sSearch:          obj.search,
4590			bSmart:           obj.smart,
4591			bRegex:           obj.regex,
4592			bCaseInsensitive: obj.caseInsensitive
4593		};
4594	}
4595	
4596	/**
4597	 * Generate the node required for the info display
4598	 *  @param {object} oSettings dataTables settings object
4599	 *  @returns {node} Information element
4600	 *  @memberof DataTable#oApi
4601	 */
4602	function _fnFeatureHtmlInfo ( settings )
4603	{
4604		var
4605			tid = settings.sTableId,
4606			nodes = settings.aanFeatures.i,
4607			n = $('<div/>', {
4608				'class': settings.oClasses.sInfo,
4609				'id': ! nodes ? tid+'_info' : null
4610			} );
4611	
4612		if ( ! nodes ) {
4613			// Update display on each draw
4614			settings.aoDrawCallback.push( {
4615				"fn": _fnUpdateInfo,
4616				"sName": "information"
4617			} );
4618	
4619			n
4620				.attr( 'role', 'status' )
4621				.attr( 'aria-live', 'polite' );
4622	
4623			// Table is described by our info div
4624			$(settings.nTable).attr( 'aria-describedby', tid+'_info' );
4625		}
4626	
4627		return n[0];
4628	}
4629	
4630	
4631	/**
4632	 * Update the information elements in the display
4633	 *  @param {object} settings dataTables settings object
4634	 *  @memberof DataTable#oApi
4635	 */
4636	function _fnUpdateInfo ( settings )
4637	{
4638		/* Show information about the table */
4639		var nodes = settings.aanFeatures.i;
4640		if ( nodes.length === 0 ) {
4641			return;
4642		}
4643	
4644		var
4645			lang  = settings.oLanguage,
4646			start = settings._iDisplayStart+1,
4647			end   = settings.fnDisplayEnd(),
4648			max   = settings.fnRecordsTotal(),
4649			total = settings.fnRecordsDisplay(),
4650			out   = total ?
4651				lang.sInfo :
4652				lang.sInfoEmpty;
4653	
4654		if ( total !== max ) {
4655			/* Record set after filtering */
4656			out += ' ' + lang.sInfoFiltered;
4657		}
4658	
4659		// Convert the macros
4660		out += lang.sInfoPostFix;
4661		out = _fnInfoMacros( settings, out );
4662	
4663		var callback = lang.fnInfoCallback;
4664		if ( callback !== null ) {
4665			out = callback.call( settings.oInstance,
4666				settings, start, end, max, total, out
4667			);
4668		}
4669	
4670		$(nodes).html( out );
4671	}
4672	
4673	
4674	function _fnInfoMacros ( settings, str )
4675	{
4676		// When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
4677		// internally
4678		var
4679			formatter  = settings.fnFormatNumber,
4680			start      = settings._iDisplayStart+1,
4681			len        = settings._iDisplayLength,
4682			vis        = settings.fnRecordsDisplay(),
4683			all        = len === -1;
4684	
4685		return str.
4686			replace(/_START_/g, formatter.call( settings, start ) ).
4687			replace(/_END_/g,   formatter.call( settings, settings.fnDisplayEnd() ) ).
4688			replace(/_MAX_/g,   formatter.call( settings, settings.fnRecordsTotal() ) ).
4689			replace(/_TOTAL_/g, formatter.call( settings, vis ) ).
4690			replace(/_PAGE_/g,  formatter.call( settings, all ? 1 : Math.ceil( start / len ) ) ).
4691			replace(/_PAGES_/g, formatter.call( settings, all ? 1 : Math.ceil( vis / len ) ) );
4692	}
4693	
4694	
4695	
4696	/**
4697	 * Draw the table for the first time, adding all required features
4698	 *  @param {object} settings dataTables settings object
4699	 *  @memberof DataTable#oApi
4700	 */
4701	function _fnInitialise ( settings )
4702	{
4703		var i, iLen, iAjaxStart=settings.iInitDisplayStart;
4704		var columns = settings.aoColumns, column;
4705		var features = settings.oFeatures;
4706		var deferLoading = settings.bDeferLoading; // value modified by the draw
4707	
4708		/* Ensure that the table data is fully initialised */
4709		if ( ! settings.bInitialised ) {
4710			setTimeout( function(){ _fnInitialise( settings ); }, 200 );
4711			return;
4712		}
4713	
4714		/* Show the display HTML options */
4715		_fnAddOptionsHtml( settings );
4716	
4717		/* Build and draw the header / footer for the table */
4718		_fnBuildHead( settings );
4719		_fnDrawHead( settings, settings.aoHeader );
4720		_fnDrawHead( settings, settings.aoFooter );
4721	
4722		/* Okay to show that something is going on now */
4723		_fnProcessingDisplay( settings, true );
4724	
4725		/* Calculate sizes for columns */
4726		if ( features.bAutoWidth ) {
4727			_fnCalculateColumnWidths( settings );
4728		}
4729	
4730		for ( i=0, iLen=columns.length ; i<iLen ; i++ ) {
4731			column = columns[i];
4732	
4733			if ( column.sWidth ) {
4734				column.nTh.style.width = _fnStringToCss( column.sWidth );
4735			}
4736		}
4737	
4738		_fnCallbackFire( settings, null, 'preInit', [settings] );
4739	
4740		// If there is default sorting required - let's do it. The sort function
4741		// will do the drawing for us. Otherwise we draw the table regardless of the
4742		// Ajax source - this allows the table to look initialised for Ajax sourcing
4743		// data (show 'loading' message possibly)
4744		_fnReDraw( settings );
4745	
4746		// Server-side processing init complete is done by _fnAjaxUpdateDraw
4747		var dataSrc = _fnDataSource( settings );
4748		if ( dataSrc != 'ssp' || deferLoading ) {
4749			// if there is an ajax source load the data
4750			if ( dataSrc == 'ajax' ) {
4751				_fnBuildAjax( settings, [], function(json) {
4752					var aData = _fnAjaxDataSrc( settings, json );
4753	
4754					// Got the data - add it to the table
4755					for ( i=0 ; i<aData.length ; i++ ) {
4756						_fnAddData( settings, aData[i] );
4757					}
4758	
4759					// Reset the init display for cookie saving. We've already done
4760					// a filter, and therefore cleared it before. So we need to make
4761					// it appear 'fresh'
4762					settings.iInitDisplayStart = iAjaxStart;
4763	
4764					_fnReDraw( settings );
4765	
4766					_fnProcessingDisplay( settings, false );
4767					_fnInitComplete( settings, json );
4768				}, settings );
4769			}
4770			else {
4771				_fnProcessingDisplay( settings, false );
4772				_fnInitComplete( settings );
4773			}
4774		}
4775	}
4776	
4777	
4778	/**
4779	 * Draw the table for the first time, adding all required features
4780	 *  @param {object} oSettings dataTables settings object
4781	 *  @param {object} [json] JSON from the server that completed the table, if using Ajax source
4782	 *    with client-side processing (optional)
4783	 *  @memberof DataTable#oApi
4784	 */
4785	function _fnInitComplete ( settings, json )
4786	{
4787		settings._bInitComplete = true;
4788	
4789		// When data was added after the initialisation (data or Ajax) we need to
4790		// calculate the column sizing
4791		if ( json || settings.oInit.aaData ) {
4792			_fnAdjustColumnSizing( settings );
4793		}
4794	
4795		_fnCallbackFire( settings, null, 'plugin-init', [settings, json] );
4796		_fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] );
4797	}
4798	
4799	
4800	function _fnLengthChange ( settings, val )
4801	{
4802		var len = parseInt( val, 10 );
4803		settings._iDisplayLength = len;
4804	
4805		_fnLengthOverflow( settings );
4806	
4807		// Fire length change event
4808		_fnCallbackFire( settings, null, 'length', [settings, len] );
4809	}
4810	
4811	
4812	/**
4813	 * Generate the node required for user display length changing
4814	 *  @param {object} settings dataTables settings object
4815	 *  @returns {node} Display length feature node
4816	 *  @memberof DataTable#oApi
4817	 */
4818	function _fnFeatureHtmlLength ( settings )
4819	{
4820		var
4821			classes  = settings.oClasses,
4822			tableId  = settings.sTableId,
4823			menu     = settings.aLengthMenu,
4824			d2       = $.isArray( menu[0] ),
4825			lengths  = d2 ? menu[0] : menu,
4826			language = d2 ? menu[1] : menu;
4827	
4828		var select = $('<select/>', {
4829			'name':          tableId+'_length',
4830			'aria-controls': tableId,
4831			'class':         classes.sLengthSelect
4832		} );
4833	
4834		for ( var i=0, ien=lengths.length ; i<ien ; i++ ) {
4835			select[0][ i ] = new Option(
4836				typeof language[i] === 'number' ?
4837					settings.fnFormatNumber( language[i] ) :
4838					language[i],
4839				lengths[i]
4840			);
4841		}
4842	
4843		var div = $('<div><label/></div>').addClass( classes.sLength );
4844		if ( ! settings.aanFeatures.l ) {
4845			div[0].id = tableId+'_length';
4846		}
4847	
4848		div.children().append(
4849			settings.oLanguage.sLengthMenu.replace( '_MENU_', select[0].outerHTML )
4850		);
4851	
4852		// Can't use `select` variable as user might provide their own and the
4853		// reference is broken by the use of outerHTML
4854		$('select', div)
4855			.val( settings._iDisplayLength )
4856			.on( 'change.DT', function(e) {
4857				_fnLengthChange( settings, $(this).val() );
4858				_fnDraw( settings );
4859			} );
4860	
4861		// Update node value whenever anything changes the table's length
4862		$(settings.nTable).on( 'length.dt.DT', function (e, s, len) {
4863			if ( settings === s ) {
4864				$('select', div).val( len );
4865			}
4866		} );
4867	
4868		return div[0];
4869	}
4870	
4871	
4872	
4873	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
4874	 * Note that most of the paging logic is done in
4875	 * DataTable.ext.pager
4876	 */
4877	
4878	/**
4879	 * Generate the node required for default pagination
4880	 *  @param {object} oSettings dataTables settings object
4881	 *  @returns {node} Pagination feature node
4882	 *  @memberof DataTable#oApi
4883	 */
4884	function _fnFeatureHtmlPaginate ( settings )
4885	{
4886		var
4887			type   = settings.sPaginationType,
4888			plugin = DataTable.ext.pager[ type ],
4889			modern = typeof plugin === 'function',
4890			redraw = function( settings ) {
4891				_fnDraw( settings );
4892			},
4893			node = $('<div/>').addClass( settings.oClasses.sPaging + type )[0],
4894			features = settings.aanFeatures;
4895	
4896		if ( ! modern ) {
4897			plugin.fnInit( settings, node, redraw );
4898		}
4899	
4900		/* Add a draw callback for the pagination on first instance, to update the paging display */
4901		if ( ! features.p )
4902		{
4903			node.id = settings.sTableId+'_paginate';
4904	
4905			settings.aoDrawCallback.push( {
4906				"fn": function( settings ) {
4907					if ( modern ) {
4908						var
4909							start      = settings._iDisplayStart,
4910							len        = settings._iDisplayLength,
4911							visRecords = settings.fnRecordsDisplay(),
4912							all        = len === -1,
4913							page = all ? 0 : Math.ceil( start / len ),
4914							pages = all ? 1 : Math.ceil( visRecords / len ),
4915							buttons = plugin(page, pages),
4916							i, ien;
4917	
4918						for ( i=0, ien=features.p.length ; i<ien ; i++ ) {
4919							_fnRenderer( settings, 'pageButton' )(
4920								settings, features.p[i], i, buttons, page, pages
4921							);
4922						}
4923					}
4924					else {
4925						plugin.fnUpdate( settings, redraw );
4926					}
4927				},
4928				"sName": "pagination"
4929			} );
4930		}
4931	
4932		return node;
4933	}
4934	
4935	
4936	/**
4937	 * Alter the display settings to change the page
4938	 *  @param {object} settings DataTables settings object
4939	 *  @param {string|int} action Paging action to take: "first", "previous",
4940	 *    "next" or "last" or page number to jump to (integer)
4941	 *  @param [bool] redraw Automatically draw the update or not
4942	 *  @returns {bool} true page has changed, false - no change
4943	 *  @memberof DataTable#oApi
4944	 */
4945	function _fnPageChange ( settings, action, redraw )
4946	{
4947		var
4948			start     = settings._iDisplayStart,
4949			len       = settings._iDisplayLength,
4950			records   = settings.fnRecordsDisplay();
4951	
4952		if ( records === 0 || len === -1 )
4953		{
4954			start = 0;
4955		}
4956		else if ( typeof action === "number" )
4957		{
4958			start = action * len;
4959	
4960			if ( start > records )
4961			{
4962				start = 0;
4963			}
4964		}
4965		else if ( action == "first" )
4966		{
4967			start = 0;
4968		}
4969		else if ( action == "previous" )
4970		{
4971			start = len >= 0 ?
4972				start - len :
4973				0;
4974	
4975			if ( start < 0 )
4976			{
4977			  start = 0;
4978			}
4979		}
4980		else if ( action == "next" )
4981		{
4982			if ( start + len < records )
4983			{
4984				start += len;
4985			}
4986		}
4987		else if ( action == "last" )
4988		{
4989			start = Math.floor( (records-1) / len) * len;
4990		}
4991		else
4992		{
4993			_fnLog( settings, 0, "Unknown paging action: "+action, 5 );
4994		}
4995	
4996		var changed = settings._iDisplayStart !== start;
4997		settings._iDisplayStart = start;
4998	
4999		if ( changed ) {
5000			_fnCallbackFire( settings, null, 'page', [settings] );
5001	
5002			if ( redraw ) {
5003				_fnDraw( settings );
5004			}
5005		}
5006	
5007		return changed;
5008	}
5009	
5010	
5011	
5012	/**
5013	 * Generate the node required for the processing node
5014	 *  @param {object} settings dataTables settings object
5015	 *  @returns {node} Processing element
5016	 *  @memberof DataTable#oApi
5017	 */
5018	function _fnFeatureHtmlProcessing ( settings )
5019	{
5020		return $('<div/>', {
5021				'id': ! settings.aanFeatures.r ? settings.sTableId+'_processing' : null,
5022				'class': settings.oClasses.sProcessing
5023			} )
5024			.html( settings.oLanguage.sProcessing )
5025			.insertBefore( settings.nTable )[0];
5026	}
5027	
5028	
5029	/**
5030	 * Display or hide the processing indicator
5031	 *  @param {object} settings dataTables settings object
5032	 *  @param {bool} show Show the processing indicator (true) or not (false)
5033	 *  @memberof DataTable#oApi
5034	 */
5035	function _fnProcessingDisplay ( settings, show )
5036	{
5037		if ( settings.oFeatures.bProcessing ) {
5038			$(settings.aanFeatures.r).css( 'display', show ? 'block' : 'none' );
5039		}
5040	
5041		_fnCallbackFire( settings, null, 'processing', [settings, show] );
5042	}
5043	
5044	/**
5045	 * Add any control elements for the table - specifically scrolling
5046	 *  @param {object} settings dataTables settings object
5047	 *  @returns {node} Node to add to the DOM
5048	 *  @memberof DataTable#oApi
5049	 */
5050	function _fnFeatureHtmlTable ( settings )
5051	{
5052		var table = $(settings.nTable);
5053	
5054		// Add the ARIA grid role to the table
5055		table.attr( 'role', 'grid' );
5056	
5057		// Scrolling from here on in
5058		var scroll = settings.oScroll;
5059	
5060		if ( scroll.sX === '' && scroll.sY === '' ) {
5061			return settings.nTable;
5062		}
5063	
5064		var scrollX = scroll.sX;
5065		var scrollY = scroll.sY;
5066		var classes = settings.oClasses;
5067		var caption = table.children('caption');
5068		var captionSide = caption.length ? caption[0]._captionSide : null;
5069		var headerClone = $( table[0].cloneNode(false) );
5070		var footerClone = $( table[0].cloneNode(false) );
5071		var footer = table.children('tfoot');
5072		var _div = '<div/>';
5073		var size = function ( s ) {
5074			return !s ? null : _fnStringToCss( s );
5075		};
5076	
5077		if ( ! footer.length ) {
5078			footer = null;
5079		}
5080	
5081		/*
5082		 * The HTML structure that we want to generate in this function is:
5083		 *  div - scroller
5084		 *    div - scroll head
5085		 *      div - scroll head inner
5086		 *        table - scroll head table
5087		 *          thead - thead
5088		 *    div - scroll body
5089		 *      table - table (master table)
5090		 *        thead - thead clone for sizing
5091		 *        tbody - tbody
5092		 *    div - scroll foot
5093		 *      div - scroll foot inner
5094		 *        table - scroll foot table
5095		 *          tfoot - tfoot
5096		 */
5097		var scroller = $( _div, { 'class': classes.sScrollWrapper } )
5098			.append(
5099				$(_div, { 'class': classes.sScrollHead } )
5100					.css( {
5101						overflow: 'hidden',
5102						position: 'relative',
5103						border: 0,
5104						width: scrollX ? size(scrollX) : '100%'
5105					} )
5106					.append(
5107						$(_div, { 'class': classes.sScrollHeadInner } )
5108							.css( {
5109								'box-sizing': 'content-box',
5110								width: scroll.sXInner || '100%'
5111							} )
5112							.append(
5113								headerClone
5114									.removeAttr('id')
5115									.css( 'margin-left', 0 )
5116									.append( captionSide === 'top' ? caption : null )
5117									.append(
5118										table.children('thead')
5119									)
5120							)
5121					)
5122			)
5123			.append(
5124				$(_div, { 'class': classes.sScrollBody } )
5125					.css( {
5126						position: 'relative',
5127						overflow: 'auto',
5128						width: size( scrollX )
5129					} )
5130					.append( table )
5131			);
5132	
5133		if ( footer ) {
5134			scroller.append(
5135				$(_div, { 'class': classes.sScrollFoot } )
5136					.css( {
5137						overflow: 'hidden',
5138						border: 0,
5139						width: scrollX ? size(scrollX) : '100%'
5140					} )
5141					.append(
5142						$(_div, { 'class': classes.sScrollFootInner } )
5143							.append(
5144								footerClone
5145									.removeAttr('id')
5146									.css( 'margin-left', 0 )
5147									.append( captionSide === 'bottom' ? caption : null )
5148									.append(
5149										table.children('tfoot')
5150									)
5151							)
5152					)
5153			);
5154		}
5155	
5156		var children = scroller.children();
5157		var scrollHead = children[0];
5158		var scrollBody = children[1];
5159		var scrollFoot = footer ? children[2] : null;
5160	
5161		// When the body is scrolled, then we also want to scroll the headers
5162		if ( scrollX ) {
5163			$(scrollBody).on( 'scroll.DT', function (e) {
5164				var scrollLeft = this.scrollLeft;
5165	
5166				scrollHead.scrollLeft = scrollLeft;
5167	
5168				if ( footer ) {
5169					scrollFoot.scrollLeft = scrollLeft;
5170				}
5171			} );
5172		}
5173	
5174		$(scrollBody).css(
5175			scrollY && scroll.bCollapse ? 'max-height' : 'height', 
5176			scrollY
5177		);
5178	
5179		settings.nScrollHead = scrollHead;
5180		settings.nScrollBody = scrollBody;
5181		settings.nScrollFoot = scrollFoot;
5182	
5183		// On redraw - align columns
5184		settings.aoDrawCallback.push( {
5185			"fn": _fnScrollDraw,
5186			"sName": "scrolling"
5187		} );
5188	
5189		return scroller[0];
5190	}
5191	
5192	
5193	
5194	/**
5195	 * Update the header, footer and body tables for resizing - i.e. column
5196	 * alignment.
5197	 *
5198	 * Welcome to the most horrible function DataTables. The process that this
5199	 * function follows is basically:
5200	 *   1. Re-create the table inside the scrolling div
5201	 *   2. Take live measurements from the DOM
5202	 *   3. Apply the measurements to align the columns
5203	 *   4. Clean up
5204	 *
5205	 *  @param {object} settings dataTables settings object
5206	 *  @memberof DataTable#oApi
5207	 */
5208	function _fnScrollDraw ( settings )
5209	{
5210		// Given that this is such a monster function, a lot of variables are use
5211		// to try and keep the minimised size as small as possible
5212		var
5213			scroll         = settings.oScroll,
5214			scrollX        = scroll.sX,
5215			scrollXInner   = scroll.sXInner,
5216			scrollY        = scroll.sY,
5217			barWidth       = scroll.iBarWidth,
5218			divHeader      = $(settings.nScrollHead),
5219			divHeaderStyle = divHeader[0].style,
5220			divHeaderInner = divHeader.children('div'),
5221			divHeaderInnerStyle = divHeaderInner[0].style,
5222			divHeaderTable = divHeaderInner.children('table'),
5223			divBodyEl      = settings.nScrollBody,
5224			divBody        = $(divBodyEl),
5225			divBodyStyle   = divBodyEl.style,
5226			divFooter      = $(settings.nScrollFoot),
5227			divFooterInner = divFooter.children('div'),
5228			divFooterTable = divFooterInner.children('table'),
5229			header         = $(settings.nTHead),
5230			table          = $(settings.nTable),
5231			tableEl        = table[0],
5232			tableStyle     = tableEl.style,
5233			footer         = settings.nTFoot ? $(settings.nTFoot) : null,
5234			browser        = settings.oBrowser,
5235			ie67           = browser.bScrollOversize,
5236			dtHeaderCells  = _pluck( settings.aoColumns, 'nTh' ),
5237			headerTrgEls, footerTrgEls,
5238			headerSrcEls, footerSrcEls,
5239			headerCopy, footerCopy,
5240			headerWidths=[], footerWidths=[],
5241			headerContent=[], footerContent=[],
5242			idx, correction, sanityWidth,
5243			zeroOut = function(nSizer) {
5244				var style = nSizer.style;
5245				style.paddingTop = "0";
5246				style.paddingBottom = "0";
5247				style.borderTopWidth = "0";
5248				style.borderBottomWidth = "0";
5249				style.height = 0;
5250			};
5251	
5252		// If the scrollbar visibility has changed from the last draw, we need to
5253		// adjust the column sizes as the table width will have changed to account
5254		// for the scrollbar
5255		var scrollBarVis = divBodyEl.scrollHeight > divBodyEl.clientHeight;
5256		
5257		if ( settings.scrollBarVis !== scrollBarVis && settings.scrollBarVis !== undefined ) {
5258			settings.scrollBarVis = scrollBarVis;
5259			_fnAdjustColumnSizing( settings );
5260			return; // adjust column sizing will call this function again
5261		}
5262		else {
5263			settings.scrollBarVis = scrollBarVis;
5264		}
5265	
5266		/*
5267		 * 1. Re-create the table inside the scrolling div
5268		 */
5269	
5270		// Remove the old minimised thead and tfoot elements in the inner table
5271		table.children('thead, tfoot').remove();
5272	
5273		if ( footer ) {
5274			footerCopy = footer.clone().prependTo( table );
5275			footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized
5276			footerSrcEls = footerCopy.find('tr');
5277		}
5278	
5279		// Clone the current header and footer elements and then place it into the inner table
5280		headerCopy = header.clone().prependTo( table );
5281		headerTrgEls = header.find('tr'); // original header is in its own table
5282		headerSrcEls = headerCopy.find('tr');
5283		headerCopy.find('th, td').removeAttr('tabindex');
5284	
5285	
5286		/*
5287		 * 2. Take live measurements from the DOM - do not alter the DOM itself!
5288		 */
5289	
5290		// Remove old sizing and apply the calculated column widths
5291		// Get the unique column headers in the newly created (cloned) header. We want to apply the
5292		// calculated sizes to this header
5293		if ( ! scrollX )
5294		{
5295			divBodyStyle.width = '100%';
5296			divHeader[0].style.width = '100%';
5297		}
5298	
5299		$.each( _fnGetUniqueThs( settings, headerCopy ), function ( i, el ) {
5300			idx = _fnVisibleToColumnIndex( settings, i );
5301			el.style.width = settings.aoColumns[idx].sWidth;
5302		} );
5303	
5304		if ( footer ) {
5305			_fnApplyToChildren( function(n) {
5306				n.style.width = "";
5307			}, footerSrcEls );
5308		}
5309	
5310		// Size the table as a whole
5311		sanityWidth = table.outerWidth();
5312		if ( scrollX === "" ) {
5313			// No x scrolling
5314			tableStyle.width = "100%";
5315	
5316			// IE7 will make the width of the table when 100% include the scrollbar
5317			// - which is shouldn't. When there is a scrollbar we need to take this
5318			// into account.
5319			if ( ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight ||
5320				divBody.css('overflow-y') == "scroll")
5321			) {
5322				tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth);
5323			}
5324	
5325			// Recalculate the sanity width
5326			sanityWidth = table.outerWidth();
5327		}
5328		else if ( scrollXInner !== "" ) {
5329			// legacy x scroll inner has been given - use it
5330			tableStyle.width = _fnStringToCss(scrollXInner);
5331	
5332			// Recalculate the sanity width
5333			sanityWidth = table.outerWidth();
5334		}
5335	
5336		// Hidden header should have zero height, so remove padding and borders. Then
5337		// set the width based on the real headers
5338	
5339		// Apply all styles in one pass
5340		_fnApplyToChildren( zeroOut, headerSrcEls );
5341	
5342		// Read all widths in next pass
5343		_fnApplyToChildren( function(nSizer) {
5344			headerContent.push( nSizer.innerHTML );
5345			headerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
5346		}, headerSrcEls );
5347	
5348		// Apply all widths in final pass
5349		_fnApplyToChildren( function(nToSize, i) {
5350			// Only apply widths to the DataTables detected header cells - this
5351			// prevents complex headers from having contradictory sizes applied
5352			if ( $.inArray( nToSize, dtHeaderCells ) !== -1 ) {
5353				nToSize.style.width = headerWidths[i];
5354			}
5355		}, headerTrgEls );
5356	
5357		$(headerSrcEls).height(0);
5358	
5359		/* Same again with the footer if we have one */
5360		if ( footer )
5361		{
5362			_fnApplyToChildren( zeroOut, footerSrcEls );
5363	
5364			_fnApplyToChildren( function(nSizer) {
5365				footerContent.push( nSizer.innerHTML );
5366				footerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
5367			}, footerSrcEls );
5368	
5369			_fnApplyToChildren( function(nToSize, i) {
5370				nToSize.style.width = footerWidths[i];
5371			}, footerTrgEls );
5372	
5373			$(footerSrcEls).height(0);
5374		}
5375	
5376	
5377		/*
5378		 * 3. Apply the measurements
5379		 */
5380	
5381		// "Hide" the header and footer that we used for the sizing. We need to keep
5382		// the content of the cell so that the width applied to the header and body
5383		// both match, but we want to hide it completely. We want to also fix their
5384		// width to what they currently are
5385		_fnApplyToChildren( function(nSizer, i) {
5386			nSizer.innerHTML = '<div class="dataTables_sizing">'+headerContent[i]+'</div>';
5387			nSizer.childNodes[0].style.height = "0";
5388			nSizer.childNodes[0].style.overflow = "hidden";
5389			nSizer.style.width = headerWidths[i];
5390		}, headerSrcEls );
5391	
5392		if ( footer )
5393		{
5394			_fnApplyToChildren( function(nSizer, i) {
5395				nSizer.innerHTML = '<div class="dataTables_sizing">'+footerContent[i]+'</div>';
5396				nSizer.childNodes[0].style.height = "0";
5397				nSizer.childNodes[0].style.overflow = "hidden";
5398				nSizer.style.width = footerWidths[i];
5399			}, footerSrcEls );
5400		}
5401	
5402		// Sanity check that the table is of a sensible width. If not then we are going to get
5403		// misalignment - try to prevent this by not allowing the table to shrink below its min width
5404		if ( table.outerWidth() < sanityWidth )
5405		{
5406			// The min width depends upon if we have a vertical scrollbar visible or not */
5407			correction = ((divBodyEl.scrollHeight > divBodyEl.offsetHeight ||
5408				divBody.css('overflow-y') == "scroll")) ?
5409					sanityWidth+barWidth :
5410					sanityWidth;
5411	
5412			// IE6/7 are a law unto themselves...
5413			if ( ie67 && (divBodyEl.scrollHeight >
5414				divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll")
5415			) {
5416				tableStyle.width = _fnStringToCss( correction-barWidth );
5417			}
5418	
5419			// And give the user a warning that we've stopped the table getting too small
5420			if ( scrollX === "" || scrollXInner !== "" ) {
5421				_fnLog( settings, 1, 'Possible column misalignment', 6 );
5422			}
5423		}
5424		else
5425		{
5426			correction = '100%';
5427		}
5428	
5429		// Apply to the container elements
5430		divBodyStyle.width = _fnStringToCss( correction );
5431		divHeaderStyle.width = _fnStringToCss( correction );
5432	
5433		if ( footer ) {
5434			settings.nScrollFoot.style.width = _fnStringToCss( correction );
5435		}
5436	
5437	
5438		/*
5439		 * 4. Clean up
5440		 */
5441		if ( ! scrollY ) {
5442			/* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
5443			 * the scrollbar height from the visible display, rather than adding it on. We need to
5444			 * set the height in order to sort this. Don't want to do it in any other browsers.
5445			 */
5446			if ( ie67 ) {
5447				divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+barWidth );
5448			}
5449		}
5450	
5451		/* Finally set the width's of the header and footer tables */
5452		var iOuterWidth = table.outerWidth();
5453		divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth );
5454		divHeaderInnerStyle.width = _fnStringToCss( iOuterWidth );
5455	
5456		// Figure out if there are scrollbar present - if so then we need a the header and footer to
5457		// provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
5458		var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll";
5459		var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' );
5460		divHeaderInnerStyle[ padding ] = bScrolling ? barWidth+"px" : "0px";
5461	
5462		if ( footer ) {
5463			divFooterTable[0].style.width = _fnStringToCss( iOuterWidth );
5464			divFooterInner[0].style.width = _fnStringToCss( iOuterWidth );
5465			divFooterInner[0].style[padding] = bScrolling ? barWidth+"px" : "0px";
5466		}
5467	
5468		// Correct DOM ordering for colgroup - comes before the thead
5469		table.children('colgroup').insertBefore( table.children('thead') );
5470	
5471		/* Adjust the position of the header in case we loose the y-scrollbar */
5472		divBody.scroll(
vendor: 11,594 bytes, lines 5472-5870
5472);
5473	
5474		// If sorting or filtering has occurred, jump the scrolling back to the top
5475		// only if we aren't holding the position
5476		if ( (settings.bSorted || settings.bFiltered) && ! settings._drawHold ) {
5477			divBodyEl.scrollTop = 0;
5478		}
5479	}
5480	
5481	
5482	
5483	/**
5484	 * Apply a given function to the display child nodes of an element array (typically
5485	 * TD children of TR rows
5486	 *  @param {function} fn Method to apply to the objects
5487	 *  @param array {nodes} an1 List of elements to look through for display children
5488	 *  @param array {nodes} an2 Another list (identical structure to the first) - optional
5489	 *  @memberof DataTable#oApi
5490	 */
5491	function _fnApplyToChildren( fn, an1, an2 )
5492	{
5493		var index=0, i=0, iLen=an1.length;
5494		var nNode1, nNode2;
5495	
5496		while ( i < iLen ) {
5497			nNode1 = an1[i].firstChild;
5498			nNode2 = an2 ? an2[i].firstChild : null;
5499	
5500			while ( nNode1 ) {
5501				if ( nNode1.nodeType === 1 ) {
5502					if ( an2 ) {
5503						fn( nNode1, nNode2, index );
5504					}
5505					else {
5506						fn( nNode1, index );
5507					}
5508	
5509					index++;
5510				}
5511	
5512				nNode1 = nNode1.nextSibling;
5513				nNode2 = an2 ? nNode2.nextSibling : null;
5514			}
5515	
5516			i++;
5517		}
5518	}
5519	
5520	
5521	
5522	var __re_html_remove = /<.*?>/g;
5523	
5524	
5525	/**
5526	 * Calculate the width of columns for the table
5527	 *  @param {object} oSettings dataTables settings object
5528	 *  @memberof DataTable#oApi
5529	 */
5530	function _fnCalculateColumnWidths ( oSettings )
5531	{
5532		var
5533			table = oSettings.nTable,
5534			columns = oSettings.aoColumns,
5535			scroll = oSettings.oScroll,
5536			scrollY = scroll.sY,
5537			scrollX = scroll.sX,
5538			scrollXInner = scroll.sXInner,
5539			columnCount = columns.length,
5540			visibleColumns = _fnGetColumns( oSettings, 'bVisible' ),
5541			headerCells = $('th', oSettings.nTHead),
5542			tableWidthAttr = table.getAttribute('width'), // from DOM element
5543			tableContainer = table.parentNode,
5544			userInputs = false,
5545			i, column, columnIdx, width, outerWidth,
5546			browser = oSettings.oBrowser,
5547			ie67 = browser.bScrollOversize;
5548	
5549		var styleWidth = table.style.width;
5550		if ( styleWidth && styleWidth.indexOf('%') !== -1 ) {
5551			tableWidthAttr = styleWidth;
5552		}
5553	
5554		/* Convert any user input sizes into pixel sizes */
5555		for ( i=0 ; i<visibleColumns.length ; i++ ) {
5556			column = columns[ visibleColumns[i] ];
5557	
5558			if ( column.sWidth !== null ) {
5559				column.sWidth = _fnConvertToWidth( column.sWidthOrig, tableContainer );
5560	
5561				userInputs = true;
5562			}
5563		}
5564	
5565		/* If the number of columns in the DOM equals the number that we have to
5566		 * process in DataTables, then we can use the offsets that are created by
5567		 * the web- browser. No custom sizes can be set in order for this to happen,
5568		 * nor scrolling used
5569		 */
5570		if ( ie67 || ! userInputs && ! scrollX && ! scrollY &&
5571		     columnCount == _fnVisbleColumns( oSettings ) &&
5572		     columnCount == headerCells.length
5573		) {
5574			for ( i=0 ; i<columnCount ; i++ ) {
5575				var colIdx = _fnVisibleToColumnIndex( oSettings, i );
5576	
5577				if ( colIdx !== null ) {
5578					columns[ colIdx ].sWidth = _fnStringToCss( headerCells.eq(i).width() );
5579				}
5580			}
5581		}
5582		else
5583		{
5584			// Otherwise construct a single row, worst case, table with the widest
5585			// node in the data, assign any user defined widths, then insert it into
5586			// the DOM and allow the browser to do all the hard work of calculating
5587			// table widths
5588			var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table
5589				.css( 'visibility', 'hidden' )
5590				.removeAttr( 'id' );
5591	
5592			// Clean up the table body
5593			tmpTable.find('tbody tr').remove();
5594			var tr = $('<tr/>').appendTo( tmpTable.find('tbody') );
5595	
5596			// Clone the table header and footer - we can't use the header / footer
5597			// from the cloned table, since if scrolling is active, the table's
5598			// real header and footer are contained in different table tags
5599			tmpTable.find('thead, tfoot').remove();
5600			tmpTable
5601				.append( $(oSettings.nTHead).clone() )
5602				.append( $(oSettings.nTFoot).clone() );
5603	
5604			// Remove any assigned widths from the footer (from scrolling)
5605			tmpTable.find('tfoot th, tfoot td').css('width', '');
5606	
5607			// Apply custom sizing to the cloned header
5608			headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] );
5609	
5610			for ( i=0 ; i<visibleColumns.length ; i++ ) {
5611				column = columns[ visibleColumns[i] ];
5612	
5613				headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ?
5614					_fnStringToCss( column.sWidthOrig ) :
5615					'';
5616	
5617				// For scrollX we need to force the column width otherwise the
5618				// browser will collapse it. If this width is smaller than the
5619				// width the column requires, then it will have no effect
5620				if ( column.sWidthOrig && scrollX ) {
5621					$( headerCells[i] ).append( $('<div/>').css( {
5622						width: column.sWidthOrig,
5623						margin: 0,
5624						padding: 0,
5625						border: 0,
5626						height: 1
5627					} ) );
5628				}
5629			}
5630	
5631			// Find the widest cell for each column and put it into the table
5632			if ( oSettings.aoData.length ) {
5633				for ( i=0 ; i<visibleColumns.length ; i++ ) {
5634					columnIdx = visibleColumns[i];
5635					column = columns[ columnIdx ];
5636	
5637					$( _fnGetWidestNode( oSettings, columnIdx ) )
5638						.clone( false )
5639						.append( column.sContentPadding )
5640						.appendTo( tr );
5641				}
5642			}
5643	
5644			// Tidy the temporary table - remove name attributes so there aren't
5645			// duplicated in the dom (radio elements for example)
5646			$('[name]', tmpTable).removeAttr('name');
5647	
5648			// Table has been built, attach to the document so we can work with it.
5649			// A holding element is used, positioned at the top of the container
5650			// with minimal height, so it has no effect on if the container scrolls
5651			// or not. Otherwise it might trigger scrolling when it actually isn't
5652			// needed
5653			var holder = $('<div/>').css( scrollX || scrollY ?
5654					{
5655						position: 'absolute',
5656						top: 0,
5657						left: 0,
5658						height: 1,
5659						right: 0,
5660						overflow: 'hidden'
5661					} :
5662					{}
5663				)
5664				.append( tmpTable )
5665				.appendTo( tableContainer );
5666	
5667			// When scrolling (X or Y) we want to set the width of the table as 
5668			// appropriate. However, when not scrolling leave the table width as it
5669			// is. This results in slightly different, but I think correct behaviour
5670			if ( scrollX && scrollXInner ) {
5671				tmpTable.width( scrollXInner );
5672			}
5673			else if ( scrollX ) {
5674				tmpTable.css( 'width', 'auto' );
5675				tmpTable.removeAttr('width');
5676	
5677				// If there is no width attribute or style, then allow the table to
5678				// collapse
5679				if ( tmpTable.width() < tableContainer.clientWidth && tableWidthAttr ) {
5680					tmpTable.width( tableContainer.clientWidth );
5681				}
5682			}
5683			else if ( scrollY ) {
5684				tmpTable.width( tableContainer.clientWidth );
5685			}
5686			else if ( tableWidthAttr ) {
5687				tmpTable.width( tableWidthAttr );
5688			}
5689	
5690			// Get the width of each column in the constructed table - we need to
5691			// know the inner width (so it can be assigned to the other table's
5692			// cells) and the outer width so we can calculate the full width of the
5693			// table. This is safe since DataTables requires a unique cell for each
5694			// column, but if ever a header can span multiple columns, this will
5695			// need to be modified.
5696			var total = 0;
5697			for ( i=0 ; i<visibleColumns.length ; i++ ) {
5698				var cell = $(headerCells[i]);
5699				var border = cell.outerWidth() - cell.width();
5700	
5701				// Use getBounding... where possible (not IE8-) because it can give
5702				// sub-pixel accuracy, which we then want to round up!
5703				var bounding = browser.bBounding ?
5704					Math.ceil( headerCells[i].getBoundingClientRect().width ) :
5705					cell.outerWidth();
5706	
5707				// Total is tracked to remove any sub-pixel errors as the outerWidth
5708				// of the table might not equal the total given here (IE!).
5709				total += bounding;
5710	
5711				// Width for each column to use
5712				columns[ visibleColumns[i] ].sWidth = _fnStringToCss( bounding - border );
5713			}
5714	
5715			table.style.width = _fnStringToCss( total );
5716	
5717			// Finished with the table - ditch it
5718			holder.remove();
5719		}
5720	
5721		// If there is a width attr, we want to attach an event listener which
5722		// allows the table sizing to automatically adjust when the window is
5723		// resized. Use the width attr rather than CSS, since we can't know if the
5724		// CSS is a relative value or absolute - DOM read is always px.
5725		if ( tableWidthAttr ) {
5726			table.style.width = _fnStringToCss( tableWidthAttr );
5727		}
5728	
5729		if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) {
5730			var bindResize = function () {
5731				$(window).on('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {
5732					_fnAdjustColumnSizing( oSettings );
5733				} ) );
5734			};
5735	
5736			// IE6/7 will crash if we bind a resize event handler on page load.
5737			// To be removed in 1.11 which drops IE6/7 support
5738			if ( ie67 ) {
5739				setTimeout( bindResize, 1000 );
5740			}
5741			else {
5742				bindResize();
5743			}
5744	
5745			oSettings._reszEvt = true;
5746		}
5747	}
5748	
5749	
5750	/**
5751	 * Throttle the calls to a function. Arguments and context are maintained for
5752	 * the throttled function
5753	 *  @param {function} fn Function to be called
5754	 *  @param {int} [freq=200] call frequency in mS
5755	 *  @returns {function} wrapped function
5756	 *  @memberof DataTable#oApi
5757	 */
5758	var _fnThrottle = DataTable.util.throttle;
5759	
5760	
5761	/**
5762	 * Convert a CSS unit width to pixels (e.g. 2em)
5763	 *  @param {string} width width to be converted
5764	 *  @param {node} parent parent to get the with for (required for relative widths) - optional
5765	 *  @returns {int} width in pixels
5766	 *  @memberof DataTable#oApi
5767	 */
5768	function _fnConvertToWidth ( width, parent )
5769	{
5770		if ( ! width ) {
5771			return 0;
5772		}
5773	
5774		var n = $('<div/>')
5775			.css( 'width', _fnStringToCss( width ) )
5776			.appendTo( parent || document.body );
5777	
5778		var val = n[0].offsetWidth;
5779		n.remove();
5780	
5781		return val;
5782	}
5783	
5784	
5785	/**
5786	 * Get the widest node
5787	 *  @param {object} settings dataTables settings object
5788	 *  @param {int} colIdx column of interest
5789	 *  @returns {node} widest table node
5790	 *  @memberof DataTable#oApi
5791	 */
5792	function _fnGetWidestNode( settings, colIdx )
5793	{
5794		var idx = _fnGetMaxLenString( settings, colIdx );
5795		if ( idx < 0 ) {
5796			return null;
5797		}
5798	
5799		var data = settings.aoData[ idx ];
5800		return ! data.nTr ? // Might not have been created when deferred rendering
5801			$('<td/>').html( _fnGetCellData( settings, idx, colIdx, 'display' ) )[0] :
5802			data.anCells[ colIdx ];
5803	}
5804	
5805	
5806	/**
5807	 * Get the maximum strlen for each data column
5808	 *  @param {object} settings dataTables settings object
5809	 *  @param {int} colIdx column of interest
5810	 *  @returns {string} max string length for each column
5811	 *  @memberof DataTable#oApi
5812	 */
5813	function _fnGetMaxLenString( settings, colIdx )
5814	{
5815		var s, max=-1, maxIdx = -1;
5816	
5817		for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
5818			s = _fnGetCellData( settings, i, colIdx, 'display' )+'';
5819			s = s.replace( __re_html_remove, '' );
5820			s = s.replace( /&nbsp;/g, ' ' );
5821	
5822			if ( s.length > max ) {
5823				max = s.length;
5824				maxIdx = i;
5825			}
5826		}
5827	
5828		return maxIdx;
5829	}
5830	
5831	
5832	/**
5833	 * Append a CSS unit (only if required) to a string
5834	 *  @param {string} value to css-ify
5835	 *  @returns {string} value with css unit
5836	 *  @memberof DataTable#oApi
5837	 */
5838	function _fnStringToCss( s )
5839	{
5840		if ( s === null ) {
5841			return '0px';
5842		}
5843	
5844		if ( typeof s == 'number' ) {
5845			return s < 0 ?
5846				'0px' :
5847				s+'px';
5848		}
5849	
5850		// Check it has a unit character already
5851		return s.match(/\d$/) ?
5852			s+'px' :
5853			s;
5854	}
5855	
5856	
5857	
5858	function _fnSortFlatten ( settings )
5859	{
5860		var
5861			i, iLen, k, kLen,
5862			aSort = [],
5863			aiOrig = [],
5864			aoColumns = settings.aoColumns,
5865			aDataSort, iCol, sType, srcCol,
5866			fixed = settings.aaSortingFixed,
5867			fixedObj = $.isPlainObject( fixed ),
5868			nestedSort = [],
5869			add = function ( a ) {
5870				if ( a.length && ! 
vendor: 39,758 bytes, lines 5870-7391
5870$.isArray( a[0] ) ) {
5871					// 1D array
5872					nestedSort.push( a );
5873				}
5874				else {
5875					// 2D array
5876					$.merge( nestedSort, a );
5877				}
5878			};
5879	
5880		// Build the sort array, with pre-fix and post-fix options if they have been
5881		// specified
5882		if ( $.isArray( fixed ) ) {
5883			add( fixed );
5884		}
5885	
5886		if ( fixedObj && fixed.pre ) {
5887			add( fixed.pre );
5888		}
5889	
5890		add( settings.aaSorting );
5891	
5892		if (fixedObj && fixed.post ) {
5893			add( fixed.post );
5894		}
5895	
5896		for ( i=0 ; i<nestedSort.length ; i++ )
5897		{
5898			srcCol = nestedSort[i][0];
5899			aDataSort = aoColumns[ srcCol ].aDataSort;
5900	
5901			for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ )
5902			{
5903				iCol = aDataSort[k];
5904				sType = aoColumns[ iCol ].sType || 'string';
5905	
5906				if ( nestedSort[i]._idx === undefined ) {
5907					nestedSort[i]._idx = $.inArray( nestedSort[i][1], aoColumns[iCol].asSorting );
5908				}
5909	
5910				aSort.push( {
5911					src:       srcCol,
5912					col:       iCol,
5913					dir:       nestedSort[i][1],
5914					index:     nestedSort[i]._idx,
5915					type:      sType,
5916					formatter: DataTable.ext.type.order[ sType+"-pre" ]
5917				} );
5918			}
5919		}
5920	
5921		return aSort;
5922	}
5923	
5924	/**
5925	 * Change the order of the table
5926	 *  @param {object} oSettings dataTables settings object
5927	 *  @memberof DataTable#oApi
5928	 *  @todo This really needs split up!
5929	 */
5930	function _fnSort ( oSettings )
5931	{
5932		var
5933			i, ien, iLen, j, jLen, k, kLen,
5934			sDataType, nTh,
5935			aiOrig = [],
5936			oExtSort = DataTable.ext.type.order,
5937			aoData = oSettings.aoData,
5938			aoColumns = oSettings.aoColumns,
5939			aDataSort, data, iCol, sType, oSort,
5940			formatters = 0,
5941			sortCol,
5942			displayMaster = oSettings.aiDisplayMaster,
5943			aSort;
5944	
5945		// Resolve any column types that are unknown due to addition or invalidation
5946		// @todo Can this be moved into a 'data-ready' handler which is called when
5947		//   data is going to be used in the table?
5948		_fnColumnTypes( oSettings );
5949	
5950		aSort = _fnSortFlatten( oSettings );
5951	
5952		for ( i=0, ien=aSort.length ; i<ien ; i++ ) {
5953			sortCol = aSort[i];
5954	
5955			// Track if we can use the fast sort algorithm
5956			if ( sortCol.formatter ) {
5957				formatters++;
5958			}
5959	
5960			// Load the data needed for the sort, for each cell
5961			_fnSortData( oSettings, sortCol.col );
5962		}
5963	
5964		/* No sorting required if server-side or no sorting array */
5965		if ( _fnDataSource( oSettings ) != 'ssp' && aSort.length !== 0 )
5966		{
5967			// Create a value - key array of the current row positions such that we can use their
5968			// current position during the sort, if values match, in order to perform stable sorting
5969			for ( i=0, iLen=displayMaster.length ; i<iLen ; i++ ) {
5970				aiOrig[ displayMaster[i] ] = i;
5971			}
5972	
5973			/* Do the sort - here we want multi-column sorting based on a given data source (column)
5974			 * and sorting function (from oSort) in a certain direction. It's reasonably complex to
5975			 * follow on it's own, but this is what we want (example two column sorting):
5976			 *  fnLocalSorting = function(a,b){
5977			 *    var iTest;
5978			 *    iTest = oSort['string-asc']('data11', 'data12');
5979			 *      if (iTest !== 0)
5980			 *        return iTest;
5981			 *    iTest = oSort['numeric-desc']('data21', 'data22');
5982			 *    if (iTest !== 0)
5983			 *      return iTest;
5984			 *    return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
5985			 *  }
5986			 * Basically we have a test for each sorting column, if the data in that column is equal,
5987			 * test the next column. If all columns match, then we use a numeric sort on the row
5988			 * positions in the original data array to provide a stable sort.
5989			 *
5990			 * Note - I know it seems excessive to have two sorting methods, but the first is around
5991			 * 15% faster, so the second is only maintained for backwards compatibility with sorting
5992			 * methods which do not have a pre-sort formatting function.
5993			 */
5994			if ( formatters === aSort.length ) {
5995				// All sort types have formatting functions
5996				displayMaster.sort( function ( a, b ) {
5997					var
5998						x, y, k, test, sort,
5999						len=aSort.length,
6000						dataA = aoData[a]._aSortData,
6001						dataB = aoData[b]._aSortData;
6002	
6003					for ( k=0 ; k<len ; k++ ) {
6004						sort = aSort[k];
6005	
6006						x = dataA[ sort.col ];
6007						y = dataB[ sort.col ];
6008	
6009						test = x<y ? -1 : x>y ? 1 : 0;
6010						if ( test !== 0 ) {
6011							return sort.dir === 'asc' ? test : -test;
6012						}
6013					}
6014	
6015					x = aiOrig[a];
6016					y = aiOrig[b];
6017					return x<y ? -1 : x>y ? 1 : 0;
6018				} );
6019			}
6020			else {
6021				// Depreciated - remove in 1.11 (providing a plug-in option)
6022				// Not all sort types have formatting methods, so we have to call their sorting
6023				// methods.
6024				displayMaster.sort( function ( a, b ) {
6025					var
6026						x, y, k, l, test, sort, fn,
6027						len=aSort.length,
6028						dataA = aoData[a]._aSortData,
6029						dataB = aoData[b]._aSortData;
6030	
6031					for ( k=0 ; k<len ; k++ ) {
6032						sort = aSort[k];
6033	
6034						x = dataA[ sort.col ];
6035						y = dataB[ sort.col ];
6036	
6037						fn = oExtSort[ sort.type+"-"+sort.dir ] || oExtSort[ "string-"+sort.dir ];
6038						test = fn( x, y );
6039						if ( test !== 0 ) {
6040							return test;
6041						}
6042					}
6043	
6044					x = aiOrig[a];
6045					y = aiOrig[b];
6046					return x<y ? -1 : x>y ? 1 : 0;
6047				} );
6048			}
6049		}
6050	
6051		/* Tell the draw function that we have sorted the data */
6052		oSettings.bSorted = true;
6053	}
6054	
6055	
6056	function _fnSortAria ( settings )
6057	{
6058		var label;
6059		var nextSort;
6060		var columns = settings.aoColumns;
6061		var aSort = _fnSortFlatten( settings );
6062		var oAria = settings.oLanguage.oAria;
6063	
6064		// ARIA attributes - need to loop all columns, to update all (removing old
6065		// attributes as needed)
6066		for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
6067		{
6068			var col = columns[i];
6069			var asSorting = col.asSorting;
6070			var sTitle = col.sTitle.replace( /<.*?>/g, "" );
6071			var th = col.nTh;
6072	
6073			// IE7 is throwing an error when setting these properties with jQuery's
6074			// attr() and removeAttr() methods...
6075			th.removeAttribute('aria-sort');
6076	
6077			/* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
6078			if ( col.bSortable ) {
6079				if ( aSort.length > 0 && aSort[0].col == i ) {
6080					th.setAttribute('aria-sort', aSort[0].dir=="asc" ? "ascending" : "descending" );
6081					nextSort = asSorting[ aSort[0].index+1 ] || asSorting[0];
6082				}
6083				else {
6084					nextSort = asSorting[0];
6085				}
6086	
6087				label = sTitle + ( nextSort === "asc" ?
6088					oAria.sSortAscending :
6089					oAria.sSortDescending
6090				);
6091			}
6092			else {
6093				label = sTitle;
6094			}
6095	
6096			th.setAttribute('aria-label', label);
6097		}
6098	}
6099	
6100	
6101	/**
6102	 * Function to run on user sort request
6103	 *  @param {object} settings dataTables settings object
6104	 *  @param {node} attachTo node to attach the handler to
6105	 *  @param {int} colIdx column sorting index
6106	 *  @param {boolean} [append=false] Append the requested sort to the existing
6107	 *    sort if true (i.e. multi-column sort)
6108	 *  @param {function} [callback] callback function
6109	 *  @memberof DataTable#oApi
6110	 */
6111	function _fnSortListener ( settings, colIdx, append, callback )
6112	{
6113		var col = settings.aoColumns[ colIdx ];
6114		var sorting = settings.aaSorting;
6115		var asSorting = col.asSorting;
6116		var nextSortIdx;
6117		var next = function ( a, overflow ) {
6118			var idx = a._idx;
6119			if ( idx === undefined ) {
6120				idx = $.inArray( a[1], asSorting );
6121			}
6122	
6123			return idx+1 < asSorting.length ?
6124				idx+1 :
6125				overflow ?
6126					null :
6127					0;
6128		};
6129	
6130		// Convert to 2D array if needed
6131		if ( typeof sorting[0] === 'number' ) {
6132			sorting = settings.aaSorting = [ sorting ];
6133		}
6134	
6135		// If appending the sort then we are multi-column sorting
6136		if ( append && settings.oFeatures.bSortMulti ) {
6137			// Are we already doing some kind of sort on this column?
6138			var sortIdx = $.inArray( colIdx, _pluck(sorting, '0') );
6139	
6140			if ( sortIdx !== -1 ) {
6141				// Yes, modify the sort
6142				nextSortIdx = next( sorting[sortIdx], true );
6143	
6144				if ( nextSortIdx === null && sorting.length === 1 ) {
6145					nextSortIdx = 0; // can't remove sorting completely
6146				}
6147	
6148				if ( nextSortIdx === null ) {
6149					sorting.splice( sortIdx, 1 );
6150				}
6151				else {
6152					sorting[sortIdx][1] = asSorting[ nextSortIdx ];
6153					sorting[sortIdx]._idx = nextSortIdx;
6154				}
6155			}
6156			else {
6157				// No sort on this column yet
6158				sorting.push( [ colIdx, asSorting[0], 0 ] );
6159				sorting[sorting.length-1]._idx = 0;
6160			}
6161		}
6162		else if ( sorting.length && sorting[0][0] == colIdx ) {
6163			// Single column - already sorting on this column, modify the sort
6164			nextSortIdx = next( sorting[0] );
6165	
6166			sorting.length = 1;
6167			sorting[0][1] = asSorting[ nextSortIdx ];
6168			sorting[0]._idx = nextSortIdx;
6169		}
6170		else {
6171			// Single column - sort only on this column
6172			sorting.length = 0;
6173			sorting.push( [ colIdx, asSorting[0] ] );
6174			sorting[0]._idx = 0;
6175		}
6176	
6177		// Run the sort by calling a full redraw
6178		_fnReDraw( settings );
6179	
6180		// callback used for async user interaction
6181		if ( typeof callback == 'function' ) {
6182			callback( settings );
6183		}
6184	}
6185	
6186	
6187	/**
6188	 * Attach a sort handler (click) to a node
6189	 *  @param {object} settings dataTables settings object
6190	 *  @param {node} attachTo node to attach the handler to
6191	 *  @param {int} colIdx column sorting index
6192	 *  @param {function} [callback] callback function
6193	 *  @memberof DataTable#oApi
6194	 */
6195	function _fnSortAttachListener ( settings, attachTo, colIdx, callback )
6196	{
6197		var col = settings.aoColumns[ colIdx ];
6198	
6199		_fnBindAction( attachTo, {}, function (e) {
6200			/* If the column is not sortable - don't to anything */
6201			if ( col.bSortable === false ) {
6202				return;
6203			}
6204	
6205			// If processing is enabled use a timeout to allow the processing
6206			// display to be shown - otherwise to it synchronously
6207			if ( settings.oFeatures.bProcessing ) {
6208				_fnProcessingDisplay( settings, true );
6209	
6210				setTimeout( function() {
6211					_fnSortListener( settings, colIdx, e.shiftKey, callback );
6212	
6213					// In server-side processing, the draw callback will remove the
6214					// processing display
6215					if ( _fnDataSource( settings ) !== 'ssp' ) {
6216						_fnProcessingDisplay( settings, false );
6217					}
6218				}, 0 );
6219			}
6220			else {
6221				_fnSortListener( settings, colIdx, e.shiftKey, callback );
6222			}
6223		} );
6224	}
6225	
6226	
6227	/**
6228	 * Set the sorting classes on table's body, Note: it is safe to call this function
6229	 * when bSort and bSortClasses are false
6230	 *  @param {object} oSettings dataTables settings object
6231	 *  @memberof DataTable#oApi
6232	 */
6233	function _fnSortingClasses( settings )
6234	{
6235		var oldSort = settings.aLastSort;
6236		var sortClass = settings.oClasses.sSortColumn;
6237		var sort = _fnSortFlatten( settings );
6238		var features = settings.oFeatures;
6239		var i, ien, colIdx;
6240	
6241		if ( features.bSort && features.bSortClasses ) {
6242			// Remove old sorting classes
6243			for ( i=0, ien=oldSort.length ; i<ien ; i++ ) {
6244				colIdx = oldSort[i].src;
6245	
6246				// Remove column sorting
6247				$( _pluck( settings.aoData, 'anCells', colIdx ) )
6248					.removeClass( sortClass + (i<2 ? i+1 : 3) );
6249			}
6250	
6251			// Add new column sorting
6252			for ( i=0, ien=sort.length ; i<ien ; i++ ) {
6253				colIdx = sort[i].src;
6254	
6255				$( _pluck( settings.aoData, 'anCells', colIdx ) )
6256					.addClass( sortClass + (i<2 ? i+1 : 3) );
6257			}
6258		}
6259	
6260		settings.aLastSort = sort;
6261	}
6262	
6263	
6264	// Get the data to sort a column, be it from cache, fresh (populating the
6265	// cache), or from a sort formatter
6266	function _fnSortData( settings, idx )
6267	{
6268		// Custom sorting function - provided by the sort data type
6269		var column = settings.aoColumns[ idx ];
6270		var customSort = DataTable.ext.order[ column.sSortDataType ];
6271		var customData;
6272	
6273		if ( customSort ) {
6274			customData = customSort.call( settings.oInstance, settings, idx,
6275				_fnColumnIndexToVisible( settings, idx )
6276			);
6277		}
6278	
6279		// Use / populate cache
6280		var row, cellData;
6281		var formatter = DataTable.ext.type.order[ column.sType+"-pre" ];
6282	
6283		for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
6284			row = settings.aoData[i];
6285	
6286			if ( ! row._aSortData ) {
6287				row._aSortData = [];
6288			}
6289	
6290			if ( ! row._aSortData[idx] || customSort ) {
6291				cellData = customSort ?
6292					customData[i] : // If there was a custom sort function, use data from there
6293					_fnGetCellData( settings, i, idx, 'sort' );
6294	
6295				row._aSortData[ idx ] = formatter ?
6296					formatter( cellData ) :
6297					cellData;
6298			}
6299		}
6300	}
6301	
6302	
6303	
6304	/**
6305	 * Save the state of a table
6306	 *  @param {object} oSettings dataTables settings object
6307	 *  @memberof DataTable#oApi
6308	 */
6309	function _fnSaveState ( settings )
6310	{
6311		if ( !settings.oFeatures.bStateSave || settings.bDestroying )
6312		{
6313			return;
6314		}
6315	
6316		/* Store the interesting variables */
6317		var state = {
6318			time:    +new Date(),
6319			start:   settings._iDisplayStart,
6320			length:  settings._iDisplayLength,
6321			order:   $.extend( true, [], settings.aaSorting ),
6322			search:  _fnSearchToCamel( settings.oPreviousSearch ),
6323			columns: $.map( settings.aoColumns, function ( col, i ) {
6324				return {
6325					visible: col.bVisible,
6326					search: _fnSearchToCamel( settings.aoPreSearchCols[i] )
6327				};
6328			} )
6329		};
6330	
6331		_fnCallbackFire( settings, "aoStateSaveParams", 'stateSaveParams', [settings, state] );
6332	
6333		settings.oSavedState = state;
6334		settings.fnStateSaveCallback.call( settings.oInstance, settings, state );
6335	}
6336	
6337	
6338	/**
6339	 * Attempt to load a saved table state
6340	 *  @param {object} oSettings dataTables settings object
6341	 *  @param {object} oInit DataTables init object so we can override settings
6342	 *  @param {function} callback Callback to execute when the state has been loaded
6343	 *  @memberof DataTable#oApi
6344	 */
6345	function _fnLoadState ( settings, oInit, callback )
6346	{
6347		var i, ien;
6348		var columns = settings.aoColumns;
6349		var loaded = function ( s ) {
6350			if ( ! s || ! s.time ) {
6351				callback();
6352				return;
6353			}
6354	
6355			// Allow custom and plug-in manipulation functions to alter the saved data set and
6356			// cancelling of loading by returning false
6357			var abStateLoad = _fnCallbackFire( settings, 'aoStateLoadParams', 'stateLoadParams', [settings, s] );
6358			if ( $.inArray( false, abStateLoad ) !== -1 ) {
6359				callback();
6360				return;
6361			}
6362	
6363			// Reject old data
6364			var duration = settings.iStateDuration;
6365			if ( duration > 0 && s.time < +new Date() - (duration*1000) ) {
6366				callback();
6367				return;
6368			}
6369	
6370			// Number of columns have changed - all bets are off, no restore of settings
6371			if ( s.columns && columns.length !== s.columns.length ) {
6372				callback();
6373				return;
6374			}
6375	
6376			// Store the saved state so it might be accessed at any time
6377			settings.oLoadedState = $.extend( true, {}, s );
6378	
6379			// Restore key features - todo - for 1.11 this needs to be done by
6380			// subscribed events
6381			if ( s.start !== undefined ) {
6382				settings._iDisplayStart    = s.start;
6383				settings.iInitDisplayStart = s.start;
6384			}
6385			if ( s.length !== undefined ) {
6386				settings._iDisplayLength   = s.length;
6387			}
6388	
6389			// Order
6390			if ( s.order !== undefined ) {
6391				settings.aaSorting = [];
6392				$.each( s.order, function ( i, col ) {
6393					settings.aaSorting.push( col[0] >= columns.length ?
6394						[ 0, col[1] ] :
6395						col
6396					);
6397				} );
6398			}
6399	
6400			// Search
6401			if ( s.search !== undefined ) {
6402				$.extend( settings.oPreviousSearch, _fnSearchToHung( s.search ) );
6403			}
6404	
6405			// Columns
6406			//
6407			if ( s.columns ) {
6408				for ( i=0, ien=s.columns.length ; i<ien ; i++ ) {
6409					var col = s.columns[i];
6410	
6411					// Visibility
6412					if ( col.visible !== undefined ) {
6413						columns[i].bVisible = col.visible;
6414					}
6415	
6416					// Search
6417					if ( col.search !== undefined ) {
6418						$.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) );
6419					}
6420				}
6421			}
6422	
6423			_fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, s] );
6424			callback();
6425		}
6426	
6427		if ( ! settings.oFeatures.bStateSave ) {
6428			callback();
6429			return;
6430		}
6431	
6432		var state = settings.fnStateLoadCallback.call( settings.oInstance, settings, loaded );
6433	
6434		if ( state !== undefined ) {
6435			loaded( state );
6436		}
6437		// otherwise, wait for the loaded callback to be executed
6438	}
6439	
6440	
6441	/**
6442	 * Return the settings object for a particular table
6443	 *  @param {node} table table we are using as a dataTable
6444	 *  @returns {object} Settings object - or null if not found
6445	 *  @memberof DataTable#oApi
6446	 */
6447	function _fnSettingsFromNode ( table )
6448	{
6449		var settings = DataTable.settings;
6450		var idx = $.inArray( table, _pluck( settings, 'nTable' ) );
6451	
6452		return idx !== -1 ?
6453			settings[ idx ] :
6454			null;
6455	}
6456	
6457	
6458	/**
6459	 * Log an error message
6460	 *  @param {object} settings dataTables settings object
6461	 *  @param {int} level log error messages, or display them to the user
6462	 *  @param {string} msg error message
6463	 *  @param {int} tn Technical note id to get more information about the error.
6464	 *  @memberof DataTable#oApi
6465	 */
6466	function _fnLog( settings, level, msg, tn )
6467	{
6468		msg = 'DataTables warning: '+
6469			(settings ? 'table id='+settings.sTableId+' - ' : '')+msg;
6470	
6471		if ( tn ) {
6472			msg += '. For more information about this error, please see '+
6473			'http://datatables.net/tn/'+tn;
6474		}
6475	
6476		if ( ! level  ) {
6477			// Backwards compatibility pre 1.10
6478			var ext = DataTable.ext;
6479			var type = ext.sErrMode || ext.errMode;
6480	
6481			if ( settings ) {
6482				_fnCallbackFire( settings, null, 'error', [ settings, tn, msg ] );
6483			}
6484	
6485			if ( type == 'alert' ) {
6486				alert( msg );
6487			}
6488			else if ( type == 'throw' ) {
6489				throw new Error(msg);
6490			}
6491			else if ( typeof type == 'function' ) {
6492				type( settings, tn, msg );
6493			}
6494		}
6495		else if ( window.console && console.log ) {
6496			console.log( msg );
6497		}
6498	}
6499	
6500	
6501	/**
6502	 * See if a property is defined on one object, if so assign it to the other object
6503	 *  @param {object} ret target object
6504	 *  @param {object} src source object
6505	 *  @param {string} name property
6506	 *  @param {string} [mappedName] name to map too - optional, name used if not given
6507	 *  @memberof DataTable#oApi
6508	 */
6509	function _fnMap( ret, src, name, mappedName )
6510	{
6511		if ( $.isArray( name ) ) {
6512			$.each( name, function (i, val) {
6513				if ( $.isArray( val ) ) {
6514					_fnMap( ret, src, val[0], val[1] );
6515				}
6516				else {
6517					_fnMap( ret, src, val );
6518				}
6519			} );
6520	
6521			return;
6522		}
6523	
6524		if ( mappedName === undefined ) {
6525			mappedName = name;
6526		}
6527	
6528		if ( src[name] !== undefined ) {
6529			ret[mappedName] = src[name];
6530		}
6531	}
6532	
6533	
6534	/**
6535	 * Extend objects - very similar to jQuery.extend, but deep copy objects, and
6536	 * shallow copy arrays. The reason we need to do this, is that we don't want to
6537	 * deep copy array init values (such as aaSorting) since the dev wouldn't be
6538	 * able to override them, but we do want to deep copy arrays.
6539	 *  @param {object} out Object to extend
6540	 *  @param {object} extender Object from which the properties will be applied to
6541	 *      out
6542	 *  @param {boolean} breakRefs If true, then arrays will be sliced to take an
6543	 *      independent copy with the exception of the `data` or `aaData` parameters
6544	 *      if they are present. This is so you can pass in a collection to
6545	 *      DataTables and have that used as your data source without breaking the
6546	 *      references
6547	 *  @returns {object} out Reference, just for convenience - out === the return.
6548	 *  @memberof DataTable#oApi
6549	 *  @todo This doesn't take account of arrays inside the deep copied objects.
6550	 */
6551	function _fnExtend( out, extender, breakRefs )
6552	{
6553		var val;
6554	
6555		for ( var prop in extender ) {
6556			if ( extender.hasOwnProperty(prop) ) {
6557				val = extender[prop];
6558	
6559				if ( $.isPlainObject( val ) ) {
6560					if ( ! $.isPlainObject( out[prop] ) ) {
6561						out[prop] = {};
6562					}
6563					$.extend( true, out[prop], val );
6564				}
6565				else if ( breakRefs && prop !== 'data' && prop !== 'aaData' && $.isArray(val) ) {
6566					out[prop] = val.slice();
6567				}
6568				else {
6569					out[prop] = val;
6570				}
6571			}
6572		}
6573	
6574		return out;
6575	}
6576	
6577	
6578	/**
6579	 * Bind an event handers to allow a click or return key to activate the callback.
6580	 * This is good for accessibility since a return on the keyboard will have the
6581	 * same effect as a click, if the element has focus.
6582	 *  @param {element} n Element to bind the action to
6583	 *  @param {object} oData Data object to pass to the triggered function
6584	 *  @param {function} fn Callback function for when the event is triggered
6585	 *  @memberof DataTable#oApi
6586	 */
6587	function _fnBindAction( n, oData, fn )
6588	{
6589		$(n)
6590			.on( 'click.DT', oData, function (e) {
6591					$(n).blur(); // Remove focus outline for mouse users
6592					fn(e);
6593				} )
6594			.on( 'keypress.DT', oData, function (e){
6595					if ( e.which === 13 ) {
6596						e.preventDefault();
6597						fn(e);
6598					}
6599				} )
6600			.on( 'selectstart.DT', function () {
6601					/* Take the brutal approach to cancelling text selection */
6602					return false;
6603				} );
6604	}
6605	
6606	
6607	/**
6608	 * Register a callback function. Easily allows a callback function to be added to
6609	 * an array store of callback functions that can then all be called together.
6610	 *  @param {object} oSettings dataTables settings object
6611	 *  @param {string} sStore Name of the array storage for the callbacks in oSettings
6612	 *  @param {function} fn Function to be called back
6613	 *  @param {string} sName Identifying name for the callback (i.e. a label)
6614	 *  @memberof DataTable#oApi
6615	 */
6616	function _fnCallbackReg( oSettings, sStore, fn, sName )
6617	{
6618		if ( fn )
6619		{
6620			oSettings[sStore].push( {
6621				"fn": fn,
6622				"sName": sName
6623			} );
6624		}
6625	}
6626	
6627	
6628	/**
6629	 * Fire callback functions and trigger events. Note that the loop over the
6630	 * callback array store is done backwards! Further note that you do not want to
6631	 * fire off triggers in time sensitive applications (for example cell creation)
6632	 * as its slow.
6633	 *  @param {object} settings dataTables settings object
6634	 *  @param {string} callbackArr Name of the array storage for the callbacks in
6635	 *      oSettings
6636	 *  @param {string} eventName Name of the jQuery custom event to trigger. If
6637	 *      null no trigger is fired
6638	 *  @param {array} args Array of arguments to pass to the callback function /
6639	 *      trigger
6640	 *  @memberof DataTable#oApi
6641	 */
6642	function _fnCallbackFire( settings, callbackArr, eventName, args )
6643	{
6644		var ret = [];
6645	
6646		if ( callbackArr ) {
6647			ret = $.map( settings[callbackArr].slice().reverse(), function (val, i) {
6648				return val.fn.apply( settings.oInstance, args );
6649			} );
6650		}
6651	
6652		if ( eventName !== null ) {
6653			var e = $.Event( eventName+'.dt' );
6654	
6655			$(settings.nTable).trigger( e, args );
6656	
6657			ret.push( e.result );
6658		}
6659	
6660		return ret;
6661	}
6662	
6663	
6664	function _fnLengthOverflow ( settings )
6665	{
6666		var
6667			start = settings._iDisplayStart,
6668			end = settings.fnDisplayEnd(),
6669			len = settings._iDisplayLength;
6670	
6671		/* If we have space to show extra rows (backing up from the end point - then do so */
6672		if ( start >= end )
6673		{
6674			start = end - len;
6675		}
6676	
6677		// Keep the start record on the current page
6678		start -= (start % len);
6679	
6680		if ( len === -1 || start < 0 )
6681		{
6682			start = 0;
6683		}
6684	
6685		settings._iDisplayStart = start;
6686	}
6687	
6688	
6689	function _fnRenderer( settings, type )
6690	{
6691		var renderer = settings.renderer;
6692		var host = DataTable.ext.renderer[type];
6693	
6694		if ( $.isPlainObject( renderer ) && renderer[type] ) {
6695			// Specific renderer for this type. If available use it, otherwise use
6696			// the default.
6697			return host[renderer[type]] || host._;
6698		}
6699		else if ( typeof renderer === 'string' ) {
6700			// Common renderer - if there is one available for this type use it,
6701			// otherwise use the default
6702			return host[renderer] || host._;
6703		}
6704	
6705		// Use the default
6706		return host._;
6707	}
6708	
6709	
6710	/**
6711	 * Detect the data source being used for the table. Used to simplify the code
6712	 * a little (ajax) and to make it compress a little smaller.
6713	 *
6714	 *  @param {object} settings dataTables settings object
6715	 *  @returns {string} Data source
6716	 *  @memberof DataTable#oApi
6717	 */
6718	function _fnDataSource ( settings )
6719	{
6720		if ( settings.oFeatures.bServerSide ) {
6721			return 'ssp';
6722		}
6723		else if ( settings.ajax || settings.sAjaxSource ) {
6724			return 'ajax';
6725		}
6726		return 'dom';
6727	}
6728	
6729
6730	
6731	
6732	/**
6733	 * Computed structure of the DataTables API, defined by the options passed to
6734	 * `DataTable.Api.register()` when building the API.
6735	 *
6736	 * The structure is built in order to speed creation and extension of the Api
6737	 * objects since the extensions are effectively pre-parsed.
6738	 *
6739	 * The array is an array of objects with the following structure, where this
6740	 * base array represents the Api prototype base:
6741	 *
6742	 *     [
6743	 *       {
6744	 *         name:      'data'                -- string   - Property name
6745	 *         val:       function () {},       -- function - Api method (or undefined if just an object
6746	 *         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
6747	 *         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
6748	 *       },
6749	 *       {
6750	 *         name:     'row'
6751	 *         val:       {},
6752	 *         methodExt: [ ... ],
6753	 *         propExt:   [
6754	 *           {
6755	 *             name:      'data'
6756	 *             val:       function () {},
6757	 *             methodExt: [ ... ],
6758	 *             propExt:   [ ... ]
6759	 *           },
6760	 *           ...
6761	 *         ]
6762	 *       }
6763	 *     ]
6764	 *
6765	 * @type {Array}
6766	 * @ignore
6767	 */
6768	var __apiStruct = [];
6769	
6770	
6771	/**
6772	 * `Array.prototype` reference.
6773	 *
6774	 * @type object
6775	 * @ignore
6776	 */
6777	var __arrayProto = Array.prototype;
6778	
6779	
6780	/**
6781	 * Abstraction for `context` parameter of the `Api` constructor to allow it to
6782	 * take several different forms for ease of use.
6783	 *
6784	 * Each of the input parameter types will be converted to a DataTables settings
6785	 * object where possible.
6786	 *
6787	 * @param  {string|node|jQuery|object} mixed DataTable identifier. Can be one
6788	 *   of:
6789	 *
6790	 *   * `string` - jQuery selector. Any DataTables' matching the given selector
6791	 *     with be found and used.
6792	 *   * `node` - `TABLE` node which has already been formed into a DataTable.
6793	 *   * `jQuery` - A jQuery object of `TABLE` nodes.
6794	 *   * `object` - DataTables settings object
6795	 *   * `DataTables.Api` - API instance
6796	 * @return {array|null} Matching DataTables settings objects. `null` or
6797	 *   `undefined` is returned if no matching DataTable is found.
6798	 * @ignore
6799	 */
6800	var _toSettings = function ( mixed )
6801	{
6802		var idx, jq;
6803		var settings = DataTable.settings;
6804		var tables = $.map( settings, function (el, i) {
6805			return el.nTable;
6806		} );
6807	
6808		if ( ! mixed ) {
6809			return [];
6810		}
6811		else if ( mixed.nTable && mixed.oApi ) {
6812			// DataTables settings object
6813			return [ mixed ];
6814		}
6815		else if ( mixed.nodeName && mixed.nodeName.toLowerCase() === 'table' ) {
6816			// Table node
6817			idx = $.inArray( mixed, tables );
6818			return idx !== -1 ? [ settings[idx] ] : null;
6819		}
6820		else if ( mixed && typeof mixed.settings === 'function' ) {
6821			return mixed.settings().toArray();
6822		}
6823		else if ( typeof mixed === 'string' ) {
6824			// jQuery selector
6825			jq = $(mixed);
6826		}
6827		else if ( mixed instanceof $ ) {
6828			// jQuery object (also DataTables instance)
6829			jq = mixed;
6830		}
6831	
6832		if ( jq ) {
6833			return jq.map( function(i) {
6834				idx = $.inArray( this, tables );
6835				return idx !== -1 ? settings[idx] : null;
6836			} ).toArray();
6837		}
6838	};
6839	
6840	
6841	/**
6842	 * DataTables API class - used to control and interface with  one or more
6843	 * DataTables enhanced tables.
6844	 *
6845	 * The API class is heavily based on jQuery, presenting a chainable interface
6846	 * that you can use to interact with tables. Each instance of the API class has
6847	 * a "context" - i.e. the tables that it will operate on. This could be a single
6848	 * table, all tables on a page or a sub-set thereof.
6849	 *
6850	 * Additionally the API is designed to allow you to easily work with the data in
6851	 * the tables, retrieving and manipulating it as required. This is done by
6852	 * presenting the API class as an array like interface. The contents of the
6853	 * array depend upon the actions requested by each method (for example
6854	 * `rows().nodes()` will return an array of nodes, while `rows().data()` will
6855	 * return an array of objects or arrays depending upon your table's
6856	 * configuration). The API object has a number of array like methods (`push`,
6857	 * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`,
6858	 * `unique` etc) to assist your working with the data held in a table.
6859	 *
6860	 * Most methods (those which return an Api instance) are chainable, which means
6861	 * the return from a method call also has all of the methods available that the
6862	 * top level object had. For example, these two calls are equivalent:
6863	 *
6864	 *     // Not chained
6865	 *     api.row.add( {...} );
6866	 *     api.draw();
6867	 *
6868	 *     // Chained
6869	 *     api.row.add( {...} ).draw();
6870	 *
6871	 * @class DataTable.Api
6872	 * @param {array|object|string|jQuery} context DataTable identifier. This is
6873	 *   used to define which DataTables enhanced tables this API will operate on.
6874	 *   Can be one of:
6875	 *
6876	 *   * `string` - jQuery selector. Any DataTables' matching the given selector
6877	 *     with be found and used.
6878	 *   * `node` - `TABLE` node which has already been formed into a DataTable.
6879	 *   * `jQuery` - A jQuery object of `TABLE` nodes.
6880	 *   * `object` - DataTables settings object
6881	 * @param {array} [data] Data to initialise the Api instance with.
6882	 *
6883	 * @example
6884	 *   // Direct initialisation during DataTables construction
6885	 *   var api = $('#example').DataTable();
6886	 *
6887	 * @example
6888	 *   // Initialisation using a DataTables jQuery object
6889	 *   var api = $('#example').dataTable().api();
6890	 *
6891	 * @example
6892	 *   // Initialisation as a constructor
6893	 *   var api = new $.fn.DataTable.Api( 'table.dataTable' );
6894	 */
6895	_Api = function ( context, data )
6896	{
6897		if ( ! (this instanceof _Api) ) {
6898			return new _Api( context, data );
6899		}
6900	
6901		var settings = [];
6902		var ctxSettings = function ( o ) {
6903			var a = _toSettings( o );
6904			if ( a ) {
6905				settings = settings.concat( a );
6906			}
6907		};
6908	
6909		if ( $.isArray( context ) ) {
6910			for ( var i=0, ien=context.length ; i<ien ; i++ ) {
6911				ctxSettings( context[i] );
6912			}
6913		}
6914		else {
6915			ctxSettings( context );
6916		}
6917	
6918		// Remove duplicates
6919		this.context = _unique( settings );
6920	
6921		// Initial data
6922		if ( data ) {
6923			$.merge( this, data );
6924		}
6925	
6926		// selector
6927		this.selector = {
6928			rows: null,
6929			cols: null,
6930			opts: null
6931		};
6932	
6933		_Api.extend( this, this, __apiStruct );
6934	};
6935	
6936	DataTable.Api = _Api;
6937	
6938	// Don't destroy the existing prototype, just extend it. Required for jQuery 2's
6939	// isPlainObject.
6940	$.extend( _Api.prototype, {
6941		any: function ()
6942		{
6943			return this.count() !== 0;
6944		},
6945	
6946	
6947		concat:  __arrayProto.concat,
6948	
6949	
6950		context: [], // array of table settings objects
6951	
6952	
6953		count: function ()
6954		{
6955			return this.flatten().length;
6956		},
6957	
6958	
6959		each: function ( fn )
6960		{
6961			for ( var i=0, ien=this.length ; i<ien; i++ ) {
6962				fn.call( this, this[i], i, this );
6963			}
6964	
6965			return this;
6966		},
6967	
6968	
6969		eq: function ( idx )
6970		{
6971			var ctx = this.context;
6972	
6973			return ctx.length > idx ?
6974				new _Api( ctx[idx], this[idx] ) :
6975				null;
6976		},
6977	
6978	
6979		filter: function ( fn )
6980		{
6981			var a = [];
6982	
6983			if ( __arrayProto.filter ) {
6984				a = __arrayProto.filter.call( this, fn, this );
6985			}
6986			else {
6987				// Compatibility for browsers without EMCA-252-5 (JS 1.6)
6988				for ( var i=0, ien=this.length ; i<ien ; i++ ) {
6989					if ( fn.call( this, this[i], i, this ) ) {
6990						a.push( this[i] );
6991					}
6992				}
6993			}
6994	
6995			return new _Api( this.context, a );
6996		},
6997	
6998	
6999		flatten: function ()
7000		{
7001			var a = [];
7002			return new _Api( this.context, a.concat.apply( a, this.toArray() ) );
7003		},
7004	
7005	
7006		join:    __arrayProto.join,
7007	
7008	
7009		indexOf: __arrayProto.indexOf || function (obj, start)
7010		{
7011			for ( var i=(start || 0), ien=this.length ; i<ien ; i++ ) {
7012				if ( this[i] === obj ) {
7013					return i;
7014				}
7015			}
7016			return -1;
7017		},
7018	
7019		iterator: function ( flatten, type, fn, alwaysNew ) {
7020			var
7021				a = [], ret,
7022				i, ien, j, jen,
7023				context = this.context,
7024				rows, items, item,
7025				selector = this.selector;
7026	
7027			// Argument shifting
7028			if ( typeof flatten === 'string' ) {
7029				alwaysNew = fn;
7030				fn = type;
7031				type = flatten;
7032				flatten = false;
7033			}
7034	
7035			for ( i=0, ien=context.length ; i<ien ; i++ ) {
7036				var apiInst = new _Api( context[i] );
7037	
7038				if ( type === 'table' ) {
7039					ret = fn.call( apiInst, context[i], i );
7040	
7041					if ( ret !== undefined ) {
7042						a.push( ret );
7043					}
7044				}
7045				else if ( type === 'columns' || type === 'rows' ) {
7046					// this has same length as context - one entry for each table
7047					ret = fn.call( apiInst, context[i], this[i], i );
7048	
7049					if ( ret !== undefined ) {
7050						a.push( ret );
7051					}
7052				}
7053				else if ( type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell' ) {
7054					// columns and rows share the same structure.
7055					// 'this' is an array of column indexes for each context
7056					items = this[i];
7057	
7058					if ( type === 'column-rows' ) {
7059						rows = _selector_row_indexes( context[i], selector.opts );
7060					}
7061	
7062					for ( j=0, jen=items.length ; j<jen ; j++ ) {
7063						item = items[j];
7064	
7065						if ( type === 'cell' ) {
7066							ret = fn.call( apiInst, context[i], item.row, item.column, i, j );
7067						}
7068						else {
7069							ret = fn.call( apiInst, context[i], item, i, j, rows );
7070						}
7071	
7072						if ( ret !== undefined ) {
7073							a.push( ret );
7074						}
7075					}
7076				}
7077			}
7078	
7079			if ( a.length || alwaysNew ) {
7080				var api = new _Api( context, flatten ? a.concat.apply( [], a ) : a );
7081				var apiSelector = api.selector;
7082				apiSelector.rows = selector.rows;
7083				apiSelector.cols = selector.cols;
7084				apiSelector.opts = selector.opts;
7085				return api;
7086			}
7087			return this;
7088		},
7089	
7090	
7091		lastIndexOf: __arrayProto.lastIndexOf || function (obj, start)
7092		{
7093			// Bit cheeky...
7094			return this.indexOf.apply( this.toArray.reverse(), arguments );
7095		},
7096	
7097	
7098		length:  0,
7099	
7100	
7101		map: function ( fn )
7102		{
7103			var a = [];
7104	
7105			if ( __arrayProto.map ) {
7106				a = __arrayProto.map.call( this, fn, this );
7107			}
7108			else {
7109				// Compatibility for browsers without EMCA-252-5 (JS 1.6)
7110				for ( var i=0, ien=this.length ; i<ien ; i++ ) {
7111					a.push( fn.call( this, this[i], i ) );
7112				}
7113			}
7114	
7115			return new _Api( this.context, a );
7116		},
7117	
7118	
7119		pluck: function ( prop )
7120		{
7121			return this.map( function ( el ) {
7122				return el[ prop ];
7123			} );
7124		},
7125	
7126		pop:     __arrayProto.pop,
7127	
7128	
7129		push:    __arrayProto.push,
7130	
7131	
7132		// Does not return an API instance
7133		reduce: __arrayProto.reduce || function ( fn, init )
7134		{
7135			return _fnReduce( this, fn, init, 0, this.length, 1 );
7136		},
7137	
7138	
7139		reduceRight: __arrayProto.reduceRight || function ( fn, init )
7140		{
7141			return _fnReduce( this, fn, init, this.length-1, -1, -1 );
7142		},
7143	
7144	
7145		reverse: __arrayProto.reverse,
7146	
7147	
7148		// Object with rows, columns and opts
7149		selector: null,
7150	
7151	
7152		shift:   __arrayProto.shift,
7153	
7154	
7155		slice: function () {
7156			return new _Api( this.context, this );
7157		},
7158	
7159	
7160		sort:    __arrayProto.sort, // ? name - order?
7161	
7162	
7163		splice:  __arrayProto.splice,
7164	
7165	
7166		toArray: function ()
7167		{
7168			return __arrayProto.slice.call( this );
7169		},
7170	
7171	
7172		to$: function ()
7173		{
7174			return $( this );
7175		},
7176	
7177	
7178		toJQuery: function ()
7179		{
7180			return $( this );
7181		},
7182	
7183	
7184		unique: function ()
7185		{
7186			return new _Api( this.context, _unique(this) );
7187		},
7188	
7189	
7190		unshift: __arrayProto.unshift
7191	} );
7192	
7193	
7194	_Api.extend = function ( scope, obj, ext )
7195	{
7196		// Only extend API instances and static properties of the API
7197		if ( ! ext.length || ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) {
7198			return;
7199		}
7200	
7201		var
7202			i, ien,
7203			j, jen,
7204			struct, inner,
7205			methodScoping = function ( scope, fn, struc ) {
7206				return function () {
7207					var ret = fn.apply( scope, arguments );
7208	
7209					// Method extension
7210					_Api.extend( ret, ret, struc.methodExt );
7211					return ret;
7212				};
7213			};
7214	
7215		for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7216			struct = ext[i];
7217	
7218			// Value
7219			obj[ struct.name ] = typeof struct.val === 'function' ?
7220				methodScoping( scope, struct.val, struct ) :
7221				$.isPlainObject( struct.val ) ?
7222					{} :
7223					struct.val;
7224	
7225			obj[ struct.name ].__dt_wrapper = true;
7226	
7227			// Property extension
7228			_Api.extend( scope, obj[ struct.name ], struct.propExt );
7229		}
7230	};
7231	
7232	
7233	// @todo - Is there need for an augment function?
7234	// _Api.augment = function ( inst, name )
7235	// {
7236	// 	// Find src object in the structure from the name
7237	// 	var parts = name.split('.');
7238	
7239	// 	_Api.extend( inst, obj );
7240	// };
7241	
7242	
7243	//     [
7244	//       {
7245	//         name:      'data'                -- string   - Property name
7246	//         val:       function () {},       -- function - Api method (or undefined if just an object
7247	//         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
7248	//         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
7249	//       },
7250	//       {
7251	//         name:     'row'
7252	//         val:       {},
7253	//         methodExt: [ ... ],
7254	//         propExt:   [
7255	//           {
7256	//             name:      'data'
7257	//             val:       function () {},
7258	//             methodExt: [ ... ],
7259	//             propExt:   [ ... ]
7260	//           },
7261	//           ...
7262	//         ]
7263	//       }
7264	//     ]
7265	
7266	_Api.register = _api_register = function ( name, val )
7267	{
7268		if ( $.isArray( name ) ) {
7269			for ( var j=0, jen=name.length ; j<jen ; j++ ) {
7270				_Api.register( name[j], val );
7271			}
7272			return;
7273		}
7274	
7275		var
7276			i, ien,
7277			heir = name.split('.'),
7278			struct = __apiStruct,
7279			key, method;
7280	
7281		var find = function ( src, name ) {
7282			for ( var i=0, ien=src.length ; i<ien ; i++ ) {
7283				if ( src[i].name === name ) {
7284					return src[i];
7285				}
7286			}
7287			return null;
7288		};
7289	
7290		for ( i=0, ien=heir.length ; i<ien ; i++ ) {
7291			method = heir[i].indexOf('()') !== -1;
7292			key = method ?
7293				heir[i].replace('()', '') :
7294				heir[i];
7295	
7296			var src = find( struct, key );
7297			if ( ! src ) {
7298				src = {
7299					name:      key,
7300					val:       {},
7301					methodExt: [],
7302					propExt:   []
7303				};
7304				struct.push( src );
7305			}
7306	
7307			if ( i === ien-1 ) {
7308				src.val = val;
7309			}
7310			else {
7311				struct = method ?
7312					src.methodExt :
7313					src.propExt;
7314			}
7315		}
7316	};
7317	
7318	
7319	_Api.registerPlural = _api_registerPlural = function ( pluralName, singularName, val ) {
7320		_Api.register( pluralName, val );
7321	
7322		_Api.register( singularName, function () {
7323			var ret = val.apply( this, arguments );
7324	
7325			if ( ret === this ) {
7326				// Returned item is the API instance that was passed in, return it
7327				return this;
7328			}
7329			else if ( ret instanceof _Api ) {
7330				// New API instance returned, want the value from the first item
7331				// in the returned array for the singular result.
7332				return ret.length ?
7333					$.isArray( ret[0] ) ?
7334						new _Api( ret.context, ret[0] ) : // Array results are 'enhanced'
7335						ret[0] :
7336					undefined;
7337			}
7338	
7339			// Non-API return - just fire it back
7340			return ret;
7341		} );
7342	};
7343	
7344	
7345	/**
7346	 * Selector for HTML tables. Apply the given selector to the give array of
7347	 * DataTables settings objects.
7348	 *
7349	 * @param {string|integer} [selector] jQuery selector string or integer
7350	 * @param  {array} Array of DataTables settings objects to be filtered
7351	 * @return {array}
7352	 * @ignore
7353	 */
7354	var __table_selector = function ( selector, a )
7355	{
7356		// Integer is used to pick out a table by index
7357		if ( typeof selector === 'number' ) {
7358			return [ a[ selector ] ];
7359		}
7360	
7361		// Perform a jQuery selector on the table nodes
7362		var nodes = $.map( a, function (el, i) {
7363			return el.nTable;
7364		} );
7365	
7366		return $(nodes)
7367			.filter( selector )
7368			.map( function (i) {
7369				// Need to translate back from the table node to the settings
7370				var idx = $.inArray( this, nodes );
7371				return a[ idx ];
7372			} )
7373			.toArray();
7374	};
7375	
7376	
7377	
7378	/**
7379	 * Context selector for the API's context (i.e. the tables the API instance
7380	 * refers to.
7381	 *
7382	 * @name    DataTable.Api#tables
7383	 * @param {string|integer} [selector] Selector to pick which tables the iterator
7384	 *   should operate on. If not given, all tables in the current context are
7385	 *   used. This can be given as a jQuery selector (for example `':gt(0)'`) to
7386	 *   select multiple tables or as an integer to select a single table.
7387	 * @returns {DataTable.Api} Returns a new API instance if a selector is given.
7388	 */
7389	_api_register( 'tables()', function ( selector ) {
7390		// A new instance is created if there was a selector specified
7391		return selector
vendor: 9,632 bytes, lines 7391-7739
7391 ?
7392			new _Api( __table_selector( selector, this.context ) ) :
7393			this;
7394	} );
7395	
7396	
7397	_api_register( 'table()', function ( selector ) {
7398		var tables = this.tables( selector );
7399		var ctx = tables.context;
7400	
7401		// Truncate to the first matched table
7402		return ctx.length ?
7403			new _Api( ctx[0] ) :
7404			tables;
7405	} );
7406	
7407	
7408	_api_registerPlural( 'tables().nodes()', 'table().node()' , function () {
7409		return this.iterator( 'table', function ( ctx ) {
7410			return ctx.nTable;
7411		}, 1 );
7412	} );
7413	
7414	
7415	_api_registerPlural( 'tables().body()', 'table().body()' , function () {
7416		return this.iterator( 'table', function ( ctx ) {
7417			return ctx.nTBody;
7418		}, 1 );
7419	} );
7420	
7421	
7422	_api_registerPlural( 'tables().header()', 'table().header()' , function () {
7423		return this.iterator( 'table', function ( ctx ) {
7424			return ctx.nTHead;
7425		}, 1 );
7426	} );
7427	
7428	
7429	_api_registerPlural( 'tables().footer()', 'table().footer()' , function () {
7430		return this.iterator( 'table', function ( ctx ) {
7431			return ctx.nTFoot;
7432		}, 1 );
7433	} );
7434	
7435	
7436	_api_registerPlural( 'tables().containers()', 'table().container()' , function () {
7437		return this.iterator( 'table', function ( ctx ) {
7438			return ctx.nTableWrapper;
7439		}, 1 );
7440	} );
7441	
7442	
7443	
7444	/**
7445	 * Redraw the tables in the current context.
7446	 */
7447	_api_register( 'draw()', function ( paging ) {
7448		return this.iterator( 'table', function ( settings ) {
7449			if ( paging === 'page' ) {
7450				_fnDraw( settings );
7451			}
7452			else {
7453				if ( typeof paging === 'string' ) {
7454					paging = paging === 'full-hold' ?
7455						false :
7456						true;
7457				}
7458	
7459				_fnReDraw( settings, paging===false );
7460			}
7461		} );
7462	} );
7463	
7464	
7465	
7466	/**
7467	 * Get the current page index.
7468	 *
7469	 * @return {integer} Current page index (zero based)
7470	 *//**
7471	 * Set the current page.
7472	 *
7473	 * Note that if you attempt to show a page which does not exist, DataTables will
7474	 * not throw an error, but rather reset the paging.
7475	 *
7476	 * @param {integer|string} action The paging action to take. This can be one of:
7477	 *  * `integer` - The page index to jump to
7478	 *  * `string` - An action to take:
7479	 *    * `first` - Jump to first page.
7480	 *    * `next` - Jump to the next page
7481	 *    * `previous` - Jump to previous page
7482	 *    * `last` - Jump to the last page.
7483	 * @returns {DataTables.Api} this
7484	 */
7485	_api_register( 'page()', function ( action ) {
7486		if ( action === undefined ) {
7487			return this.page.info().page; // not an expensive call
7488		}
7489	
7490		// else, have an action to take on all tables
7491		return this.iterator( 'table', function ( settings ) {
7492			_fnPageChange( settings, action );
7493		} );
7494	} );
7495	
7496	
7497	/**
7498	 * Paging information for the first table in the current context.
7499	 *
7500	 * If you require paging information for another table, use the `table()` method
7501	 * with a suitable selector.
7502	 *
7503	 * @return {object} Object with the following properties set:
7504	 *  * `page` - Current page index (zero based - i.e. the first page is `0`)
7505	 *  * `pages` - Total number of pages
7506	 *  * `start` - Display index for the first record shown on the current page
7507	 *  * `end` - Display index for the last record shown on the current page
7508	 *  * `length` - Display length (number of records). Note that generally `start
7509	 *    + length = end`, but this is not always true, for example if there are
7510	 *    only 2 records to show on the final page, with a length of 10.
7511	 *  * `recordsTotal` - Full data set length
7512	 *  * `recordsDisplay` - Data set length once the current filtering criterion
7513	 *    are applied.
7514	 */
7515	_api_register( 'page.info()', function ( action ) {
7516		if ( this.context.length === 0 ) {
7517			return undefined;
7518		}
7519	
7520		var
7521			settings   = this.context[0],
7522			start      = settings._iDisplayStart,
7523			len        = settings.oFeatures.bPaginate ? settings._iDisplayLength : -1,
7524			visRecords = settings.fnRecordsDisplay(),
7525			all        = len === -1;
7526	
7527		return {
7528			"page":           all ? 0 : Math.floor( start / len ),
7529			"pages":          all ? 1 : Math.ceil( visRecords / len ),
7530			"start":          start,
7531			"end":            settings.fnDisplayEnd(),
7532			"length":         len,
7533			"recordsTotal":   settings.fnRecordsTotal(),
7534			"recordsDisplay": visRecords,
7535			"serverSide":     _fnDataSource( settings ) === 'ssp'
7536		};
7537	} );
7538	
7539	
7540	/**
7541	 * Get the current page length.
7542	 *
7543	 * @return {integer} Current page length. Note `-1` indicates that all records
7544	 *   are to be shown.
7545	 *//**
7546	 * Set the current page length.
7547	 *
7548	 * @param {integer} Page length to set. Use `-1` to show all records.
7549	 * @returns {DataTables.Api} this
7550	 */
7551	_api_register( 'page.len()', function ( len ) {
7552		// Note that we can't call this function 'length()' because `length`
7553		// is a Javascript property of functions which defines how many arguments
7554		// the function expects.
7555		if ( len === undefined ) {
7556			return this.context.length !== 0 ?
7557				this.context[0]._iDisplayLength :
7558				undefined;
7559		}
7560	
7561		// else, set the page length
7562		return this.iterator( 'table', function ( settings ) {
7563			_fnLengthChange( settings, len );
7564		} );
7565	} );
7566	
7567	
7568	
7569	var __reload = function ( settings, holdPosition, callback ) {
7570		// Use the draw event to trigger a callback
7571		if ( callback ) {
7572			var api = new _Api( settings );
7573	
7574			api.one( 'draw', function () {
7575				callback( api.ajax.json() );
7576			} );
7577		}
7578	
7579		if ( _fnDataSource( settings ) == 'ssp' ) {
7580			_fnReDraw( settings, holdPosition );
7581		}
7582		else {
7583			_fnProcessingDisplay( settings, true );
7584	
7585			// Cancel an existing request
7586			var xhr = settings.jqXHR;
7587			if ( xhr && xhr.readyState !== 4 ) {
7588				xhr.abort();
7589			}
7590	
7591			// Trigger xhr
7592			_fnBuildAjax( settings, [], function( json ) {
7593				_fnClearTable( settings );
7594	
7595				var data = _fnAjaxDataSrc( settings, json );
7596				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7597					_fnAddData( settings, data[i] );
7598				}
7599	
7600				_fnReDraw( settings, holdPosition );
7601				_fnProcessingDisplay( settings, false );
7602			} );
7603		}
7604	};
7605	
7606	
7607	/**
7608	 * Get the JSON response from the last Ajax request that DataTables made to the
7609	 * server. Note that this returns the JSON from the first table in the current
7610	 * context.
7611	 *
7612	 * @return {object} JSON received from the server.
7613	 */
7614	_api_register( 'ajax.json()', function () {
7615		var ctx = this.context;
7616	
7617		if ( ctx.length > 0 ) {
7618			return ctx[0].json;
7619		}
7620	
7621		// else return undefined;
7622	} );
7623	
7624	
7625	/**
7626	 * Get the data submitted in the last Ajax request
7627	 */
7628	_api_register( 'ajax.params()', function () {
7629		var ctx = this.context;
7630	
7631		if ( ctx.length > 0 ) {
7632			return ctx[0].oAjaxData;
7633		}
7634	
7635		// else return undefined;
7636	} );
7637	
7638	
7639	/**
7640	 * Reload tables from the Ajax data source. Note that this function will
7641	 * automatically re-draw the table when the remote data has been loaded.
7642	 *
7643	 * @param {boolean} [reset=true] Reset (default) or hold the current paging
7644	 *   position. A full re-sort and re-filter is performed when this method is
7645	 *   called, which is why the pagination reset is the default action.
7646	 * @returns {DataTables.Api} this
7647	 */
7648	_api_register( 'ajax.reload()', function ( callback, resetPaging ) {
7649		return this.iterator( 'table', function (settings) {
7650			__reload( settings, resetPaging===false, callback );
7651		} );
7652	} );
7653	
7654	
7655	/**
7656	 * Get the current Ajax URL. Note that this returns the URL from the first
7657	 * table in the current context.
7658	 *
7659	 * @return {string} Current Ajax source URL
7660	 *//**
7661	 * Set the Ajax URL. Note that this will set the URL for all tables in the
7662	 * current context.
7663	 *
7664	 * @param {string} url URL to set.
7665	 * @returns {DataTables.Api} this
7666	 */
7667	_api_register( 'ajax.url()', function ( url ) {
7668		var ctx = this.context;
7669	
7670		if ( url === undefined ) {
7671			// get
7672			if ( ctx.length === 0 ) {
7673				return undefined;
7674			}
7675			ctx = ctx[0];
7676	
7677			return ctx.ajax ?
7678				$.isPlainObject( ctx.ajax ) ?
7679					ctx.ajax.url :
7680					ctx.ajax :
7681				ctx.sAjaxSource;
7682		}
7683	
7684		// set
7685		return this.iterator( 'table', function ( settings ) {
7686			if ( $.isPlainObject( settings.ajax ) ) {
7687				settings.ajax.url = url;
7688			}
7689			else {
7690				settings.ajax = url;
7691			}
7692			// No need to consider sAjaxSource here since DataTables gives priority
7693			// to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any
7694			// value of `sAjaxSource` redundant.
7695		} );
7696	} );
7697	
7698	
7699	/**
7700	 * Load data from the newly set Ajax URL. Note that this method is only
7701	 * available when `ajax.url()` is used to set a URL. Additionally, this method
7702	 * has the same effect as calling `ajax.reload()` but is provided for
7703	 * convenience when setting a new URL. Like `ajax.reload()` it will
7704	 * automatically redraw the table once the remote data has been loaded.
7705	 *
7706	 * @returns {DataTables.Api} this
7707	 */
7708	_api_register( 'ajax.url().load()', function ( callback, resetPaging ) {
7709		// Same as a reload, but makes sense to present it for easy access after a
7710		// url change
7711		return this.iterator( 'table', function ( ctx ) {
7712			__reload( ctx, resetPaging===false, callback );
7713		} );
7714	} );
7715	
7716	
7717	
7718	
7719	var _selector_run = function ( type, selector, selectFn, settings, opts )
7720	{
7721		var
7722			out = [], res,
7723			a, i, ien, j, jen,
7724			selectorType = typeof selector;
7725	
7726		// Can't just check for isArray here, as an API or jQuery instance might be
7727		// given with their array like look
7728		if ( ! selector || selectorType === 'string' || selectorType === 'function' || selector.length === undefined ) {
7729			selector = [ selector ];
7730		}
7731	
7732		for ( i=0, ien=selector.length ; i<ien ; i++ ) {
7733			// Only split on simple strings - complex expressions will be jQuery selectors
7734			a = selector[i] && selector[i].split && ! selector[i].match(/[\[\(:]/) ?
7735				selector[i].split(',') :
7736				[ selector[i] ];
7737	
7738			for ( j=0, jen=a.length ; j<jen ; j++ ) {
7739				res = selectFn( typeof a[j] === 'string' ? 
vendor: 47,871 bytes, lines 7739-9539
7739$.trim(a[j]) : a[j] );
7740	
7741				if ( res && res.length ) {
7742					out = out.concat( res );
7743				}
7744			}
7745		}
7746	
7747		// selector extensions
7748		var ext = _ext.selector[ type ];
7749		if ( ext.length ) {
7750			for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7751				out = ext[i]( settings, opts, out );
7752			}
7753		}
7754	
7755		return _unique( out );
7756	};
7757	
7758	
7759	var _selector_opts = function ( opts )
7760	{
7761		if ( ! opts ) {
7762			opts = {};
7763		}
7764	
7765		// Backwards compatibility for 1.9- which used the terminology filter rather
7766		// than search
7767		if ( opts.filter && opts.search === undefined ) {
7768			opts.search = opts.filter;
7769		}
7770	
7771		return $.extend( {
7772			search: 'none',
7773			order: 'current',
7774			page: 'all'
7775		}, opts );
7776	};
7777	
7778	
7779	var _selector_first = function ( inst )
7780	{
7781		// Reduce the API instance to the first item found
7782		for ( var i=0, ien=inst.length ; i<ien ; i++ ) {
7783			if ( inst[i].length > 0 ) {
7784				// Assign the first element to the first item in the instance
7785				// and truncate the instance and context
7786				inst[0] = inst[i];
7787				inst[0].length = 1;
7788				inst.length = 1;
7789				inst.context = [ inst.context[i] ];
7790	
7791				return inst;
7792			}
7793		}
7794	
7795		// Not found - return an empty instance
7796		inst.length = 0;
7797		return inst;
7798	};
7799	
7800	
7801	var _selector_row_indexes = function ( settings, opts )
7802	{
7803		var
7804			i, ien, tmp, a=[],
7805			displayFiltered = settings.aiDisplay,
7806			displayMaster = settings.aiDisplayMaster;
7807	
7808		var
7809			search = opts.search,  // none, applied, removed
7810			order  = opts.order,   // applied, current, index (original - compatibility with 1.9)
7811			page   = opts.page;    // all, current
7812	
7813		if ( _fnDataSource( settings ) == 'ssp' ) {
7814			// In server-side processing mode, most options are irrelevant since
7815			// rows not shown don't exist and the index order is the applied order
7816			// Removed is a special case - for consistency just return an empty
7817			// array
7818			return search === 'removed' ?
7819				[] :
7820				_range( 0, displayMaster.length );
7821		}
7822		else if ( page == 'current' ) {
7823			// Current page implies that order=current and fitler=applied, since it is
7824			// fairly senseless otherwise, regardless of what order and search actually
7825			// are
7826			for ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i<ien ; i++ ) {
7827				a.push( displayFiltered[i] );
7828			}
7829		}
7830		else if ( order == 'current' || order == 'applied' ) {
7831			if ( search == 'none') {
7832				a = displayMaster.slice();
7833			}
7834			else if ( search == 'applied' ) {
7835				a = displayFiltered.slice();
7836			}
7837			else if ( search == 'removed' ) {
7838				// O(n+m) solution by creating a hash map
7839				var displayFilteredMap = {};
7840	
7841				for ( var i=0, ien=displayFiltered.length ; i<ien ; i++ ) {
7842					displayFilteredMap[displayFiltered[i]] = null;
7843				}
7844	
7845				a = $.map( displayMaster, function (el) {
7846					return ! displayFilteredMap.hasOwnProperty(el) ?
7847						el :
7848						null;
7849				} );
7850			}
7851		}
7852		else if ( order == 'index' || order == 'original' ) {
7853			for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
7854				if ( search == 'none' ) {
7855					a.push( i );
7856				}
7857				else { // applied | removed
7858					tmp = $.inArray( i, displayFiltered );
7859	
7860					if ((tmp === -1 && search == 'removed') ||
7861						(tmp >= 0   && search == 'applied') )
7862					{
7863						a.push( i );
7864					}
7865				}
7866			}
7867		}
7868	
7869		return a;
7870	};
7871	
7872	
7873	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
7874	 * Rows
7875	 *
7876	 * {}          - no selector - use all available rows
7877	 * {integer}   - row aoData index
7878	 * {node}      - TR node
7879	 * {string}    - jQuery selector to apply to the TR elements
7880	 * {array}     - jQuery array of nodes, or simply an array of TR nodes
7881	 *
7882	 */
7883	var __row_selector = function ( settings, selector, opts )
7884	{
7885		var rows;
7886		var run = function ( sel ) {
7887			var selInt = _intVal( sel );
7888			var i, ien;
7889			var aoData = settings.aoData;
7890	
7891			// Short cut - selector is a number and no options provided (default is
7892			// all records, so no need to check if the index is in there, since it
7893			// must be - dev error if the index doesn't exist).
7894			if ( selInt !== null && ! opts ) {
7895				return [ selInt ];
7896			}
7897	
7898			if ( ! rows ) {
7899				rows = _selector_row_indexes( settings, opts );
7900			}
7901	
7902			if ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) {
7903				// Selector - integer
7904				return [ selInt ];
7905			}
7906			else if ( sel === null || sel === undefined || sel === '' ) {
7907				// Selector - none
7908				return rows;
7909			}
7910	
7911			// Selector - function
7912			if ( typeof sel === 'function' ) {
7913				return $.map( rows, function (idx) {
7914					var row = aoData[ idx ];
7915					return sel( idx, row._aData, row.nTr ) ? idx : null;
7916				} );
7917			}
7918	
7919			// Selector - node
7920			if ( sel.nodeName ) {
7921				var rowIdx = sel._DT_RowIndex;  // Property added by DT for fast lookup
7922				var cellIdx = sel._DT_CellIndex;
7923	
7924				if ( rowIdx !== undefined ) {
7925					// Make sure that the row is actually still present in the table
7926					return aoData[ rowIdx ] && aoData[ rowIdx ].nTr === sel ?
7927						[ rowIdx ] :
7928						[];
7929				}
7930				else if ( cellIdx ) {
7931					return aoData[ cellIdx.row ] && aoData[ cellIdx.row ].nTr === sel ?
7932						[ cellIdx.row ] :
7933						[];
7934				}
7935				else {
7936					var host = $(sel).closest('*[data-dt-row]');
7937					return host.length ?
7938						[ host.data('dt-row') ] :
7939						[];
7940				}
7941			}
7942	
7943			// ID selector. Want to always be able to select rows by id, regardless
7944			// of if the tr element has been created or not, so can't rely upon
7945			// jQuery here - hence a custom implementation. This does not match
7946			// Sizzle's fast selector or HTML4 - in HTML5 the ID can be anything,
7947			// but to select it using a CSS selector engine (like Sizzle or
7948			// querySelect) it would need to need to be escaped for some characters.
7949			// DataTables simplifies this for row selectors since you can select
7950			// only a row. A # indicates an id any anything that follows is the id -
7951			// unescaped.
7952			if ( typeof sel === 'string' && sel.charAt(0) === '#' ) {
7953				// get row index from id
7954				var rowObj = settings.aIds[ sel.replace( /^#/, '' ) ];
7955				if ( rowObj !== undefined ) {
7956					return [ rowObj.idx ];
7957				}
7958	
7959				// need to fall through to jQuery in case there is DOM id that
7960				// matches
7961			}
7962			
7963			// Get nodes in the order from the `rows` array with null values removed
7964			var nodes = _removeEmpty(
7965				_pluck_order( settings.aoData, rows, 'nTr' )
7966			);
7967	
7968			// Selector - jQuery selector string, array of nodes or jQuery object/
7969			// As jQuery's .filter() allows jQuery objects to be passed in filter,
7970			// it also allows arrays, so this will cope with all three options
7971			return $(nodes)
7972				.filter( sel )
7973				.map( function () {
7974					return this._DT_RowIndex;
7975				} )
7976				.toArray();
7977		};
7978	
7979		return _selector_run( 'row', selector, run, settings, opts );
7980	};
7981	
7982	
7983	_api_register( 'rows()', function ( selector, opts ) {
7984		// argument shifting
7985		if ( selector === undefined ) {
7986			selector = '';
7987		}
7988		else if ( $.isPlainObject( selector ) ) {
7989			opts = selector;
7990			selector = '';
7991		}
7992	
7993		opts = _selector_opts( opts );
7994	
7995		var inst = this.iterator( 'table', function ( settings ) {
7996			return __row_selector( settings, selector, opts );
7997		}, 1 );
7998	
7999		// Want argument shifting here and in __row_selector?
8000		inst.selector.rows = selector;
8001		inst.selector.opts = opts;
8002	
8003		return inst;
8004	} );
8005	
8006	_api_register( 'rows().nodes()', function () {
8007		return this.iterator( 'row', function ( settings, row ) {
8008			return settings.aoData[ row ].nTr || undefined;
8009		}, 1 );
8010	} );
8011	
8012	_api_register( 'rows().data()', function () {
8013		return this.iterator( true, 'rows', function ( settings, rows ) {
8014			return _pluck_order( settings.aoData, rows, '_aData' );
8015		}, 1 );
8016	} );
8017	
8018	_api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) {
8019		return this.iterator( 'row', function ( settings, row ) {
8020			var r = settings.aoData[ row ];
8021			return type === 'search' ? r._aFilterData : r._aSortData;
8022		}, 1 );
8023	} );
8024	
8025	_api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) {
8026		return this.iterator( 'row', function ( settings, row ) {
8027			_fnInvalidate( settings, row, src );
8028		} );
8029	} );
8030	
8031	_api_registerPlural( 'rows().indexes()', 'row().index()', function () {
8032		return this.iterator( 'row', function ( settings, row ) {
8033			return row;
8034		}, 1 );
8035	} );
8036	
8037	_api_registerPlural( 'rows().ids()', 'row().id()', function ( hash ) {
8038		var a = [];
8039		var context = this.context;
8040	
8041		// `iterator` will drop undefined values, but in this case we want them
8042		for ( var i=0, ien=context.length ; i<ien ; i++ ) {
8043			for ( var j=0, jen=this[i].length ; j<jen ; j++ ) {
8044				var id = context[i].rowIdFn( context[i].aoData[ this[i][j] ]._aData );
8045				a.push( (hash === true ? '#' : '' )+ id );
8046			}
8047		}
8048	
8049		return new _Api( context, a );
8050	} );
8051	
8052	_api_registerPlural( 'rows().remove()', 'row().remove()', function () {
8053		var that = this;
8054	
8055		this.iterator( 'row', function ( settings, row, thatIdx ) {
8056			var data = settings.aoData;
8057			var rowData = data[ row ];
8058			var i, ien, j, jen;
8059			var loopRow, loopCells;
8060	
8061			data.splice( row, 1 );
8062	
8063			// Update the cached indexes
8064			for ( i=0, ien=data.length ; i<ien ; i++ ) {
8065				loopRow = data[i];
8066				loopCells = loopRow.anCells;
8067	
8068				// Rows
8069				if ( loopRow.nTr !== null ) {
8070					loopRow.nTr._DT_RowIndex = i;
8071				}
8072	
8073				// Cells
8074				if ( loopCells !== null ) {
8075					for ( j=0, jen=loopCells.length ; j<jen ; j++ ) {
8076						loopCells[j]._DT_CellIndex.row = i;
8077					}
8078				}
8079			}
8080	
8081			// Delete from the display arrays
8082			_fnDeleteIndex( settings.aiDisplayMaster, row );
8083			_fnDeleteIndex( settings.aiDisplay, row );
8084			_fnDeleteIndex( that[ thatIdx ], row, false ); // maintain local indexes
8085	
8086			// For server-side processing tables - subtract the deleted row from the count
8087			if ( settings._iRecordsDisplay > 0 ) {
8088				settings._iRecordsDisplay--;
8089			}
8090	
8091			// Check for an 'overflow' they case for displaying the table
8092			_fnLengthOverflow( settings );
8093	
8094			// Remove the row's ID reference if there is one
8095			var id = settings.rowIdFn( rowData._aData );
8096			if ( id !== undefined ) {
8097				delete settings.aIds[ id ];
8098			}
8099		} );
8100	
8101		this.iterator( 'table', function ( settings ) {
8102			for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
8103				settings.aoData[i].idx = i;
8104			}
8105		} );
8106	
8107		return this;
8108	} );
8109	
8110	
8111	_api_register( 'rows.add()', function ( rows ) {
8112		var newRows = this.iterator( 'table', function ( settings ) {
8113				var row, i, ien;
8114				var out = [];
8115	
8116				for ( i=0, ien=rows.length ; i<ien ; i++ ) {
8117					row = rows[i];
8118	
8119					if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
8120						out.push( _fnAddTr( settings, row )[0] );
8121					}
8122					else {
8123						out.push( _fnAddData( settings, row ) );
8124					}
8125				}
8126	
8127				return out;
8128			}, 1 );
8129	
8130		// Return an Api.rows() extended instance, so rows().nodes() etc can be used
8131		var modRows = this.rows( -1 );
8132		modRows.pop();
8133		$.merge( modRows, newRows );
8134	
8135		return modRows;
8136	} );
8137	
8138	
8139	
8140	
8141	
8142	/**
8143	 *
8144	 */
8145	_api_register( 'row()', function ( selector, opts ) {
8146		return _selector_first( this.rows( selector, opts ) );
8147	} );
8148	
8149	
8150	_api_register( 'row().data()', function ( data ) {
8151		var ctx = this.context;
8152	
8153		if ( data === undefined ) {
8154			// Get
8155			return ctx.length && this.length ?
8156				ctx[0].aoData[ this[0] ]._aData :
8157				undefined;
8158		}
8159	
8160		// Set
8161		var row = ctx[0].aoData[ this[0] ];
8162		row._aData = data;
8163	
8164		// If the DOM has an id, and the data source is an array
8165		if ( $.isArray( data ) && row.nTr.id ) {
8166			_fnSetObjectDataFn( ctx[0].rowId )( data, row.nTr.id );
8167		}
8168	
8169		// Automatically invalidate
8170		_fnInvalidate( ctx[0], this[0], 'data' );
8171	
8172		return this;
8173	} );
8174	
8175	
8176	_api_register( 'row().node()', function () {
8177		var ctx = this.context;
8178	
8179		return ctx.length && this.length ?
8180			ctx[0].aoData[ this[0] ].nTr || null :
8181			null;
8182	} );
8183	
8184	
8185	_api_register( 'row.add()', function ( row ) {
8186		// Allow a jQuery object to be passed in - only a single row is added from
8187		// it though - the first element in the set
8188		if ( row instanceof $ && row.length ) {
8189			row = row[0];
8190		}
8191	
8192		var rows = this.iterator( 'table', function ( settings ) {
8193			if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
8194				return _fnAddTr( settings, row )[0];
8195			}
8196			return _fnAddData( settings, row );
8197		} );
8198	
8199		// Return an Api.rows() extended instance, with the newly added row selected
8200		return this.row( rows[0] );
8201	} );
8202	
8203	
8204	
8205	var __details_add = function ( ctx, row, data, klass )
8206	{
8207		// Convert to array of TR elements
8208		var rows = [];
8209		var addRow = function ( r, k ) {
8210			// Recursion to allow for arrays of jQuery objects
8211			if ( $.isArray( r ) || r instanceof $ ) {
8212				for ( var i=0, ien=r.length ; i<ien ; i++ ) {
8213					addRow( r[i], k );
8214				}
8215				return;
8216			}
8217	
8218			// If we get a TR element, then just add it directly - up to the dev
8219			// to add the correct number of columns etc
8220			if ( r.nodeName && r.nodeName.toLowerCase() === 'tr' ) {
8221				rows.push( r );
8222			}
8223			else {
8224				// Otherwise create a row with a wrapper
8225				var created = $('<tr><td/></tr>').addClass( k );
8226				$('td', created)
8227					.addClass( k )
8228					.html( r )
8229					[0].colSpan = _fnVisbleColumns( ctx );
8230	
8231				rows.push( created[0] );
8232			}
8233		};
8234	
8235		addRow( data, klass );
8236	
8237		if ( row._details ) {
8238			row._details.detach();
8239		}
8240	
8241		row._details = $(rows);
8242	
8243		// If the children were already shown, that state should be retained
8244		if ( row._detailsShow ) {
8245			row._details.insertAfter( row.nTr );
8246		}
8247	};
8248	
8249	
8250	var __details_remove = function ( api, idx )
8251	{
8252		var ctx = api.context;
8253	
8254		if ( ctx.length ) {
8255			var row = ctx[0].aoData[ idx !== undefined ? idx : api[0] ];
8256	
8257			if ( row && row._details ) {
8258				row._details.remove();
8259	
8260				row._detailsShow = undefined;
8261				row._details = undefined;
8262			}
8263		}
8264	};
8265	
8266	
8267	var __details_display = function ( api, show ) {
8268		var ctx = api.context;
8269	
8270		if ( ctx.length && api.length ) {
8271			var row = ctx[0].aoData[ api[0] ];
8272	
8273			if ( row._details ) {
8274				row._detailsShow = show;
8275	
8276				if ( show ) {
8277					row._details.insertAfter( row.nTr );
8278				}
8279				else {
8280					row._details.detach();
8281				}
8282	
8283				__details_events( ctx[0] );
8284			}
8285		}
8286	};
8287	
8288	
8289	var __details_events = function ( settings )
8290	{
8291		var api = new _Api( settings );
8292		var namespace = '.dt.DT_details';
8293		var drawEvent = 'draw'+namespace;
8294		var colvisEvent = 'column-visibility'+namespace;
8295		var destroyEvent = 'destroy'+namespace;
8296		var data = settings.aoData;
8297	
8298		api.off( drawEvent +' '+ colvisEvent +' '+ destroyEvent );
8299	
8300		if ( _pluck( data, '_details' ).length > 0 ) {
8301			// On each draw, insert the required elements into the document
8302			api.on( drawEvent, function ( e, ctx ) {
8303				if ( settings !== ctx ) {
8304					return;
8305				}
8306	
8307				api.rows( {page:'current'} ).eq(0).each( function (idx) {
8308					// Internal data grab
8309					var row = data[ idx ];
8310	
8311					if ( row._detailsShow ) {
8312						row._details.insertAfter( row.nTr );
8313					}
8314				} );
8315			} );
8316	
8317			// Column visibility change - update the colspan
8318			api.on( colvisEvent, function ( e, ctx, idx, vis ) {
8319				if ( settings !== ctx ) {
8320					return;
8321				}
8322	
8323				// Update the colspan for the details rows (note, only if it already has
8324				// a colspan)
8325				var row, visible = _fnVisbleColumns( ctx );
8326	
8327				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
8328					row = data[i];
8329	
8330					if ( row._details ) {
8331						row._details.children('td[colspan]').attr('colspan', visible );
8332					}
8333				}
8334			} );
8335	
8336			// Table destroyed - nuke any child rows
8337			api.on( destroyEvent, function ( e, ctx ) {
8338				if ( settings !== ctx ) {
8339					return;
8340				}
8341	
8342				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
8343					if ( data[i]._details ) {
8344						__details_remove( api, i );
8345					}
8346				}
8347			} );
8348		}
8349	};
8350	
8351	// Strings for the method names to help minification
8352	var _emp = '';
8353	var _child_obj = _emp+'row().child';
8354	var _child_mth = _child_obj+'()';
8355	
8356	// data can be:
8357	//  tr
8358	//  string
8359	//  jQuery or array of any of the above
8360	_api_register( _child_mth, function ( data, klass ) {
8361		var ctx = this.context;
8362	
8363		if ( data === undefined ) {
8364			// get
8365			return ctx.length && this.length ?
8366				ctx[0].aoData[ this[0] ]._details :
8367				undefined;
8368		}
8369		else if ( data === true ) {
8370			// show
8371			this.child.show();
8372		}
8373		else if ( data === false ) {
8374			// remove
8375			__details_remove( this );
8376		}
8377		else if ( ctx.length && this.length ) {
8378			// set
8379			__details_add( ctx[0], ctx[0].aoData[ this[0] ], data, klass );
8380		}
8381	
8382		return this;
8383	} );
8384	
8385	
8386	_api_register( [
8387		_child_obj+'.show()',
8388		_child_mth+'.show()' // only when `child()` was called with parameters (without
8389	], function ( show ) {   // it returns an object and this method is not executed)
8390		__details_display( this, true );
8391		return this;
8392	} );
8393	
8394	
8395	_api_register( [
8396		_child_obj+'.hide()',
8397		_child_mth+'.hide()' // only when `child()` was called with parameters (without
8398	], function () {         // it returns an object and this method is not executed)
8399		__details_display( this, false );
8400		return this;
8401	} );
8402	
8403	
8404	_api_register( [
8405		_child_obj+'.remove()',
8406		_child_mth+'.remove()' // only when `child()` was called with parameters (without
8407	], function () {           // it returns an object and this method is not executed)
8408		__details_remove( this );
8409		return this;
8410	} );
8411	
8412	
8413	_api_register( _child_obj+'.isShown()', function () {
8414		var ctx = this.context;
8415	
8416		if ( ctx.length && this.length ) {
8417			// _detailsShown as false or undefined will fall through to return false
8418			return ctx[0].aoData[ this[0] ]._detailsShow || false;
8419		}
8420		return false;
8421	} );
8422	
8423	
8424	
8425	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
8426	 * Columns
8427	 *
8428	 * {integer}           - column index (>=0 count from left, <0 count from right)
8429	 * "{integer}:visIdx"  - visible column index (i.e. translate to column index)  (>=0 count from left, <0 count from right)
8430	 * "{integer}:visible" - alias for {integer}:visIdx  (>=0 count from left, <0 count from right)
8431	 * "{string}:name"     - column name
8432	 * "{string}"          - jQuery selector on column header nodes
8433	 *
8434	 */
8435	
8436	// can be an array of these items, comma separated list, or an array of comma
8437	// separated lists
8438	
8439	var __re_column_selector = /^([^:]+):(name|visIdx|visible)$/;
8440	
8441	
8442	// r1 and r2 are redundant - but it means that the parameters match for the
8443	// iterator callback in columns().data()
8444	var __columnData = function ( settings, column, r1, r2, rows ) {
8445		var a = [];
8446		for ( var row=0, ien=rows.length ; row<ien ; row++ ) {
8447			a.push( _fnGetCellData( settings, rows[row], column ) );
8448		}
8449		return a;
8450	};
8451	
8452	
8453	var __column_selector = function ( settings, selector, opts )
8454	{
8455		var
8456			columns = settings.aoColumns,
8457			names = _pluck( columns, 'sName' ),
8458			nodes = _pluck( columns, 'nTh' );
8459	
8460		var run = function ( s ) {
8461			var selInt = _intVal( s );
8462	
8463			// Selector - all
8464			if ( s === '' ) {
8465				return _range( columns.length );
8466			}
8467	
8468			// Selector - index
8469			if ( selInt !== null ) {
8470				return [ selInt >= 0 ?
8471					selInt : // Count from left
8472					columns.length + selInt // Count from right (+ because its a negative value)
8473				];
8474			}
8475	
8476			// Selector = function
8477			if ( typeof s === 'function' ) {
8478				var rows = _selector_row_indexes( settings, opts );
8479	
8480				return $.map( columns, function (col, idx) {
8481					return s(
8482							idx,
8483							__columnData( settings, idx, 0, 0, rows ),
8484							nodes[ idx ]
8485						) ? idx : null;
8486				} );
8487			}
8488	
8489			// jQuery or string selector
8490			var match = typeof s === 'string' ?
8491				s.match( __re_column_selector ) :
8492				'';
8493	
8494			if ( match ) {
8495				switch( match[2] ) {
8496					case 'visIdx':
8497					case 'visible':
8498						var idx = parseInt( match[1], 10 );
8499						// Visible index given, convert to column index
8500						if ( idx < 0 ) {
8501							// Counting from the right
8502							var visColumns = $.map( columns, function (col,i) {
8503								return col.bVisible ? i : null;
8504							} );
8505							return [ visColumns[ visColumns.length + idx ] ];
8506						}
8507						// Counting from the left
8508						return [ _fnVisibleToColumnIndex( settings, idx ) ];
8509	
8510					case 'name':
8511						// match by name. `names` is column index complete and in order
8512						return $.map( names, function (name, i) {
8513							return name === match[1] ? i : null;
8514						} );
8515	
8516					default:
8517						return [];
8518				}
8519			}
8520	
8521			// Cell in the table body
8522			if ( s.nodeName && s._DT_CellIndex ) {
8523				return [ s._DT_CellIndex.column ];
8524			}
8525	
8526			// jQuery selector on the TH elements for the columns
8527			var jqResult = $( nodes )
8528				.filter( s )
8529				.map( function () {
8530					return $.inArray( this, nodes ); // `nodes` is column index complete and in order
8531				} )
8532				.toArray();
8533	
8534			if ( jqResult.length || ! s.nodeName ) {
8535				return jqResult;
8536			}
8537	
8538			// Otherwise a node which might have a `dt-column` data attribute, or be
8539			// a child or such an element
8540			var host = $(s).closest('*[data-dt-column]');
8541			return host.length ?
8542				[ host.data('dt-column') ] :
8543				[];
8544		};
8545	
8546		return _selector_run( 'column', selector, run, settings, opts );
8547	};
8548	
8549	
8550	var __setColumnVis = function ( settings, column, vis ) {
8551		var
8552			cols = settings.aoColumns,
8553			col  = cols[ column ],
8554			data = settings.aoData,
8555			row, cells, i, ien, tr;
8556	
8557		// Get
8558		if ( vis === undefined ) {
8559			return col.bVisible;
8560		}
8561	
8562		// Set
8563		// No change
8564		if ( col.bVisible === vis ) {
8565			return;
8566		}
8567	
8568		if ( vis ) {
8569			// Insert column
8570			// Need to decide if we should use appendChild or insertBefore
8571			var insertBefore = $.inArray( true, _pluck(cols, 'bVisible'), column+1 );
8572	
8573			for ( i=0, ien=data.length ; i<ien ; i++ ) {
8574				tr = data[i].nTr;
8575				cells = data[i].anCells;
8576	
8577				if ( tr ) {
8578					// insertBefore can act like appendChild if 2nd arg is null
8579					tr.insertBefore( cells[ column ], cells[ insertBefore ] || null );
8580				}
8581			}
8582		}
8583		else {
8584			// Remove column
8585			$( _pluck( settings.aoData, 'anCells', column ) ).detach();
8586		}
8587	
8588		// Common actions
8589		col.bVisible = vis;
8590		_fnDrawHead( settings, settings.aoHeader );
8591		_fnDrawHead( settings, settings.aoFooter );
8592	
8593		// Update colspan for no records display. Child rows and extensions will use their own
8594		// listeners to do this - only need to update the empty table item here
8595		if ( ! settings.aiDisplay.length ) {
8596			$(settings.nTBody).find('td[colspan]').attr('colspan', _fnVisbleColumns(settings));
8597		}
8598	
8599		_fnSaveState( settings );
8600	};
8601	
8602	
8603	_api_register( 'columns()', function ( selector, opts ) {
8604		// argument shifting
8605		if ( selector === undefined ) {
8606			selector = '';
8607		}
8608		else if ( $.isPlainObject( selector ) ) {
8609			opts = selector;
8610			selector = '';
8611		}
8612	
8613		opts = _selector_opts( opts );
8614	
8615		var inst = this.iterator( 'table', function ( settings ) {
8616			return __column_selector( settings, selector, opts );
8617		}, 1 );
8618	
8619		// Want argument shifting here and in _row_selector?
8620		inst.selector.cols = selector;
8621		inst.selector.opts = opts;
8622	
8623		return inst;
8624	} );
8625	
8626	_api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) {
8627		return this.iterator( 'column', function ( settings, column ) {
8628			return settings.aoColumns[column].nTh;
8629		}, 1 );
8630	} );
8631	
8632	_api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) {
8633		return this.iterator( 'column', function ( settings, column ) {
8634			return settings.aoColumns[column].nTf;
8635		}, 1 );
8636	} );
8637	
8638	_api_registerPlural( 'columns().data()', 'column().data()', function () {
8639		return this.iterator( 'column-rows', __columnData, 1 );
8640	} );
8641	
8642	_api_registerPlural( 'columns().dataSrc()', 'column().dataSrc()', function () {
8643		return this.iterator( 'column', function ( settings, column ) {
8644			return settings.aoColumns[column].mData;
8645		}, 1 );
8646	} );
8647	
8648	_api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) {
8649		return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8650			return _pluck_order( settings.aoData, rows,
8651				type === 'search' ? '_aFilterData' : '_aSortData', column
8652			);
8653		}, 1 );
8654	} );
8655	
8656	_api_registerPlural( 'columns().nodes()', 'column().nodes()', function () {
8657		return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8658			return _pluck_order( settings.aoData, rows, 'anCells', column ) ;
8659		}, 1 );
8660	} );
8661	
8662	_api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis, calc ) {
8663		var ret = this.iterator( 'column', function ( settings, column ) {
8664			if ( vis === undefined ) {
8665				return settings.aoColumns[ column ].bVisible;
8666			} // else
8667			__setColumnVis( settings, column, vis );
8668		} );
8669	
8670		// Group the column visibility changes
8671		if ( vis !== undefined ) {
8672			// Second loop once the first is done for events
8673			this.iterator( 'column', function ( settings, column ) {
8674				_fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis, calc] );
8675			} );
8676	
8677			if ( calc === undefined || calc ) {
8678				this.columns.adjust();
8679			}
8680		}
8681	
8682		return ret;
8683	} );
8684	
8685	_api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) {
8686		return this.iterator( 'column', function ( settings, column ) {
8687			return type === 'visible' ?
8688				_fnColumnIndexToVisible( settings, column ) :
8689				column;
8690		}, 1 );
8691	} );
8692	
8693	_api_register( 'columns.adjust()', function () {
8694		return this.iterator( 'table', function ( settings ) {
8695			_fnAdjustColumnSizing( settings );
8696		}, 1 );
8697	} );
8698	
8699	_api_register( 'column.index()', function ( type, idx ) {
8700		if ( this.context.length !== 0 ) {
8701			var ctx = this.context[0];
8702	
8703			if ( type === 'fromVisible' || type === 'toData' ) {
8704				return _fnVisibleToColumnIndex( ctx, idx );
8705			}
8706			else if ( type === 'fromData' || type === 'toVisible' ) {
8707				return _fnColumnIndexToVisible( ctx, idx );
8708			}
8709		}
8710	} );
8711	
8712	_api_register( 'column()', function ( selector, opts ) {
8713		return _selector_first( this.columns( selector, opts ) );
8714	} );
8715	
8716	
8717	
8718	var __cell_selector = function ( settings, selector, opts )
8719	{
8720		var data = settings.aoData;
8721		var rows = _selector_row_indexes( settings, opts );
8722		var cells = _removeEmpty( _pluck_order( data, rows, 'anCells' ) );
8723		var allCells = $( [].concat.apply([], cells) );
8724		var row;
8725		var columns = settings.aoColumns.length;
8726		var a, i, ien, j, o, host;
8727	
8728		var run = function ( s ) {
8729			var fnSelector = typeof s === 'function';
8730	
8731			if ( s === null || s === undefined || fnSelector ) {
8732				// All cells and function selectors
8733				a = [];
8734	
8735				for ( i=0, ien=rows.length ; i<ien ; i++ ) {
8736					row = rows[i];
8737	
8738					for ( j=0 ; j<columns ; j++ ) {
8739						o = {
8740							row: row,
8741							column: j
8742						};
8743	
8744						if ( fnSelector ) {
8745							// Selector - function
8746							host = data[ row ];
8747	
8748							if ( s( o, _fnGetCellData(settings, row, j), host.anCells ? host.anCells[j] : null ) ) {
8749								a.push( o );
8750							}
8751						}
8752						else {
8753							// Selector - all
8754							a.push( o );
8755						}
8756					}
8757				}
8758	
8759				return a;
8760			}
8761			
8762			// Selector - index
8763			if ( $.isPlainObject( s ) ) {
8764				// Valid cell index and its in the array of selectable rows
8765				return s.column !== undefined && s.row !== undefined && $.inArray( s.row, rows ) !== -1 ?
8766					[s] :
8767					[];
8768			}
8769	
8770			// Selector - jQuery filtered cells
8771			var jqResult = allCells
8772				.filter( s )
8773				.map( function (i, el) {
8774					return { // use a new object, in case someone changes the values
8775						row:    el._DT_CellIndex.row,
8776						column: el._DT_CellIndex.column
8777	 				};
8778				} )
8779				.toArray();
8780	
8781			if ( jqResult.length || ! s.nodeName ) {
8782				return jqResult;
8783			}
8784	
8785			// Otherwise the selector is a node, and there is one last option - the
8786			// element might be a child of an element which has dt-row and dt-column
8787			// data attributes
8788			host = $(s).closest('*[data-dt-row]');
8789			return host.length ?
8790				[ {
8791					row: host.data('dt-row'),
8792					column: host.data('dt-column')
8793				} ] :
8794				[];
8795		};
8796	
8797		return _selector_run( 'cell', selector, run, settings, opts );
8798	};
8799	
8800	
8801	
8802	
8803	_api_register( 'cells()', function ( rowSelector, columnSelector, opts ) {
8804		// Argument shifting
8805		if ( $.isPlainObject( rowSelector ) ) {
8806			// Indexes
8807			if ( rowSelector.row === undefined ) {
8808				// Selector options in first parameter
8809				opts = rowSelector;
8810				rowSelector = null;
8811			}
8812			else {
8813				// Cell index objects in first parameter
8814				opts = columnSelector;
8815				columnSelector = null;
8816			}
8817		}
8818		if ( $.isPlainObject( columnSelector ) ) {
8819			opts = columnSelector;
8820			columnSelector = null;
8821		}
8822	
8823		// Cell selector
8824		if ( columnSelector === null || columnSelector === undefined ) {
8825			return this.iterator( 'table', function ( settings ) {
8826				return __cell_selector( settings, rowSelector, _selector_opts( opts ) );
8827			} );
8828		}
8829	
8830		// Row + column selector
8831		var columns = this.columns( columnSelector );
8832		var rows = this.rows( rowSelector );
8833		var a, i, ien, j, jen;
8834	
8835		this.iterator( 'table', function ( settings, idx ) {
8836			a = [];
8837	
8838			for ( i=0, ien=rows[idx].length ; i<ien ; i++ ) {
8839				for ( j=0, jen=columns[idx].length ; j<jen ; j++ ) {
8840					a.push( {
8841						row:    rows[idx][i],
8842						column: columns[idx][j]
8843					} );
8844				}
8845			}
8846		}, 1 );
8847	
8848	    // Now pass through the cell selector for options
8849	    var cells = this.cells( a, opts );
8850	
8851		$.extend( cells.selector, {
8852			cols: columnSelector,
8853			rows: rowSelector,
8854			opts: opts
8855		} );
8856	
8857		return cells;
8858	} );
8859	
8860	
8861	_api_registerPlural( 'cells().nodes()', 'cell().node()', function () {
8862		return this.iterator( 'cell', function ( settings, row, column ) {
8863			var data = settings.aoData[ row ];
8864	
8865			return data && data.anCells ?
8866				data.anCells[ column ] :
8867				undefined;
8868		}, 1 );
8869	} );
8870	
8871	
8872	_api_register( 'cells().data()', function () {
8873		return this.iterator( 'cell', function ( settings, row, column ) {
8874			return _fnGetCellData( settings, row, column );
8875		}, 1 );
8876	} );
8877	
8878	
8879	_api_registerPlural( 'cells().cache()', 'cell().cache()', function ( type ) {
8880		type = type === 'search' ? '_aFilterData' : '_aSortData';
8881	
8882		return this.iterator( 'cell', function ( settings, row, column ) {
8883			return settings.aoData[ row ][ type ][ column ];
8884		}, 1 );
8885	} );
8886	
8887	
8888	_api_registerPlural( 'cells().render()', 'cell().render()', function ( type ) {
8889		return this.iterator( 'cell', function ( settings, row, column ) {
8890			return _fnGetCellData( settings, row, column, type );
8891		}, 1 );
8892	} );
8893	
8894	
8895	_api_registerPlural( 'cells().indexes()', 'cell().index()', function () {
8896		return this.iterator( 'cell', function ( settings, row, column ) {
8897			return {
8898				row: row,
8899				column: column,
8900				columnVisible: _fnColumnIndexToVisible( settings, column )
8901			};
8902		}, 1 );
8903	} );
8904	
8905	
8906	_api_registerPlural( 'cells().invalidate()', 'cell().invalidate()', function ( src ) {
8907		return this.iterator( 'cell', function ( settings, row, column ) {
8908			_fnInvalidate( settings, row, src, column );
8909		} );
8910	} );
8911	
8912	
8913	
8914	_api_register( 'cell()', function ( rowSelector, columnSelector, opts ) {
8915		return _selector_first( this.cells( rowSelector, columnSelector, opts ) );
8916	} );
8917	
8918	
8919	_api_register( 'cell().data()', function ( data ) {
8920		var ctx = this.context;
8921		var cell = this[0];
8922	
8923		if ( data === undefined ) {
8924			// Get
8925			return ctx.length && cell.length ?
8926				_fnGetCellData( ctx[0], cell[0].row, cell[0].column ) :
8927				undefined;
8928		}
8929	
8930		// Set
8931		_fnSetCellData( ctx[0], cell[0].row, cell[0].column, data );
8932		_fnInvalidate( ctx[0], cell[0].row, 'data', cell[0].column );
8933	
8934		return this;
8935	} );
8936	
8937	
8938	
8939	/**
8940	 * Get current ordering (sorting) that has been applied to the table.
8941	 *
8942	 * @returns {array} 2D array containing the sorting information for the first
8943	 *   table in the current context. Each element in the parent array represents
8944	 *   a column being sorted upon (i.e. multi-sorting with two columns would have
8945	 *   2 inner arrays). The inner arrays may have 2 or 3 elements. The first is
8946	 *   the column index that the sorting condition applies to, the second is the
8947	 *   direction of the sort (`desc` or `asc`) and, optionally, the third is the
8948	 *   index of the sorting order from the `column.sorting` initialisation array.
8949	 *//**
8950	 * Set the ordering for the table.
8951	 *
8952	 * @param {integer} order Column index to sort upon.
8953	 * @param {string} direction Direction of the sort to be applied (`asc` or `desc`)
8954	 * @returns {DataTables.Api} this
8955	 *//**
8956	 * Set the ordering for the table.
8957	 *
8958	 * @param {array} order 1D array of sorting information to be applied.
8959	 * @param {array} [...] Optional additional sorting conditions
8960	 * @returns {DataTables.Api} this
8961	 *//**
8962	 * Set the ordering for the table.
8963	 *
8964	 * @param {array} order 2D array of sorting information to be applied.
8965	 * @returns {DataTables.Api} this
8966	 */
8967	_api_register( 'order()', function ( order, dir ) {
8968		var ctx = this.context;
8969	
8970		if ( order === undefined ) {
8971			// get
8972			return ctx.length !== 0 ?
8973				ctx[0].aaSorting :
8974				undefined;
8975		}
8976	
8977		// set
8978		if ( typeof order === 'number' ) {
8979			// Simple column / direction passed in
8980			order = [ [ order, dir ] ];
8981		}
8982		else if ( order.length && ! $.isArray( order[0] ) ) {
8983			// Arguments passed in (list of 1D arrays)
8984			order = Array.prototype.slice.call( arguments );
8985		}
8986		// otherwise a 2D array was passed in
8987	
8988		return this.iterator( 'table', function ( settings ) {
8989			settings.aaSorting = order.slice();
8990		} );
8991	} );
8992	
8993	
8994	/**
8995	 * Attach a sort listener to an element for a given column
8996	 *
8997	 * @param {node|jQuery|string} node Identifier for the element(s) to attach the
8998	 *   listener to. This can take the form of a single DOM node, a jQuery
8999	 *   collection of nodes or a jQuery selector which will identify the node(s).
9000	 * @param {integer} column the column that a click on this node will sort on
9001	 * @param {function} [callback] callback function when sort is run
9002	 * @returns {DataTables.Api} this
9003	 */
9004	_api_register( 'order.listener()', function ( node, column, callback ) {
9005		return this.iterator( 'table', function ( settings ) {
9006			_fnSortAttachListener( settings, node, column, callback );
9007		} );
9008	} );
9009	
9010	
9011	_api_register( 'order.fixed()', function ( set ) {
9012		if ( ! set ) {
9013			var ctx = this.context;
9014			var fixed = ctx.length ?
9015				ctx[0].aaSortingFixed :
9016				undefined;
9017	
9018			return $.isArray( fixed ) ?
9019				{ pre: fixed } :
9020				fixed;
9021		}
9022	
9023		return this.iterator( 'table', function ( settings ) {
9024			settings.aaSortingFixed = $.extend( true, {}, set );
9025		} );
9026	} );
9027	
9028	
9029	// Order by the selected column(s)
9030	_api_register( [
9031		'columns().order()',
9032		'column().order()'
9033	], function ( dir ) {
9034		var that = this;
9035	
9036		return this.iterator( 'table', function ( settings, i ) {
9037			var sort = [];
9038	
9039			$.each( that[i], function (j, col) {
9040				sort.push( [ col, dir ] );
9041			} );
9042	
9043			settings.aaSorting = sort;
9044		} );
9045	} );
9046	
9047	
9048	
9049	_api_register( 'search()', function ( input, regex, smart, caseInsen ) {
9050		var ctx = this.context;
9051	
9052		if ( input === undefined ) {
9053			// get
9054			return ctx.length !== 0 ?
9055				ctx[0].oPreviousSearch.sSearch :
9056				undefined;
9057		}
9058	
9059		// set
9060		return this.iterator( 'table', function ( settings ) {
9061			if ( ! settings.oFeatures.bFilter ) {
9062				return;
9063			}
9064	
9065			_fnFilterComplete( settings, $.extend( {}, settings.oPreviousSearch, {
9066				"sSearch": input+"",
9067				"bRegex":  regex === null ? false : regex,
9068				"bSmart":  smart === null ? true  : smart,
9069				"bCaseInsensitive": caseInsen === null ? true : caseInsen
9070			} ), 1 );
9071		} );
9072	} );
9073	
9074	
9075	_api_registerPlural(
9076		'columns().search()',
9077		'column().search()',
9078		function ( input, regex, smart, caseInsen ) {
9079			return this.iterator( 'column', function ( settings, column ) {
9080				var preSearch = settings.aoPreSearchCols;
9081	
9082				if ( input === undefined ) {
9083					// get
9084					return preSearch[ column ].sSearch;
9085				}
9086	
9087				// set
9088				if ( ! settings.oFeatures.bFilter ) {
9089					return;
9090				}
9091	
9092				$.extend( preSearch[ column ], {
9093					"sSearch": input+"",
9094					"bRegex":  regex === null ? false : regex,
9095					"bSmart":  smart === null ? true  : smart,
9096					"bCaseInsensitive": caseInsen === null ? true : caseInsen
9097				} );
9098	
9099				_fnFilterComplete( settings, settings.oPreviousSearch, 1 );
9100			} );
9101		}
9102	);
9103	
9104	/*
9105	 * State API methods
9106	 */
9107	
9108	_api_register( 'state()', function () {
9109		return this.context.length ?
9110			this.context[0].oSavedState :
9111			null;
9112	} );
9113	
9114	
9115	_api_register( 'state.clear()', function () {
9116		return this.iterator( 'table', function ( settings ) {
9117			// Save an empty object
9118			settings.fnStateSaveCallback.call( settings.oInstance, settings, {} );
9119		} );
9120	} );
9121	
9122	
9123	_api_register( 'state.loaded()', function () {
9124		return this.context.length ?
9125			this.context[0].oLoadedState :
9126			null;
9127	} );
9128	
9129	
9130	_api_register( 'state.save()', function () {
9131		return this.iterator( 'table', function ( settings ) {
9132			_fnSaveState( settings );
9133		} );
9134	} );
9135	
9136	
9137	
9138	/**
9139	 * Provide a common method for plug-ins to check the version of DataTables being
9140	 * used, in order to ensure compatibility.
9141	 *
9142	 *  @param {string} version Version string to check for, in the format "X.Y.Z".
9143	 *    Note that the formats "X" and "X.Y" are also acceptable.
9144	 *  @returns {boolean} true if this version of DataTables is greater or equal to
9145	 *    the required version, or false if this version of DataTales is not
9146	 *    suitable
9147	 *  @static
9148	 *  @dtopt API-Static
9149	 *
9150	 *  @example
9151	 *    alert( $.fn.dataTable.versionCheck( '1.9.0' ) );
9152	 */
9153	DataTable.versionCheck = DataTable.fnVersionCheck = function( version )
9154	{
9155		var aThis = DataTable.version.split('.');
9156		var aThat = version.split('.');
9157		var iThis, iThat;
9158	
9159		for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) {
9160			iThis = parseInt( aThis[i], 10 ) || 0;
9161			iThat = parseInt( aThat[i], 10 ) || 0;
9162	
9163			// Parts are the same, keep comparing
9164			if (iThis === iThat) {
9165				continue;
9166			}
9167	
9168			// Parts are different, return immediately
9169			return iThis > iThat;
9170		}
9171	
9172		return true;
9173	};
9174	
9175	
9176	/**
9177	 * Check if a `<table>` node is a DataTable table already or not.
9178	 *
9179	 *  @param {node|jquery|string} table Table node, jQuery object or jQuery
9180	 *      selector for the table to test. Note that if more than more than one
9181	 *      table is passed on, only the first will be checked
9182	 *  @returns {boolean} true the table given is a DataTable, or false otherwise
9183	 *  @static
9184	 *  @dtopt API-Static
9185	 *
9186	 *  @example
9187	 *    if ( ! $.fn.DataTable.isDataTable( '#example' ) ) {
9188	 *      $('#example').dataTable();
9189	 *    }
9190	 */
9191	DataTable.isDataTable = DataTable.fnIsDataTable = function ( table )
9192	{
9193		var t = $(table).get(0);
9194		var is = false;
9195	
9196		if ( table instanceof DataTable.Api ) {
9197			return true;
9198		}
9199	
9200		$.each( DataTable.settings, function (i, o) {
9201			var head = o.nScrollHead ? $('table', o.nScrollHead)[0] : null;
9202			var foot = o.nScrollFoot ? $('table', o.nScrollFoot)[0] : null;
9203	
9204			if ( o.nTable === t || head === t || foot === t ) {
9205				is = true;
9206			}
9207		} );
9208	
9209		return is;
9210	};
9211	
9212	
9213	/**
9214	 * Get all DataTable tables that have been initialised - optionally you can
9215	 * select to get only currently visible tables.
9216	 *
9217	 *  @param {boolean} [visible=false] Flag to indicate if you want all (default)
9218	 *    or visible tables only.
9219	 *  @returns {array} Array of `table` nodes (not DataTable instances) which are
9220	 *    DataTables
9221	 *  @static
9222	 *  @dtopt API-Static
9223	 *
9224	 *  @example
9225	 *    $.each( $.fn.dataTable.tables(true), function () {
9226	 *      $(table).DataTable().columns.adjust();
9227	 *    } );
9228	 */
9229	DataTable.tables = DataTable.fnTables = function ( visible )
9230	{
9231		var api = false;
9232	
9233		if ( $.isPlainObject( visible ) ) {
9234			api = visible.api;
9235			visible = visible.visible;
9236		}
9237	
9238		var a = $.map( DataTable.settings, function (o) {
9239			if ( !visible || (visible && $(o.nTable).is(':visible')) ) {
9240				return o.nTable;
9241			}
9242		} );
9243	
9244		return api ?
9245			new _Api( a ) :
9246			a;
9247	};
9248	
9249	
9250	/**
9251	 * Convert from camel case parameters to Hungarian notation. This is made public
9252	 * for the extensions to provide the same ability as DataTables core to accept
9253	 * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase
9254	 * parameters.
9255	 *
9256	 *  @param {object} src The model object which holds all parameters that can be
9257	 *    mapped.
9258	 *  @param {object} user The object to convert from camel case to Hungarian.
9259	 *  @param {boolean} force When set to `true`, properties which already have a
9260	 *    Hungarian value in the `user` object will be overwritten. Otherwise they
9261	 *    won't be.
9262	 */
9263	DataTable.camelToHungarian = _fnCamelToHungarian;
9264	
9265	
9266	
9267	/**
9268	 *
9269	 */
9270	_api_register( '$()', function ( selector, opts ) {
9271		var
9272			rows   = this.rows( opts ).nodes(), // Get all rows
9273			jqRows = $(rows);
9274	
9275		return $( [].concat(
9276			jqRows.filter( selector ).toArray(),
9277			jqRows.find( selector ).toArray()
9278		) );
9279	} );
9280	
9281	
9282	// jQuery functions to operate on the tables
9283	$.each( [ 'on', 'one', 'off' ], function (i, key) {
9284		_api_register( key+'()', function ( /* event, handler */ ) {
9285			var args = Array.prototype.slice.call(arguments);
9286	
9287			// Add the `dt` namespace automatically if it isn't already present
9288			args[0] = $.map( args[0].split( /\s/ ), function ( e ) {
9289				return ! e.match(/\.dt\b/) ?
9290					e+'.dt' :
9291					e;
9292				} ).join( ' ' );
9293	
9294			var inst = $( this.tables().nodes() );
9295			inst[key].apply( inst, args );
9296			return this;
9297		} );
9298	} );
9299	
9300	
9301	_api_register( 'clear()', function () {
9302		return this.iterator( 'table', function ( settings ) {
9303			_fnClearTable( settings );
9304		} );
9305	} );
9306	
9307	
9308	_api_register( 'settings()', function () {
9309		return new _Api( this.context, this.context );
9310	} );
9311	
9312	
9313	_api_register( 'init()', function () {
9314		var ctx = this.context;
9315		return ctx.length ? ctx[0].oInit : null;
9316	} );
9317	
9318	
9319	_api_register( 'data()', function () {
9320		return this.iterator( 'table', function ( settings ) {
9321			return _pluck( settings.aoData, '_aData' );
9322		} ).flatten();
9323	} );
9324	
9325	
9326	_api_register( 'destroy()', function ( remove ) {
9327		remove = remove || false;
9328	
9329		return this.iterator( 'table', function ( settings ) {
9330			var orig      = settings.nTableWrapper.parentNode;
9331			var classes   = settings.oClasses;
9332			var table     = settings.nTable;
9333			var tbody     = settings.nTBody;
9334			var thead     = settings.nTHead;
9335			var tfoot     = settings.nTFoot;
9336			var jqTable   = $(table);
9337			var jqTbody   = $(tbody);
9338			var jqWrapper = $(settings.nTableWrapper);
9339			var rows      = $.map( settings.aoData, function (r) { return r.nTr; } );
9340			var i, ien;
9341	
9342			// Flag to note that the table is currently being destroyed - no action
9343			// should be taken
9344			settings.bDestroying = true;
9345	
9346			// Fire off the destroy callbacks for plug-ins etc
9347			_fnCallbackFire( settings, "aoDestroyCallback", "destroy", [settings] );
9348	
9349			// If not being removed from the document, make all columns visible
9350			if ( ! remove ) {
9351				new _Api( settings ).columns().visible( true );
9352			}
9353	
9354			// Blitz all `DT` namespaced events (these are internal events, the
9355			// lowercase, `dt` events are user subscribed and they are responsible
9356			// for removing them
9357			jqWrapper.off('.DT').find(':not(tbody *)').off('.DT');
9358			$(window).off('.DT-'+settings.sInstance);
9359	
9360			// When scrolling we had to break the table up - restore it
9361			if ( table != thead.parentNode ) {
9362				jqTable.children('thead').detach();
9363				jqTable.append( thead );
9364			}
9365	
9366			if ( tfoot && table != tfoot.parentNode ) {
9367				jqTable.children('tfoot').detach();
9368				jqTable.append( tfoot );
9369			}
9370	
9371			settings.aaSorting = [];
9372			settings.aaSortingFixed = [];
9373			_fnSortingClasses( settings );
9374	
9375			$( rows ).removeClass( settings.asStripeClasses.join(' ') );
9376	
9377			$('th, td', thead).removeClass( classes.sSortable+' '+
9378				classes.sSortableAsc+' '+classes.sSortableDesc+' '+classes.sSortableNone
9379			);
9380	
9381			// Add the TR elements back into the table in their original order
9382			jqTbody.children().detach();
9383			jqTbody.append( rows );
9384	
9385			// Remove the DataTables generated nodes, events and classes
9386			var removedMethod = remove ? 'remove' : 'detach';
9387			jqTable[ removedMethod ]();
9388			jqWrapper[ removedMethod ]();
9389	
9390			// If we need to reattach the table to the document
9391			if ( ! remove && orig ) {
9392				// insertBefore acts like appendChild if !arg[1]
9393				orig.insertBefore( table, settings.nTableReinsertBefore );
9394	
9395				// Restore the width of the original table - was read from the style property,
9396				// so we can restore directly to that
9397				jqTable
9398					.css( 'width', settings.sDestroyWidth )
9399					.removeClass( classes.sTable );
9400	
9401				// If the were originally stripe classes - then we add them back here.
9402				// Note this is not fool proof (for example if not all rows had stripe
9403				// classes - but it's a good effort without getting carried away
9404				ien = settings.asDestroyStripes.length;
9405	
9406				if ( ien ) {
9407					jqTbody.children().each( function (i) {
9408						$(this).addClass( settings.asDestroyStripes[i % ien] );
9409					} );
9410				}
9411			}
9412	
9413			/* Remove the settings object from the settings array */
9414			var idx = $.inArray( settings, DataTable.settings );
9415			if ( idx !== -1 ) {
9416				DataTable.settings.splice( idx, 1 );
9417			}
9418		} );
9419	} );
9420	
9421	
9422	// Add the `every()` method for rows, columns and cells in a compact form
9423	$.each( [ 'column', 'row', 'cell' ], function ( i, type ) {
9424		_api_register( type+'s().every()', function ( fn ) {
9425			var opts = this.selector.opts;
9426			var api = this;
9427	
9428			return this.iterator( type, function ( settings, arg1, arg2, arg3, arg4 ) {
9429				// Rows and columns:
9430				//  arg1 - index
9431				//  arg2 - table counter
9432				//  arg3 - loop counter
9433				//  arg4 - undefined
9434				// Cells:
9435				//  arg1 - row index
9436				//  arg2 - column index
9437				//  arg3 - table counter
9438				//  arg4 - loop counter
9439				fn.call(
9440					api[ type ](
9441						arg1,
9442						type==='cell' ? arg2 : opts,
9443						type==='cell' ? opts : undefined
9444					),
9445					arg1, arg2, arg3, arg4
9446				);
9447			} );
9448		} );
9449	} );
9450	
9451	
9452	// i18n method for extensions to be able to use the language object from the
9453	// DataTable
9454	_api_register( 'i18n()', function ( token, def, plural ) {
9455		var ctx = this.context[0];
9456		var resolved = _fnGetObjectDataFn( token )( ctx.oLanguage );
9457	
9458		if ( resolved === undefined ) {
9459			resolved = def;
9460		}
9461	
9462		if ( plural !== undefined && $.isPlainObject( resolved ) ) {
9463			resolved = resolved[ plural ] !== undefined ?
9464				resolved[ plural ] :
9465				resolved._;
9466		}
9467	
9468		return resolved.replace( '%d', plural ); // nb: plural might be undefined,
9469	} );
9470
9471	/**
9472	 * Version string for plug-ins to check compatibility. Allowed format is
9473	 * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used
9474	 * only for non-release builds. See http://semver.org/ for more information.
9475	 *  @member
9476	 *  @type string
9477	 *  @default Version number
9478	 */
9479	DataTable.version = "1.10.18";
9480
9481	/**
9482	 * Private data store, containing all of the settings objects that are
9483	 * created for the tables on a given page.
9484	 *
9485	 * Note that the `DataTable.settings` object is aliased to
9486	 * `jQuery.fn.dataTableExt` through which it may be accessed and
9487	 * manipulated, or `jQuery.fn.dataTable.settings`.
9488	 *  @member
9489	 *  @type array
9490	 *  @default []
9491	 *  @private
9492	 */
9493	DataTable.settings = [];
9494
9495	/**
9496	 * Object models container, for the various models that DataTables has
9497	 * available to it. These models define the objects that are used to hold
9498	 * the active state and configuration of the table.
9499	 *  @namespace
9500	 */
9501	DataTable.models = {};
9502	
9503	
9504	
9505	/**
9506	 * Template object for the way in which DataTables holds information about
9507	 * search information for the global filter and individual column filters.
9508	 *  @namespace
9509	 */
9510	DataTable.models.oSearch = {
9511		/**
9512		 * Flag to indicate if the filtering should be case insensitive or not
9513		 *  @type boolean
9514		 *  @default true
9515		 */
9516		"bCaseInsensitive": true,
9517	
9518		/**
9519		 * Applied search term
9520		 *  @type string
9521		 *  @default <i>Empty string</i>
9522		 */
9523		"sSearch": "",
9524	
9525		/**
9526		 * Flag to indicate if the search term should be interpreted as a
9527		 * regular expression (true) or not (false) and therefore and special
9528		 * regex characters escaped.
9529		 *  @type boolean
9530		 *  @default false
9531		 */
9532		"bRegex": false,
9533	
9534		/**
9535		 * Flag to indicate if DataTables is to use its smart filtering or not.
9536		 *  @type boolean
9537		 *  @default true
9538		 */
9539		"bSmart": tru
vendor: 11,217 bytes, lines 9539-9897
9539e
9540	};
9541	
9542	
9543	
9544	
9545	/**
9546	 * Template object for the way in which DataTables holds information about
9547	 * each individual row. This is the object format used for the settings
9548	 * aoData array.
9549	 *  @namespace
9550	 */
9551	DataTable.models.oRow = {
9552		/**
9553		 * TR element for the row
9554		 *  @type node
9555		 *  @default null
9556		 */
9557		"nTr": null,
9558	
9559		/**
9560		 * Array of TD elements for each row. This is null until the row has been
9561		 * created.
9562		 *  @type array nodes
9563		 *  @default []
9564		 */
9565		"anCells": null,
9566	
9567		/**
9568		 * Data object from the original data source for the row. This is either
9569		 * an array if using the traditional form of DataTables, or an object if
9570		 * using mData options. The exact type will depend on the passed in
9571		 * data from the data source, or will be an array if using DOM a data
9572		 * source.
9573		 *  @type array|object
9574		 *  @default []
9575		 */
9576		"_aData": [],
9577	
9578		/**
9579		 * Sorting data cache - this array is ostensibly the same length as the
9580		 * number of columns (although each index is generated only as it is
9581		 * needed), and holds the data that is used for sorting each column in the
9582		 * row. We do this cache generation at the start of the sort in order that
9583		 * the formatting of the sort data need be done only once for each cell
9584		 * per sort. This array should not be read from or written to by anything
9585		 * other than the master sorting methods.
9586		 *  @type array
9587		 *  @default null
9588		 *  @private
9589		 */
9590		"_aSortData": null,
9591	
9592		/**
9593		 * Per cell filtering data cache. As per the sort data cache, used to
9594		 * increase the performance of the filtering in DataTables
9595		 *  @type array
9596		 *  @default null
9597		 *  @private
9598		 */
9599		"_aFilterData": null,
9600	
9601		/**
9602		 * Filtering data cache. This is the same as the cell filtering cache, but
9603		 * in this case a string rather than an array. This is easily computed with
9604		 * a join on `_aFilterData`, but is provided as a cache so the join isn't
9605		 * needed on every search (memory traded for performance)
9606		 *  @type array
9607		 *  @default null
9608		 *  @private
9609		 */
9610		"_sFilterRow": null,
9611	
9612		/**
9613		 * Cache of the class name that DataTables has applied to the row, so we
9614		 * can quickly look at this variable rather than needing to do a DOM check
9615		 * on className for the nTr property.
9616		 *  @type string
9617		 *  @default <i>Empty string</i>
9618		 *  @private
9619		 */
9620		"_sRowStripe": "",
9621	
9622		/**
9623		 * Denote if the original data source was from the DOM, or the data source
9624		 * object. This is used for invalidating data, so DataTables can
9625		 * automatically read data from the original source, unless uninstructed
9626		 * otherwise.
9627		 *  @type string
9628		 *  @default null
9629		 *  @private
9630		 */
9631		"src": null,
9632	
9633		/**
9634		 * Index in the aoData array. This saves an indexOf lookup when we have the
9635		 * object, but want to know the index
9636		 *  @type integer
9637		 *  @default -1
9638		 *  @private
9639		 */
9640		"idx": -1
9641	};
9642	
9643	
9644	/**
9645	 * Template object for the column information object in DataTables. This object
9646	 * is held in the settings aoColumns array and contains all the information that
9647	 * DataTables needs about each individual column.
9648	 *
9649	 * Note that this object is related to {@link DataTable.defaults.column}
9650	 * but this one is the internal data store for DataTables's cache of columns.
9651	 * It should NOT be manipulated outside of DataTables. Any configuration should
9652	 * be done through the initialisation options.
9653	 *  @namespace
9654	 */
9655	DataTable.models.oColumn = {
9656		/**
9657		 * Column index. This could be worked out on-the-fly with $.inArray, but it
9658		 * is faster to just hold it as a variable
9659		 *  @type integer
9660		 *  @default null
9661		 */
9662		"idx": null,
9663	
9664		/**
9665		 * A list of the columns that sorting should occur on when this column
9666		 * is sorted. That this property is an array allows multi-column sorting
9667		 * to be defined for a column (for example first name / last name columns
9668		 * would benefit from this). The values are integers pointing to the
9669		 * columns to be sorted on (typically it will be a single integer pointing
9670		 * at itself, but that doesn't need to be the case).
9671		 *  @type array
9672		 */
9673		"aDataSort": null,
9674	
9675		/**
9676		 * Define the sorting directions that are applied to the column, in sequence
9677		 * as the column is repeatedly sorted upon - i.e. the first value is used
9678		 * as the sorting direction when the column if first sorted (clicked on).
9679		 * Sort it again (click again) and it will move on to the next index.
9680		 * Repeat until loop.
9681		 *  @type array
9682		 */
9683		"asSorting": null,
9684	
9685		/**
9686		 * Flag to indicate if the column is searchable, and thus should be included
9687		 * in the filtering or not.
9688		 *  @type boolean
9689		 */
9690		"bSearchable": null,
9691	
9692		/**
9693		 * Flag to indicate if the column is sortable or not.
9694		 *  @type boolean
9695		 */
9696		"bSortable": null,
9697	
9698		/**
9699		 * Flag to indicate if the column is currently visible in the table or not
9700		 *  @type boolean
9701		 */
9702		"bVisible": null,
9703	
9704		/**
9705		 * Store for manual type assignment using the `column.type` option. This
9706		 * is held in store so we can manipulate the column's `sType` property.
9707		 *  @type string
9708		 *  @default null
9709		 *  @private
9710		 */
9711		"_sManualType": null,
9712	
9713		/**
9714		 * Flag to indicate if HTML5 data attributes should be used as the data
9715		 * source for filtering or sorting. True is either are.
9716		 *  @type boolean
9717		 *  @default false
9718		 *  @private
9719		 */
9720		"_bAttrSrc": false,
9721	
9722		/**
9723		 * Developer definable function that is called whenever a cell is created (Ajax source,
9724		 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
9725		 * allowing you to modify the DOM element (add background colour for example) when the
9726		 * element is available.
9727		 *  @type function
9728		 *  @param {element} nTd The TD node that has been created
9729		 *  @param {*} sData The Data for the cell
9730		 *  @param {array|object} oData The data for the whole row
9731		 *  @param {int} iRow The row index for the aoData data store
9732		 *  @default null
9733		 */
9734		"fnCreatedCell": null,
9735	
9736		/**
9737		 * Function to get data from a cell in a column. You should <b>never</b>
9738		 * access data directly through _aData internally in DataTables - always use
9739		 * the method attached to this property. It allows mData to function as
9740		 * required. This function is automatically assigned by the column
9741		 * initialisation method
9742		 *  @type function
9743		 *  @param {array|object} oData The data array/object for the array
9744		 *    (i.e. aoData[]._aData)
9745		 *  @param {string} sSpecific The specific data type you want to get -
9746		 *    'display', 'type' 'filter' 'sort'
9747		 *  @returns {*} The data for the cell from the given row's data
9748		 *  @default null
9749		 */
9750		"fnGetData": null,
9751	
9752		/**
9753		 * Function to set data for a cell in the column. You should <b>never</b>
9754		 * set the data directly to _aData internally in DataTables - always use
9755		 * this method. It allows mData to function as required. This function
9756		 * is automatically assigned by the column initialisation method
9757		 *  @type function
9758		 *  @param {array|object} oData The data array/object for the array
9759		 *    (i.e. aoData[]._aData)
9760		 *  @param {*} sValue Value to set
9761		 *  @default null
9762		 */
9763		"fnSetData": null,
9764	
9765		/**
9766		 * Property to read the value for the cells in the column from the data
9767		 * source array / object. If null, then the default content is used, if a
9768		 * function is given then the return from the function is used.
9769		 *  @type function|int|string|null
9770		 *  @default null
9771		 */
9772		"mData": null,
9773	
9774		/**
9775		 * Partner property to mData which is used (only when defined) to get
9776		 * the data - i.e. it is basically the same as mData, but without the
9777		 * 'set' option, and also the data fed to it is the result from mData.
9778		 * This is the rendering method to match the data method of mData.
9779		 *  @type function|int|string|null
9780		 *  @default null
9781		 */
9782		"mRender": null,
9783	
9784		/**
9785		 * Unique header TH/TD element for this column - this is what the sorting
9786		 * listener is attached to (if sorting is enabled.)
9787		 *  @type node
9788		 *  @default null
9789		 */
9790		"nTh": null,
9791	
9792		/**
9793		 * Unique footer TH/TD element for this column (if there is one). Not used
9794		 * in DataTables as such, but can be used for plug-ins to reference the
9795		 * footer for each column.
9796		 *  @type node
9797		 *  @default null
9798		 */
9799		"nTf": null,
9800	
9801		/**
9802		 * The class to apply to all TD elements in the table's TBODY for the column
9803		 *  @type string
9804		 *  @default null
9805		 */
9806		"sClass": null,
9807	
9808		/**
9809		 * When DataTables calculates the column widths to assign to each column,
9810		 * it finds the longest string in each column and then constructs a
9811		 * temporary table and reads the widths from that. The problem with this
9812		 * is that "mmm" is much wider then "iiii", but the latter is a longer
9813		 * string - thus the calculation can go wrong (doing it properly and putting
9814		 * it into an DOM object and measuring that is horribly(!) slow). Thus as
9815		 * a "work around" we provide this option. It will append its value to the
9816		 * text that is found to be the longest string for the column - i.e. padding.
9817		 *  @type string
9818		 */
9819		"sContentPadding": null,
9820	
9821		/**
9822		 * Allows a default value to be given for a column's data, and will be used
9823		 * whenever a null data source is encountered (this can be because mData
9824		 * is set to null, or because the data source itself is null).
9825		 *  @type string
9826		 *  @default null
9827		 */
9828		"sDefaultContent": null,
9829	
9830		/**
9831		 * Name for the column, allowing reference to the column by name as well as
9832		 * by index (needs a lookup to work by name).
9833		 *  @type string
9834		 */
9835		"sName": null,
9836	
9837		/**
9838		 * Custom sorting data type - defines which of the available plug-ins in
9839		 * afnSortData the custom sorting will use - if any is defined.
9840		 *  @type string
9841		 *  @default std
9842		 */
9843		"sSortDataType": 'std',
9844	
9845		/**
9846		 * Class to be applied to the header element when sorting on this column
9847		 *  @type string
9848		 *  @default null
9849		 */
9850		"sSortingClass": null,
9851	
9852		/**
9853		 * Class to be applied to the header element when sorting on this column -
9854		 * when jQuery UI theming is used.
9855		 *  @type string
9856		 *  @default null
9857		 */
9858		"sSortingClassJUI": null,
9859	
9860		/**
9861		 * Title of the column - what is seen in the TH element (nTh).
9862		 *  @type string
9863		 */
9864		"sTitle": null,
9865	
9866		/**
9867		 * Column sorting and filtering type
9868		 *  @type string
9869		 *  @default null
9870		 */
9871		"sType": null,
9872	
9873		/**
9874		 * Width of the column
9875		 *  @type string
9876		 *  @default null
9877		 */
9878		"sWidth": null,
9879	
9880		/**
9881		 * Width of the column when it was first "encountered"
9882		 *  @type string
9883		 *  @default null
9884		 */
9885		"sWidthOrig": null
9886	};
9887	
9888	
9889	/*
9890	 * Developer note: The properties of the object below are given in Hungarian
9891	 * notation, that was used as the interface for DataTables prior to v1.10, however
9892	 * from v1.10 onwards the primary interface is camel case. In order to avoid
9893	 * breaking backwards compatibility utterly with this change, the Hungarian
9894	 * version is still, internally the primary interface, but is is not documented
9895	 * - hence the @name tags in each doc comment. This allows a Javascript function
9896	 * to create a map from Hungarian notation to camel case (going the other direction
9897	 * would require each property to be listed, which would a
9897t around 3K to the size
9898	 * of DataTables, while this method is about a 0.5K hit
vendor: 57,087 bytes, lines 9898-11674
9898.
9899	 *
9900	 * Ultimately this does pave the way for Hungarian notation to be dropped
9901	 * completely, but that is a massive amount of work and will break current
9902	 * installs (therefore is on-hold until v2).
9903	 */
9904	
9905	/**
9906	 * Initialisation options that can be given to DataTables at initialisation
9907	 * time.
9908	 *  @namespace
9909	 */
9910	DataTable.defaults = {
9911		/**
9912		 * An array of data to use for the table, passed in at initialisation which
9913		 * will be used in preference to any data which is already in the DOM. This is
9914		 * particularly useful for constructing tables purely in Javascript, for
9915		 * example with a custom Ajax call.
9916		 *  @type array
9917		 *  @default null
9918		 *
9919		 *  @dtopt Option
9920		 *  @name DataTable.defaults.data
9921		 *
9922		 *  @example
9923		 *    // Using a 2D array data source
9924		 *    $(document).ready( function () {
9925		 *      $('#example').dataTable( {
9926		 *        "data": [
9927		 *          ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
9928		 *          ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
9929		 *        ],
9930		 *        "columns": [
9931		 *          { "title": "Engine" },
9932		 *          { "title": "Browser" },
9933		 *          { "title": "Platform" },
9934		 *          { "title": "Version" },
9935		 *          { "title": "Grade" }
9936		 *        ]
9937		 *      } );
9938		 *    } );
9939		 *
9940		 *  @example
9941		 *    // Using an array of objects as a data source (`data`)
9942		 *    $(document).ready( function () {
9943		 *      $('#example').dataTable( {
9944		 *        "data": [
9945		 *          {
9946		 *            "engine":   "Trident",
9947		 *            "browser":  "Internet Explorer 4.0",
9948		 *            "platform": "Win 95+",
9949		 *            "version":  4,
9950		 *            "grade":    "X"
9951		 *          },
9952		 *          {
9953		 *            "engine":   "Trident",
9954		 *            "browser":  "Internet Explorer 5.0",
9955		 *            "platform": "Win 95+",
9956		 *            "version":  5,
9957		 *            "grade":    "C"
9958		 *          }
9959		 *        ],
9960		 *        "columns": [
9961		 *          { "title": "Engine",   "data": "engine" },
9962		 *          { "title": "Browser",  "data": "browser" },
9963		 *          { "title": "Platform", "data": "platform" },
9964		 *          { "title": "Version",  "data": "version" },
9965		 *          { "title": "Grade",    "data": "grade" }
9966		 *        ]
9967		 *      } );
9968		 *    } );
9969		 */
9970		"aaData": null,
9971	
9972	
9973		/**
9974		 * If ordering is enabled, then DataTables will perform a first pass sort on
9975		 * initialisation. You can define which column(s) the sort is performed
9976		 * upon, and the sorting direction, with this variable. The `sorting` array
9977		 * should contain an array for each column to be sorted initially containing
9978		 * the column's index and a direction string ('asc' or 'desc').
9979		 *  @type array
9980		 *  @default [[0,'asc']]
9981		 *
9982		 *  @dtopt Option
9983		 *  @name DataTable.defaults.order
9984		 *
9985		 *  @example
9986		 *    // Sort by 3rd column first, and then 4th column
9987		 *    $(document).ready( function() {
9988		 *      $('#example').dataTable( {
9989		 *        "order": [[2,'asc'], [3,'desc']]
9990		 *      } );
9991		 *    } );
9992		 *
9993		 *    // No initial sorting
9994		 *    $(document).ready( function() {
9995		 *      $('#example').dataTable( {
9996		 *        "order": []
9997		 *      } );
9998		 *    } );
9999		 */
10000		"aaSorting": [[0,'asc']],
10001	
10002	
10003		/**
10004		 * This parameter is basically identical to the `sorting` parameter, but
10005		 * cannot be overridden by user interaction with the table. What this means
10006		 * is that you could have a column (visible or hidden) which the sorting
10007		 * will always be forced on first - any sorting after that (from the user)
10008		 * will then be performed as required. This can be useful for grouping rows
10009		 * together.
10010		 *  @type array
10011		 *  @default null
10012		 *
10013		 *  @dtopt Option
10014		 *  @name DataTable.defaults.orderFixed
10015		 *
10016		 *  @example
10017		 *    $(document).ready( function() {
10018		 *      $('#example').dataTable( {
10019		 *        "orderFixed": [[0,'asc']]
10020		 *      } );
10021		 *    } )
10022		 */
10023		"aaSortingFixed": [],
10024	
10025	
10026		/**
10027		 * DataTables can be instructed to load data to display in the table from a
10028		 * Ajax source. This option defines how that Ajax call is made and where to.
10029		 *
10030		 * The `ajax` property has three different modes of operation, depending on
10031		 * how it is defined. These are:
10032		 *
10033		 * * `string` - Set the URL from where the data should be loaded from.
10034		 * * `object` - Define properties for `jQuery.ajax`.
10035		 * * `function` - Custom data get function
10036		 *
10037		 * `string`
10038		 * --------
10039		 *
10040		 * As a string, the `ajax` property simply defines the URL from which
10041		 * DataTables will load data.
10042		 *
10043		 * `object`
10044		 * --------
10045		 *
10046		 * As an object, the parameters in the object are passed to
10047		 * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control
10048		 * of the Ajax request. DataTables has a number of default parameters which
10049		 * you can override using this option. Please refer to the jQuery
10050		 * documentation for a full description of the options available, although
10051		 * the following parameters provide additional options in DataTables or
10052		 * require special consideration:
10053		 *
10054		 * * `data` - As with jQuery, `data` can be provided as an object, but it
10055		 *   can also be used as a function to manipulate the data DataTables sends
10056		 *   to the server. The function takes a single parameter, an object of
10057		 *   parameters with the values that DataTables has readied for sending. An
10058		 *   object may be returned which will be merged into the DataTables
10059		 *   defaults, or you can add the items to the object that was passed in and
10060		 *   not return anything from the function. This supersedes `fnServerParams`
10061		 *   from DataTables 1.9-.
10062		 *
10063		 * * `dataSrc` - By default DataTables will look for the property `data` (or
10064		 *   `aaData` for compatibility with DataTables 1.9-) when obtaining data
10065		 *   from an Ajax source or for server-side processing - this parameter
10066		 *   allows that property to be changed. You can use Javascript dotted
10067		 *   object notation to get a data source for multiple levels of nesting, or
10068		 *   it my be used as a function. As a function it takes a single parameter,
10069		 *   the JSON returned from the server, which can be manipulated as
10070		 *   required, with the returned value being that used by DataTables as the
10071		 *   data source for the table. This supersedes `sAjaxDataProp` from
10072		 *   DataTables 1.9-.
10073		 *
10074		 * * `success` - Should not be overridden it is used internally in
10075		 *   DataTables. To manipulate / transform the data returned by the server
10076		 *   use `ajax.dataSrc`, or use `ajax` as a function (see below).
10077		 *
10078		 * `function`
10079		 * ----------
10080		 *
10081		 * As a function, making the Ajax call is left up to yourself allowing
10082		 * complete control of the Ajax request. Indeed, if desired, a method other
10083		 * than Ajax could be used to obtain the required data, such as Web storage
10084		 * or an AIR database.
10085		 *
10086		 * The function is given four parameters and no return is required. The
10087		 * parameters are:
10088		 *
10089		 * 1. _object_ - Data to send to the server
10090		 * 2. _function_ - Callback function that must be executed when the required
10091		 *    data has been obtained. That data should be passed into the callback
10092		 *    as the only parameter
10093		 * 3. _object_ - DataTables settings object for the table
10094		 *
10095		 * Note that this supersedes `fnServerData` from DataTables 1.9-.
10096		 *
10097		 *  @type string|object|function
10098		 *  @default null
10099		 *
10100		 *  @dtopt Option
10101		 *  @name DataTable.defaults.ajax
10102		 *  @since 1.10.0
10103		 *
10104		 * @example
10105		 *   // Get JSON data from a file via Ajax.
10106		 *   // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default).
10107		 *   $('#example').dataTable( {
10108		 *     "ajax": "data.json"
10109		 *   } );
10110		 *
10111		 * @example
10112		 *   // Get JSON data from a file via Ajax, using `dataSrc` to change
10113		 *   // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`)
10114		 *   $('#example').dataTable( {
10115		 *     "ajax": {
10116		 *       "url": "data.json",
10117		 *       "dataSrc": "tableData"
10118		 *     }
10119		 *   } );
10120		 *
10121		 * @example
10122		 *   // Get JSON data from a file via Ajax, using `dataSrc` to read data
10123		 *   // from a plain array rather than an array in an object
10124		 *   $('#example').dataTable( {
10125		 *     "ajax": {
10126		 *       "url": "data.json",
10127		 *       "dataSrc": ""
10128		 *     }
10129		 *   } );
10130		 *
10131		 * @example
10132		 *   // Manipulate the data returned from the server - add a link to data
10133		 *   // (note this can, should, be done using `render` for the column - this
10134		 *   // is just a simple example of how the data can be manipulated).
10135		 *   $('#example').dataTable( {
10136		 *     "ajax": {
10137		 *       "url": "data.json",
10138		 *       "dataSrc": function ( json ) {
10139		 *         for ( var i=0, ien=json.length ; i<ien ; i++ ) {
10140		 *           json[i][0] = '<a href="/message/'+json[i][0]+'>View message</a>';
10141		 *         }
10142		 *         return json;
10143		 *       }
10144		 *     }
10145		 *   } );
10146		 *
10147		 * @example
10148		 *   // Add data to the request
10149		 *   $('#example').dataTable( {
10150		 *     "ajax": {
10151		 *       "url": "data.json",
10152		 *       "data": function ( d ) {
10153		 *         return {
10154		 *           "extra_search": $('#extra').val()
10155		 *         };
10156		 *       }
10157		 *     }
10158		 *   } );
10159		 *
10160		 * @example
10161		 *   // Send request as POST
10162		 *   $('#example').dataTable( {
10163		 *     "ajax": {
10164		 *       "url": "data.json",
10165		 *       "type": "POST"
10166		 *     }
10167		 *   } );
10168		 *
10169		 * @example
10170		 *   // Get the data from localStorage (could interface with a form for
10171		 *   // adding, editing and removing rows).
10172		 *   $('#example').dataTable( {
10173		 *     "ajax": function (data, callback, settings) {
10174		 *       callback(
10175		 *         JSON.parse( localStorage.getItem('dataTablesData') )
10176		 *       );
10177		 *     }
10178		 *   } );
10179		 */
10180		"ajax": null,
10181	
10182	
10183		/**
10184		 * This parameter allows you to readily specify the entries in the length drop
10185		 * down menu that DataTables shows when pagination is enabled. It can be
10186		 * either a 1D array of options which will be used for both the displayed
10187		 * option and the value, or a 2D array which will use the array in the first
10188		 * position as the value, and the array in the second position as the
10189		 * displayed options (useful for language strings such as 'All').
10190		 *
10191		 * Note that the `pageLength` property will be automatically set to the
10192		 * first value given in this array, unless `pageLength` is also provided.
10193		 *  @type array
10194		 *  @default [ 10, 25, 50, 100 ]
10195		 *
10196		 *  @dtopt Option
10197		 *  @name DataTable.defaults.lengthMenu
10198		 *
10199		 *  @example
10200		 *    $(document).ready( function() {
10201		 *      $('#example').dataTable( {
10202		 *        "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
10203		 *      } );
10204		 *    } );
10205		 */
10206		"aLengthMenu": [ 10, 25, 50, 100 ],
10207	
10208	
10209		/**
10210		 * The `columns` option in the initialisation parameter allows you to define
10211		 * details about the way individual columns behave. For a full list of
10212		 * column options that can be set, please see
10213		 * {@link DataTable.defaults.column}. Note that if you use `columns` to
10214		 * define your columns, you must have an entry in the array for every single
10215		 * column that you have in your table (these can be null if you don't which
10216		 * to specify any options).
10217		 *  @member
10218		 *
10219		 *  @name DataTable.defaults.column
10220		 */
10221		"aoColumns": null,
10222	
10223		/**
10224		 * Very similar to `columns`, `columnDefs` allows you to target a specific
10225		 * column, multiple columns, or all columns, using the `targets` property of
10226		 * each object in the array. This allows great flexibility when creating
10227		 * tables, as the `columnDefs` arrays can be of any length, targeting the
10228		 * columns you specifically want. `columnDefs` may use any of the column
10229		 * options available: {@link DataTable.defaults.column}, but it _must_
10230		 * have `targets` defined in each object in the array. Values in the `targets`
10231		 * array may be:
10232		 *   <ul>
10233		 *     <li>a string - class name will be matched on the TH for the column</li>
10234		 *     <li>0 or a positive integer - column index counting from the left</li>
10235		 *     <li>a negative integer - column index counting from the right</li>
10236		 *     <li>the string "_all" - all columns (i.e. assign a default)</li>
10237		 *   </ul>
10238		 *  @member
10239		 *
10240		 *  @name DataTable.defaults.columnDefs
10241		 */
10242		"aoColumnDefs": null,
10243	
10244	
10245		/**
10246		 * Basically the same as `search`, this parameter defines the individual column
10247		 * filtering state at initialisation time. The array must be of the same size
10248		 * as the number of columns, and each element be an object with the parameters
10249		 * `search` and `escapeRegex` (the latter is optional). 'null' is also
10250		 * accepted and the default will be used.
10251		 *  @type array
10252		 *  @default []
10253		 *
10254		 *  @dtopt Option
10255		 *  @name DataTable.defaults.searchCols
10256		 *
10257		 *  @example
10258		 *    $(document).ready( function() {
10259		 *      $('#example').dataTable( {
10260		 *        "searchCols": [
10261		 *          null,
10262		 *          { "search": "My filter" },
10263		 *          null,
10264		 *          { "search": "^[0-9]", "escapeRegex": false }
10265		 *        ]
10266		 *      } );
10267		 *    } )
10268		 */
10269		"aoSearchCols": [],
10270	
10271	
10272		/**
10273		 * An array of CSS classes that should be applied to displayed rows. This
10274		 * array may be of any length, and DataTables will apply each class
10275		 * sequentially, looping when required.
10276		 *  @type array
10277		 *  @default null <i>Will take the values determined by the `oClasses.stripe*`
10278		 *    options</i>
10279		 *
10280		 *  @dtopt Option
10281		 *  @name DataTable.defaults.stripeClasses
10282		 *
10283		 *  @example
10284		 *    $(document).ready( function() {
10285		 *      $('#example').dataTable( {
10286		 *        "stripeClasses": [ 'strip1', 'strip2', 'strip3' ]
10287		 *      } );
10288		 *    } )
10289		 */
10290		"asStripeClasses": null,
10291	
10292	
10293		/**
10294		 * Enable or disable automatic column width calculation. This can be disabled
10295		 * as an optimisation (it takes some time to calculate the widths) if the
10296		 * tables widths are passed in using `columns`.
10297		 *  @type boolean
10298		 *  @default true
10299		 *
10300		 *  @dtopt Features
10301		 *  @name DataTable.defaults.autoWidth
10302		 *
10303		 *  @example
10304		 *    $(document).ready( function () {
10305		 *      $('#example').dataTable( {
10306		 *        "autoWidth": false
10307		 *      } );
10308		 *    } );
10309		 */
10310		"bAutoWidth": true,
10311	
10312	
10313		/**
10314		 * Deferred rendering can provide DataTables with a huge speed boost when you
10315		 * are using an Ajax or JS data source for the table. This option, when set to
10316		 * true, will cause DataTables to defer the creation of the table elements for
10317		 * each row until they are needed for a draw - saving a significant amount of
10318		 * time.
10319		 *  @type boolean
10320		 *  @default false
10321		 *
10322		 *  @dtopt Features
10323		 *  @name DataTable.defaults.deferRender
10324		 *
10325		 *  @example
10326		 *    $(document).ready( function() {
10327		 *      $('#example').dataTable( {
10328		 *        "ajax": "sources/arrays.txt",
10329		 *        "deferRender": true
10330		 *      } );
10331		 *    } );
10332		 */
10333		"bDeferRender": false,
10334	
10335	
10336		/**
10337		 * Replace a DataTable which matches the given selector and replace it with
10338		 * one which has the properties of the new initialisation object passed. If no
10339		 * table matches the selector, then the new DataTable will be constructed as
10340		 * per normal.
10341		 *  @type boolean
10342		 *  @default false
10343		 *
10344		 *  @dtopt Options
10345		 *  @name DataTable.defaults.destroy
10346		 *
10347		 *  @example
10348		 *    $(document).ready( function() {
10349		 *      $('#example').dataTable( {
10350		 *        "srollY": "200px",
10351		 *        "paginate": false
10352		 *      } );
10353		 *
10354		 *      // Some time later....
10355		 *      $('#example').dataTable( {
10356		 *        "filter": false,
10357		 *        "destroy": true
10358		 *      } );
10359		 *    } );
10360		 */
10361		"bDestroy": false,
10362	
10363	
10364		/**
10365		 * Enable or disable filtering of data. Filtering in DataTables is "smart" in
10366		 * that it allows the end user to input multiple words (space separated) and
10367		 * will match a row containing those words, even if not in the order that was
10368		 * specified (this allow matching across multiple columns). Note that if you
10369		 * wish to use filtering in DataTables this must remain 'true' - to remove the
10370		 * default filtering input box and retain filtering abilities, please use
10371		 * {@link DataTable.defaults.dom}.
10372		 *  @type boolean
10373		 *  @default true
10374		 *
10375		 *  @dtopt Features
10376		 *  @name DataTable.defaults.searching
10377		 *
10378		 *  @example
10379		 *    $(document).ready( function () {
10380		 *      $('#example').dataTable( {
10381		 *        "searching": false
10382		 *      } );
10383		 *    } );
10384		 */
10385		"bFilter": true,
10386	
10387	
10388		/**
10389		 * Enable or disable the table information display. This shows information
10390		 * about the data that is currently visible on the page, including information
10391		 * about filtered data if that action is being performed.
10392		 *  @type boolean
10393		 *  @default true
10394		 *
10395		 *  @dtopt Features
10396		 *  @name DataTable.defaults.info
10397		 *
10398		 *  @example
10399		 *    $(document).ready( function () {
10400		 *      $('#example').dataTable( {
10401		 *        "info": false
10402		 *      } );
10403		 *    } );
10404		 */
10405		"bInfo": true,
10406	
10407	
10408		/**
10409		 * Allows the end user to select the size of a formatted page from a select
10410		 * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`).
10411		 *  @type boolean
10412		 *  @default true
10413		 *
10414		 *  @dtopt Features
10415		 *  @name DataTable.defaults.lengthChange
10416		 *
10417		 *  @example
10418		 *    $(document).ready( function () {
10419		 *      $('#example').dataTable( {
10420		 *        "lengthChange": false
10421		 *      } );
10422		 *    } );
10423		 */
10424		"bLengthChange": true,
10425	
10426	
10427		/**
10428		 * Enable or disable pagination.
10429		 *  @type boolean
10430		 *  @default true
10431		 *
10432		 *  @dtopt Features
10433		 *  @name DataTable.defaults.paging
10434		 *
10435		 *  @example
10436		 *    $(document).ready( function () {
10437		 *      $('#example').dataTable( {
10438		 *        "paging": false
10439		 *      } );
10440		 *    } );
10441		 */
10442		"bPaginate": true,
10443	
10444	
10445		/**
10446		 * Enable or disable the display of a 'processing' indicator when the table is
10447		 * being processed (e.g. a sort). This is particularly useful for tables with
10448		 * large amounts of data where it can take a noticeable amount of time to sort
10449		 * the entries.
10450		 *  @type boolean
10451		 *  @default false
10452		 *
10453		 *  @dtopt Features
10454		 *  @name DataTable.defaults.processing
10455		 *
10456		 *  @example
10457		 *    $(document).ready( function () {
10458		 *      $('#example').dataTable( {
10459		 *        "processing": true
10460		 *      } );
10461		 *    } );
10462		 */
10463		"bProcessing": false,
10464	
10465	
10466		/**
10467		 * Retrieve the DataTables object for the given selector. Note that if the
10468		 * table has already been initialised, this parameter will cause DataTables
10469		 * to simply return the object that has already been set up - it will not take
10470		 * account of any changes you might have made to the initialisation object
10471		 * passed to DataTables (setting this parameter to true is an acknowledgement
10472		 * that you understand this). `destroy` can be used to reinitialise a table if
10473		 * you need.
10474		 *  @type boolean
10475		 *  @default false
10476		 *
10477		 *  @dtopt Options
10478		 *  @name DataTable.defaults.retrieve
10479		 *
10480		 *  @example
10481		 *    $(document).ready( function() {
10482		 *      initTable();
10483		 *      tableActions();
10484		 *    } );
10485		 *
10486		 *    function initTable ()
10487		 *    {
10488		 *      return $('#example').dataTable( {
10489		 *        "scrollY": "200px",
10490		 *        "paginate": false,
10491		 *        "retrieve": true
10492		 *      } );
10493		 *    }
10494		 *
10495		 *    function tableActions ()
10496		 *    {
10497		 *      var table = initTable();
10498		 *      // perform API operations with oTable
10499		 *    }
10500		 */
10501		"bRetrieve": false,
10502	
10503	
10504		/**
10505		 * When vertical (y) scrolling is enabled, DataTables will force the height of
10506		 * the table's viewport to the given height at all times (useful for layout).
10507		 * However, this can look odd when filtering data down to a small data set,
10508		 * and the footer is left "floating" further down. This parameter (when
10509		 * enabled) will cause DataTables to collapse the table's viewport down when
10510		 * the result set will fit within the given Y height.
10511		 *  @type boolean
10512		 *  @default false
10513		 *
10514		 *  @dtopt Options
10515		 *  @name DataTable.defaults.scrollCollapse
10516		 *
10517		 *  @example
10518		 *    $(document).ready( function() {
10519		 *      $('#example').dataTable( {
10520		 *        "scrollY": "200",
10521		 *        "scrollCollapse": true
10522		 *      } );
10523		 *    } );
10524		 */
10525		"bScrollCollapse": false,
10526	
10527	
10528		/**
10529		 * Configure DataTables to use server-side processing. Note that the
10530		 * `ajax` parameter must also be given in order to give DataTables a
10531		 * source to obtain the required data for each draw.
10532		 *  @type boolean
10533		 *  @default false
10534		 *
10535		 *  @dtopt Features
10536		 *  @dtopt Server-side
10537		 *  @name DataTable.defaults.serverSide
10538		 *
10539		 *  @example
10540		 *    $(document).ready( function () {
10541		 *      $('#example').dataTable( {
10542		 *        "serverSide": true,
10543		 *        "ajax": "xhr.php"
10544		 *      } );
10545		 *    } );
10546		 */
10547		"bServerSide": false,
10548	
10549	
10550		/**
10551		 * Enable or disable sorting of columns. Sorting of individual columns can be
10552		 * disabled by the `sortable` option for each column.
10553		 *  @type boolean
10554		 *  @default true
10555		 *
10556		 *  @dtopt Features
10557		 *  @name DataTable.defaults.ordering
10558		 *
10559		 *  @example
10560		 *    $(document).ready( function () {
10561		 *      $('#example').dataTable( {
10562		 *        "ordering": false
10563		 *      } );
10564		 *    } );
10565		 */
10566		"bSort": true,
10567	
10568	
10569		/**
10570		 * Enable or display DataTables' ability to sort multiple columns at the
10571		 * same time (activated by shift-click by the user).
10572		 *  @type boolean
10573		 *  @default true
10574		 *
10575		 *  @dtopt Options
10576		 *  @name DataTable.defaults.orderMulti
10577		 *
10578		 *  @example
10579		 *    // Disable multiple column sorting ability
10580		 *    $(document).ready( function () {
10581		 *      $('#example').dataTable( {
10582		 *        "orderMulti": false
10583		 *      } );
10584		 *    } );
10585		 */
10586		"bSortMulti": true,
10587	
10588	
10589		/**
10590		 * Allows control over whether DataTables should use the top (true) unique
10591		 * cell that is found for a single column, or the bottom (false - default).
10592		 * This is useful when using complex headers.
10593		 *  @type boolean
10594		 *  @default false
10595		 *
10596		 *  @dtopt Options
10597		 *  @name DataTable.defaults.orderCellsTop
10598		 *
10599		 *  @example
10600		 *    $(document).ready( function() {
10601		 *      $('#example').dataTable( {
10602		 *        "orderCellsTop": true
10603		 *      } );
10604		 *    } );
10605		 */
10606		"bSortCellsTop": false,
10607	
10608	
10609		/**
10610		 * Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and
10611		 * `sorting\_3` to the columns which are currently being sorted on. This is
10612		 * presented as a feature switch as it can increase processing time (while
10613		 * classes are removed and added) so for large data sets you might want to
10614		 * turn this off.
10615		 *  @type boolean
10616		 *  @default true
10617		 *
10618		 *  @dtopt Features
10619		 *  @name DataTable.defaults.orderClasses
10620		 *
10621		 *  @example
10622		 *    $(document).ready( function () {
10623		 *      $('#example').dataTable( {
10624		 *        "orderClasses": false
10625		 *      } );
10626		 *    } );
10627		 */
10628		"bSortClasses": true,
10629	
10630	
10631		/**
10632		 * Enable or disable state saving. When enabled HTML5 `localStorage` will be
10633		 * used to save table display information such as pagination information,
10634		 * display length, filtering and sorting. As such when the end user reloads
10635		 * the page the display display will match what thy had previously set up.
10636		 *
10637		 * Due to the use of `localStorage` the default state saving is not supported
10638		 * in IE6 or 7. If state saving is required in those browsers, use
10639		 * `stateSaveCallback` to provide a storage solution such as cookies.
10640		 *  @type boolean
10641		 *  @default false
10642		 *
10643		 *  @dtopt Features
10644		 *  @name DataTable.defaults.stateSave
10645		 *
10646		 *  @example
10647		 *    $(document).ready( function () {
10648		 *      $('#example').dataTable( {
10649		 *        "stateSave": true
10650		 *      } );
10651		 *    } );
10652		 */
10653		"bStateSave": false,
10654	
10655	
10656		/**
10657		 * This function is called when a TR element is created (and all TD child
10658		 * elements have been inserted), or registered if using a DOM source, allowing
10659		 * manipulation of the TR element (adding classes etc).
10660		 *  @type function
10661		 *  @param {node} row "TR" element for the current row
10662		 *  @param {array} data Raw data array for this row
10663		 *  @param {int} dataIndex The index of this row in the internal aoData array
10664		 *
10665		 *  @dtopt Callbacks
10666		 *  @name DataTable.defaults.createdRow
10667		 *
10668		 *  @example
10669		 *    $(document).ready( function() {
10670		 *      $('#example').dataTable( {
10671		 *        "createdRow": function( row, data, dataIndex ) {
10672		 *          // Bold the grade for all 'A' grade browsers
10673		 *          if ( data[4] == "A" )
10674		 *          {
10675		 *            $('td:eq(4)', row).html( '<b>A</b>' );
10676		 *          }
10677		 *        }
10678		 *      } );
10679		 *    } );
10680		 */
10681		"fnCreatedRow": null,
10682	
10683	
10684		/**
10685		 * This function is called on every 'draw' event, and allows you to
10686		 * dynamically modify any aspect you want about the created DOM.
10687		 *  @type function
10688		 *  @param {object} settings DataTables settings object
10689		 *
10690		 *  @dtopt Callbacks
10691		 *  @name DataTable.defaults.drawCallback
10692		 *
10693		 *  @example
10694		 *    $(document).ready( function() {
10695		 *      $('#example').dataTable( {
10696		 *        "drawCallback": function( settings ) {
10697		 *          alert( 'DataTables has redrawn the table' );
10698		 *        }
10699		 *      } );
10700		 *    } );
10701		 */
10702		"fnDrawCallback": null,
10703	
10704	
10705		/**
10706		 * Identical to fnHeaderCallback() but for the table footer this function
10707		 * allows you to modify the table footer on every 'draw' event.
10708		 *  @type function
10709		 *  @param {node} foot "TR" element for the footer
10710		 *  @param {array} data Full table data (as derived from the original HTML)
10711		 *  @param {int} start Index for the current display starting point in the
10712		 *    display array
10713		 *  @param {int} end Index for the current display ending point in the
10714		 *    display array
10715		 *  @param {array int} display Index array to translate the visual position
10716		 *    to the full data array
10717		 *
10718		 *  @dtopt Callbacks
10719		 *  @name DataTable.defaults.footerCallback
10720		 *
10721		 *  @example
10722		 *    $(document).ready( function() {
10723		 *      $('#example').dataTable( {
10724		 *        "footerCallback": function( tfoot, data, start, end, display ) {
10725		 *          tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start;
10726		 *        }
10727		 *      } );
10728		 *    } )
10729		 */
10730		"fnFooterCallback": null,
10731	
10732	
10733		/**
10734		 * When rendering large numbers in the information element for the table
10735		 * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
10736		 * to have a comma separator for the 'thousands' units (e.g. 1 million is
10737		 * rendered as "1,000,000") to help readability for the end user. This
10738		 * function will override the default method DataTables uses.
10739		 *  @type function
10740		 *  @member
10741		 *  @param {int} toFormat number to be formatted
10742		 *  @returns {string} formatted string for DataTables to show the number
10743		 *
10744		 *  @dtopt Callbacks
10745		 *  @name DataTable.defaults.formatNumber
10746		 *
10747		 *  @example
10748		 *    // Format a number using a single quote for the separator (note that
10749		 *    // this can also be done with the language.thousands option)
10750		 *    $(document).ready( function() {
10751		 *      $('#example').dataTable( {
10752		 *        "formatNumber": function ( toFormat ) {
10753		 *          return toFormat.toString().replace(
10754		 *            /\B(?=(\d{3})+(?!\d))/g, "'"
10755		 *          );
10756		 *        };
10757		 *      } );
10758		 *    } );
10759		 */
10760		"fnFormatNumber": function ( toFormat ) {
10761			return toFormat.toString().replace(
10762				/\B(?=(\d{3})+(?!\d))/g,
10763				this.oLanguage.sThousands
10764			);
10765		},
10766	
10767	
10768		/**
10769		 * This function is called on every 'draw' event, and allows you to
10770		 * dynamically modify the header row. This can be used to calculate and
10771		 * display useful information about the table.
10772		 *  @type function
10773		 *  @param {node} head "TR" element for the header
10774		 *  @param {array} data Full table data (as derived from the original HTML)
10775		 *  @param {int} start Index for the current display starting point in the
10776		 *    display array
10777		 *  @param {int} end Index for the current display ending point in the
10778		 *    display array
10779		 *  @param {array int} display Index array to translate the visual position
10780		 *    to the full data array
10781		 *
10782		 *  @dtopt Callbacks
10783		 *  @name DataTable.defaults.headerCallback
10784		 *
10785		 *  @example
10786		 *    $(document).ready( function() {
10787		 *      $('#example').dataTable( {
10788		 *        "fheaderCallback": function( head, data, start, end, display ) {
10789		 *          head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records";
10790		 *        }
10791		 *      } );
10792		 *    } )
10793		 */
10794		"fnHeaderCallback": null,
10795	
10796	
10797		/**
10798		 * The information element can be used to convey information about the current
10799		 * state of the table. Although the internationalisation options presented by
10800		 * DataTables are quite capable of dealing with most customisations, there may
10801		 * be times where you wish to customise the string further. This callback
10802		 * allows you to do exactly that.
10803		 *  @type function
10804		 *  @param {object} oSettings DataTables settings object
10805		 *  @param {int} start Starting position in data for the draw
10806		 *  @param {int} end End position in data for the draw
10807		 *  @param {int} max Total number of rows in the table (regardless of
10808		 *    filtering)
10809		 *  @param {int} total Total number of rows in the data set, after filtering
10810		 *  @param {string} pre The string that DataTables has formatted using it's
10811		 *    own rules
10812		 *  @returns {string} The string to be displayed in the information element.
10813		 *
10814		 *  @dtopt Callbacks
10815		 *  @name DataTable.defaults.infoCallback
10816		 *
10817		 *  @example
10818		 *    $('#example').dataTable( {
10819		 *      "infoCallback": function( settings, start, end, max, total, pre ) {
10820		 *        return start +" to "+ end;
10821		 *      }
10822		 *    } );
10823		 */
10824		"fnInfoCallback": null,
10825	
10826	
10827		/**
10828		 * Called when the table has been initialised. Normally DataTables will
10829		 * initialise sequentially and there will be no need for this function,
10830		 * however, this does not hold true when using external language information
10831		 * since that is obtained using an async XHR call.
10832		 *  @type function
10833		 *  @param {object} settings DataTables settings object
10834		 *  @param {object} json The JSON object request from the server - only
10835		 *    present if client-side Ajax sourced data is used
10836		 *
10837		 *  @dtopt Callbacks
10838		 *  @name DataTable.defaults.initComplete
10839		 *
10840		 *  @example
10841		 *    $(document).ready( function() {
10842		 *      $('#example').dataTable( {
10843		 *        "initComplete": function(settings, json) {
10844		 *          alert( 'DataTables has finished its initialisation.' );
10845		 *        }
10846		 *      } );
10847		 *    } )
10848		 */
10849		"fnInitComplete": null,
10850	
10851	
10852		/**
10853		 * Called at the very start of each table draw and can be used to cancel the
10854		 * draw by returning false, any other return (including undefined) results in
10855		 * the full draw occurring).
10856		 *  @type function
10857		 *  @param {object} settings DataTables settings object
10858		 *  @returns {boolean} False will cancel the draw, anything else (including no
10859		 *    return) will allow it to complete.
10860		 *
10861		 *  @dtopt Callbacks
10862		 *  @name DataTable.defaults.preDrawCallback
10863		 *
10864		 *  @example
10865		 *    $(document).ready( function() {
10866		 *      $('#example').dataTable( {
10867		 *        "preDrawCallback": function( settings ) {
10868		 *          if ( $('#test').val() == 1 ) {
10869		 *            return false;
10870		 *          }
10871		 *        }
10872		 *      } );
10873		 *    } );
10874		 */
10875		"fnPreDrawCallback": null,
10876	
10877	
10878		/**
10879		 * This function allows you to 'post process' each row after it have been
10880		 * generated for each table draw, but before it is rendered on screen. This
10881		 * function might be used for setting the row class name etc.
10882		 *  @type function
10883		 *  @param {node} row "TR" element for the current row
10884		 *  @param {array} data Raw data array for this row
10885		 *  @param {int} displayIndex The display index for the current table draw
10886		 *  @param {int} displayIndexFull The index of the data in the full list of
10887		 *    rows (after filtering)
10888		 *
10889		 *  @dtopt Callbacks
10890		 *  @name DataTable.defaults.rowCallback
10891		 *
10892		 *  @example
10893		 *    $(document).ready( function() {
10894		 *      $('#example').dataTable( {
10895		 *        "rowCallback": function( row, data, displayIndex, displayIndexFull ) {
10896		 *          // Bold the grade for all 'A' grade browsers
10897		 *          if ( data[4] == "A" ) {
10898		 *            $('td:eq(4)', row).html( '<b>A</b>' );
10899		 *          }
10900		 *        }
10901		 *      } );
10902		 *    } );
10903		 */
10904		"fnRowCallback": null,
10905	
10906	
10907		/**
10908		 * __Deprecated__ The functionality provided by this parameter has now been
10909		 * superseded by that provided through `ajax`, which should be used instead.
10910		 *
10911		 * This parameter allows you to override the default function which obtains
10912		 * the data from the server so something more suitable for your application.
10913		 * For example you could use POST data, or pull information from a Gears or
10914		 * AIR database.
10915		 *  @type function
10916		 *  @member
10917		 *  @param {string} source HTTP source to obtain the data from (`ajax`)
10918		 *  @param {array} data A key/value pair object containing the data to send
10919		 *    to the server
10920		 *  @param {function} callback to be called on completion of the data get
10921		 *    process that will draw the data on the page.
10922		 *  @param {object} settings DataTables settings object
10923		 *
10924		 *  @dtopt Callbacks
10925		 *  @dtopt Server-side
10926		 *  @name DataTable.defaults.serverData
10927		 *
10928		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
10929		 */
10930		"fnServerData": null,
10931	
10932	
10933		/**
10934		 * __Deprecated__ The functionality provided by this parameter has now been
10935		 * superseded by that provided through `ajax`, which should be used instead.
10936		 *
10937		 *  It is often useful to send extra data to the server when making an Ajax
10938		 * request - for example custom filtering information, and this callback
10939		 * function makes it trivial to send extra information to the server. The
10940		 * passed in parameter is the data set that has been constructed by
10941		 * DataTables, and you can add to this or modify it as you require.
10942		 *  @type function
10943		 *  @param {array} data Data array (array of objects which are name/value
10944		 *    pairs) that has been constructed by DataTables and will be sent to the
10945		 *    server. In the case of Ajax sourced data with server-side processing
10946		 *    this will be an empty array, for server-side processing there will be a
10947		 *    significant number of parameters!
10948		 *  @returns {undefined} Ensure that you modify the data array passed in,
10949		 *    as this is passed by reference.
10950		 *
10951		 *  @dtopt Callbacks
10952		 *  @dtopt Server-side
10953		 *  @name DataTable.defaults.serverParams
10954		 *
10955		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
10956		 */
10957		"fnServerParams": null,
10958	
10959	
10960		/**
10961		 * Load the table state. With this function you can define from where, and how, the
10962		 * state of a table is loaded. By default DataTables will load from `localStorage`
10963		 * but you might wish to use a server-side database or cookies.
10964		 *  @type function
10965		 *  @member
10966		 *  @param {object} settings DataTables settings object
10967		 *  @param {object} callback Callback that can be executed when done. It
10968		 *    should be passed the loaded state object.
10969		 *  @return {object} The DataTables state object to be loaded
10970		 *
10971		 *  @dtopt Callbacks
10972		 *  @name DataTable.defaults.stateLoadCallback
10973		 *
10974		 *  @example
10975		 *    $(document).ready( function() {
10976		 *      $('#example').dataTable( {
10977		 *        "stateSave": true,
10978		 *        "stateLoadCallback": function (settings, callback) {
10979		 *          $.ajax( {
10980		 *            "url": "/state_load",
10981		 *            "dataType": "json",
10982		 *            "success": function (json) {
10983		 *              callback( json );
10984		 *            }
10985		 *          } );
10986		 *        }
10987		 *      } );
10988		 *    } );
10989		 */
10990		"fnStateLoadCallback": function ( settings ) {
10991			try {
10992				return JSON.parse(
10993					(settings.iStateDuration === -1 ? sessionStorage : localStorage).getItem(
10994						'DataTables_'+settings.sInstance+'_'+location.pathname
10995					)
10996				);
10997			} catch (e) {}
10998		},
10999	
11000	
11001		/**
11002		 * Callback which allows modification of the saved state prior to loading that state.
11003		 * This callback is called when the table is loading state from the stored data, but
11004		 * prior to the settings object being modified by the saved state. Note that for
11005		 * plug-in authors, you should use the `stateLoadParams` event to load parameters for
11006		 * a plug-in.
11007		 *  @type function
11008		 *  @param {object} settings DataTables settings object
11009		 *  @param {object} data The state object that is to be loaded
11010		 *
11011		 *  @dtopt Callbacks
11012		 *  @name DataTable.defaults.stateLoadParams
11013		 *
11014		 *  @example
11015		 *    // Remove a saved filter, so filtering is never loaded
11016		 *    $(document).ready( function() {
11017		 *      $('#example').dataTable( {
11018		 *        "stateSave": true,
11019		 *        "stateLoadParams": function (settings, data) {
11020		 *          data.oSearch.sSearch = "";
11021		 *        }
11022		 *      } );
11023		 *    } );
11024		 *
11025		 *  @example
11026		 *    // Disallow state loading by returning false
11027		 *    $(document).ready( function() {
11028		 *      $('#example').dataTable( {
11029		 *        "stateSave": true,
11030		 *        "stateLoadParams": function (settings, data) {
11031		 *          return false;
11032		 *        }
11033		 *      } );
11034		 *    } );
11035		 */
11036		"fnStateLoadParams": null,
11037	
11038	
11039		/**
11040		 * Callback that is called when the state has been loaded from the state saving method
11041		 * and the DataTables settings object has been modified as a result of the loaded state.
11042		 *  @type function
11043		 *  @param {object} settings DataTables settings object
11044		 *  @param {object} data The state object that was loaded
11045		 *
11046		 *  @dtopt Callbacks
11047		 *  @name DataTable.defaults.stateLoaded
11048		 *
11049		 *  @example
11050		 *    // Show an alert with the filtering value that was saved
11051		 *    $(document).ready( function() {
11052		 *      $('#example').dataTable( {
11053		 *        "stateSave": true,
11054		 *        "stateLoaded": function (settings, data) {
11055		 *          alert( 'Saved filter was: '+data.oSearch.sSearch );
11056		 *        }
11057		 *      } );
11058		 *    } );
11059		 */
11060		"fnStateLoaded": null,
11061	
11062	
11063		/**
11064		 * Save the table state. This function allows you to define where and how the state
11065		 * information for the table is stored By default DataTables will use `localStorage`
11066		 * but you might wish to use a server-side database or cookies.
11067		 *  @type function
11068		 *  @member
11069		 *  @param {object} settings DataTables settings object
11070		 *  @param {object} data The state object to be saved
11071		 *
11072		 *  @dtopt Callbacks
11073		 *  @name DataTable.defaults.stateSaveCallback
11074		 *
11075		 *  @example
11076		 *    $(document).ready( function() {
11077		 *      $('#example').dataTable( {
11078		 *        "stateSave": true,
11079		 *        "stateSaveCallback": function (settings, data) {
11080		 *          // Send an Ajax request to the server with the state object
11081		 *          $.ajax( {
11082		 *            "url": "/state_save",
11083		 *            "data": data,
11084		 *            "dataType": "json",
11085		 *            "method": "POST"
11086		 *            "success": function () {}
11087		 *          } );
11088		 *        }
11089		 *      } );
11090		 *    } );
11091		 */
11092		"fnStateSaveCallback": function ( settings, data ) {
11093			try {
11094				(settings.iStateDuration === -1 ? sessionStorage : localStorage).setItem(
11095					'DataTables_'+settings.sInstance+'_'+location.pathname,
11096					JSON.stringify( data )
11097				);
11098			} catch (e) {}
11099		},
11100	
11101	
11102		/**
11103		 * Callback which allows modification of the state to be saved. Called when the table
11104		 * has changed state a new state save is required. This method allows modification of
11105		 * the state saving object prior to actually doing the save, including addition or
11106		 * other state properties or modification. Note that for plug-in authors, you should
11107		 * use the `stateSaveParams` event to save parameters for a plug-in.
11108		 *  @type function
11109		 *  @param {object} settings DataTables settings object
11110		 *  @param {object} data The state object to be saved
11111		 *
11112		 *  @dtopt Callbacks
11113		 *  @name DataTable.defaults.stateSaveParams
11114		 *
11115		 *  @example
11116		 *    // Remove a saved filter, so filtering is never saved
11117		 *    $(document).ready( function() {
11118		 *      $('#example').dataTable( {
11119		 *        "stateSave": true,
11120		 *        "stateSaveParams": function (settings, data) {
11121		 *          data.oSearch.sSearch = "";
11122		 *        }
11123		 *      } );
11124		 *    } );
11125		 */
11126		"fnStateSaveParams": null,
11127	
11128	
11129		/**
11130		 * Duration for which the saved state information is considered valid. After this period
11131		 * has elapsed the state will be returned to the default.
11132		 * Value is given in seconds.
11133		 *  @type int
11134		 *  @default 7200 <i>(2 hours)</i>
11135		 *
11136		 *  @dtopt Options
11137		 *  @name DataTable.defaults.stateDuration
11138		 *
11139		 *  @example
11140		 *    $(document).ready( function() {
11141		 *      $('#example').dataTable( {
11142		 *        "stateDuration": 60*60*24; // 1 day
11143		 *      } );
11144		 *    } )
11145		 */
11146		"iStateDuration": 7200,
11147	
11148	
11149		/**
11150		 * When enabled DataTables will not make a request to the server for the first
11151		 * page draw - rather it will use the data already on the page (no sorting etc
11152		 * will be applied to it), thus saving on an XHR at load time. `deferLoading`
11153		 * is used to indicate that deferred loading is required, but it is also used
11154		 * to tell DataTables how many records there are in the full table (allowing
11155		 * the information element and pagination to be displayed correctly). In the case
11156		 * where a filtering is applied to the table on initial load, this can be
11157		 * indicated by giving the parameter as an array, where the first element is
11158		 * the number of records available after filtering and the second element is the
11159		 * number of records without filtering (allowing the table information element
11160		 * to be shown correctly).
11161		 *  @type int | array
11162		 *  @default null
11163		 *
11164		 *  @dtopt Options
11165		 *  @name DataTable.defaults.deferLoading
11166		 *
11167		 *  @example
11168		 *    // 57 records available in the table, no filtering applied
11169		 *    $(document).ready( function() {
11170		 *      $('#example').dataTable( {
11171		 *        "serverSide": true,
11172		 *        "ajax": "scripts/server_processing.php",
11173		 *        "deferLoading": 57
11174		 *      } );
11175		 *    } );
11176		 *
11177		 *  @example
11178		 *    // 57 records after filtering, 100 without filtering (an initial filter applied)
11179		 *    $(document).ready( function() {
11180		 *      $('#example').dataTable( {
11181		 *        "serverSide": true,
11182		 *        "ajax": "scripts/server_processing.php",
11183		 *        "deferLoading": [ 57, 100 ],
11184		 *        "search": {
11185		 *          "search": "my_filter"
11186		 *        }
11187		 *      } );
11188		 *    } );
11189		 */
11190		"iDeferLoading": null,
11191	
11192	
11193		/**
11194		 * Number of rows to display on a single page when using pagination. If
11195		 * feature enabled (`lengthChange`) then the end user will be able to override
11196		 * this to a custom setting using a pop-up menu.
11197		 *  @type int
11198		 *  @default 10
11199		 *
11200		 *  @dtopt Options
11201		 *  @name DataTable.defaults.pageLength
11202		 *
11203		 *  @example
11204		 *    $(document).ready( function() {
11205		 *      $('#example').dataTable( {
11206		 *        "pageLength": 50
11207		 *      } );
11208		 *    } )
11209		 */
11210		"iDisplayLength": 10,
11211	
11212	
11213		/**
11214		 * Define the starting point for data display when using DataTables with
11215		 * pagination. Note that this parameter is the number of records, rather than
11216		 * the page number, so if you have 10 records per page and want to start on
11217		 * the third page, it should be "20".
11218		 *  @type int
11219		 *  @default 0
11220		 *
11221		 *  @dtopt Options
11222		 *  @name DataTable.defaults.displayStart
11223		 *
11224		 *  @example
11225		 *    $(document).ready( function() {
11226		 *      $('#example').dataTable( {
11227		 *        "displayStart": 20
11228		 *      } );
11229		 *    } )
11230		 */
11231		"iDisplayStart": 0,
11232	
11233	
11234		/**
11235		 * By default DataTables allows keyboard navigation of the table (sorting, paging,
11236		 * and filtering) by adding a `tabindex` attribute to the required elements. This
11237		 * allows you to tab through the controls and press the enter key to activate them.
11238		 * The tabindex is default 0, meaning that the tab follows the flow of the document.
11239		 * You can overrule this using this parameter if you wish. Use a value of -1 to
11240		 * disable built-in keyboard navigation.
11241		 *  @type int
11242		 *  @default 0
11243		 *
11244		 *  @dtopt Options
11245		 *  @name DataTable.defaults.tabIndex
11246		 *
11247		 *  @example
11248		 *    $(document).ready( function() {
11249		 *      $('#example').dataTable( {
11250		 *        "tabIndex": 1
11251		 *      } );
11252		 *    } );
11253		 */
11254		"iTabIndex": 0,
11255	
11256	
11257		/**
11258		 * Classes that DataTables assigns to the various components and features
11259		 * that it adds to the HTML table. This allows classes to be configured
11260		 * during initialisation in addition to through the static
11261		 * {@link DataTable.ext.oStdClasses} object).
11262		 *  @namespace
11263		 *  @name DataTable.defaults.classes
11264		 */
11265		"oClasses": {},
11266	
11267	
11268		/**
11269		 * All strings that DataTables uses in the user interface that it creates
11270		 * are defined in this object, allowing you to modified them individually or
11271		 * completely replace them all as required.
11272		 *  @namespace
11273		 *  @name DataTable.defaults.language
11274		 */
11275		"oLanguage": {
11276			/**
11277			 * Strings that are used for WAI-ARIA labels and controls only (these are not
11278			 * actually visible on the page, but will be read by screenreaders, and thus
11279			 * must be internationalised as well).
11280			 *  @namespace
11281			 *  @name DataTable.defaults.language.aria
11282			 */
11283			"oAria": {
11284				/**
11285				 * ARIA label that is added to the table headers when the column may be
11286				 * sorted ascending by activing the column (click or return when focused).
11287				 * Note that the column header is prefixed to this string.
11288				 *  @type string
11289				 *  @default : activate to sort column ascending
11290				 *
11291				 *  @dtopt Language
11292				 *  @name DataTable.defaults.language.aria.sortAscending
11293				 *
11294				 *  @example
11295				 *    $(document).ready( function() {
11296				 *      $('#example').dataTable( {
11297				 *        "language": {
11298				 *          "aria": {
11299				 *            "sortAscending": " - click/return to sort ascending"
11300				 *          }
11301				 *        }
11302				 *      } );
11303				 *    } );
11304				 */
11305				"sSortAscending": ": activate to sort column ascending",
11306	
11307				/**
11308				 * ARIA label that is added to the table headers when the column may be
11309				 * sorted descending by activing the column (click or return when focused).
11310				 * Note that the column header is prefixed to this string.
11311				 *  @type string
11312				 *  @default : activate to sort column ascending
11313				 *
11314				 *  @dtopt Language
11315				 *  @name DataTable.defaults.language.aria.sortDescending
11316				 *
11317				 *  @example
11318				 *    $(document).ready( function() {
11319				 *      $('#example').dataTable( {
11320				 *        "language": {
11321				 *          "aria": {
11322				 *            "sortDescending": " - click/return to sort descending"
11323				 *          }
11324				 *        }
11325				 *      } );
11326				 *    } );
11327				 */
11328				"sSortDescending": ": activate to sort column descending"
11329			},
11330	
11331			/**
11332			 * Pagination string used by DataTables for the built-in pagination
11333			 * control types.
11334			 *  @namespace
11335			 *  @name DataTable.defaults.language.paginate
11336			 */
11337			"oPaginate": {
11338				/**
11339				 * Text to use when using the 'full_numbers' type of pagination for the
11340				 * button to take the user to the first page.
11341				 *  @type string
11342				 *  @default First
11343				 *
11344				 *  @dtopt Language
11345				 *  @name DataTable.defaults.language.paginate.first
11346				 *
11347				 *  @example
11348				 *    $(document).ready( function() {
11349				 *      $('#example').dataTable( {
11350				 *        "language": {
11351				 *          "paginate": {
11352				 *            "first": "First page"
11353				 *          }
11354				 *        }
11355				 *      } );
11356				 *    } );
11357				 */
11358				"sFirst": "First",
11359	
11360	
11361				/**
11362				 * Text to use when using the 'full_numbers' type of pagination for the
11363				 * button to take the user to the last page.
11364				 *  @type string
11365				 *  @default Last
11366				 *
11367				 *  @dtopt Language
11368				 *  @name DataTable.defaults.language.paginate.last
11369				 *
11370				 *  @example
11371				 *    $(document).ready( function() {
11372				 *      $('#example').dataTable( {
11373				 *        "language": {
11374				 *          "paginate": {
11375				 *            "last": "Last page"
11376				 *          }
11377				 *        }
11378				 *      } );
11379				 *    } );
11380				 */
11381				"sLast": "Last",
11382	
11383	
11384				/**
11385				 * Text to use for the 'next' pagination button (to take the user to the
11386				 * next page).
11387				 *  @type string
11388				 *  @default Next
11389				 *
11390				 *  @dtopt Language
11391				 *  @name DataTable.defaults.language.paginate.next
11392				 *
11393				 *  @example
11394				 *    $(document).ready( function() {
11395				 *      $('#example').dataTable( {
11396				 *        "language": {
11397				 *          "paginate": {
11398				 *            "next": "Next page"
11399				 *          }
11400				 *        }
11401				 *      } );
11402				 *    } );
11403				 */
11404				"sNext": "Next",
11405	
11406	
11407				/**
11408				 * Text to use for the 'previous' pagination button (to take the user to
11409				 * the previous page).
11410				 *  @type string
11411				 *  @default Previous
11412				 *
11413				 *  @dtopt Language
11414				 *  @name DataTable.defaults.language.paginate.previous
11415				 *
11416				 *  @example
11417				 *    $(document).ready( function() {
11418				 *      $('#example').dataTable( {
11419				 *        "language": {
11420				 *          "paginate": {
11421				 *            "previous": "Previous page"
11422				 *          }
11423				 *        }
11424				 *      } );
11425				 *    } );
11426				 */
11427				"sPrevious": "Previous"
11428			},
11429	
11430			/**
11431			 * This string is shown in preference to `zeroRecords` when the table is
11432			 * empty of data (regardless of filtering). Note that this is an optional
11433			 * parameter - if it is not given, the value of `zeroRecords` will be used
11434			 * instead (either the default or given value).
11435			 *  @type string
11436			 *  @default No data available in table
11437			 *
11438			 *  @dtopt Language
11439			 *  @name DataTable.defaults.language.emptyTable
11440			 *
11441			 *  @example
11442			 *    $(document).ready( function() {
11443			 *      $('#example').dataTable( {
11444			 *        "language": {
11445			 *          "emptyTable": "No data available in table"
11446			 *        }
11447			 *      } );
11448			 *    } );
11449			 */
11450			"sEmptyTable": "No data available in table",
11451	
11452	
11453			/**
11454			 * This string gives information to the end user about the information
11455			 * that is current on display on the page. The following tokens can be
11456			 * used in the string and will be dynamically replaced as the table
11457			 * display updates. This tokens can be placed anywhere in the string, or
11458			 * removed as needed by the language requires:
11459			 *
11460			 * * `\_START\_` - Display index of the first record on the current page
11461			 * * `\_END\_` - Display index of the last record on the current page
11462			 * * `\_TOTAL\_` - Number of records in the table after filtering
11463			 * * `\_MAX\_` - Number of records in the table without filtering
11464			 * * `\_PAGE\_` - Current page number
11465			 * * `\_PAGES\_` - Total number of pages of data in the table
11466			 *
11467			 *  @type string
11468			 *  @default Showing _START_ to _END_ of _TOTAL_ entries
11469			 *
11470			 *  @dtopt Language
11471			 *  @name DataTable.defaults.language.info
11472			 *
11473			 *  @example
11474			 *    $(document).ready( function() {
11475			 *      $('#example').dataTable( {
11476			 *        "language": {
11477			 *          "info": "Showing page _PAGE_ of _PAGES_"
11478			 *        }
11479			 *      } );
11480			 *    } );
11481			 */
11482			"sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
11483	
11484	
11485			/**
11486			 * Display information string for when the table is empty. Typically the
11487			 * format of this string should match `info`.
11488			 *  @type string
11489			 *  @default Showing 0 to 0 of 0 entries
11490			 *
11491			 *  @dtopt Language
11492			 *  @name DataTable.defaults.language.infoEmpty
11493			 *
11494			 *  @example
11495			 *    $(document).ready( function() {
11496			 *      $('#example').dataTable( {
11497			 *        "language": {
11498			 *          "infoEmpty": "No entries to show"
11499			 *        }
11500			 *      } );
11501			 *    } );
11502			 */
11503			"sInfoEmpty": "Showing 0 to 0 of 0 entries",
11504	
11505	
11506			/**
11507			 * When a user filters the information in a table, this string is appended
11508			 * to the information (`info`) to give an idea of how strong the filtering
11509			 * is. The variable _MAX_ is dynamically updated.
11510			 *  @type string
11511			 *  @default (filtered from _MAX_ total entries)
11512			 *
11513			 *  @dtopt Language
11514			 *  @name DataTable.defaults.language.infoFiltered
11515			 *
11516			 *  @example
11517			 *    $(document).ready( function() {
11518			 *      $('#example').dataTable( {
11519			 *        "language": {
11520			 *          "infoFiltered": " - filtering from _MAX_ records"
11521			 *        }
11522			 *      } );
11523			 *    } );
11524			 */
11525			"sInfoFiltered": "(filtered from _MAX_ total entries)",
11526	
11527	
11528			/**
11529			 * If can be useful to append extra information to the info string at times,
11530			 * and this variable does exactly that. This information will be appended to
11531			 * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are
11532			 * being used) at all times.
11533			 *  @type string
11534			 *  @default <i>Empty string</i>
11535			 *
11536			 *  @dtopt Language
11537			 *  @name DataTable.defaults.language.infoPostFix
11538			 *
11539			 *  @example
11540			 *    $(document).ready( function() {
11541			 *      $('#example').dataTable( {
11542			 *        "language": {
11543			 *          "infoPostFix": "All records shown are derived from real information."
11544			 *        }
11545			 *      } );
11546			 *    } );
11547			 */
11548			"sInfoPostFix": "",
11549	
11550	
11551			/**
11552			 * This decimal place operator is a little different from the other
11553			 * language options since DataTables doesn't output floating point
11554			 * numbers, so it won't ever use this for display of a number. Rather,
11555			 * what this parameter does is modify the sort methods of the table so
11556			 * that numbers which are in a format which has a character other than
11557			 * a period (`.`) as a decimal place will be sorted numerically.
11558			 *
11559			 * Note that numbers with different decimal places cannot be shown in
11560			 * the same table and still be sortable, the table must be consistent.
11561			 * However, multiple different tables on the page can use different
11562			 * decimal place characters.
11563			 *  @type string
11564			 *  @default 
11565			 *
11566			 *  @dtopt Language
11567			 *  @name DataTable.defaults.language.decimal
11568			 *
11569			 *  @example
11570			 *    $(document).ready( function() {
11571			 *      $('#example').dataTable( {
11572			 *        "language": {
11573			 *          "decimal": ","
11574			 *          "thousands": "."
11575			 *        }
11576			 *      } );
11577			 *    } );
11578			 */
11579			"sDecimal": "",
11580	
11581	
11582			/**
11583			 * DataTables has a build in number formatter (`formatNumber`) which is
11584			 * used to format large numbers that are used in the table information.
11585			 * By default a comma is used, but this can be trivially changed to any
11586			 * character you wish with this parameter.
11587			 *  @type string
11588			 *  @default ,
11589			 *
11590			 *  @dtopt Language
11591			 *  @name DataTable.defaults.language.thousands
11592			 *
11593			 *  @example
11594			 *    $(document).ready( function() {
11595			 *      $('#example').dataTable( {
11596			 *        "language": {
11597			 *          "thousands": "'"
11598			 *        }
11599			 *      } );
11600			 *    } );
11601			 */
11602			"sThousands": ",",
11603	
11604	
11605			/**
11606			 * Detail the action that will be taken when the drop down menu for the
11607			 * pagination length option is changed. The '_MENU_' variable is replaced
11608			 * with a default select list of 10, 25, 50 and 100, and can be replaced
11609			 * with a custom select box if required.
11610			 *  @type string
11611			 *  @default Show _MENU_ entries
11612			 *
11613			 *  @dtopt Language
11614			 *  @name DataTable.defaults.language.lengthMenu
11615			 *
11616			 *  @example
11617			 *    // Language change only
11618			 *    $(document).ready( function() {
11619			 *      $('#example').dataTable( {
11620			 *        "language": {
11621			 *          "lengthMenu": "Display _MENU_ records"
11622			 *        }
11623			 *      } );
11624			 *    } );
11625			 *
11626			 *  @example
11627			 *    // Language and options change
11628			 *    $(document).ready( function() {
11629			 *      $('#example').dataTable( {
11630			 *        "language": {
11631			 *          "lengthMenu": 'Display <select>'+
11632			 *            '<option value="10">10</option>'+
11633			 *            '<option value="20">20</option>'+
11634			 *            '<option value="30">30</option>'+
11635			 *            '<option value="40">40</option>'+
11636			 *            '<option value="50">50</option>'+
11637			 *            '<option value="-1">All</option>'+
11638			 *            '</select> records'
11639			 *        }
11640			 *      } );
11641			 *    } );
11642			 */
11643			"sLengthMenu": "Show _MENU_ entries",
11644	
11645	
11646			/**
11647			 * When using Ajax sourced data and during the first draw when DataTables is
11648			 * gathering the data, this message is shown in an empty row in the table to
11649			 * indicate to the end user the the data is being loaded. Note that this
11650			 * parameter is not used when loading data by server-side processing, just
11651			 * Ajax sourced data with client-side processing.
11652			 *  @type string
11653			 *  @default Loading...
11654			 *
11655			 *  @dtopt Language
11656			 *  @name DataTable.defaults.language.loadingRecords
11657			 *
11658			 *  @example
11659			 *    $(document).ready( function() {
11660			 *      $('#example').dataTable( {
11661			 *        "language": {
11662			 *          "loadingRecords": "Please wait - loading..."
11663			 *        }
11664			 *      } );
11665			 *    } );
11666			 */
11667			"sLoadingRecords": "Loading...",
11668	
11669	
11670			/**
11671			 * Text which is displayed when the table is processing a user action
11672			 * (usually a sort command or similar).
11673			 *  @type string
11674			 *
11674  @default Processing...
11675			 *
11676			 *  @dtopt Language
11677			 *  @name DataTable.defaults.language.processing
11678			 *
11679			 *  @example
11680			 *    $(document).ready( function() {
11681			 *      $('#example').dataTable( {
11682			 *        "language": {
11683			 *          "processing": "DataTables is currently busy"
11684			 *        }
11685			 *      } );
11686			 *    } );
11687			 */
11688			"sProcessing": "Processing...
vendor: 42,942 bytes, lines 11688-12982
11688",
11689	
11690	
11691			/**
11692			 * Details the actions that will be taken when the user types into the
11693			 * filtering input text box. The variable "_INPUT_", if used in the string,
11694			 * is replaced with the HTML text box for the filtering input allowing
11695			 * control over where it appears in the string. If "_INPUT_" is not given
11696			 * then the input box is appended to the string automatically.
11697			 *  @type string
11698			 *  @default Search:
11699			 *
11700			 *  @dtopt Language
11701			 *  @name DataTable.defaults.language.search
11702			 *
11703			 *  @example
11704			 *    // Input text box will be appended at the end automatically
11705			 *    $(document).ready( function() {
11706			 *      $('#example').dataTable( {
11707			 *        "language": {
11708			 *          "search": "Filter records:"
11709			 *        }
11710			 *      } );
11711			 *    } );
11712			 *
11713			 *  @example
11714			 *    // Specify where the filter should appear
11715			 *    $(document).ready( function() {
11716			 *      $('#example').dataTable( {
11717			 *        "language": {
11718			 *          "search": "Apply filter _INPUT_ to table"
11719			 *        }
11720			 *      } );
11721			 *    } );
11722			 */
11723			"sSearch": "Search:",
11724	
11725	
11726			/**
11727			 * Assign a `placeholder` attribute to the search `input` element
11728			 *  @type string
11729			 *  @default 
11730			 *
11731			 *  @dtopt Language
11732			 *  @name DataTable.defaults.language.searchPlaceholder
11733			 */
11734			"sSearchPlaceholder": "",
11735	
11736	
11737			/**
11738			 * All of the language information can be stored in a file on the
11739			 * server-side, which DataTables will look up if this parameter is passed.
11740			 * It must store the URL of the language file, which is in a JSON format,
11741			 * and the object has the same properties as the oLanguage object in the
11742			 * initialiser object (i.e. the above parameters). Please refer to one of
11743			 * the example language files to see how this works in action.
11744			 *  @type string
11745			 *  @default <i>Empty string - i.e. disabled</i>
11746			 *
11747			 *  @dtopt Language
11748			 *  @name DataTable.defaults.language.url
11749			 *
11750			 *  @example
11751			 *    $(document).ready( function() {
11752			 *      $('#example').dataTable( {
11753			 *        "language": {
11754			 *          "url": "http://www.sprymedia.co.uk/dataTables/lang.txt"
11755			 *        }
11756			 *      } );
11757			 *    } );
11758			 */
11759			"sUrl": "",
11760	
11761	
11762			/**
11763			 * Text shown inside the table records when the is no information to be
11764			 * displayed after filtering. `emptyTable` is shown when there is simply no
11765			 * information in the table at all (regardless of filtering).
11766			 *  @type string
11767			 *  @default No matching records found
11768			 *
11769			 *  @dtopt Language
11770			 *  @name DataTable.defaults.language.zeroRecords
11771			 *
11772			 *  @example
11773			 *    $(document).ready( function() {
11774			 *      $('#example').dataTable( {
11775			 *        "language": {
11776			 *          "zeroRecords": "No records to display"
11777			 *        }
11778			 *      } );
11779			 *    } );
11780			 */
11781			"sZeroRecords": "No matching records found"
11782		},
11783	
11784	
11785		/**
11786		 * This parameter allows you to have define the global filtering state at
11787		 * initialisation time. As an object the `search` parameter must be
11788		 * defined, but all other parameters are optional. When `regex` is true,
11789		 * the search string will be treated as a regular expression, when false
11790		 * (default) it will be treated as a straight string. When `smart`
11791		 * DataTables will use it's smart filtering methods (to word match at
11792		 * any point in the data), when false this will not be done.
11793		 *  @namespace
11794		 *  @extends DataTable.models.oSearch
11795		 *
11796		 *  @dtopt Options
11797		 *  @name DataTable.defaults.search
11798		 *
11799		 *  @example
11800		 *    $(document).ready( function() {
11801		 *      $('#example').dataTable( {
11802		 *        "search": {"search": "Initial search"}
11803		 *      } );
11804		 *    } )
11805		 */
11806		"oSearch": $.extend( {}, DataTable.models.oSearch ),
11807	
11808	
11809		/**
11810		 * __Deprecated__ The functionality provided by this parameter has now been
11811		 * superseded by that provided through `ajax`, which should be used instead.
11812		 *
11813		 * By default DataTables will look for the property `data` (or `aaData` for
11814		 * compatibility with DataTables 1.9-) when obtaining data from an Ajax
11815		 * source or for server-side processing - this parameter allows that
11816		 * property to be changed. You can use Javascript dotted object notation to
11817		 * get a data source for multiple levels of nesting.
11818		 *  @type string
11819		 *  @default data
11820		 *
11821		 *  @dtopt Options
11822		 *  @dtopt Server-side
11823		 *  @name DataTable.defaults.ajaxDataProp
11824		 *
11825		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11826		 */
11827		"sAjaxDataProp": "data",
11828	
11829	
11830		/**
11831		 * __Deprecated__ The functionality provided by this parameter has now been
11832		 * superseded by that provided through `ajax`, which should be used instead.
11833		 *
11834		 * You can instruct DataTables to load data from an external
11835		 * source using this parameter (use aData if you want to pass data in you
11836		 * already have). Simply provide a url a JSON object can be obtained from.
11837		 *  @type string
11838		 *  @default null
11839		 *
11840		 *  @dtopt Options
11841		 *  @dtopt Server-side
11842		 *  @name DataTable.defaults.ajaxSource
11843		 *
11844		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11845		 */
11846		"sAjaxSource": null,
11847	
11848	
11849		/**
11850		 * This initialisation variable allows you to specify exactly where in the
11851		 * DOM you want DataTables to inject the various controls it adds to the page
11852		 * (for example you might want the pagination controls at the top of the
11853		 * table). DIV elements (with or without a custom class) can also be added to
11854		 * aid styling. The follow syntax is used:
11855		 *   <ul>
11856		 *     <li>The following options are allowed:
11857		 *       <ul>
11858		 *         <li>'l' - Length changing</li>
11859		 *         <li>'f' - Filtering input</li>
11860		 *         <li>'t' - The table!</li>
11861		 *         <li>'i' - Information</li>
11862		 *         <li>'p' - Pagination</li>
11863		 *         <li>'r' - pRocessing</li>
11864		 *       </ul>
11865		 *     </li>
11866		 *     <li>The following constants are allowed:
11867		 *       <ul>
11868		 *         <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>
11869		 *         <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>
11870		 *       </ul>
11871		 *     </li>
11872		 *     <li>The following syntax is expected:
11873		 *       <ul>
11874		 *         <li>'&lt;' and '&gt;' - div elements</li>
11875		 *         <li>'&lt;"class" and '&gt;' - div with a class</li>
11876		 *         <li>'&lt;"#id" and '&gt;' - div with an ID</li>
11877		 *       </ul>
11878		 *     </li>
11879		 *     <li>Examples:
11880		 *       <ul>
11881		 *         <li>'&lt;"wrapper"flipt&gt;'</li>
11882		 *         <li>'&lt;lf&lt;t&gt;ip&gt;'</li>
11883		 *       </ul>
11884		 *     </li>
11885		 *   </ul>
11886		 *  @type string
11887		 *  @default lfrtip <i>(when `jQueryUI` is false)</i> <b>or</b>
11888		 *    <"H"lfr>t<"F"ip> <i>(when `jQueryUI` is true)</i>
11889		 *
11890		 *  @dtopt Options
11891		 *  @name DataTable.defaults.dom
11892		 *
11893		 *  @example
11894		 *    $(document).ready( function() {
11895		 *      $('#example').dataTable( {
11896		 *        "dom": '&lt;"top"i&gt;rt&lt;"bottom"flp&gt;&lt;"clear"&gt;'
11897		 *      } );
11898		 *    } );
11899		 */
11900		"sDom": "lfrtip",
11901	
11902	
11903		/**
11904		 * Search delay option. This will throttle full table searches that use the
11905		 * DataTables provided search input element (it does not effect calls to
11906		 * `dt-api search()`, providing a delay before the search is made.
11907		 *  @type integer
11908		 *  @default 0
11909		 *
11910		 *  @dtopt Options
11911		 *  @name DataTable.defaults.searchDelay
11912		 *
11913		 *  @example
11914		 *    $(document).ready( function() {
11915		 *      $('#example').dataTable( {
11916		 *        "searchDelay": 200
11917		 *      } );
11918		 *    } )
11919		 */
11920		"searchDelay": null,
11921	
11922	
11923		/**
11924		 * DataTables features six different built-in options for the buttons to
11925		 * display for pagination control:
11926		 *
11927		 * * `numbers` - Page number buttons only
11928		 * * `simple` - 'Previous' and 'Next' buttons only
11929		 * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers
11930		 * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons
11931		 * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus page numbers
11932		 * * `first_last_numbers` - 'First' and 'Last' buttons, plus page numbers
11933		 *  
11934		 * Further methods can be added using {@link DataTable.ext.oPagination}.
11935		 *  @type string
11936		 *  @default simple_numbers
11937		 *
11938		 *  @dtopt Options
11939		 *  @name DataTable.defaults.pagingType
11940		 *
11941		 *  @example
11942		 *    $(document).ready( function() {
11943		 *      $('#example').dataTable( {
11944		 *        "pagingType": "full_numbers"
11945		 *      } );
11946		 *    } )
11947		 */
11948		"sPaginationType": "simple_numbers",
11949	
11950	
11951		/**
11952		 * Enable horizontal scrolling. When a table is too wide to fit into a
11953		 * certain layout, or you have a large number of columns in the table, you
11954		 * can enable x-scrolling to show the table in a viewport, which can be
11955		 * scrolled. This property can be `true` which will allow the table to
11956		 * scroll horizontally when needed, or any CSS unit, or a number (in which
11957		 * case it will be treated as a pixel measurement). Setting as simply `true`
11958		 * is recommended.
11959		 *  @type boolean|string
11960		 *  @default <i>blank string - i.e. disabled</i>
11961		 *
11962		 *  @dtopt Features
11963		 *  @name DataTable.defaults.scrollX
11964		 *
11965		 *  @example
11966		 *    $(document).ready( function() {
11967		 *      $('#example').dataTable( {
11968		 *        "scrollX": true,
11969		 *        "scrollCollapse": true
11970		 *      } );
11971		 *    } );
11972		 */
11973		"sScrollX": "",
11974	
11975	
11976		/**
11977		 * This property can be used to force a DataTable to use more width than it
11978		 * might otherwise do when x-scrolling is enabled. For example if you have a
11979		 * table which requires to be well spaced, this parameter is useful for
11980		 * "over-sizing" the table, and thus forcing scrolling. This property can by
11981		 * any CSS unit, or a number (in which case it will be treated as a pixel
11982		 * measurement).
11983		 *  @type string
11984		 *  @default <i>blank string - i.e. disabled</i>
11985		 *
11986		 *  @dtopt Options
11987		 *  @name DataTable.defaults.scrollXInner
11988		 *
11989		 *  @example
11990		 *    $(document).ready( function() {
11991		 *      $('#example').dataTable( {
11992		 *        "scrollX": "100%",
11993		 *        "scrollXInner": "110%"
11994		 *      } );
11995		 *    } );
11996		 */
11997		"sScrollXInner": "",
11998	
11999	
12000		/**
12001		 * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
12002		 * to the given height, and enable scrolling for any data which overflows the
12003		 * current viewport. This can be used as an alternative to paging to display
12004		 * a lot of data in a small area (although paging and scrolling can both be
12005		 * enabled at the same time). This property can be any CSS unit, or a number
12006		 * (in which case it will be treated as a pixel measurement).
12007		 *  @type string
12008		 *  @default <i>blank string - i.e. disabled</i>
12009		 *
12010		 *  @dtopt Features
12011		 *  @name DataTable.defaults.scrollY
12012		 *
12013		 *  @example
12014		 *    $(document).ready( function() {
12015		 *      $('#example').dataTable( {
12016		 *        "scrollY": "200px",
12017		 *        "paginate": false
12018		 *      } );
12019		 *    } );
12020		 */
12021		"sScrollY": "",
12022	
12023	
12024		/**
12025		 * __Deprecated__ The functionality provided by this parameter has now been
12026		 * superseded by that provided through `ajax`, which should be used instead.
12027		 *
12028		 * Set the HTTP method that is used to make the Ajax call for server-side
12029		 * processing or Ajax sourced data.
12030		 *  @type string
12031		 *  @default GET
12032		 *
12033		 *  @dtopt Options
12034		 *  @dtopt Server-side
12035		 *  @name DataTable.defaults.serverMethod
12036		 *
12037		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
12038		 */
12039		"sServerMethod": "GET",
12040	
12041	
12042		/**
12043		 * DataTables makes use of renderers when displaying HTML elements for
12044		 * a table. These renderers can be added or modified by plug-ins to
12045		 * generate suitable mark-up for a site. For example the Bootstrap
12046		 * integration plug-in for DataTables uses a paging button renderer to
12047		 * display pagination buttons in the mark-up required by Bootstrap.
12048		 *
12049		 * For further information about the renderers available see
12050		 * DataTable.ext.renderer
12051		 *  @type string|object
12052		 *  @default null
12053		 *
12054		 *  @name DataTable.defaults.renderer
12055		 *
12056		 */
12057		"renderer": null,
12058	
12059	
12060		/**
12061		 * Set the data property name that DataTables should use to get a row's id
12062		 * to set as the `id` property in the node.
12063		 *  @type string
12064		 *  @default DT_RowId
12065		 *
12066		 *  @name DataTable.defaults.rowId
12067		 */
12068		"rowId": "DT_RowId"
12069	};
12070	
12071	_fnHungarianMap( DataTable.defaults );
12072	
12073	
12074	
12075	/*
12076	 * Developer note - See note in model.defaults.js about the use of Hungarian
12077	 * notation and camel case.
12078	 */
12079	
12080	/**
12081	 * Column options that can be given to DataTables at initialisation time.
12082	 *  @namespace
12083	 */
12084	DataTable.defaults.column = {
12085		/**
12086		 * Define which column(s) an order will occur on for this column. This
12087		 * allows a column's ordering to take multiple columns into account when
12088		 * doing a sort or use the data from a different column. For example first
12089		 * name / last name columns make sense to do a multi-column sort over the
12090		 * two columns.
12091		 *  @type array|int
12092		 *  @default null <i>Takes the value of the column index automatically</i>
12093		 *
12094		 *  @name DataTable.defaults.column.orderData
12095		 *  @dtopt Columns
12096		 *
12097		 *  @example
12098		 *    // Using `columnDefs`
12099		 *    $(document).ready( function() {
12100		 *      $('#example').dataTable( {
12101		 *        "columnDefs": [
12102		 *          { "orderData": [ 0, 1 ], "targets": [ 0 ] },
12103		 *          { "orderData": [ 1, 0 ], "targets": [ 1 ] },
12104		 *          { "orderData": 2, "targets": [ 2 ] }
12105		 *        ]
12106		 *      } );
12107		 *    } );
12108		 *
12109		 *  @example
12110		 *    // Using `columns`
12111		 *    $(document).ready( function() {
12112		 *      $('#example').dataTable( {
12113		 *        "columns": [
12114		 *          { "orderData": [ 0, 1 ] },
12115		 *          { "orderData": [ 1, 0 ] },
12116		 *          { "orderData": 2 },
12117		 *          null,
12118		 *          null
12119		 *        ]
12120		 *      } );
12121		 *    } );
12122		 */
12123		"aDataSort": null,
12124		"iDataSort": -1,
12125	
12126	
12127		/**
12128		 * You can control the default ordering direction, and even alter the
12129		 * behaviour of the sort handler (i.e. only allow ascending ordering etc)
12130		 * using this parameter.
12131		 *  @type array
12132		 *  @default [ 'asc', 'desc' ]
12133		 *
12134		 *  @name DataTable.defaults.column.orderSequence
12135		 *  @dtopt Columns
12136		 *
12137		 *  @example
12138		 *    // Using `columnDefs`
12139		 *    $(document).ready( function() {
12140		 *      $('#example').dataTable( {
12141		 *        "columnDefs": [
12142		 *          { "orderSequence": [ "asc" ], "targets": [ 1 ] },
12143		 *          { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] },
12144		 *          { "orderSequence": [ "desc" ], "targets": [ 3 ] }
12145		 *        ]
12146		 *      } );
12147		 *    } );
12148		 *
12149		 *  @example
12150		 *    // Using `columns`
12151		 *    $(document).ready( function() {
12152		 *      $('#example').dataTable( {
12153		 *        "columns": [
12154		 *          null,
12155		 *          { "orderSequence": [ "asc" ] },
12156		 *          { "orderSequence": [ "desc", "asc", "asc" ] },
12157		 *          { "orderSequence": [ "desc" ] },
12158		 *          null
12159		 *        ]
12160		 *      } );
12161		 *    } );
12162		 */
12163		"asSorting": [ 'asc', 'desc' ],
12164	
12165	
12166		/**
12167		 * Enable or disable filtering on the data in this column.
12168		 *  @type boolean
12169		 *  @default true
12170		 *
12171		 *  @name DataTable.defaults.column.searchable
12172		 *  @dtopt Columns
12173		 *
12174		 *  @example
12175		 *    // Using `columnDefs`
12176		 *    $(document).ready( function() {
12177		 *      $('#example').dataTable( {
12178		 *        "columnDefs": [
12179		 *          { "searchable": false, "targets": [ 0 ] }
12180		 *        ] } );
12181		 *    } );
12182		 *
12183		 *  @example
12184		 *    // Using `columns`
12185		 *    $(document).ready( function() {
12186		 *      $('#example').dataTable( {
12187		 *        "columns": [
12188		 *          { "searchable": false },
12189		 *          null,
12190		 *          null,
12191		 *          null,
12192		 *          null
12193		 *        ] } );
12194		 *    } );
12195		 */
12196		"bSearchable": true,
12197	
12198	
12199		/**
12200		 * Enable or disable ordering on this column.
12201		 *  @type boolean
12202		 *  @default true
12203		 *
12204		 *  @name DataTable.defaults.column.orderable
12205		 *  @dtopt Columns
12206		 *
12207		 *  @example
12208		 *    // Using `columnDefs`
12209		 *    $(document).ready( function() {
12210		 *      $('#example').dataTable( {
12211		 *        "columnDefs": [
12212		 *          { "orderable": false, "targets": [ 0 ] }
12213		 *        ] } );
12214		 *    } );
12215		 *
12216		 *  @example
12217		 *    // Using `columns`
12218		 *    $(document).ready( function() {
12219		 *      $('#example').dataTable( {
12220		 *        "columns": [
12221		 *          { "orderable": false },
12222		 *          null,
12223		 *          null,
12224		 *          null,
12225		 *          null
12226		 *        ] } );
12227		 *    } );
12228		 */
12229		"bSortable": true,
12230	
12231	
12232		/**
12233		 * Enable or disable the display of this column.
12234		 *  @type boolean
12235		 *  @default true
12236		 *
12237		 *  @name DataTable.defaults.column.visible
12238		 *  @dtopt Columns
12239		 *
12240		 *  @example
12241		 *    // Using `columnDefs`
12242		 *    $(document).ready( function() {
12243		 *      $('#example').dataTable( {
12244		 *        "columnDefs": [
12245		 *          { "visible": false, "targets": [ 0 ] }
12246		 *        ] } );
12247		 *    } );
12248		 *
12249		 *  @example
12250		 *    // Using `columns`
12251		 *    $(document).ready( function() {
12252		 *      $('#example').dataTable( {
12253		 *        "columns": [
12254		 *          { "visible": false },
12255		 *          null,
12256		 *          null,
12257		 *          null,
12258		 *          null
12259		 *        ] } );
12260		 *    } );
12261		 */
12262		"bVisible": true,
12263	
12264	
12265		/**
12266		 * Developer definable function that is called whenever a cell is created (Ajax source,
12267		 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
12268		 * allowing you to modify the DOM element (add background colour for example) when the
12269		 * element is available.
12270		 *  @type function
12271		 *  @param {element} td The TD node that has been created
12272		 *  @param {*} cellData The Data for the cell
12273		 *  @param {array|object} rowData The data for the whole row
12274		 *  @param {int} row The row index for the aoData data store
12275		 *  @param {int} col The column index for aoColumns
12276		 *
12277		 *  @name DataTable.defaults.column.createdCell
12278		 *  @dtopt Columns
12279		 *
12280		 *  @example
12281		 *    $(document).ready( function() {
12282		 *      $('#example').dataTable( {
12283		 *        "columnDefs": [ {
12284		 *          "targets": [3],
12285		 *          "createdCell": function (td, cellData, rowData, row, col) {
12286		 *            if ( cellData == "1.7" ) {
12287		 *              $(td).css('color', 'blue')
12288		 *            }
12289		 *          }
12290		 *        } ]
12291		 *      });
12292		 *    } );
12293		 */
12294		"fnCreatedCell": null,
12295	
12296	
12297		/**
12298		 * This parameter has been replaced by `data` in DataTables to ensure naming
12299		 * consistency. `dataProp` can still be used, as there is backwards
12300		 * compatibility in DataTables for this option, but it is strongly
12301		 * recommended that you use `data` in preference to `dataProp`.
12302		 *  @name DataTable.defaults.column.dataProp
12303		 */
12304	
12305	
12306		/**
12307		 * This property can be used to read data from any data source property,
12308		 * including deeply nested objects / properties. `data` can be given in a
12309		 * number of different ways which effect its behaviour:
12310		 *
12311		 * * `integer` - treated as an array index for the data source. This is the
12312		 *   default that DataTables uses (incrementally increased for each column).
12313		 * * `string` - read an object property from the data source. There are
12314		 *   three 'special' options that can be used in the string to alter how
12315		 *   DataTables reads the data from the source object:
12316		 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
12317		 *      Javascript to read from nested objects, so to can the options
12318		 *      specified in `data`. For example: `browser.version` or
12319		 *      `browser.name`. If your object parameter name contains a period, use
12320		 *      `\\` to escape it - i.e. `first\\.name`.
12321		 *    * `[]` - Array notation. DataTables can automatically combine data
12322		 *      from and array source, joining the data with the characters provided
12323		 *      between the two brackets. For example: `name[, ]` would provide a
12324		 *      comma-space separated list from the source array. If no characters
12325		 *      are provided between the brackets, the original array source is
12326		 *      returned.
12327		 *    * `()` - Function notation. Adding `()` to the end of a parameter will
12328		 *      execute a function of the name given. For example: `browser()` for a
12329		 *      simple function on the data source, `browser.version()` for a
12330		 *      function in a nested property or even `browser().version` to get an
12331		 *      object property if the function called returns an object. Note that
12332		 *      function notation is recommended for use in `render` rather than
12333		 *      `data` as it is much simpler to use as a renderer.
12334		 * * `null` - use the original data source for the row rather than plucking
12335		 *   data directly from it. This action has effects on two other
12336		 *   initialisation options:
12337		 *    * `defaultContent` - When null is given as the `data` option and
12338		 *      `defaultContent` is specified for the column, the value defined by
12339		 *      `defaultContent` will be used for the cell.
12340		 *    * `render` - When null is used for the `data` option and the `render`
12341		 *      option is specified for the column, the whole data source for the
12342		 *      row is used for the renderer.
12343		 * * `function` - the function given will be executed whenever DataTables
12344		 *   needs to set or get the data for a cell in the column. The function
12345		 *   takes three parameters:
12346		 *    * Parameters:
12347		 *      * `{array|object}` The data source for the row
12348		 *      * `{string}` The type call data requested - this will be 'set' when
12349		 *        setting data or 'filter', 'display', 'type', 'sort' or undefined
12350		 *        when gathering data. Note that when `undefined` is given for the
12351		 *        type DataTables expects to get the raw data for the object back<
12352		 *      * `{*}` Data to set when the second parameter is 'set'.
12353		 *    * Return:
12354		 *      * The return value from the function is not required when 'set' is
12355		 *        the type of call, but otherwise the return is what will be used
12356		 *        for the data requested.
12357		 *
12358		 * Note that `data` is a getter and setter option. If you just require
12359		 * formatting of data for output, you will likely want to use `render` which
12360		 * is simply a getter and thus simpler to use.
12361		 *
12362		 * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The
12363		 * name change reflects the flexibility of this property and is consistent
12364		 * with the naming of mRender. If 'mDataProp' is given, then it will still
12365		 * be used by DataTables, as it automatically maps the old name to the new
12366		 * if required.
12367		 *
12368		 *  @type string|int|function|null
12369		 *  @default null <i>Use automatically calculated column index</i>
12370		 *
12371		 *  @name DataTable.defaults.column.data
12372		 *  @dtopt Columns
12373		 *
12374		 *  @example
12375		 *    // Read table data from objects
12376		 *    // JSON structure for each row:
12377		 *    //   {
12378		 *    //      "engine": {value},
12379		 *    //      "browser": {value},
12380		 *    //      "platform": {value},
12381		 *    //      "version": {value},
12382		 *    //      "grade": {value}
12383		 *    //   }
12384		 *    $(document).ready( function() {
12385		 *      $('#example').dataTable( {
12386		 *        "ajaxSource": "sources/objects.txt",
12387		 *        "columns": [
12388		 *          { "data": "engine" },
12389		 *          { "data": "browser" },
12390		 *          { "data": "platform" },
12391		 *          { "data": "version" },
12392		 *          { "data": "grade" }
12393		 *        ]
12394		 *      } );
12395		 *    } );
12396		 *
12397		 *  @example
12398		 *    // Read information from deeply nested objects
12399		 *    // JSON structure for each row:
12400		 *    //   {
12401		 *    //      "engine": {value},
12402		 *    //      "browser": {value},
12403		 *    //      "platform": {
12404		 *    //         "inner": {value}
12405		 *    //      },
12406		 *    //      "details": [
12407		 *    //         {value}, {value}
12408		 *    //      ]
12409		 *    //   }
12410		 *    $(document).ready( function() {
12411		 *      $('#example').dataTable( {
12412		 *        "ajaxSource": "sources/deep.txt",
12413		 *        "columns": [
12414		 *          { "data": "engine" },
12415		 *          { "data": "browser" },
12416		 *          { "data": "platform.inner" },
12417		 *          { "data": "details.0" },
12418		 *          { "data": "details.1" }
12419		 *        ]
12420		 *      } );
12421		 *    } );
12422		 *
12423		 *  @example
12424		 *    // Using `data` as a function to provide different information for
12425		 *    // sorting, filtering and display. In this case, currency (price)
12426		 *    $(document).ready( function() {
12427		 *      $('#example').dataTable( {
12428		 *        "columnDefs": [ {
12429		 *          "targets": [ 0 ],
12430		 *          "data": function ( source, type, val ) {
12431		 *            if (type === 'set') {
12432		 *              source.price = val;
12433		 *              // Store the computed dislay and filter values for efficiency
12434		 *              source.price_display = val=="" ? "" : "$"+numberFormat(val);
12435		 *              source.price_filter  = val=="" ? "" : "$"+numberFormat(val)+" "+val;
12436		 *              return;
12437		 *            }
12438		 *            else if (type === 'display') {
12439		 *              return source.price_display;
12440		 *            }
12441		 *            else if (type === 'filter') {
12442		 *              return source.price_filter;
12443		 *            }
12444		 *            // 'sort', 'type' and undefined all just use the integer
12445		 *            return source.price;
12446		 *          }
12447		 *        } ]
12448		 *      } );
12449		 *    } );
12450		 *
12451		 *  @example
12452		 *    // Using default content
12453		 *    $(document).ready( function() {
12454		 *      $('#example').dataTable( {
12455		 *        "columnDefs": [ {
12456		 *          "targets": [ 0 ],
12457		 *          "data": null,
12458		 *          "defaultContent": "Click to edit"
12459		 *        } ]
12460		 *      } );
12461		 *    } );
12462		 *
12463		 *  @example
12464		 *    // Using array notation - outputting a list from an array
12465		 *    $(document).ready( function() {
12466		 *      $('#example').dataTable( {
12467		 *        "columnDefs": [ {
12468		 *          "targets": [ 0 ],
12469		 *          "data": "name[, ]"
12470		 *        } ]
12471		 *      } );
12472		 *    } );
12473		 *
12474		 */
12475		"mData": null,
12476	
12477	
12478		/**
12479		 * This property is the rendering partner to `data` and it is suggested that
12480		 * when you want to manipulate data for display (including filtering,
12481		 * sorting etc) without altering the underlying data for the table, use this
12482		 * property. `render` can be considered to be the the read only companion to
12483		 * `data` which is read / write (then as such more complex). Like `data`
12484		 * this option can be given in a number of different ways to effect its
12485		 * behaviour:
12486		 *
12487		 * * `integer` - treated as an array index for the data source. This is the
12488		 *   default that DataTables uses (incrementally increased for each column).
12489		 * * `string` - read an object property from the data source. There are
12490		 *   three 'special' options that can be used in the string to alter how
12491		 *   DataTables reads the data from the source object:
12492		 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
12493		 *      Javascript to read from nested objects, so to can the options
12494		 *      specified in `data`. For example: `browser.version` or
12495		 *      `browser.name`. If your object parameter name contains a period, use
12496		 *      `\\` to escape it - i.e. `first\\.name`.
12497		 *    * `[]` - Array notation. DataTables can automatically combine data
12498		 *      from and array source, joining the data with the characters provided
12499		 *      between the two brackets. For example: `name[, ]` would provide a
12500		 *      comma-space separated list from the source array. If no characters
12501		 *      are provided between the brackets, the original array source is
12502		 *      returned.
12503		 *    * `()` - Function notation. Adding `()` to the end of a parameter will
12504		 *      execute a function of the name given. For example: `browser()` for a
12505		 *      simple function on the data source, `browser.version()` for a
12506		 *      function in a nested property or even `browser().version` to get an
12507		 *      object property if the function called returns an object.
12508		 * * `object` - use different data for the different data types requested by
12509		 *   DataTables ('filter', 'display', 'type' or 'sort'). The property names
12510		 *   of the object is the data type the property refers to and the value can
12511		 *   defined using an integer, string or function using the same rules as
12512		 *   `render` normally does. Note that an `_` option _must_ be specified.
12513		 *   This is the default value to use if you haven't specified a value for
12514		 *   the data type requested by DataTables.
12515		 * * `function` - the function given will be executed whenever DataTables
12516		 *   needs to set or get the data for a cell in the column. The function
12517		 *   takes three parameters:
12518		 *    * Parameters:
12519		 *      * {array|object} The data source for the row (based on `data`)
12520		 *      * {string} The type call data requested - this will be 'filter',
12521		 *        'display', 'type' or 'sort'.
12522		 *      * {array|object} The full data source for the row (not based on
12523		 *        `data`)
12524		 *    * Return:
12525		 *      * The return value from the function is what will be used for the
12526		 *        data requested.
12527		 *
12528		 *  @type string|int|function|object|null
12529		 *  @default null Use the data source value.
12530		 *
12531		 *  @name DataTable.defaults.column.render
12532		 *  @dtopt Columns
12533		 *
12534		 *  @example
12535		 *    // Create a comma separated list from an array of objects
12536		 *    $(document).ready( function() {
12537		 *      $('#example').dataTable( {
12538		 *        "ajaxSource": "sources/deep.txt",
12539		 *        "columns": [
12540		 *          { "data": "engine" },
12541		 *          { "data": "browser" },
12542		 *          {
12543		 *            "data": "platform",
12544		 *            "render": "[, ].name"
12545		 *          }
12546		 *        ]
12547		 *      } );
12548		 *    } );
12549		 *
12550		 *  @example
12551		 *    // Execute a function to obtain data
12552		 *    $(document).ready( function() {
12553		 *      $('#example').dataTable( {
12554		 *        "columnDefs": [ {
12555		 *          "targets": [ 0 ],
12556		 *          "data": null, // Use the full data source object for the renderer's source
12557		 *          "render": "browserName()"
12558		 *        } ]
12559		 *      } );
12560		 *    } );
12561		 *
12562		 *  @example
12563		 *    // As an object, extracting different data for the different types
12564		 *    // This would be used with a data source such as:
12565		 *    //   { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" }
12566		 *    // Here the `phone` integer is used for sorting and type detection, while `phone_filter`
12567		 *    // (which has both forms) is used for filtering for if a user inputs either format, while
12568		 *    // the formatted phone number is the one that is shown in the table.
12569		 *    $(document).ready( function() {
12570		 *      $('#example').dataTable( {
12571		 *        "columnDefs": [ {
12572		 *          "targets": [ 0 ],
12573		 *          "data": null, // Use the full data source object for the renderer's source
12574		 *          "render": {
12575		 *            "_": "phone",
12576		 *            "filter": "phone_filter",
12577		 *            "display": "phone_display"
12578		 *          }
12579		 *        } ]
12580		 *      } );
12581		 *    } );
12582		 *
12583		 *  @example
12584		 *    // Use as a function to create a link from the data source
12585		 *    $(document).ready( function() {
12586		 *      $('#example').dataTable( {
12587		 *        "columnDefs": [ {
12588		 *          "targets": [ 0 ],
12589		 *          "data": "download_link",
12590		 *          "render": function ( data, type, full ) {
12591		 *            return '<a href="'+data+'">Download</a>';
12592		 *          }
12593		 *        } ]
12594		 *      } );
12595		 *    } );
12596		 */
12597		"mRender": null,
12598	
12599	
12600		/**
12601		 * Change the cell type created for the column - either TD cells or TH cells. This
12602		 * can be useful as TH cells have semantic meaning in the table body, allowing them
12603		 * to act as a header for a row (you may wish to add scope='row' to the TH elements).
12604		 *  @type string
12605		 *  @default td
12606		 *
12607		 *  @name DataTable.defaults.column.cellType
12608		 *  @dtopt Columns
12609		 *
12610		 *  @example
12611		 *    // Make the first column use TH cells
12612		 *    $(document).ready( function() {
12613		 *      $('#example').dataTable( {
12614		 *        "columnDefs": [ {
12615		 *          "targets": [ 0 ],
12616		 *          "cellType": "th"
12617		 *        } ]
12618		 *      } );
12619		 *    } );
12620		 */
12621		"sCellType": "td",
12622	
12623	
12624		/**
12625		 * Class to give to each cell in this column.
12626		 *  @type string
12627		 *  @default <i>Empty string</i>
12628		 *
12629		 *  @name DataTable.defaults.column.class
12630		 *  @dtopt Columns
12631		 *
12632		 *  @example
12633		 *    // Using `columnDefs`
12634		 *    $(document).ready( function() {
12635		 *      $('#example').dataTable( {
12636		 *        "columnDefs": [
12637		 *          { "class": "my_class", "targets": [ 0 ] }
12638		 *        ]
12639		 *      } );
12640		 *    } );
12641		 *
12642		 *  @example
12643		 *    // Using `columns`
12644		 *    $(document).ready( function() {
12645		 *      $('#example').dataTable( {
12646		 *        "columns": [
12647		 *          { "class": "my_class" },
12648		 *          null,
12649		 *          null,
12650		 *          null,
12651		 *          null
12652		 *        ]
12653		 *      } );
12654		 *    } );
12655		 */
12656		"sClass": "",
12657	
12658		/**
12659		 * When DataTables calculates the column widths to assign to each column,
12660		 * it finds the longest string in each column and then constructs a
12661		 * temporary table and reads the widths from that. The problem with this
12662		 * is that "mmm" is much wider then "iiii", but the latter is a longer
12663		 * string - thus the calculation can go wrong (doing it properly and putting
12664		 * it into an DOM object and measuring that is horribly(!) slow). Thus as
12665		 * a "work around" we provide this option. It will append its value to the
12666		 * text that is found to be the longest string for the column - i.e. padding.
12667		 * Generally you shouldn't need this!
12668		 *  @type string
12669		 *  @default <i>Empty string<i>
12670		 *
12671		 *  @name DataTable.defaults.column.contentPadding
12672		 *  @dtopt Columns
12673		 *
12674		 *  @example
12675		 *    // Using `columns`
12676		 *    $(document).ready( function() {
12677		 *      $('#example').dataTable( {
12678		 *        "columns": [
12679		 *          null,
12680		 *          null,
12681		 *          null,
12682		 *          {
12683		 *            "contentPadding": "mmm"
12684		 *          }
12685		 *        ]
12686		 *      } );
12687		 *    } );
12688		 */
12689		"sContentPadding": "",
12690	
12691	
12692		/**
12693		 * Allows a default value to be given for a column's data, and will be used
12694		 * whenever a null data source is encountered (this can be because `data`
12695		 * is set to null, or because the data source itself is null).
12696		 *  @type string
12697		 *  @default null
12698		 *
12699		 *  @name DataTable.defaults.column.defaultContent
12700		 *  @dtopt Columns
12701		 *
12702		 *  @example
12703		 *    // Using `columnDefs`
12704		 *    $(document).ready( function() {
12705		 *      $('#example').dataTable( {
12706		 *        "columnDefs": [
12707		 *          {
12708		 *            "data": null,
12709		 *            "defaultContent": "Edit",
12710		 *            "targets": [ -1 ]
12711		 *          }
12712		 *        ]
12713		 *      } );
12714		 *    } );
12715		 *
12716		 *  @example
12717		 *    // Using `columns`
12718		 *    $(document).ready( function() {
12719		 *      $('#example').dataTable( {
12720		 *        "columns": [
12721		 *          null,
12722		 *          null,
12723		 *          null,
12724		 *          {
12725		 *            "data": null,
12726		 *            "defaultContent": "Edit"
12727		 *          }
12728		 *        ]
12729		 *      } );
12730		 *    } );
12731		 */
12732		"sDefaultContent": null,
12733	
12734	
12735		/**
12736		 * This parameter is only used in DataTables' server-side processing. It can
12737		 * be exceptionally useful to know what columns are being displayed on the
12738		 * client side, and to map these to database fields. When defined, the names
12739		 * also allow DataTables to reorder information from the server if it comes
12740		 * back in an unexpected order (i.e. if you switch your columns around on the
12741		 * client-side, your server-side code does not also need updating).
12742		 *  @type string
12743		 *  @default <i>Empty string</i>
12744		 *
12745		 *  @name DataTable.defaults.column.name
12746		 *  @dtopt Columns
12747		 *
12748		 *  @example
12749		 *    // Using `columnDefs`
12750		 *    $(document).ready( function() {
12751		 *      $('#example').dataTable( {
12752		 *        "columnDefs": [
12753		 *          { "name": "engine", "targets": [ 0 ] },
12754		 *          { "name": "browser", "targets": [ 1 ] },
12755		 *          { "name": "platform", "targets": [ 2 ] },
12756		 *          { "name": "version", "targets": [ 3 ] },
12757		 *          { "name": "grade", "targets": [ 4 ] }
12758		 *        ]
12759		 *      } );
12760		 *    } );
12761		 *
12762		 *  @example
12763		 *    // Using `columns`
12764		 *    $(document).ready( function() {
12765		 *      $('#example').dataTable( {
12766		 *        "columns": [
12767		 *          { "name": "engine" },
12768		 *          { "name": "browser" },
12769		 *          { "name": "platform" },
12770		 *          { "name": "version" },
12771		 *          { "name": "grade" }
12772		 *        ]
12773		 *      } );
12774		 *    } );
12775		 */
12776		"sName": "",
12777	
12778	
12779		/**
12780		 * Defines a data source type for the ordering which can be used to read
12781		 * real-time information from the table (updating the internally cached
12782		 * version) prior to ordering. This allows ordering to occur on user
12783		 * editable elements such as form inputs.
12784		 *  @type string
12785		 *  @default std
12786		 *
12787		 *  @name DataTable.defaults.column.orderDataType
12788		 *  @dtopt Columns
12789		 *
12790		 *  @example
12791		 *    // Using `columnDefs`
12792		 *    $(document).ready( function() {
12793		 *      $('#example').dataTable( {
12794		 *        "columnDefs": [
12795		 *          { "orderDataType": "dom-text", "targets": [ 2, 3 ] },
12796		 *          { "type": "numeric", "targets": [ 3 ] },
12797		 *          { "orderDataType": "dom-select", "targets": [ 4 ] },
12798		 *          { "orderDataType": "dom-checkbox", "targets": [ 5 ] }
12799		 *        ]
12800		 *      } );
12801		 *    } );
12802		 *
12803		 *  @example
12804		 *    // Using `columns`
12805		 *    $(document).ready( function() {
12806		 *      $('#example').dataTable( {
12807		 *        "columns": [
12808		 *          null,
12809		 *          null,
12810		 *          { "orderDataType": "dom-text" },
12811		 *          { "orderDataType": "dom-text", "type": "numeric" },
12812		 *          { "orderDataType": "dom-select" },
12813		 *          { "orderDataType": "dom-checkbox" }
12814		 *        ]
12815		 *      } );
12816		 *    } );
12817		 */
12818		"sSortDataType": "std",
12819	
12820	
12821		/**
12822		 * The title of this column.
12823		 *  @type string
12824		 *  @default null <i>Derived from the 'TH' value for this column in the
12825		 *    original HTML table.</i>
12826		 *
12827		 *  @name DataTable.defaults.column.title
12828		 *  @dtopt Columns
12829		 *
12830		 *  @example
12831		 *    // Using `columnDefs`
12832		 *    $(document).ready( function() {
12833		 *      $('#example').dataTable( {
12834		 *        "columnDefs": [
12835		 *          { "title": "My column title", "targets": [ 0 ] }
12836		 *        ]
12837		 *      } );
12838		 *    } );
12839		 *
12840		 *  @example
12841		 *    // Using `columns`
12842		 *    $(document).ready( function() {
12843		 *      $('#example').dataTable( {
12844		 *        "columns": [
12845		 *          { "title": "My column title" },
12846		 *          null,
12847		 *          null,
12848		 *          null,
12849		 *          null
12850		 *        ]
12851		 *      } );
12852		 *    } );
12853		 */
12854		"sTitle": null,
12855	
12856	
12857		/**
12858		 * The type allows you to specify how the data for this column will be
12859		 * ordered. Four types (string, numeric, date and html (which will strip
12860		 * HTML tags before ordering)) are currently available. Note that only date
12861		 * formats understood by Javascript's Date() object will be accepted as type
12862		 * date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string',
12863		 * 'numeric', 'date' or 'html' (by default). Further types can be adding
12864		 * through plug-ins.
12865		 *  @type string
12866		 *  @default null <i>Auto-detected from raw data</i>
12867		 *
12868		 *  @name DataTable.defaults.column.type
12869		 *  @dtopt Columns
12870		 *
12871		 *  @example
12872		 *    // Using `columnDefs`
12873		 *    $(document).ready( function() {
12874		 *      $('#example').dataTable( {
12875		 *        "columnDefs": [
12876		 *          { "type": "html", "targets": [ 0 ] }
12877		 *        ]
12878		 *      } );
12879		 *    } );
12880		 *
12881		 *  @example
12882		 *    // Using `columns`
12883		 *    $(document).ready( function() {
12884		 *      $('#example').dataTable( {
12885		 *        "columns": [
12886		 *          { "type": "html" },
12887		 *          null,
12888		 *          null,
12889		 *          null,
12890		 *          null
12891		 *        ]
12892		 *      } );
12893		 *    } );
12894		 */
12895		"sType": null,
12896	
12897	
12898		/**
12899		 * Defining the width of the column, this parameter may take any CSS value
12900		 * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not
12901		 * been given a specific width through this interface ensuring that the table
12902		 * remains readable.
12903		 *  @type string
12904		 *  @default null <i>Automatic</i>
12905		 *
12906		 *  @name DataTable.defaults.column.width
12907		 *  @dtopt Columns
12908		 *
12909		 *  @example
12910		 *    // Using `columnDefs`
12911		 *    $(document).ready( function() {
12912		 *      $('#example').dataTable( {
12913		 *        "columnDefs": [
12914		 *          { "width": "20%", "targets": [ 0 ] }
12915		 *        ]
12916		 *      } );
12917		 *    } );
12918		 *
12919		 *  @example
12920		 *    // Using `columns`
12921		 *    $(document).ready( function() {
12922		 *      $('#example').dataTable( {
12923		 *        "columns": [
12924		 *          { "width": "20%" },
12925		 *          null,
12926		 *          null,
12927		 *          null,
12928		 *          null
12929		 *        ]
12930		 *      } );
12931		 *    } );
12932		 */
12933		"sWidth": null
12934	};
12935	
12936	_fnHungarianMap( DataTable.defaults.column );
12937	
12938	
12939	
12940	/**
12941	 * DataTables settings object - this holds all the information needed for a
12942	 * given table, including configuration, data and current application of the
12943	 * table options. DataTables does not have a single instance for each DataTable
12944	 * with the settings attached to that instance, but rather instances of the
12945	 * DataTable "class" are created on-the-fly as needed (typically by a
12946	 * $().dataTable() call) and the settings object is then applied to that
12947	 * instance.
12948	 *
12949	 * Note that this object is related to {@link DataTable.defaults} but this
12950	 * one is the internal data store for DataTables's cache of columns. It should
12951	 * NOT be manipulated outside of DataTables. Any configuration should be done
12952	 * through the initialisation options.
12953	 *  @namespace
12954	 *  @todo Really should attach the settings object to individual instances so we
12955	 *    don't need to create new instances on each $().dataTable() call (if the
12956	 *    table already exists). It would also save passing oSettings around and
12957	 *    into every single function. However, this is a very significant
12958	 *    architecture change for DataTables and will almost certainly break
12959	 *    backwards compatibility with older installations. This is something that
12960	 *    will be done in 2.0.
12961	 */
12962	DataTable.models.oSettings = {
12963		/**
12964		 * Primary features of DataTables and their enablement state.
12965		 *  @namespace
12966		 */
12967		"oFeatures": {
12968	
12969			/**
12970			 * Flag to say if DataTables should automatically try to calculate the
12971			 * optimum table and columns widths (true) or not (false).
12972			 * Note that this parameter will be set by the initialisation routine. To
12973			 * set a default use {@link DataTable.defaults}.
12974			 *  @type boolean
12975			 */
12976			"bAutoWidth": null,
12977	
12978			/**
12979			 * Delay the creation of TR and TD elements until they are actually
12980			 * needed by a driven page draw. This can give a significant speed
12981			 * increase for Ajax source and Javascript source data, but makes no
12982			 * difference at all f
12982ro
vendor: 14,836 bytes, lines 12982-13559
12982 DOM and server-side processing tables.
12983			 * Note that this parameter will be set by the initialisation routine. To
12984			 * set a default use {@link DataTable.defaults}.
12985			 *  @type boolean
12986			 */
12987			"bDeferRender": null,
12988	
12989			/**
12990			 * Enable filtering on the table or not. Note that if this is disabled
12991			 * then there is no filtering at all on the table, including fnFilter.
12992			 * To just remove the filtering input use sDom and remove the 'f' option.
12993			 * Note that this parameter will be set by the initialisation routine. To
12994			 * set a default use {@link DataTable.defaults}.
12995			 *  @type boolean
12996			 */
12997			"bFilter": null,
12998	
12999			/**
13000			 * Table information element (the 'Showing x of y records' div) enable
13001			 * flag.
13002			 * Note that this parameter will be set by the initialisation routine. To
13003			 * set a default use {@link DataTable.defaults}.
13004			 *  @type boolean
13005			 */
13006			"bInfo": null,
13007	
13008			/**
13009			 * Present a user control allowing the end user to change the page size
13010			 * when pagination is enabled.
13011			 * Note that this parameter will be set by the initialisation routine. To
13012			 * set a default use {@link DataTable.defaults}.
13013			 *  @type boolean
13014			 */
13015			"bLengthChange": null,
13016	
13017			/**
13018			 * Pagination enabled or not. Note that if this is disabled then length
13019			 * changing must also be disabled.
13020			 * Note that this parameter will be set by the initialisation routine. To
13021			 * set a default use {@link DataTable.defaults}.
13022			 *  @type boolean
13023			 */
13024			"bPaginate": null,
13025	
13026			/**
13027			 * Processing indicator enable flag whenever DataTables is enacting a
13028			 * user request - typically an Ajax request for server-side processing.
13029			 * Note that this parameter will be set by the initialisation routine. To
13030			 * set a default use {@link DataTable.defaults}.
13031			 *  @type boolean
13032			 */
13033			"bProcessing": null,
13034	
13035			/**
13036			 * Server-side processing enabled flag - when enabled DataTables will
13037			 * get all data from the server for every draw - there is no filtering,
13038			 * sorting or paging done on the client-side.
13039			 * Note that this parameter will be set by the initialisation routine. To
13040			 * set a default use {@link DataTable.defaults}.
13041			 *  @type boolean
13042			 */
13043			"bServerSide": null,
13044	
13045			/**
13046			 * Sorting enablement flag.
13047			 * Note that this parameter will be set by the initialisation routine. To
13048			 * set a default use {@link DataTable.defaults}.
13049			 *  @type boolean
13050			 */
13051			"bSort": null,
13052	
13053			/**
13054			 * Multi-column sorting
13055			 * Note that this parameter will be set by the initialisation routine. To
13056			 * set a default use {@link DataTable.defaults}.
13057			 *  @type boolean
13058			 */
13059			"bSortMulti": null,
13060	
13061			/**
13062			 * Apply a class to the columns which are being sorted to provide a
13063			 * visual highlight or not. This can slow things down when enabled since
13064			 * there is a lot of DOM interaction.
13065			 * Note that this parameter will be set by the initialisation routine. To
13066			 * set a default use {@link DataTable.defaults}.
13067			 *  @type boolean
13068			 */
13069			"bSortClasses": null,
13070	
13071			/**
13072			 * State saving enablement flag.
13073			 * Note that this parameter will be set by the initialisation routine. To
13074			 * set a default use {@link DataTable.defaults}.
13075			 *  @type boolean
13076			 */
13077			"bStateSave": null
13078		},
13079	
13080	
13081		/**
13082		 * Scrolling settings for a table.
13083		 *  @namespace
13084		 */
13085		"oScroll": {
13086			/**
13087			 * When the table is shorter in height than sScrollY, collapse the
13088			 * table container down to the height of the table (when true).
13089			 * Note that this parameter will be set by the initialisation routine. To
13090			 * set a default use {@link DataTable.defaults}.
13091			 *  @type boolean
13092			 */
13093			"bCollapse": null,
13094	
13095			/**
13096			 * Width of the scrollbar for the web-browser's platform. Calculated
13097			 * during table initialisation.
13098			 *  @type int
13099			 *  @default 0
13100			 */
13101			"iBarWidth": 0,
13102	
13103			/**
13104			 * Viewport width for horizontal scrolling. Horizontal scrolling is
13105			 * disabled if an empty string.
13106			 * Note that this parameter will be set by the initialisation routine. To
13107			 * set a default use {@link DataTable.defaults}.
13108			 *  @type string
13109			 */
13110			"sX": null,
13111	
13112			/**
13113			 * Width to expand the table to when using x-scrolling. Typically you
13114			 * should not need to use this.
13115			 * Note that this parameter will be set by the initialisation routine. To
13116			 * set a default use {@link DataTable.defaults}.
13117			 *  @type string
13118			 *  @deprecated
13119			 */
13120			"sXInner": null,
13121	
13122			/**
13123			 * Viewport height for vertical scrolling. Vertical scrolling is disabled
13124			 * if an empty string.
13125			 * Note that this parameter will be set by the initialisation routine. To
13126			 * set a default use {@link DataTable.defaults}.
13127			 *  @type string
13128			 */
13129			"sY": null
13130		},
13131	
13132		/**
13133		 * Language information for the table.
13134		 *  @namespace
13135		 *  @extends DataTable.defaults.oLanguage
13136		 */
13137		"oLanguage": {
13138			/**
13139			 * Information callback function. See
13140			 * {@link DataTable.defaults.fnInfoCallback}
13141			 *  @type function
13142			 *  @default null
13143			 */
13144			"fnInfoCallback": null
13145		},
13146	
13147		/**
13148		 * Browser support parameters
13149		 *  @namespace
13150		 */
13151		"oBrowser": {
13152			/**
13153			 * Indicate if the browser incorrectly calculates width:100% inside a
13154			 * scrolling element (IE6/7)
13155			 *  @type boolean
13156			 *  @default false
13157			 */
13158			"bScrollOversize": false,
13159	
13160			/**
13161			 * Determine if the vertical scrollbar is on the right or left of the
13162			 * scrolling container - needed for rtl language layout, although not
13163			 * all browsers move the scrollbar (Safari).
13164			 *  @type boolean
13165			 *  @default false
13166			 */
13167			"bScrollbarLeft": false,
13168	
13169			/**
13170			 * Flag for if `getBoundingClientRect` is fully supported or not
13171			 *  @type boolean
13172			 *  @default false
13173			 */
13174			"bBounding": false,
13175	
13176			/**
13177			 * Browser scrollbar width
13178			 *  @type integer
13179			 *  @default 0
13180			 */
13181			"barWidth": 0
13182		},
13183	
13184	
13185		"ajax": null,
13186	
13187	
13188		/**
13189		 * Array referencing the nodes which are used for the features. The
13190		 * parameters of this object match what is allowed by sDom - i.e.
13191		 *   <ul>
13192		 *     <li>'l' - Length changing</li>
13193		 *     <li>'f' - Filtering input</li>
13194		 *     <li>'t' - The table!</li>
13195		 *     <li>'i' - Information</li>
13196		 *     <li>'p' - Pagination</li>
13197		 *     <li>'r' - pRocessing</li>
13198		 *   </ul>
13199		 *  @type array
13200		 *  @default []
13201		 */
13202		"aanFeatures": [],
13203	
13204		/**
13205		 * Store data information - see {@link DataTable.models.oRow} for detailed
13206		 * information.
13207		 *  @type array
13208		 *  @default []
13209		 */
13210		"aoData": [],
13211	
13212		/**
13213		 * Array of indexes which are in the current display (after filtering etc)
13214		 *  @type array
13215		 *  @default []
13216		 */
13217		"aiDisplay": [],
13218	
13219		/**
13220		 * Array of indexes for display - no filtering
13221		 *  @type array
13222		 *  @default []
13223		 */
13224		"aiDisplayMaster": [],
13225	
13226		/**
13227		 * Map of row ids to data indexes
13228		 *  @type object
13229		 *  @default {}
13230		 */
13231		"aIds": {},
13232	
13233		/**
13234		 * Store information about each column that is in use
13235		 *  @type array
13236		 *  @default []
13237		 */
13238		"aoColumns": [],
13239	
13240		/**
13241		 * Store information about the table's header
13242		 *  @type array
13243		 *  @default []
13244		 */
13245		"aoHeader": [],
13246	
13247		/**
13248		 * Store information about the table's footer
13249		 *  @type array
13250		 *  @default []
13251		 */
13252		"aoFooter": [],
13253	
13254		/**
13255		 * Store the applied global search information in case we want to force a
13256		 * research or compare the old search to a new one.
13257		 * Note that this parameter will be set by the initialisation routine. To
13258		 * set a default use {@link DataTable.defaults}.
13259		 *  @namespace
13260		 *  @extends DataTable.models.oSearch
13261		 */
13262		"oPreviousSearch": {},
13263	
13264		/**
13265		 * Store the applied search for each column - see
13266		 * {@link DataTable.models.oSearch} for the format that is used for the
13267		 * filtering information for each column.
13268		 *  @type array
13269		 *  @default []
13270		 */
13271		"aoPreSearchCols": [],
13272	
13273		/**
13274		 * Sorting that is applied to the table. Note that the inner arrays are
13275		 * used in the following manner:
13276		 * <ul>
13277		 *   <li>Index 0 - column number</li>
13278		 *   <li>Index 1 - current sorting direction</li>
13279		 * </ul>
13280		 * Note that this parameter will be set by the initialisation routine. To
13281		 * set a default use {@link DataTable.defaults}.
13282		 *  @type array
13283		 *  @todo These inner arrays should really be objects
13284		 */
13285		"aaSorting": null,
13286	
13287		/**
13288		 * Sorting that is always applied to the table (i.e. prefixed in front of
13289		 * aaSorting).
13290		 * Note that this parameter will be set by the initialisation routine. To
13291		 * set a default use {@link DataTable.defaults}.
13292		 *  @type array
13293		 *  @default []
13294		 */
13295		"aaSortingFixed": [],
13296	
13297		/**
13298		 * Classes to use for the striping of a table.
13299		 * Note that this parameter will be set by the initialisation routine. To
13300		 * set a default use {@link DataTable.defaults}.
13301		 *  @type array
13302		 *  @default []
13303		 */
13304		"asStripeClasses": null,
13305	
13306		/**
13307		 * If restoring a table - we should restore its striping classes as well
13308		 *  @type array
13309		 *  @default []
13310		 */
13311		"asDestroyStripes": [],
13312	
13313		/**
13314		 * If restoring a table - we should restore its width
13315		 *  @type int
13316		 *  @default 0
13317		 */
13318		"sDestroyWidth": 0,
13319	
13320		/**
13321		 * Callback functions array for every time a row is inserted (i.e. on a draw).
13322		 *  @type array
13323		 *  @default []
13324		 */
13325		"aoRowCallback": [],
13326	
13327		/**
13328		 * Callback functions for the header on each draw.
13329		 *  @type array
13330		 *  @default []
13331		 */
13332		"aoHeaderCallback": [],
13333	
13334		/**
13335		 * Callback function for the footer on each draw.
13336		 *  @type array
13337		 *  @default []
13338		 */
13339		"aoFooterCallback": [],
13340	
13341		/**
13342		 * Array of callback functions for draw callback functions
13343		 *  @type array
13344		 *  @default []
13345		 */
13346		"aoDrawCallback": [],
13347	
13348		/**
13349		 * Array of callback functions for row created function
13350		 *  @type array
13351		 *  @default []
13352		 */
13353		"aoRowCreatedCallback": [],
13354	
13355		/**
13356		 * Callback functions for just before the table is redrawn. A return of
13357		 * false will be used to cancel the draw.
13358		 *  @type array
13359		 *  @default []
13360		 */
13361		"aoPreDrawCallback": [],
13362	
13363		/**
13364		 * Callback functions for when the table has been initialised.
13365		 *  @type array
13366		 *  @default []
13367		 */
13368		"aoInitComplete": [],
13369	
13370	
13371		/**
13372		 * Callbacks for modifying the settings to be stored for state saving, prior to
13373		 * saving state.
13374		 *  @type array
13375		 *  @default []
13376		 */
13377		"aoStateSaveParams": [],
13378	
13379		/**
13380		 * Callbacks for modifying the settings that have been stored for state saving
13381		 * prior to using the stored values to restore the state.
13382		 *  @type array
13383		 *  @default []
13384		 */
13385		"aoStateLoadParams": [],
13386	
13387		/**
13388		 * Callbacks for operating on the settings object once the saved state has been
13389		 * loaded
13390		 *  @type array
13391		 *  @default []
13392		 */
13393		"aoStateLoaded": [],
13394	
13395		/**
13396		 * Cache the table ID for quick access
13397		 *  @type string
13398		 *  @default <i>Empty string</i>
13399		 */
13400		"sTableId": "",
13401	
13402		/**
13403		 * The TABLE node for the main table
13404		 *  @type node
13405		 *  @default null
13406		 */
13407		"nTable": null,
13408	
13409		/**
13410		 * Permanent ref to the thead element
13411		 *  @type node
13412		 *  @default null
13413		 */
13414		"nTHead": null,
13415	
13416		/**
13417		 * Permanent ref to the tfoot element - if it exists
13418		 *  @type node
13419		 *  @default null
13420		 */
13421		"nTFoot": null,
13422	
13423		/**
13424		 * Permanent ref to the tbody element
13425		 *  @type node
13426		 *  @default null
13427		 */
13428		"nTBody": null,
13429	
13430		/**
13431		 * Cache the wrapper node (contains all DataTables controlled elements)
13432		 *  @type node
13433		 *  @default null
13434		 */
13435		"nTableWrapper": null,
13436	
13437		/**
13438		 * Indicate if when using server-side processing the loading of data
13439		 * should be deferred until the second draw.
13440		 * Note that this parameter will be set by the initialisation routine. To
13441		 * set a default use {@link DataTable.defaults}.
13442		 *  @type boolean
13443		 *  @default false
13444		 */
13445		"bDeferLoading": false,
13446	
13447		/**
13448		 * Indicate if all required information has been read in
13449		 *  @type boolean
13450		 *  @default false
13451		 */
13452		"bInitialised": false,
13453	
13454		/**
13455		 * Information about open rows. Each object in the array has the parameters
13456		 * 'nTr' and 'nParent'
13457		 *  @type array
13458		 *  @default []
13459		 */
13460		"aoOpenRows": [],
13461	
13462		/**
13463		 * Dictate the positioning of DataTables' control elements - see
13464		 * {@link DataTable.model.oInit.sDom}.
13465		 * Note that this parameter will be set by the initialisation routine. To
13466		 * set a default use {@link DataTable.defaults}.
13467		 *  @type string
13468		 *  @default null
13469		 */
13470		"sDom": null,
13471	
13472		/**
13473		 * Search delay (in mS)
13474		 *  @type integer
13475		 *  @default null
13476		 */
13477		"searchDelay": null,
13478	
13479		/**
13480		 * Which type of pagination should be used.
13481		 * Note that this parameter will be set by the initialisation routine. To
13482		 * set a default use {@link DataTable.defaults}.
13483		 *  @type string
13484		 *  @default two_button
13485		 */
13486		"sPaginationType": "two_button",
13487	
13488		/**
13489		 * The state duration (for `stateSave`) in seconds.
13490		 * Note that this parameter will be set by the initialisation routine. To
13491		 * set a default use {@link DataTable.defaults}.
13492		 *  @type int
13493		 *  @default 0
13494		 */
13495		"iStateDuration": 0,
13496	
13497		/**
13498		 * Array of callback functions for state saving. Each array element is an
13499		 * object with the following parameters:
13500		 *   <ul>
13501		 *     <li>function:fn - function to call. Takes two parameters, oSettings
13502		 *       and the JSON string to save that has been thus far created. Returns
13503		 *       a JSON string to be inserted into a json object
13504		 *       (i.e. '"param": [ 0, 1, 2]')</li>
13505		 *     <li>string:sName - name of callback</li>
13506		 *   </ul>
13507		 *  @type array
13508		 *  @default []
13509		 */
13510		"aoStateSave": [],
13511	
13512		/**
13513		 * Array of callback functions for state loading. Each array element is an
13514		 * object with the following parameters:
13515		 *   <ul>
13516		 *     <li>function:fn - function to call. Takes two parameters, oSettings
13517		 *       and the object stored. May return false to cancel state loading</li>
13518		 *     <li>string:sName - name of callback</li>
13519		 *   </ul>
13520		 *  @type array
13521		 *  @default []
13522		 */
13523		"aoStateLoad": [],
13524	
13525		/**
13526		 * State that was saved. Useful for back reference
13527		 *  @type object
13528		 *  @default null
13529		 */
13530		"oSavedState": null,
13531	
13532		/**
13533		 * State that was loaded. Useful for back reference
13534		 *  @type object
13535		 *  @default null
13536		 */
13537		"oLoadedState": null,
13538	
13539		/**
13540		 * Source url for AJAX data for the table.
13541		 * Note that this parameter will be set by the initialisation routine. To
13542		 * set a default use {@link DataTable.defaults}.
13543		 *  @type string
13544		 *  @default null
13545		 */
13546		"sAjaxSource": null,
13547	
13548		/**
13549		 * Property from a given object from which to read the table data from. This
13550		 * can be an empty string (when not server-side processing), in which case
13551		 * it is  assumed an an array is given directly.
13552		 * Note that this parameter will be set by the initialisation routine. To
13553		 * set a default use {@link DataTable.defaults}.
13554		 *  @type string
13555		 */
13556		"sAjaxDataProp": null,
13557	
13558		/**
13559		 * 
13559Note if draw should be blocked while getting data
13560		 *  @type boolean
13561		 *  @default true
13562		 */
13563		"bAjaxDataGet": true,
13564	
13565		/**
13566		 * The last jQuery XHR object that was used for server-side data gathering.
13567		 * This can be used for working with the XHR information in one of the
13568		 * callbacks
13569		 *  @type object
13570		 *  @default null
13571		 */
13572		"jqXHR": null,
13573	
13574		/**
13575		 * JSON returned from the server in the last Ajax request
13576		 *  @type object
13577		 *  @default undefined
13578		 */
13579		"json": undefined,
13580	
13581		/**
13582		 * Data submitted as part of the last Ajax request
13583		 *  @type object
13584		 *  @default undefined
13585		 */
13586		"oAjaxData": undefined,
13587	
13588		/**
13589		 * Function to get the server-side data.
13590		 * Note that this parameter will be set by the initialisation routine. To
13591		 * set a default use {@link DataTable.defaults}.
13592		 *  @type function
13593		 */
13594		"fnServerData": null,
13595	
13596		/**
13597		 * Functions which are called prior to sending an Ajax request so extra
13598		 * parameters can easily be sent to the server
13599		 *  @type array
13600		 *  @default []
13601		 */
13602		"aoServerParams": [],
13603	
13604		/**
13605		 * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
13606		 * required).
13607		 * Note that this parameter will be set by the initialisation routine. To
13608		 * set a default use {@link DataTable.defaults}.
13609		 *  @type string
13610		 */
13611		"sServerMethod": null,
13612	
13613		/**
13614		 * Format numbers for display.
13615		 * Note that this parameter will be set by the initialisation routine. To
13616		 * set a default use {@link DataTable.defaults}.
13617		 *  @type function
13618		 */
13619		"fnFormatNumber": null,
13620	
13621		/**
13622		 * List of options that can be used for the user selectable length menu.
13623		 * Note that this parameter will be set by the initialisation routine. To
13624		 * set a default use {@link DataTable.defaults}.
13625		 *  @type array
13626		 *  @default []
13627		 */
13628		"aLengthMenu": null,
13629	
13630		/**
13631		 * Counter for the draws that the table does. Also used as a tracker for
13632		 * server-side processing
13633		 *  @type int
13634		 *  @default 0
13635		 */
13636		"iDraw": 0,
13637	
13638		/**
13639		 * Indicate if a redraw is being done - useful for Ajax
13640		 *  @type boolean
13641		 *  @default false
13642		 */
13643		"bDrawing": false,
13644	
13645		/**
13646		 * Draw index (iDraw) of the last error when parsing the returned data
13647		 *  @type int
13648		 *  @default -1
13649		 */
13650		"iDrawError": -1,
13651	
13652		/**
13653		 * Paging display length
13654		 *  @type int
13655		 *  @default 10
13656		 */
13657		"_iDisplayLength": 10,
13658	
13659		/**
13660		 * Paging start point - aiDisplay index
13661		 *  @type int
13662		 *  @default 0
13663		 */
13664		"_iDisplayStart": 0,
13665	
13666		/**
13667		 * Server-side processing - number of records in the result set
13668		 * (i.e. before filtering), Use fnRecordsTotal rather than
13669		 * this property to get the value of the number of records, regardless of
13670		 * the server-side processing setting.
13671		 *  @type int
13672		 *  @default 0
13673		 *  @private
13674		 */
13675		"_iRecordsTotal": 0,
13676	
13677		/**
13678		 * Server-side processing - number of records in the current display set
13679		 * (i.e. after filtering). Use fnRecordsDisplay rather than
13680		 * this property to get the value of the number of records, regardless of
13681		 * the server-side processing setting.
13682		 *  @type boolean
13683		 *  @default 0
13684		 *  @private
13685		 */
13686		"_iRecordsDisplay": 0,
13687	
13688		/**
13689		 * The classes to use for the table
13690		 *  @type object
13691		 *  @default {}
13692		 */
vendor: 4,822 bytes, lines 13693-13901
13693		"oClasses": {},
13694	
13695		/**
13696		 * Flag attached to the settings object so you can check in the draw
13697		 * callback if filtering has been done in the draw. Deprecated in favour of
13698		 * events.
13699		 *  @type boolean
13700		 *  @default false
13701		 *  @deprecated
13702		 */
13703		"bFiltered": false,
13704	
13705		/**
13706		 * Flag attached to the settings object so you can check in the draw
13707		 * callback if sorting has been done in the draw. Deprecated in favour of
13708		 * events.
13709		 *  @type boolean
13710		 *  @default false
13711		 *  @deprecated
13712		 */
13713		"bSorted": false,
13714	
13715		/**
13716		 * Indicate that if multiple rows are in the header and there is more than
13717		 * one unique cell per column, if the top one (true) or bottom one (false)
13718		 * should be used for sorting / title by DataTables.
13719		 * Note that this parameter will be set by the initialisation routine. To
13720		 * set a default use {@link DataTable.defaults}.
13721		 *  @type boolean
13722		 */
13723		"bSortCellsTop": null,
13724	
13725		/**
13726		 * Initialisation object that is used for the table
13727		 *  @type object
13728		 *  @default null
13729		 */
13730		"oInit": null,
13731	
13732		/**
13733		 * Destroy callback functions - for plug-ins to attach themselves to the
13734		 * destroy so they can clean up markup and events.
13735		 *  @type array
13736		 *  @default []
13737		 */
13738		"aoDestroyCallback": [],
13739	
13740	
13741		/**
13742		 * Get the number of records in the current record set, before filtering
13743		 *  @type function
13744		 */
13745		"fnRecordsTotal": function ()
13746		{
13747			return _fnDataSource( this ) == 'ssp' ?
13748				this._iRecordsTotal * 1 :
13749				this.aiDisplayMaster.length;
13750		},
13751	
13752		/**
13753		 * Get the number of records in the current record set, after filtering
13754		 *  @type function
13755		 */
13756		"fnRecordsDisplay": function ()
13757		{
13758			return _fnDataSource( this ) == 'ssp' ?
13759				this._iRecordsDisplay * 1 :
13760				this.aiDisplay.length;
13761		},
13762	
13763		/**
13764		 * Get the display end point - aiDisplay index
13765		 *  @type function
13766		 */
13767		"fnDisplayEnd": function ()
13768		{
13769			var
13770				len      = this._iDisplayLength,
13771				start    = this._iDisplayStart,
13772				calc     = start + len,
13773				records  = this.aiDisplay.length,
13774				features = this.oFeatures,
13775				paginate = features.bPaginate;
13776	
13777			if ( features.bServerSide ) {
13778				return paginate === false || len === -1 ?
13779					start + records :
13780					Math.min( start+len, this._iRecordsDisplay );
13781			}
13782			else {
13783				return ! paginate || calc>records || len===-1 ?
13784					records :
13785					calc;
13786			}
13787		},
13788	
13789		/**
13790		 * The DataTables object for this table
13791		 *  @type object
13792		 *  @default null
13793		 */
13794		"oInstance": null,
13795	
13796		/**
13797		 * Unique identifier for each instance of the DataTables object. If there
13798		 * is an ID on the table node, then it takes that value, otherwise an
13799		 * incrementing internal counter is used.
13800		 *  @type string
13801		 *  @default null
13802		 */
13803		"sInstance": null,
13804	
13805		/**
13806		 * tabindex attribute value that is added to DataTables control elements, allowing
13807		 * keyboard navigation of the table and its controls.
13808		 */
13809		"iTabIndex": 0,
13810	
13811		/**
13812		 * DIV container for the footer scrolling table if scrolling
13813		 */
13814		"nScrollHead": null,
13815	
13816		/**
13817		 * DIV container for the footer scrolling table if scrolling
13818		 */
13819		"nScrollFoot": null,
13820	
13821		/**
13822		 * Last applied sort
13823		 *  @type array
13824		 *  @default []
13825		 */
13826		"aLastSort": [],
13827	
13828		/**
13829		 * Stored plug-in instances
13830		 *  @type object
13831		 *  @default {}
13832		 */
13833		"oPlugins": {},
13834	
13835		/**
13836		 * Function used to get a row's id from the row's data
13837		 *  @type function
13838		 *  @default null
13839		 */
13840		"rowIdFn": null,
13841	
13842		/**
13843		 * Data location where to store a row's id
13844		 *  @type string
13845		 *  @default null
13846		 */
13847		"rowId": null
13848	};
13849
13850	/**
13851	 * Extension object for DataTables that is used to provide all extension
13852	 * options.
13853	 *
13854	 * Note that the `DataTable.ext` object is available through
13855	 * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is
13856	 * also aliased to `jQuery.fn.dataTableExt` for historic reasons.
13857	 *  @namespace
13858	 *  @extends DataTable.models.ext
13859	 */
13860	
13861	
13862	/**
13863	 * DataTables extensions
13864	 * 
13865	 * This namespace acts as a collection area for plug-ins that can be used to
13866	 * extend DataTables capabilities. Indeed many of the build in methods
13867	 * use this method to provide their own capabilities (sorting methods for
13868	 * example).
13869	 *
13870	 * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy
13871	 * reasons
13872	 *
13873	 *  @namespace
13874	 */
13875	DataTable.ext = _ext = {
13876		/**
13877		 * Buttons. For use with the Buttons extension for DataTables. This is
13878		 * defined here so other extensions can define buttons regardless of load
13879		 * order. It is _not_ used by DataTables core.
13880		 *
13881		 *  @type object
13882		 *  @default {}
13883		 */
13884		buttons: {},
13885	
13886	
13887		/**
13888		 * Element class names
13889		 *
13890		 *  @type object
13891		 *  @default {}
13892		 */
13893		classes: {},
13894	
13895	
13896		/**
13897		 * DataTables build type (expanded by the download builder)
13898		 *
13899		 *  @type string
13900		 */
13901		build:"dt/dt-1.10.18
vendor: 15,138 bytes, lines 13901-14347
13901",
13902	
13903	
13904		/**
13905		 * Error reporting.
13906		 * 
13907		 * How should DataTables report an error. Can take the value 'alert',
13908		 * 'throw', 'none' or a function.
13909		 *
13910		 *  @type string|function
13911		 *  @default alert
13912		 */
13913		errMode: "alert",
13914	
13915	
13916		/**
13917		 * Feature plug-ins.
13918		 * 
13919		 * This is an array of objects which describe the feature plug-ins that are
13920		 * available to DataTables. These feature plug-ins are then available for
13921		 * use through the `dom` initialisation option.
13922		 * 
13923		 * Each feature plug-in is described by an object which must have the
13924		 * following properties:
13925		 * 
13926		 * * `fnInit` - function that is used to initialise the plug-in,
13927		 * * `cFeature` - a character so the feature can be enabled by the `dom`
13928		 *   instillation option. This is case sensitive.
13929		 *
13930		 * The `fnInit` function has the following input parameters:
13931		 *
13932		 * 1. `{object}` DataTables settings object: see
13933		 *    {@link DataTable.models.oSettings}
13934		 *
13935		 * And the following return is expected:
13936		 * 
13937		 * * {node|null} The element which contains your feature. Note that the
13938		 *   return may also be void if your plug-in does not require to inject any
13939		 *   DOM elements into DataTables control (`dom`) - for example this might
13940		 *   be useful when developing a plug-in which allows table control via
13941		 *   keyboard entry
13942		 *
13943		 *  @type array
13944		 *
13945		 *  @example
13946		 *    $.fn.dataTable.ext.features.push( {
13947		 *      "fnInit": function( oSettings ) {
13948		 *        return new TableTools( { "oDTSettings": oSettings } );
13949		 *      },
13950		 *      "cFeature": "T"
13951		 *    } );
13952		 */
13953		feature: [],
13954	
13955	
13956		/**
13957		 * Row searching.
13958		 * 
13959		 * This method of searching is complimentary to the default type based
13960		 * searching, and a lot more comprehensive as it allows you complete control
13961		 * over the searching logic. Each element in this array is a function
13962		 * (parameters described below) that is called for every row in the table,
13963		 * and your logic decides if it should be included in the searching data set
13964		 * or not.
13965		 *
13966		 * Searching functions have the following input parameters:
13967		 *
13968		 * 1. `{object}` DataTables settings object: see
13969		 *    {@link DataTable.models.oSettings}
13970		 * 2. `{array|object}` Data for the row to be processed (same as the
13971		 *    original format that was passed in as the data source, or an array
13972		 *    from a DOM data source
13973		 * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which
13974		 *    can be useful to retrieve the `TR` element if you need DOM interaction.
13975		 *
13976		 * And the following return is expected:
13977		 *
13978		 * * {boolean} Include the row in the searched result set (true) or not
13979		 *   (false)
13980		 *
13981		 * Note that as with the main search ability in DataTables, technically this
13982		 * is "filtering", since it is subtractive. However, for consistency in
13983		 * naming we call it searching here.
13984		 *
13985		 *  @type array
13986		 *  @default []
13987		 *
13988		 *  @example
13989		 *    // The following example shows custom search being applied to the
13990		 *    // fourth column (i.e. the data[3] index) based on two input values
13991		 *    // from the end-user, matching the data in a certain range.
13992		 *    $.fn.dataTable.ext.search.push(
13993		 *      function( settings, data, dataIndex ) {
13994		 *        var min = document.getElementById('min').value * 1;
13995		 *        var max = document.getElementById('max').value * 1;
13996		 *        var version = data[3] == "-" ? 0 : data[3]*1;
13997		 *
13998		 *        if ( min == "" && max == "" ) {
13999		 *          return true;
14000		 *        }
14001		 *        else if ( min == "" && version < max ) {
14002		 *          return true;
14003		 *        }
14004		 *        else if ( min < version && "" == max ) {
14005		 *          return true;
14006		 *        }
14007		 *        else if ( min < version && version < max ) {
14008		 *          return true;
14009		 *        }
14010		 *        return false;
14011		 *      }
14012		 *    );
14013		 */
14014		search: [],
14015	
14016	
14017		/**
14018		 * Selector extensions
14019		 *
14020		 * The `selector` option can be used to extend the options available for the
14021		 * selector modifier options (`selector-modifier` object data type) that
14022		 * each of the three built in selector types offer (row, column and cell +
14023		 * their plural counterparts). For example the Select extension uses this
14024		 * mechanism to provide an option to select only rows, columns and cells
14025		 * that have been marked as selected by the end user (`{selected: true}`),
14026		 * which can be used in conjunction with the existing built in selector
14027		 * options.
14028		 *
14029		 * Each property is an array to which functions can be pushed. The functions
14030		 * take three attributes:
14031		 *
14032		 * * Settings object for the host table
14033		 * * Options object (`selector-modifier` object type)
14034		 * * Array of selected item indexes
14035		 *
14036		 * The return is an array of the resulting item indexes after the custom
14037		 * selector has been applied.
14038		 *
14039		 *  @type object
14040		 */
14041		selector: {
14042			cell: [],
14043			column: [],
14044			row: []
14045		},
14046	
14047	
14048		/**
14049		 * Internal functions, exposed for used in plug-ins.
14050		 * 
14051		 * Please note that you should not need to use the internal methods for
14052		 * anything other than a plug-in (and even then, try to avoid if possible).
14053		 * The internal function may change between releases.
14054		 *
14055		 *  @type object
14056		 *  @default {}
14057		 */
14058		internal: {},
14059	
14060	
14061		/**
14062		 * Legacy configuration options. Enable and disable legacy options that
14063		 * are available in DataTables.
14064		 *
14065		 *  @type object
14066		 */
14067		legacy: {
14068			/**
14069			 * Enable / disable DataTables 1.9 compatible server-side processing
14070			 * requests
14071			 *
14072			 *  @type boolean
14073			 *  @default null
14074			 */
14075			ajax: null
14076		},
14077	
14078	
14079		/**
14080		 * Pagination plug-in methods.
14081		 * 
14082		 * Each entry in this object is a function and defines which buttons should
14083		 * be shown by the pagination rendering method that is used for the table:
14084		 * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the
14085		 * buttons are displayed in the document, while the functions here tell it
14086		 * what buttons to display. This is done by returning an array of button
14087		 * descriptions (what each button will do).
14088		 *
14089		 * Pagination types (the four built in options and any additional plug-in
14090		 * options defined here) can be used through the `paginationType`
14091		 * initialisation parameter.
14092		 *
14093		 * The functions defined take two parameters:
14094		 *
14095		 * 1. `{int} page` The current page index
14096		 * 2. `{int} pages` The number of pages in the table
14097		 *
14098		 * Each function is expected to return an array where each element of the
14099		 * array can be one of:
14100		 *
14101		 * * `first` - Jump to first page when activated
14102		 * * `last` - Jump to last page when activated
14103		 * * `previous` - Show previous page when activated
14104		 * * `next` - Show next page when activated
14105		 * * `{int}` - Show page of the index given
14106		 * * `{array}` - A nested array containing the above elements to add a
14107		 *   containing 'DIV' element (might be useful for styling).
14108		 *
14109		 * Note that DataTables v1.9- used this object slightly differently whereby
14110		 * an object with two functions would be defined for each plug-in. That
14111		 * ability is still supported by DataTables 1.10+ to provide backwards
14112		 * compatibility, but this option of use is now decremented and no longer
14113		 * documented in DataTables 1.10+.
14114		 *
14115		 *  @type object
14116		 *  @default {}
14117		 *
14118		 *  @example
14119		 *    // Show previous, next and current page buttons only
14120		 *    $.fn.dataTableExt.oPagination.current = function ( page, pages ) {
14121		 *      return [ 'previous', page, 'next' ];
14122		 *    };
14123		 */
14124		pager: {},
14125	
14126	
14127		renderer: {
14128			pageButton: {},
14129			header: {}
14130		},
14131	
14132	
14133		/**
14134		 * Ordering plug-ins - custom data source
14135		 * 
14136		 * The extension options for ordering of data available here is complimentary
14137		 * to the default type based ordering that DataTables typically uses. It
14138		 * allows much greater control over the the data that is being used to
14139		 * order a column, but is necessarily therefore more complex.
14140		 * 
14141		 * This type of ordering is useful if you want to do ordering based on data
14142		 * live from the DOM (for example the contents of an 'input' element) rather
14143		 * than just the static string that DataTables knows of.
14144		 * 
14145		 * The way these plug-ins work is that you create an array of the values you
14146		 * wish to be ordering for the column in question and then return that
14147		 * array. The data in the array much be in the index order of the rows in
14148		 * the table (not the currently ordering order!). Which order data gathering
14149		 * function is run here depends on the `dt-init columns.orderDataType`
14150		 * parameter that is used for the column (if any).
14151		 *
14152		 * The functions defined take two parameters:
14153		 *
14154		 * 1. `{object}` DataTables settings object: see
14155		 *    {@link DataTable.models.oSettings}
14156		 * 2. `{int}` Target column index
14157		 *
14158		 * Each function is expected to return an array:
14159		 *
14160		 * * `{array}` Data for the column to be ordering upon
14161		 *
14162		 *  @type array
14163		 *
14164		 *  @example
14165		 *    // Ordering using `input` node values
14166		 *    $.fn.dataTable.ext.order['dom-text'] = function  ( settings, col )
14167		 *    {
14168		 *      return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
14169		 *        return $('input', td).val();
14170		 *      } );
14171		 *    }
14172		 */
14173		order: {},
14174	
14175	
14176		/**
14177		 * Type based plug-ins.
14178		 *
14179		 * Each column in DataTables has a type assigned to it, either by automatic
14180		 * detection or by direct assignment using the `type` option for the column.
14181		 * The type of a column will effect how it is ordering and search (plug-ins
14182		 * can also make use of the column type if required).
14183		 *
14184		 * @namespace
14185		 */
14186		type: {
14187			/**
14188			 * Type detection functions.
14189			 *
14190			 * The functions defined in this object are used to automatically detect
14191			 * a column's type, making initialisation of DataTables super easy, even
14192			 * when complex data is in the table.
14193			 *
14194			 * The functions defined take two parameters:
14195			 *
14196		     *  1. `{*}` Data from the column cell to be analysed
14197		     *  2. `{settings}` DataTables settings object. This can be used to
14198		     *     perform context specific type detection - for example detection
14199		     *     based on language settings such as using a comma for a decimal
14200		     *     place. Generally speaking the options from the settings will not
14201		     *     be required
14202			 *
14203			 * Each function is expected to return:
14204			 *
14205			 * * `{string|null}` Data type detected, or null if unknown (and thus
14206			 *   pass it on to the other type detection functions.
14207			 *
14208			 *  @type array
14209			 *
14210			 *  @example
14211			 *    // Currency type detection plug-in:
14212			 *    $.fn.dataTable.ext.type.detect.push(
14213			 *      function ( data, settings ) {
14214			 *        // Check the numeric part
14215			 *        if ( ! data.substring(1).match(/[0-9]/) ) {
14216			 *          return null;
14217			 *        }
14218			 *
14219			 *        // Check prefixed by currency
14220			 *        if ( data.charAt(0) == '$' || data.charAt(0) == '&pound;' ) {
14221			 *          return 'currency';
14222			 *        }
14223			 *        return null;
14224			 *      }
14225			 *    );
14226			 */
14227			detect: [],
14228	
14229	
14230			/**
14231			 * Type based search formatting.
14232			 *
14233			 * The type based searching functions can be used to pre-format the
14234			 * data to be search on. For example, it can be used to strip HTML
14235			 * tags or to de-format telephone numbers for numeric only searching.
14236			 *
14237			 * Note that is a search is not defined for a column of a given type,
14238			 * no search formatting will be performed.
14239			 * 
14240			 * Pre-processing of searching data plug-ins - When you assign the sType
14241			 * for a column (or have it automatically detected for you by DataTables
14242			 * or a type detection plug-in), you will typically be using this for
14243			 * custom sorting, but it can also be used to provide custom searching
14244			 * by allowing you to pre-processing the data and returning the data in
14245			 * the format that should be searched upon. This is done by adding
14246			 * functions this object with a parameter name which matches the sType
14247			 * for that target column. This is the corollary of <i>afnSortData</i>
14248			 * for searching data.
14249			 *
14250			 * The functions defined take a single parameter:
14251			 *
14252		     *  1. `{*}` Data from the column cell to be prepared for searching
14253			 *
14254			 * Each function is expected to return:
14255			 *
14256			 * * `{string|null}` Formatted string that will be used for the searching.
14257			 *
14258			 *  @type object
14259			 *  @default {}
14260			 *
14261			 *  @example
14262			 *    $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) {
14263			 *      return d.replace(/\n/g," ").replace( /<.*?>/g, "" );
14264			 *    }
14265			 */
14266			search: {},
14267	
14268	
14269			/**
14270			 * Type based ordering.
14271			 *
14272			 * The column type tells DataTables what ordering to apply to the table
14273			 * when a column is sorted upon. The order for each type that is defined,
14274			 * is defined by the functions available in this object.
14275			 *
14276			 * Each ordering option can be described by three properties added to
14277			 * this object:
14278			 *
14279			 * * `{type}-pre` - Pre-formatting function
14280			 * * `{type}-asc` - Ascending order function
14281			 * * `{type}-desc` - Descending order function
14282			 *
14283			 * All three can be used together, only `{type}-pre` or only
14284			 * `{type}-asc` and `{type}-desc` together. It is generally recommended
14285			 * that only `{type}-pre` is used, as this provides the optimal
14286			 * implementation in terms of speed, although the others are provided
14287			 * for compatibility with existing Javascript sort functions.
14288			 *
14289			 * `{type}-pre`: Functions defined take a single parameter:
14290			 *
14291		     *  1. `{*}` Data from the column cell to be prepared for ordering
14292			 *
14293			 * And return:
14294			 *
14295			 * * `{*}` Data to be sorted upon
14296			 *
14297			 * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort
14298			 * functions, taking two parameters:
14299			 *
14300		     *  1. `{*}` Data to compare to the second parameter
14301		     *  2. `{*}` Data to compare to the first parameter
14302			 *
14303			 * And returning:
14304			 *
14305			 * * `{*}` Ordering match: <0 if first parameter should be sorted lower
14306			 *   than the second parameter, ===0 if the two parameters are equal and
14307			 *   >0 if the first parameter should be sorted height than the second
14308			 *   parameter.
14309			 * 
14310			 *  @type object
14311			 *  @default {}
14312			 *
14313			 *  @example
14314			 *    // Numeric ordering of formatted numbers with a pre-formatter
14315			 *    $.extend( $.fn.dataTable.ext.type.order, {
14316			 *      "string-pre": function(x) {
14317			 *        a = (a === "-" || a === "") ? 0 : a.replace( /[^\d\-\.]/g, "" );
14318			 *        return parseFloat( a );
14319			 *      }
14320			 *    } );
14321			 *
14322			 *  @example
14323			 *    // Case-sensitive string ordering, with no pre-formatting method
14324			 *    $.extend( $.fn.dataTable.ext.order, {
14325			 *      "string-case-asc": function(x,y) {
14326			 *        return ((x < y) ? -1 : ((x > y) ? 1 : 0));
14327			 *      },
14328			 *      "string-case-desc": function(x,y) {
14329			 *        return ((x < y) ? 1 : ((x > y) ? -1 : 0));
14330			 *      }
14331			 *    } );
14332			 */
14333			order: {}
14334		},
14335	
14336		/**
14337		 * Unique DataTables instance counter
14338		 *
14339		 * @type int
14340		 * @private
14341		 */
14342		_unique: 0,
14343	
14344	
14345		//
14346		// Depreciated
14347		// The following properties are retained for backwards compatib
vendor: 3,173 bytes, lines 14347-14484
14347lity only.
14348		// The should not be used in new projects and will be removed in a future
14349		// version
14350		//
14351	
14352		/**
14353		 * Version check function.
14354		 *  @type function
14355		 *  @depreciated Since 1.10
14356		 */
14357		fnVersionCheck: DataTable.fnVersionCheck,
14358	
14359	
14360		/**
14361		 * Index for what 'this' index API functions should use
14362		 *  @type int
14363		 *  @deprecated Since v1.10
14364		 */
14365		iApiIndex: 0,
14366	
14367	
14368		/**
14369		 * jQuery UI class container
14370		 *  @type object
14371		 *  @deprecated Since v1.10
14372		 */
14373		oJUIClasses: {},
14374	
14375	
14376		/**
14377		 * Software version
14378		 *  @type string
14379		 *  @deprecated Since v1.10
14380		 */
14381		sVersion: DataTable.version
14382	};
14383	
14384	
14385	//
14386	// Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts
14387	//
14388	$.extend( _ext, {
14389		afnFiltering: _ext.search,
14390		aTypes:       _ext.type.detect,
14391		ofnSearch:    _ext.type.search,
14392		oSort:        _ext.type.order,
14393		afnSortData:  _ext.order,
14394		aoFeatures:   _ext.feature,
14395		oApi:         _ext.internal,
14396		oStdClasses:  _ext.classes,
14397		oPagination:  _ext.pager
14398	} );
14399	
14400	
14401	$.extend( DataTable.ext.classes, {
14402		"sTable": "dataTable",
14403		"sNoFooter": "no-footer",
14404	
14405		/* Paging buttons */
14406		"sPageButton": "paginate_button",
14407		"sPageButtonActive": "current",
14408		"sPageButtonDisabled": "disabled hide",
14409	
14410		/* Striping classes */
14411		"sStripeOdd": "odd",
14412		"sStripeEven": "even",
14413	
14414		/* Empty row */
14415		"sRowEmpty": "dataTables_empty",
14416	
14417		/* Features */
14418		"sWrapper": "dataTables_wrapper",
14419		"sFilter": "dataTables_filter",
14420		"sInfo": "dataTables_info",
14421		"sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
14422		"sLength": "dataTables_length",
14423		"sProcessing": "dataTables_processing",
14424	
14425		/* Sorting */
14426		"sSortAsc": "sorting_asc",
14427		"sSortDesc": "sorting_desc",
14428		"sSortable": "sorting", /* Sortable in both directions */
14429		"sSortableAsc": "sorting_asc_disabled",
14430		"sSortableDesc": "sorting_desc_disabled",
14431		"sSortableNone": "sorting_disabled",
14432		"sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
14433	
14434		/* Filtering */
14435		"sFilterInput": "",
14436	
14437		/* Page length */
14438		"sLengthSelect": "",
14439	
14440		/* Scrolling */
14441		"sScrollWrapper": "dataTables_scroll",
14442		"sScrollHead": "dataTables_scrollHead",
14443		"sScrollHeadInner": "dataTables_scrollHeadInner",
14444		"sScrollBody": "dataTables_scrollBody",
14445		"sScrollFoot": "dataTables_scrollFoot",
14446		"sScrollFootInner": "dataTables_scrollFootInner",
14447	
14448		/* Misc */
14449		"sHeaderTH": "",
14450		"sFooterTH": "",
14451	
14452		// Deprecated
14453		"sSortJUIAsc": "",
14454		"sSortJUIDesc": "",
14455		"sSortJUI": "",
14456		"sSortJUIAscAllowed": "",
14457		"sSortJUIDescAllowed": "",
14458		"sSortJUIWrapper": "",
14459		"sSortIcon": "",
14460		"sJUIHeader": "",
14461		"sJUIFooter": ""
14462	} );
14463	
14464	
14465	var extPagination = DataTable.ext.pager;
14466	
14467	function _numbers ( page, pages ) {
14468		var
14469			numbers = [],
14470			buttons = extPagination.numbers_length,
14471			half = Math.floor( buttons / 2 ),
14472			i = 1;
14473	
14474		if ( pages <= buttons ) {
14475			numbers = _range( 0, pages );
14476		}
14477		else if ( page <= half ) {
14478			numbers = _range( 0, buttons-2 );
14479			numbers.push( 'ellipsis' );
14480			numbers.push( pages-1 );
14481		}
14482		else if ( page >= pages - 1 - half ) {
14483			numbers = _range( pages-(buttons-2), pages );
14484			numbers.splice( 0, 0, 'ellipsis' );
14484 // no unshift in ie6
14485			numbers.splice( 0, 0, 0 );
14486		}
14487		else {
14488			numbers = _range( page-half+2, page+half-1 );
14489			numbers.push( 'ellipsis' );
14490			numbers.push( pages-1 );
14491			numbers.splice( 0, 0, 'ellipsis' );
14492			numbers.splice( 0, 0, 0 );
14493		}
14494	
14495		numbers.DT_el = 'span';
14496		return numbers;
14497	}
14498	
14499	
14500	$.extend( extPagination, {
14501		simple: function ( page, pages ) {
14502			return [ 'previous', 'next' ];
14503		},
14504	
14505		full: function ( page, pages ) {
14506			return [  'first', 'previous', 'next', 'last' ];
14507		},
14508	
14509		numbers: function ( page, pages ) {
14510			return [ _numbers(page, pages) ];
14511		},
14512	
14513		simple_numbers: function ( page, pages ) {
14514			return [ 'previous', _numbers(page, pages), 'next' ];
14515		},
14516	
14517		full_numbers: function ( page, pages ) {
14518			return [ 'first', 'previous', _numbers(page, pages), 'next', 'last' ];
14519		},
14520		
14521		first_last_numbers: function (page, pages) {
14522	 		return ['first', _numbers(page, pages), 'last'];
14523	 	},
14524	
14525		// For testing and plug-ins to use
14526		_numbers: _numbers,
14527	
14528		// Number of number buttons (including ellipsis) to show. _Must be odd!_
14529		numbers_length: 7
14530	} );
14531	
14532	
14533	$.extend( true, DataTable.ext.renderer, {
14534		pageButton: {
14535			_: function ( settings, host, idx, buttons, page, pages ) {
14536				var classes = settings.oClasses;
14537				var lang = settings.oLanguage.oPaginate;
14538				var aria = settings.oLanguage.oAria.paginate || {};
14539				var btnDisplay, btnClass, counter=0;
14540	
14541				var attach = function( container, buttons ) {
14542					var i, ien, node, button;
14543					var clickHandler = function ( e ) {
14544						_fnPageChange( settings, e.data.action, true );
14545					};
14546	
14547					for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
14548						button = buttons[i];
14549	
14550						if ( $.isArray( button ) ) {
14551							var inner = $( '<'+(button.DT_el || 'div')+'/>' )
14552								.appendTo( container );
14553							attach( inner, button );
14554						}
14555						else {
14556							btnDisplay = null;
14557							btnClass = '';
14558	
14559							switch ( button ) {
14560								case 'ellipsis':
14561									container.append('<span class="ellipsis">&#x2026;</span>');
14562									break;
14563	
14564								case 'first':
14565									btnDisplay = lang.sFirst;
14566									btnClass = button + (page > 0 ?
14567										'' : ' '+classes.sPageButtonDisabled);
14568									break;
14569	
14570								case 'previous':
14571									btnDisplay = lang.sPrevious;
14572									btnClass = button + (page > 0 ?
14573										'' : ' '+classes.sPageButtonDisabled);
14574									break;
14575	
14576								case 'next':
14577									btnDisplay = lang.sNext;
14578									btnClass = button + (page < pages-1 ?
14579										'' : ' '+classes.sPageButtonDisabled);
14580									break;
14581	
14582								case 'last':
14583									btnDisplay = lang.sLast;
14584									btnClass = button + (page < pages-1 ?
14585										'' : ' '+classes.sPageButtonDisabled);
14586									break;
14587	
14588								default:
14589									btnDisplay = button + 1;
14590									btnClass = page === button ?
14591										classes.sPageButtonActive : '';
14592									break;
14593							}
14594	
14595							if ( btnDisplay !== null ) {
14596								node = $('<a>', {
14597										'class': classes.sPageButton+' '+btnClass,
14598										'aria-controls': settings.sTableId,
14599										'aria-label': aria[ button ],
14600										'data-dt-idx': counter,
14601										'tabindex': settings.iTabIndex,
14602										'id': idx === 0 && typeof button === 'string' ?
14603											settings.sTableId +'_'+ button :
14604											null
14605									} )
14606									.html( btnDisplay )
14607									.appendTo( container );
14608	
14609								_fnBindAction(
14610									node, {action: button}, clickHandler
14611								);
14612	
14613								counter++;
14614							}
14615						}
14616					}
14617				};
14618	
14619				// IE9 throws an 'unknown error' if document.activeElement is used
14620				// inside an iframe or frame. Try / catch the error. Not good for
14621				// accessibility, but neither are frames.
14622				var activeEl;
14623	
14624				try {
14625					// Because this approach is destroying and recreating the paging
14626					// elements, focus is lost on the select button which is bad for
14627					// accessibility. So we want to restore focus once the draw has
14628					// completed
14629					activeEl = $(host).find(document.activeElement).data('dt-idx');
14630				}
14631				catch (e) {}
14632	
14633				attach( $(host).empty(), buttons );
14634	
14635				if ( activeEl !== undefined ) {
14636					$(host).find( '[data-dt-idx='+activeEl+']' ).focus();
14637				}
14638			}
14639		}
14640	} );
14641	
14642	
14643	
14644	// Built in type detection. See model.ext.aTypes for information about
14645	// what is required from this methods.
14646	$.extend( DataTable.ext.type.detect, [
vendor: 18,465 bytes, lines 14647-15246
14647		// Plain numbers - first since V8 detects some plain numbers as dates
14648		// e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...).
14649		function ( d, settings )
14650		{
14651			var decimal = settings.oLanguage.sDecimal;
14652			return _isNumber( d, decimal ) ? 'num'+decimal : null;
14653		},
14654	
14655		// Dates (only those recognised by the browser's Date.parse)
14656		function ( d, settings )
14657		{
14658			// V8 tries _very_ hard to make a string passed into `Date.parse()`
14659			// valid, so we need to use a regex to restrict date formats. Use a
14660			// plug-in for anything other than ISO8601 style strings
14661			if ( d && !(d instanceof Date) && ! _re_date.test(d) ) {
14662				return null;
14663			}
14664			var parsed = Date.parse(d);
14665			return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null;
14666		},
14667	
14668		// Formatted numbers
14669		function ( d, settings )
14670		{
14671			var decimal = settings.oLanguage.sDecimal;
14672			return _isNumber( d, decimal, true ) ? 'num-fmt'+decimal : null;
14673		},
14674	
14675		// HTML numeric
14676		function ( d, settings )
14677		{
14678			var decimal = settings.oLanguage.sDecimal;
14679			return _htmlNumeric( d, decimal ) ? 'html-num'+decimal : null;
14680		},
14681	
14682		// HTML numeric, formatted
14683		function ( d, settings )
14684		{
14685			var decimal = settings.oLanguage.sDecimal;
14686			return _htmlNumeric( d, decimal, true ) ? 'html-num-fmt'+decimal : null;
14687		},
14688	
14689		// HTML (this is strict checking - there must be html)
14690		function ( d, settings )
14691		{
14692			return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ?
14693				'html' : null;
14694		}
14695	] );
14696	
14697	
14698	
14699	// Filter formatting functions. See model.ext.ofnSearch for information about
14700	// what is required from these methods.
14701	// 
14702	// Note that additional search methods are added for the html numbers and
14703	// html formatted numbers by `_addNumericSort()` when we know what the decimal
14704	// place is
14705	
14706	
14707	$.extend( DataTable.ext.type.search, {
14708		html: function ( data ) {
14709			return _empty(data) ?
14710				data :
14711				typeof data === 'string' ?
14712					data
14713						.replace( _re_new_lines, " " )
14714						.replace( _re_html, "" ) :
14715					'';
14716		},
14717	
14718		string: function ( data ) {
14719			return _empty(data) ?
14720				data :
14721				typeof data === 'string' ?
14722					data.replace( _re_new_lines, " " ) :
14723					data;
14724		}
14725	} );
14726	
14727	
14728	
14729	var __numericReplace = function ( d, decimalPlace, re1, re2 ) {
14730		if ( d !== 0 && (!d || d === '-') ) {
14731			return -Infinity;
14732		}
14733	
14734		// If a decimal place other than `.` is used, it needs to be given to the
14735		// function so we can detect it and replace with a `.` which is the only
14736		// decimal place Javascript recognises - it is not locale aware.
14737		if ( decimalPlace ) {
14738			d = _numToDecimal( d, decimalPlace );
14739		}
14740	
14741		if ( d.replace ) {
14742			if ( re1 ) {
14743				d = d.replace( re1, '' );
14744			}
14745	
14746			if ( re2 ) {
14747				d = d.replace( re2, '' );
14748			}
14749		}
14750	
14751		return d * 1;
14752	};
14753	
14754	
14755	// Add the numeric 'deformatting' functions for sorting and search. This is done
14756	// in a function to provide an easy ability for the language options to add
14757	// additional methods if a non-period decimal place is used.
14758	function _addNumericSort ( decimalPlace ) {
14759		$.each(
14760			{
14761				// Plain numbers
14762				"num": function ( d ) {
14763					return __numericReplace( d, decimalPlace );
14764				},
14765	
14766				// Formatted numbers
14767				"num-fmt": function ( d ) {
14768					return __numericReplace( d, decimalPlace, _re_formatted_numeric );
14769				},
14770	
14771				// HTML numeric
14772				"html-num": function ( d ) {
14773					return __numericReplace( d, decimalPlace, _re_html );
14774				},
14775	
14776				// HTML numeric, formatted
14777				"html-num-fmt": function ( d ) {
14778					return __numericReplace( d, decimalPlace, _re_html, _re_formatted_numeric );
14779				}
14780			},
14781			function ( key, fn ) {
14782				// Add the ordering method
14783				_ext.type.order[ key+decimalPlace+'-pre' ] = fn;
14784	
14785				// For HTML types add a search formatter that will strip the HTML
14786				if ( key.match(/^html\-/) ) {
14787					_ext.type.search[ key+decimalPlace ] = _ext.type.search.html;
14788				}
14789			}
14790		);
14791	}
14792	
14793	
14794	// Default sort methods
14795	$.extend( _ext.type.order, {
14796		// Dates
14797		"date-pre": function ( d ) {
14798			var ts = Date.parse( d );
14799			return isNaN(ts) ? -Infinity : ts;
14800		},
14801	
14802		// html
14803		"html-pre": function ( a ) {
14804			return _empty(a) ?
14805				'' :
14806				a.replace ?
14807					a.replace( /<.*?>/g, "" ).toLowerCase() :
14808					a+'';
14809		},
14810	
14811		// string
14812		"string-pre": function ( a ) {
14813			// This is a little complex, but faster than always calling toString,
14814			// http://jsperf.com/tostring-v-check
14815			return _empty(a) ?
14816				'' :
14817				typeof a === 'string' ?
14818					a.toLowerCase() :
14819					! a.toString ?
14820						'' :
14821						a.toString();
14822		},
14823	
14824		// string-asc and -desc are retained only for compatibility with the old
14825		// sort methods
14826		"string-asc": function ( x, y ) {
14827			return ((x < y) ? -1 : ((x > y) ? 1 : 0));
14828		},
14829	
14830		"string-desc": function ( x, y ) {
14831			return ((x < y) ? 1 : ((x > y) ? -1 : 0));
14832		}
14833	} );
14834	
14835	
14836	// Numeric sorting types - order doesn't matter here
14837	_addNumericSort( '' );
14838	
14839	
14840	$.extend( true, DataTable.ext.renderer, {
14841		header: {
14842			_: function ( settings, cell, column, classes ) {
14843				// No additional mark-up required
14844				// Attach a sort listener to update on sort - note that using the
14845				// `DT` namespace will allow the event to be removed automatically
14846				// on destroy, while the `dt` namespaced event is the one we are
14847				// listening for
14848				$(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
14849					if ( settings !== ctx ) { // need to check this this is the host
14850						return;               // table, not a nested one
14851					}
14852	
14853					var colIdx = column.idx;
14854	
14855					cell.removeClass(
14856							column.sSortingClass +' '+
14857							classes.sSortAsc +' '+
14858							classes.sSortDesc
14859						);
14860					cell.find(".sort-icon").removeClass(
14861							column.sSortingClass +' '+
14862							classes.sSortAsc +' '+
14863							classes.sSortDesc
14864						);
14865					cell.find(".sort-icon").addClass( columns[ colIdx ] == 'asc' ?
14866							classes.sSortAsc : columns[ colIdx ] == 'desc' ?
14867								classes.sSortDesc :
14868								column.sSortingClass
14869						);
14870				} );
14871			},
14872	
14873			jqueryui: function ( settings, cell, column, classes ) {
14874				$('<div/>')
14875					.addClass( classes.sSortJUIWrapper )
14876					.append( cell.contents() )
14877					.append( $('<span/>')
14878						.addClass( classes.sSortIcon+' '+column.sSortingClassJUI )
14879					)
14880					.appendTo( cell );
14881	
14882				// Attach a sort listener to update on sort
14883				$(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
14884					if ( settings !== ctx ) {
14885						return;
14886					}
14887	
14888					var colIdx = column.idx;
14889					cell.removeClass( classes.sSortAsc +" "+classes.sSortDesc );
14890					cell.find(".sort-icon").removeClass( classes.sSortAsc +" "+classes.sSortDesc );
14891					cell.find(".sort-icon").addClass( columns[ colIdx ] == 'asc' ?
14892							classes.sSortAsc : columns[ colIdx ] == 'desc' ?
14893								classes.sSortDesc :
14894								column.sSortingClass
14895						);
14896	
14897					cell
14898						.find( 'span.'+classes.sSortIcon )
14899						.removeClass(
14900							classes.sSortJUIAsc +" "+
14901							classes.sSortJUIDesc +" "+
14902							classes.sSortJUI +" "+
14903							classes.sSortJUIAscAllowed +" "+
14904							classes.sSortJUIDescAllowed
14905						)
14906						.addClass( columns[ colIdx ] == 'asc' ?
14907							classes.sSortJUIAsc : columns[ colIdx ] == 'desc' ?
14908								classes.sSortJUIDesc :
14909								column.sSortingClassJUI
14910						);
14911				} );
14912			}
14913		}
14914	} );
14915	
14916	/*
14917	 * Public helper functions. These aren't used internally by DataTables, or
14918	 * called by any of the options passed into DataTables, but they can be used
14919	 * externally by developers working with DataTables. They are helper functions
14920	 * to make working with DataTables a little bit easier.
14921	 */
14922	
14923	var __htmlEscapeEntities = function ( d ) {
14924		return typeof d === 'string' ?
14925			d.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;') :
14926			d;
14927	};
14928	
14929	/**
14930	 * Helpers for `columns.render`.
14931	 *
14932	 * The options defined here can be used with the `columns.render` initialisation
14933	 * option to provide a display renderer. The following functions are defined:
14934	 *
14935	 * * `number` - Will format numeric data (defined by `columns.data`) for
14936	 *   display, retaining the original unformatted data for sorting and filtering.
14937	 *   It takes 5 parameters:
14938	 *   * `string` - Thousands grouping separator
14939	 *   * `string` - Decimal point indicator
14940	 *   * `integer` - Number of decimal points to show
14941	 *   * `string` (optional) - Prefix.
14942	 *   * `string` (optional) - Postfix (/suffix).
14943	 * * `text` - Escape HTML to help prevent XSS attacks. It has no optional
14944	 *   parameters.
14945	 *
14946	 * @example
14947	 *   // Column definition using the number renderer
14948	 *   {
14949	 *     data: "salary",
14950	 *     render: $.fn.dataTable.render.number( '\'', '.', 0, '$' )
14951	 *   }
14952	 *
14953	 * @namespace
14954	 */
14955	DataTable.render = {
14956		number: function ( thousands, decimal, precision, prefix, postfix ) {
14957			return {
14958				display: function ( d ) {
14959					if ( typeof d !== 'number' && typeof d !== 'string' ) {
14960						return d;
14961					}
14962	
14963					var negative = d < 0 ? '-' : '';
14964					var flo = parseFloat( d );
14965	
14966					// If NaN then there isn't much formatting that we can do - just
14967					// return immediately, escaping any HTML (this was supposed to
14968					// be a number after all)
14969					if ( isNaN( flo ) ) {
14970						return __htmlEscapeEntities( d );
14971					}
14972	
14973					flo = flo.toFixed( precision );
14974					d = Math.abs( flo );
14975	
14976					var intPart = parseInt( d, 10 );
14977					var floatPart = precision ?
14978						decimal+(d - intPart).toFixed( precision ).substring( 2 ):
14979						'';
14980	
14981					return negative + (prefix||'') +
14982						intPart.toString().replace(
14983							/\B(?=(\d{3})+(?!\d))/g, thousands
14984						) +
14985						floatPart +
14986						(postfix||'');
14987				}
14988			};
14989		},
14990	
14991		text: function () {
14992			return {
14993				display: __htmlEscapeEntities
14994			};
14995		}
14996	};
14997	
14998	
14999	/*
15000	 * This is really a good bit rubbish this method of exposing the internal methods
15001	 * publicly... - To be fixed in 2.0 using methods on the prototype
15002	 */
15003	
15004	
15005	/**
15006	 * Create a wrapper function for exporting an internal functions to an external API.
15007	 *  @param {string} fn API function name
15008	 *  @returns {function} wrapped function
15009	 *  @memberof DataTable#internal
15010	 */
15011	function _fnExternApiFunc (fn)
15012	{
15013		return function() {
15014			var args = [_fnSettingsFromNode( this[DataTable.ext.iApiIndex] )].concat(
15015				Array.prototype.slice.call(arguments)
15016			);
15017			return DataTable.ext.internal[fn].apply( this, args );
15018		};
15019	}
15020	
15021	
15022	/**
15023	 * Reference to internal functions for use by plug-in developers. Note that
15024	 * these methods are references to internal functions and are considered to be
15025	 * private. If you use these methods, be aware that they are liable to change
15026	 * between versions.
15027	 *  @namespace
15028	 */
15029	$.extend( DataTable.ext.internal, {
15030		_fnExternApiFunc: _fnExternApiFunc,
15031		_fnBuildAjax: _fnBuildAjax,
15032		_fnAjaxUpdate: _fnAjaxUpdate,
15033		_fnAjaxParameters: _fnAjaxParameters,
15034		_fnAjaxUpdateDraw: _fnAjaxUpdateDraw,
15035		_fnAjaxDataSrc: _fnAjaxDataSrc,
15036		_fnAddColumn: _fnAddColumn,
15037		_fnColumnOptions: _fnColumnOptions,
15038		_fnAdjustColumnSizing: _fnAdjustColumnSizing,
15039		_fnVisibleToColumnIndex: _fnVisibleToColumnIndex,
15040		_fnColumnIndexToVisible: _fnColumnIndexToVisible,
15041		_fnVisbleColumns: _fnVisbleColumns,
15042		_fnGetColumns: _fnGetColumns,
15043		_fnColumnTypes: _fnColumnTypes,
15044		_fnApplyColumnDefs: _fnApplyColumnDefs,
15045		_fnHungarianMap: _fnHungarianMap,
15046		_fnCamelToHungarian: _fnCamelToHungarian,
15047		_fnLanguageCompat: _fnLanguageCompat,
15048		_fnBrowserDetect: _fnBrowserDetect,
15049		_fnAddData: _fnAddData,
15050		_fnAddTr: _fnAddTr,
15051		_fnNodeToDataIndex: _fnNodeToDataIndex,
15052		_fnNodeToColumnIndex: _fnNodeToColumnIndex,
15053		_fnGetCellData: _fnGetCellData,
15054		_fnSetCellData: _fnSetCellData,
15055		_fnSplitObjNotation: _fnSplitObjNotation,
15056		_fnGetObjectDataFn: _fnGetObjectDataFn,
15057		_fnSetObjectDataFn: _fnSetObjectDataFn,
15058		_fnGetDataMaster: _fnGetDataMaster,
15059		_fnClearTable: _fnClearTable,
15060		_fnDeleteIndex: _fnDeleteIndex,
15061		_fnInvalidate: _fnInvalidate,
15062		_fnGetRowElements: _fnGetRowElements,
15063		_fnCreateTr: _fnCreateTr,
15064		_fnBuildHead: _fnBuildHead,
15065		_fnDrawHead: _fnDrawHead,
15066		_fnDraw: _fnDraw,
15067		_fnReDraw: _fnReDraw,
15068		_fnAddOptionsHtml: _fnAddOptionsHtml,
15069		_fnDetectHeader: _fnDetectHeader,
15070		_fnGetUniqueThs: _fnGetUniqueThs,
15071		_fnFeatureHtmlFilter: _fnFeatureHtmlFilter,
15072		_fnFilterComplete: _fnFilterComplete,
15073		_fnFilterCustom: _fnFilterCustom,
15074		_fnFilterColumn: _fnFilterColumn,
15075		_fnFilter: _fnFilter,
15076		_fnFilterCreateSearch: _fnFilterCreateSearch,
15077		_fnEscapeRegex: _fnEscapeRegex,
15078		_fnFilterData: _fnFilterData,
15079		_fnFeatureHtmlInfo: _fnFeatureHtmlInfo,
15080		_fnUpdateInfo: _fnUpdateInfo,
15081		_fnInfoMacros: _fnInfoMacros,
15082		_fnInitialise: _fnInitialise,
15083		_fnInitComplete: _fnInitComplete,
15084		_fnLengthChange: _fnLengthChange,
15085		_fnFeatureHtmlLength: _fnFeatureHtmlLength,
15086		_fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate,
15087		_fnPageChange: _fnPageChange,
15088		_fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing,
15089		_fnProcessingDisplay: _fnProcessingDisplay,
15090		_fnFeatureHtmlTable: _fnFeatureHtmlTable,
15091		_fnScrollDraw: _fnScrollDraw,
15092		_fnApplyToChildren: _fnApplyToChildren,
15093		_fnCalculateColumnWidths: _fnCalculateColumnWidths,
15094		_fnThrottle: _fnThrottle,
15095		_fnConvertToWidth: _fnConvertToWidth,
15096		_fnGetWidestNode: _fnGetWidestNode,
15097		_fnGetMaxLenString: _fnGetMaxLenString,
15098		_fnStringToCss: _fnStringToCss,
15099		_fnSortFlatten: _fnSortFlatten,
15100		_fnSort: _fnSort,
15101		_fnSortAria: _fnSortAria,
15102		_fnSortListener: _fnSortListener,
15103		_fnSortAttachListener: _fnSortAttachListener,
15104		_fnSortingClasses: _fnSortingClasses,
15105		_fnSortData: _fnSortData,
15106		_fnSaveState: _fnSaveState,
15107		_fnLoadState: _fnLoadState,
15108		_fnSettingsFromNode: _fnSettingsFromNode,
15109		_fnLog: _fnLog,
15110		_fnMap: _fnMap,
15111		_fnBindAction: _fnBindAction,
15112		_fnCallbackReg: _fnCallbackReg,
15113		_fnCallbackFire: _fnCallbackFire,
15114		_fnLengthOverflow: _fnLengthOverflow,
15115		_fnRenderer: _fnRenderer,
15116		_fnDataSource: _fnDataSource,
15117		_fnRowAttributes: _fnRowAttributes,
15118		_fnExtend: _fnExtend,
15119		_fnCalculateEnd: function () {} // Used by a lot of plug-ins, but redundant
15120		                                // in 1.10, so this dead-end function is
15121		                                // added to prevent errors
15122	} );
15123	
15124
15125	// jQuery access
15126	$.fn.dataTable = DataTable;
15127
15128	// Provide access to the host jQuery object (circular reference)
15129	DataTable.$ = $;
15130
15131	// Legacy aliases
15132	$.fn.dataTableSettings = DataTable.settings;
15133	$.fn.dataTableExt = DataTable.ext;
15134
15135	// With a capital `D` we return a DataTables API instance rather than a
15136	// jQuery object
15137	$.fn.DataTable = function ( opts ) {
15138		return $(this).dataTable( opts ).api();
15139	};
15140
15141	// All properties that are available to $.fn.dataTable should also be
15142	// available on $.fn.DataTable
15143	$.each( DataTable, function ( prop, val ) {
15144		$.fn.DataTable[ prop ] = val;
15145	} );
15146
15147
15148	// Information about events fired by DataTables - for documentation.
15149	/**
15150	 * Draw event, fired whenever the table is redrawn on the page, at the same
15151	 * point as fnDrawCallback. This may be useful for binding events or
15152	 * performing calculations when the table is altered at all.
15153	 *  @name DataTable#draw.dt
15154	 *  @event
15155	 *  @param {event} e jQuery event object
15156	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15157	 */
15158
15159	/**
15160	 * Search event, fired when the searching applied to the table (using the
15161	 * built-in global search, or column filters) is altered.
15162	 *  @name DataTable#search.dt
15163	 *  @event
15164	 *  @param {event} e jQuery event object
15165	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15166	 */
15167
15168	/**
15169	 * Page change event, fired when the paging of the table is altered.
15170	 *  @name DataTable#page.dt
15171	 *  @event
15172	 *  @param {event} e jQuery event object
15173	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15174	 */
15175
15176	/**
15177	 * Order event, fired when the ordering applied to the table is altered.
15178	 *  @name DataTable#order.dt
15179	 *  @event
15180	 *  @param {event} e jQuery event object
15181	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15182	 */
15183
15184	/**
15185	 * DataTables initialisation complete event, fired when the table is fully
15186	 * drawn, including Ajax data loaded, if Ajax data is required.
15187	 *  @name DataTable#init.dt
15188	 *  @event
15189	 *  @param {event} e jQuery event object
15190	 *  @param {object} oSettings DataTables settings object
15191	 *  @param {object} json The JSON object request from the server - only
15192	 *    present if client-side Ajax sourced data is used</li></ol>
15193	 */
15194
15195	/**
15196	 * State save event, fired when the table has changed state a new state save
15197	 * is required. This event allows modification of the state saving object
15198	 * prior to actually doing the save, including addition or other state
15199	 * properties (for plug-ins) or modification of a DataTables core property.
15200	 *  @name DataTable#stateSaveParams.dt
15201	 *  @event
15202	 *  @param {event} e jQuery event object
15203	 *  @param {object} oSettings DataTables settings object
15204	 *  @param {object} json The state information to be saved
15205	 */
15206
15207	/**
15208	 * State load event, fired when the table is loading state from the stored
15209	 * data, but prior to the settings object being modified by the saved state
15210	 * - allowing modification of the saved state is required or loading of
15211	 * state for a plug-in.
15212	 *  @name DataTable#stateLoadParams.dt
15213	 *  @event
15214	 *  @param {event} e jQuery event object
15215	 *  @param {object} oSettings DataTables settings object
15216	 *  @param {object} json The saved state information
15217	 */
15218
15219	/**
15220	 * State loaded event, fired when state has been loaded from stored data and
15221	 * the settings object has been modified by the loaded data.
15222	 *  @name DataTable#stateLoaded.dt
15223	 *  @event
15224	 *  @param {event} e jQuery event object
15225	 *  @param {object} oSettings DataTables settings object
15226	 *  @param {object} json The saved state information
15227	 */
15228
15229	/**
15230	 * Processing event, fired when DataTables is doing some kind of processing
15231	 * (be it, order, searcg or anything else). It can be used to indicate to
15232	 * the end user that there is something happening, or that something has
15233	 * finished.
15234	 *  @name DataTable#processing.dt
15235	 *  @event
15236	 *  @param {event} e jQuery event object
15237	 *  @param {object} oSettings DataTables settings object
15238	 *  @param {boolean} bShow Flag for if DataTables is doing processing or not
15239	 */
15240
15241	/**
15242	 * Ajax (XHR) event, fired whenever an Ajax request is completed from a
15243	 * request to made to the server for new data. This event is called before
15244	 * DataTables processed the returned data, so it can also be used to pre-
15245	 * process the data returned from the server, if needed.
15246	 *
15247	 * Note that this trigger is called in `fnServerData`, if you override
15248	 * `fnServerData` and which to use this event, you need to trigger it in you
15249	 * success function.
15250	 *  @name DataTable#xhr.dt
15251	 *  @event
15252	 *  @param {event} e jQuery event object
15253	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15254	 *  @param {object} json JSON returned from the server
15255	 *
15256	 *  @example
15257	 *     // Use a custom property returned from the server in another DOM element
15258	 *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
15259	 *       $('#status').html( json.status );
15260	 *     } );
15261	 *
15262	 *  @example
15263	 *     // Pre-process the data returned from the server
15264	 *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
15265	 *       for ( var i=0, ien=json.aaData.length ; i<ien ; i++ ) {
15266	 *         json.aaData[i].sum = json.aaData[i].one + json.aaData[i].two;
15267	 *       }
15268	 *       // Note no return - manipulate the data directly in the JSON object.
15269	 *     } );
15270	 */
15271
15272	/**
15273	 * Destroy event, fired when the DataTable is destroyed by calling fnDestroy
15274	 * or passing the bDestroy:true parameter in the initialisation object. This
15275	 * can be used to remove bound events, added DOM nodes, etc.
15276	 *  @name DataTable#destroy.dt
15277	 *  @event
15278	 *  @param {event} e jQuery event object
15279	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15280	 */
15281
15282	/**
15283	 * Page length change event, fired when number of records to show on each
15284	 * page (the length) is changed.
15285	 *  @name DataTable#length.dt
15286	 *  @event
15287	 *  @param {event} e jQuery event object
15288	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15289	 *  @param {integer} len New length
15290	 */
15291
15292	/**
15293	 * Column sizing has changed.
15294	 *  @name DataTable#column-sizing.dt
15295	 *  @event
15296	 *  @param {event} e jQuery event object
15297	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15298	 */
15299
15300	/**
15301	 * Column visibility has changed.
15302	 *  @name DataTable#column-visibility.dt
15303	 *  @event
15304	 *  @param {event} e jQuery event object
15305	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15306	 *  @param {int} column Column index
15307	 *  @param {bool} vis `false` if column now hidden, or `true` if visible
15308	 */
15309
15310	return $.fn.dataTable;
15311}));
15312
15313

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.