LaravelTest

Форк
0
/
jquery.dataTables.js 
15345 строк · 437.7 Кб
1
/*! DataTables 1.11.4
2
 * ©2008-2021 SpryMedia Ltd - datatables.net/license
3
 */
4

5
/**
6
 * @summary     DataTables
7
 * @description Paginate, search and order HTML tables
8
 * @version     1.11.4
9
 * @file        jquery.dataTables.js
10
 * @author      SpryMedia Ltd
11
 * @contact     www.datatables.net
12
 * @copyright   Copyright 2008-2021 SpryMedia Ltd.
13
 *
14
 * This source file is free software, available under the following license:
15
 *   MIT license - http://datatables.net/license
16
 *
17
 * This source file is distributed in the hope that it will be useful, but
18
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19
 * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
20
 *
21
 * For details please refer to: http://www.datatables.net
22
 */
23

24
/*jslint evil: true, undef: true, browser: true */
25
/*globals $,require,jQuery,define,_selector_run,_selector_opts,_selector_first,_selector_row_indexes,_ext,_Api,_api_register,_api_registerPlural,_re_new_lines,_re_html,_re_formatted_numeric,_re_escape_regex,_empty,_intVal,_numToDecimal,_isNumber,_isHtml,_htmlNumeric,_pluck,_pluck_order,_range,_stripHtml,_unique,_fnBuildAjax,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnAjaxDataSrc,_fnAddColumn,_fnColumnOptions,_fnAdjustColumnSizing,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnVisbleColumns,_fnGetColumns,_fnColumnTypes,_fnApplyColumnDefs,_fnHungarianMap,_fnCamelToHungarian,_fnLanguageCompat,_fnBrowserDetect,_fnAddData,_fnAddTr,_fnNodeToDataIndex,_fnNodeToColumnIndex,_fnGetCellData,_fnSetCellData,_fnSplitObjNotation,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnGetDataMaster,_fnClearTable,_fnDeleteIndex,_fnInvalidate,_fnGetRowElements,_fnCreateTr,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAddOptionsHtml,_fnDetectHeader,_fnGetUniqueThs,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnFilterCreateSearch,_fnEscapeRegex,_fnFilterData,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnInfoMacros,_fnInitialise,_fnInitComplete,_fnLengthChange,_fnFeatureHtmlLength,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnFeatureHtmlTable,_fnScrollDraw,_fnApplyToChildren,_fnCalculateColumnWidths,_fnThrottle,_fnConvertToWidth,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnSortFlatten,_fnSort,_fnSortAria,_fnSortListener,_fnSortAttachListener,_fnSortingClasses,_fnSortData,_fnSaveState,_fnLoadState,_fnSettingsFromNode,_fnLog,_fnMap,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnLengthOverflow,_fnRenderer,_fnDataSource,_fnRowAttributes*/
26

27
(function( factory ) {
28
	"use strict";
29

30
	if ( typeof define === 'function' && define.amd ) {
31
		// AMD
32
		define( ['jquery'], function ( $ ) {
33
			return factory( $, window, document );
34
		} );
35
	}
36
	else if ( typeof exports === 'object' ) {
37
		// CommonJS
38
		module.exports = function (root, $) {
39
			if ( ! root ) {
40
				// CommonJS environments without a window global must pass a
41
				// root. This will give an error otherwise
42
				root = window;
43
			}
44

45
			if ( ! $ ) {
46
				$ = typeof window !== 'undefined' ? // jQuery's factory checks for a global window
47
					require('jquery') :
48
					require('jquery')( root );
49
			}
50

51
			return factory( $, root, root.document );
52
		};
53
	}
54
	else {
55
		// Browser
56
		window.DataTable = factory( jQuery, window, document );
57
	}
58
}
59
(function( $, window, document, undefined ) {
60
	"use strict";
61

62
	/**
63
	 * DataTables is a plug-in for the jQuery Javascript library. It is a highly
64
	 * flexible tool, based upon the foundations of progressive enhancement,
65
	 * which will add advanced interaction controls to any HTML table. For a
66
	 * full list of features please refer to
67
	 * [DataTables.net](href="http://datatables.net).
68
	 *
69
	 * Note that the `DataTable` object is not a global variable but is aliased
70
	 * to `jQuery.fn.DataTable` and `jQuery.fn.dataTable` through which it may
71
	 * be  accessed.
72
	 *
73
	 *  @class
74
	 *  @param {object} [init={}] Configuration object for DataTables. Options
75
	 *    are defined by {@link DataTable.defaults}
76
	 *  @requires jQuery 1.7+
77
	 *
78
	 *  @example
79
	 *    // Basic initialisation
80
	 *    $(document).ready( function {
81
	 *      $('#example').dataTable();
82
	 *    } );
83
	 *
84
	 *  @example
85
	 *    // Initialisation with configuration options - in this case, disable
86
	 *    // pagination and sorting.
87
	 *    $(document).ready( function {
88
	 *      $('#example').dataTable( {
89
	 *        "paginate": false,
90
	 *        "sort": false
91
	 *      } );
92
	 *    } );
93
	 */
94
	var DataTable = function ( selector, options )
95
	{
96
		// When creating with `new`, create a new DataTable, returning the API instance
97
		if (this instanceof DataTable) {
98
			return $(selector).DataTable(options);
99
		}
100
		else {
101
			// Argument switching
102
			options = selector;
103
		}
104

105
		/**
106
		 * Perform a jQuery selector action on the table's TR elements (from the tbody) and
107
		 * return the resulting jQuery object.
108
		 *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
109
		 *  @param {object} [oOpts] Optional parameters for modifying the rows to be included
110
		 *  @param {string} [oOpts.filter=none] Select TR elements that meet the current filter
111
		 *    criterion ("applied") or all TR elements (i.e. no filter).
112
		 *  @param {string} [oOpts.order=current] Order of the TR elements in the processed array.
113
		 *    Can be either 'current', whereby the current sorting of the table is used, or
114
		 *    'original' whereby the original order the data was read into the table is used.
115
		 *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
116
		 *    ("current") or not ("all"). If 'current' is given, then order is assumed to be
117
		 *    'current' and filter is 'applied', regardless of what they might be given as.
118
		 *  @returns {object} jQuery object, filtered by the given selector.
119
		 *  @dtopt API
120
		 *  @deprecated Since v1.10
121
		 *
122
		 *  @example
123
		 *    $(document).ready(function() {
124
		 *      var oTable = $('#example').dataTable();
125
		 *
126
		 *      // Highlight every second row
127
		 *      oTable.$('tr:odd').css('backgroundColor', 'blue');
128
		 *    } );
129
		 *
130
		 *  @example
131
		 *    $(document).ready(function() {
132
		 *      var oTable = $('#example').dataTable();
133
		 *
134
		 *      // Filter to rows with 'Webkit' in them, add a background colour and then
135
		 *      // remove the filter, thus highlighting the 'Webkit' rows only.
136
		 *      oTable.fnFilter('Webkit');
137
		 *      oTable.$('tr', {"search": "applied"}).css('backgroundColor', 'blue');
138
		 *      oTable.fnFilter('');
139
		 *    } );
140
		 */
141
		this.$ = function ( sSelector, oOpts )
142
		{
143
			return this.api(true).$( sSelector, oOpts );
144
		};
145
		
146
		
147
		/**
148
		 * Almost identical to $ in operation, but in this case returns the data for the matched
149
		 * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes
150
		 * rather than any descendants, so the data can be obtained for the row/cell. If matching
151
		 * rows are found, the data returned is the original data array/object that was used to
152
		 * create the row (or a generated array if from a DOM source).
153
		 *
154
		 * This method is often useful in-combination with $ where both functions are given the
155
		 * same parameters and the array indexes will match identically.
156
		 *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
157
		 *  @param {object} [oOpts] Optional parameters for modifying the rows to be included
158
		 *  @param {string} [oOpts.filter=none] Select elements that meet the current filter
159
		 *    criterion ("applied") or all elements (i.e. no filter).
160
		 *  @param {string} [oOpts.order=current] Order of the data in the processed array.
161
		 *    Can be either 'current', whereby the current sorting of the table is used, or
162
		 *    'original' whereby the original order the data was read into the table is used.
163
		 *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
164
		 *    ("current") or not ("all"). If 'current' is given, then order is assumed to be
165
		 *    'current' and filter is 'applied', regardless of what they might be given as.
166
		 *  @returns {array} Data for the matched elements. If any elements, as a result of the
167
		 *    selector, were not TR, TD or TH elements in the DataTable, they will have a null
168
		 *    entry in the array.
169
		 *  @dtopt API
170
		 *  @deprecated Since v1.10
171
		 *
172
		 *  @example
173
		 *    $(document).ready(function() {
174
		 *      var oTable = $('#example').dataTable();
175
		 *
176
		 *      // Get the data from the first row in the table
177
		 *      var data = oTable._('tr:first');
178
		 *
179
		 *      // Do something useful with the data
180
		 *      alert( "First cell is: "+data[0] );
181
		 *    } );
182
		 *
183
		 *  @example
184
		 *    $(document).ready(function() {
185
		 *      var oTable = $('#example').dataTable();
186
		 *
187
		 *      // Filter to 'Webkit' and get all data for
188
		 *      oTable.fnFilter('Webkit');
189
		 *      var data = oTable._('tr', {"search": "applied"});
190
		 *
191
		 *      // Do something with the data
192
		 *      alert( data.length+" rows matched the search" );
193
		 *    } );
194
		 */
195
		this._ = function ( sSelector, oOpts )
196
		{
197
			return this.api(true).rows( sSelector, oOpts ).data();
198
		};
199
		
200
		
201
		/**
202
		 * Create a DataTables Api instance, with the currently selected tables for
203
		 * the Api's context.
204
		 * @param {boolean} [traditional=false] Set the API instance's context to be
205
		 *   only the table referred to by the `DataTable.ext.iApiIndex` option, as was
206
		 *   used in the API presented by DataTables 1.9- (i.e. the traditional mode),
207
		 *   or if all tables captured in the jQuery object should be used.
208
		 * @return {DataTables.Api}
209
		 */
210
		this.api = function ( traditional )
211
		{
212
			return traditional ?
213
				new _Api(
214
					_fnSettingsFromNode( this[ _ext.iApiIndex ] )
215
				) :
216
				new _Api( this );
217
		};
218
		
219
		
220
		/**
221
		 * Add a single new row or multiple rows of data to the table. Please note
222
		 * that this is suitable for client-side processing only - if you are using
223
		 * server-side processing (i.e. "bServerSide": true), then to add data, you
224
		 * must add it to the data source, i.e. the server-side, through an Ajax call.
225
		 *  @param {array|object} data The data to be added to the table. This can be:
226
		 *    <ul>
227
		 *      <li>1D array of data - add a single row with the data provided</li>
228
		 *      <li>2D array of arrays - add multiple rows in a single call</li>
229
		 *      <li>object - data object when using <i>mData</i></li>
230
		 *      <li>array of objects - multiple data objects when using <i>mData</i></li>
231
		 *    </ul>
232
		 *  @param {bool} [redraw=true] redraw the table or not
233
		 *  @returns {array} An array of integers, representing the list of indexes in
234
		 *    <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to
235
		 *    the table.
236
		 *  @dtopt API
237
		 *  @deprecated Since v1.10
238
		 *
239
		 *  @example
240
		 *    // Global var for counter
241
		 *    var giCount = 2;
242
		 *
243
		 *    $(document).ready(function() {
244
		 *      $('#example').dataTable();
245
		 *    } );
246
		 *
247
		 *    function fnClickAddRow() {
248
		 *      $('#example').dataTable().fnAddData( [
249
		 *        giCount+".1",
250
		 *        giCount+".2",
251
		 *        giCount+".3",
252
		 *        giCount+".4" ]
253
		 *      );
254
		 *
255
		 *      giCount++;
256
		 *    }
257
		 */
258
		this.fnAddData = function( data, redraw )
259
		{
260
			var api = this.api( true );
261
		
262
			/* Check if we want to add multiple rows or not */
263
			var rows = Array.isArray(data) && ( Array.isArray(data[0]) || $.isPlainObject(data[0]) ) ?
264
				api.rows.add( data ) :
265
				api.row.add( data );
266
		
267
			if ( redraw === undefined || redraw ) {
268
				api.draw();
269
			}
270
		
271
			return rows.flatten().toArray();
272
		};
273
		
274
		
275
		/**
276
		 * This function will make DataTables recalculate the column sizes, based on the data
277
		 * contained in the table and the sizes applied to the columns (in the DOM, CSS or
278
		 * through the sWidth parameter). This can be useful when the width of the table's
279
		 * parent element changes (for example a window resize).
280
		 *  @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to
281
		 *  @dtopt API
282
		 *  @deprecated Since v1.10
283
		 *
284
		 *  @example
285
		 *    $(document).ready(function() {
286
		 *      var oTable = $('#example').dataTable( {
287
		 *        "sScrollY": "200px",
288
		 *        "bPaginate": false
289
		 *      } );
290
		 *
291
		 *      $(window).on('resize', function () {
292
		 *        oTable.fnAdjustColumnSizing();
293
		 *      } );
294
		 *    } );
295
		 */
296
		this.fnAdjustColumnSizing = function ( bRedraw )
297
		{
298
			var api = this.api( true ).columns.adjust();
299
			var settings = api.settings()[0];
300
			var scroll = settings.oScroll;
301
		
302
			if ( bRedraw === undefined || bRedraw ) {
303
				api.draw( false );
304
			}
305
			else if ( scroll.sX !== "" || scroll.sY !== "" ) {
306
				/* If not redrawing, but scrolling, we want to apply the new column sizes anyway */
307
				_fnScrollDraw( settings );
308
			}
309
		};
310
		
311
		
312
		/**
313
		 * Quickly and simply clear a table
314
		 *  @param {bool} [bRedraw=true] redraw the table or not
315
		 *  @dtopt API
316
		 *  @deprecated Since v1.10
317
		 *
318
		 *  @example
319
		 *    $(document).ready(function() {
320
		 *      var oTable = $('#example').dataTable();
321
		 *
322
		 *      // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...)
323
		 *      oTable.fnClearTable();
324
		 *    } );
325
		 */
326
		this.fnClearTable = function( bRedraw )
327
		{
328
			var api = this.api( true ).clear();
329
		
330
			if ( bRedraw === undefined || bRedraw ) {
331
				api.draw();
332
			}
333
		};
334
		
335
		
336
		/**
337
		 * The exact opposite of 'opening' a row, this function will close any rows which
338
		 * are currently 'open'.
339
		 *  @param {node} nTr the table row to 'close'
340
		 *  @returns {int} 0 on success, or 1 if failed (can't find the row)
341
		 *  @dtopt API
342
		 *  @deprecated Since v1.10
343
		 *
344
		 *  @example
345
		 *    $(document).ready(function() {
346
		 *      var oTable;
347
		 *
348
		 *      // 'open' an information row when a row is clicked on
349
		 *      $('#example tbody tr').click( function () {
350
		 *        if ( oTable.fnIsOpen(this) ) {
351
		 *          oTable.fnClose( this );
352
		 *        } else {
353
		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
354
		 *        }
355
		 *      } );
356
		 *
357
		 *      oTable = $('#example').dataTable();
358
		 *    } );
359
		 */
360
		this.fnClose = function( nTr )
361
		{
362
			this.api( true ).row( nTr ).child.hide();
363
		};
364
		
365
		
366
		/**
367
		 * Remove a row for the table
368
		 *  @param {mixed} target The index of the row from aoData to be deleted, or
369
		 *    the TR element you want to delete
370
		 *  @param {function|null} [callBack] Callback function
371
		 *  @param {bool} [redraw=true] Redraw the table or not
372
		 *  @returns {array} The row that was deleted
373
		 *  @dtopt API
374
		 *  @deprecated Since v1.10
375
		 *
376
		 *  @example
377
		 *    $(document).ready(function() {
378
		 *      var oTable = $('#example').dataTable();
379
		 *
380
		 *      // Immediately remove the first row
381
		 *      oTable.fnDeleteRow( 0 );
382
		 *    } );
383
		 */
384
		this.fnDeleteRow = function( target, callback, redraw )
385
		{
386
			var api = this.api( true );
387
			var rows = api.rows( target );
388
			var settings = rows.settings()[0];
389
			var data = settings.aoData[ rows[0][0] ];
390
		
391
			rows.remove();
392
		
393
			if ( callback ) {
394
				callback.call( this, settings, data );
395
			}
396
		
397
			if ( redraw === undefined || redraw ) {
398
				api.draw();
399
			}
400
		
401
			return data;
402
		};
403
		
404
		
405
		/**
406
		 * Restore the table to it's original state in the DOM by removing all of DataTables
407
		 * enhancements, alterations to the DOM structure of the table and event listeners.
408
		 *  @param {boolean} [remove=false] Completely remove the table from the DOM
409
		 *  @dtopt API
410
		 *  @deprecated Since v1.10
411
		 *
412
		 *  @example
413
		 *    $(document).ready(function() {
414
		 *      // This example is fairly pointless in reality, but shows how fnDestroy can be used
415
		 *      var oTable = $('#example').dataTable();
416
		 *      oTable.fnDestroy();
417
		 *    } );
418
		 */
419
		this.fnDestroy = function ( remove )
420
		{
421
			this.api( true ).destroy( remove );
422
		};
423
		
424
		
425
		/**
426
		 * Redraw the table
427
		 *  @param {bool} [complete=true] Re-filter and resort (if enabled) the table before the draw.
428
		 *  @dtopt API
429
		 *  @deprecated Since v1.10
430
		 *
431
		 *  @example
432
		 *    $(document).ready(function() {
433
		 *      var oTable = $('#example').dataTable();
434
		 *
435
		 *      // Re-draw the table - you wouldn't want to do it here, but it's an example :-)
436
		 *      oTable.fnDraw();
437
		 *    } );
438
		 */
439
		this.fnDraw = function( complete )
440
		{
441
			// Note that this isn't an exact match to the old call to _fnDraw - it takes
442
			// into account the new data, but can hold position.
443
			this.api( true ).draw( complete );
444
		};
445
		
446
		
447
		/**
448
		 * Filter the input based on data
449
		 *  @param {string} sInput String to filter the table on
450
		 *  @param {int|null} [iColumn] Column to limit filtering to
451
		 *  @param {bool} [bRegex=false] Treat as regular expression or not
452
		 *  @param {bool} [bSmart=true] Perform smart filtering or not
453
		 *  @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es)
454
		 *  @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false)
455
		 *  @dtopt API
456
		 *  @deprecated Since v1.10
457
		 *
458
		 *  @example
459
		 *    $(document).ready(function() {
460
		 *      var oTable = $('#example').dataTable();
461
		 *
462
		 *      // Sometime later - filter...
463
		 *      oTable.fnFilter( 'test string' );
464
		 *    } );
465
		 */
466
		this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive )
467
		{
468
			var api = this.api( true );
469
		
470
			if ( iColumn === null || iColumn === undefined ) {
471
				api.search( sInput, bRegex, bSmart, bCaseInsensitive );
472
			}
473
			else {
474
				api.column( iColumn ).search( sInput, bRegex, bSmart, bCaseInsensitive );
475
			}
476
		
477
			api.draw();
478
		};
479
		
480
		
481
		/**
482
		 * Get the data for the whole table, an individual row or an individual cell based on the
483
		 * provided parameters.
484
		 *  @param {int|node} [src] A TR row node, TD/TH cell node or an integer. If given as
485
		 *    a TR node then the data source for the whole row will be returned. If given as a
486
		 *    TD/TH cell node then iCol will be automatically calculated and the data for the
487
		 *    cell returned. If given as an integer, then this is treated as the aoData internal
488
		 *    data index for the row (see fnGetPosition) and the data for that row used.
489
		 *  @param {int} [col] Optional column index that you want the data of.
490
		 *  @returns {array|object|string} If mRow is undefined, then the data for all rows is
491
		 *    returned. If mRow is defined, just data for that row, and is iCol is
492
		 *    defined, only data for the designated cell is returned.
493
		 *  @dtopt API
494
		 *  @deprecated Since v1.10
495
		 *
496
		 *  @example
497
		 *    // Row data
498
		 *    $(document).ready(function() {
499
		 *      oTable = $('#example').dataTable();
500
		 *
501
		 *      oTable.$('tr').click( function () {
502
		 *        var data = oTable.fnGetData( this );
503
		 *        // ... do something with the array / object of data for the row
504
		 *      } );
505
		 *    } );
506
		 *
507
		 *  @example
508
		 *    // Individual cell data
509
		 *    $(document).ready(function() {
510
		 *      oTable = $('#example').dataTable();
511
		 *
512
		 *      oTable.$('td').click( function () {
513
		 *        var sData = oTable.fnGetData( this );
514
		 *        alert( 'The cell clicked on had the value of '+sData );
515
		 *      } );
516
		 *    } );
517
		 */
518
		this.fnGetData = function( src, col )
519
		{
520
			var api = this.api( true );
521
		
522
			if ( src !== undefined ) {
523
				var type = src.nodeName ? src.nodeName.toLowerCase() : '';
524
		
525
				return col !== undefined || type == 'td' || type == 'th' ?
526
					api.cell( src, col ).data() :
527
					api.row( src ).data() || null;
528
			}
529
		
530
			return api.data().toArray();
531
		};
532
		
533
		
534
		/**
535
		 * Get an array of the TR nodes that are used in the table's body. Note that you will
536
		 * typically want to use the '$' API method in preference to this as it is more
537
		 * flexible.
538
		 *  @param {int} [iRow] Optional row index for the TR element you want
539
		 *  @returns {array|node} If iRow is undefined, returns an array of all TR elements
540
		 *    in the table's body, or iRow is defined, just the TR element requested.
541
		 *  @dtopt API
542
		 *  @deprecated Since v1.10
543
		 *
544
		 *  @example
545
		 *    $(document).ready(function() {
546
		 *      var oTable = $('#example').dataTable();
547
		 *
548
		 *      // Get the nodes from the table
549
		 *      var nNodes = oTable.fnGetNodes( );
550
		 *    } );
551
		 */
552
		this.fnGetNodes = function( iRow )
553
		{
554
			var api = this.api( true );
555
		
556
			return iRow !== undefined ?
557
				api.row( iRow ).node() :
558
				api.rows().nodes().flatten().toArray();
559
		};
560
		
561
		
562
		/**
563
		 * Get the array indexes of a particular cell from it's DOM element
564
		 * and column index including hidden columns
565
		 *  @param {node} node this can either be a TR, TD or TH in the table's body
566
		 *  @returns {int} If nNode is given as a TR, then a single index is returned, or
567
		 *    if given as a cell, an array of [row index, column index (visible),
568
		 *    column index (all)] is given.
569
		 *  @dtopt API
570
		 *  @deprecated Since v1.10
571
		 *
572
		 *  @example
573
		 *    $(document).ready(function() {
574
		 *      $('#example tbody td').click( function () {
575
		 *        // Get the position of the current data from the node
576
		 *        var aPos = oTable.fnGetPosition( this );
577
		 *
578
		 *        // Get the data array for this row
579
		 *        var aData = oTable.fnGetData( aPos[0] );
580
		 *
581
		 *        // Update the data array and return the value
582
		 *        aData[ aPos[1] ] = 'clicked';
583
		 *        this.innerHTML = 'clicked';
584
		 *      } );
585
		 *
586
		 *      // Init DataTables
587
		 *      oTable = $('#example').dataTable();
588
		 *    } );
589
		 */
590
		this.fnGetPosition = function( node )
591
		{
592
			var api = this.api( true );
593
			var nodeName = node.nodeName.toUpperCase();
594
		
595
			if ( nodeName == 'TR' ) {
596
				return api.row( node ).index();
597
			}
598
			else if ( nodeName == 'TD' || nodeName == 'TH' ) {
599
				var cell = api.cell( node ).index();
600
		
601
				return [
602
					cell.row,
603
					cell.columnVisible,
604
					cell.column
605
				];
606
			}
607
			return null;
608
		};
609
		
610
		
611
		/**
612
		 * Check to see if a row is 'open' or not.
613
		 *  @param {node} nTr the table row to check
614
		 *  @returns {boolean} true if the row is currently open, false otherwise
615
		 *  @dtopt API
616
		 *  @deprecated Since v1.10
617
		 *
618
		 *  @example
619
		 *    $(document).ready(function() {
620
		 *      var oTable;
621
		 *
622
		 *      // 'open' an information row when a row is clicked on
623
		 *      $('#example tbody tr').click( function () {
624
		 *        if ( oTable.fnIsOpen(this) ) {
625
		 *          oTable.fnClose( this );
626
		 *        } else {
627
		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
628
		 *        }
629
		 *      } );
630
		 *
631
		 *      oTable = $('#example').dataTable();
632
		 *    } );
633
		 */
634
		this.fnIsOpen = function( nTr )
635
		{
636
			return this.api( true ).row( nTr ).child.isShown();
637
		};
638
		
639
		
640
		/**
641
		 * This function will place a new row directly after a row which is currently
642
		 * on display on the page, with the HTML contents that is passed into the
643
		 * function. This can be used, for example, to ask for confirmation that a
644
		 * particular record should be deleted.
645
		 *  @param {node} nTr The table row to 'open'
646
		 *  @param {string|node|jQuery} mHtml The HTML to put into the row
647
		 *  @param {string} sClass Class to give the new TD cell
648
		 *  @returns {node} The row opened. Note that if the table row passed in as the
649
		 *    first parameter, is not found in the table, this method will silently
650
		 *    return.
651
		 *  @dtopt API
652
		 *  @deprecated Since v1.10
653
		 *
654
		 *  @example
655
		 *    $(document).ready(function() {
656
		 *      var oTable;
657
		 *
658
		 *      // 'open' an information row when a row is clicked on
659
		 *      $('#example tbody tr').click( function () {
660
		 *        if ( oTable.fnIsOpen(this) ) {
661
		 *          oTable.fnClose( this );
662
		 *        } else {
663
		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
664
		 *        }
665
		 *      } );
666
		 *
667
		 *      oTable = $('#example').dataTable();
668
		 *    } );
669
		 */
670
		this.fnOpen = function( nTr, mHtml, sClass )
671
		{
672
			return this.api( true )
673
				.row( nTr )
674
				.child( mHtml, sClass )
675
				.show()
676
				.child()[0];
677
		};
678
		
679
		
680
		/**
681
		 * Change the pagination - provides the internal logic for pagination in a simple API
682
		 * function. With this function you can have a DataTables table go to the next,
683
		 * previous, first or last pages.
684
		 *  @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
685
		 *    or page number to jump to (integer), note that page 0 is the first page.
686
		 *  @param {bool} [bRedraw=true] Redraw the table or not
687
		 *  @dtopt API
688
		 *  @deprecated Since v1.10
689
		 *
690
		 *  @example
691
		 *    $(document).ready(function() {
692
		 *      var oTable = $('#example').dataTable();
693
		 *      oTable.fnPageChange( 'next' );
694
		 *    } );
695
		 */
696
		this.fnPageChange = function ( mAction, bRedraw )
697
		{
698
			var api = this.api( true ).page( mAction );
699
		
700
			if ( bRedraw === undefined || bRedraw ) {
701
				api.draw(false);
702
			}
703
		};
704
		
705
		
706
		/**
707
		 * Show a particular column
708
		 *  @param {int} iCol The column whose display should be changed
709
		 *  @param {bool} bShow Show (true) or hide (false) the column
710
		 *  @param {bool} [bRedraw=true] Redraw the table or not
711
		 *  @dtopt API
712
		 *  @deprecated Since v1.10
713
		 *
714
		 *  @example
715
		 *    $(document).ready(function() {
716
		 *      var oTable = $('#example').dataTable();
717
		 *
718
		 *      // Hide the second column after initialisation
719
		 *      oTable.fnSetColumnVis( 1, false );
720
		 *    } );
721
		 */
722
		this.fnSetColumnVis = function ( iCol, bShow, bRedraw )
723
		{
724
			var api = this.api( true ).column( iCol ).visible( bShow );
725
		
726
			if ( bRedraw === undefined || bRedraw ) {
727
				api.columns.adjust().draw();
728
			}
729
		};
730
		
731
		
732
		/**
733
		 * Get the settings for a particular table for external manipulation
734
		 *  @returns {object} DataTables settings object. See
735
		 *    {@link DataTable.models.oSettings}
736
		 *  @dtopt API
737
		 *  @deprecated Since v1.10
738
		 *
739
		 *  @example
740
		 *    $(document).ready(function() {
741
		 *      var oTable = $('#example').dataTable();
742
		 *      var oSettings = oTable.fnSettings();
743
		 *
744
		 *      // Show an example parameter from the settings
745
		 *      alert( oSettings._iDisplayStart );
746
		 *    } );
747
		 */
748
		this.fnSettings = function()
749
		{
750
			return _fnSettingsFromNode( this[_ext.iApiIndex] );
751
		};
752
		
753
		
754
		/**
755
		 * Sort the table by a particular column
756
		 *  @param {int} iCol the data index to sort on. Note that this will not match the
757
		 *    'display index' if you have hidden data entries
758
		 *  @dtopt API
759
		 *  @deprecated Since v1.10
760
		 *
761
		 *  @example
762
		 *    $(document).ready(function() {
763
		 *      var oTable = $('#example').dataTable();
764
		 *
765
		 *      // Sort immediately with columns 0 and 1
766
		 *      oTable.fnSort( [ [0,'asc'], [1,'asc'] ] );
767
		 *    } );
768
		 */
769
		this.fnSort = function( aaSort )
770
		{
771
			this.api( true ).order( aaSort ).draw();
772
		};
773
		
774
		
775
		/**
776
		 * Attach a sort listener to an element for a given column
777
		 *  @param {node} nNode the element to attach the sort listener to
778
		 *  @param {int} iColumn the column that a click on this node will sort on
779
		 *  @param {function} [fnCallback] callback function when sort is run
780
		 *  @dtopt API
781
		 *  @deprecated Since v1.10
782
		 *
783
		 *  @example
784
		 *    $(document).ready(function() {
785
		 *      var oTable = $('#example').dataTable();
786
		 *
787
		 *      // Sort on column 1, when 'sorter' is clicked on
788
		 *      oTable.fnSortListener( document.getElementById('sorter'), 1 );
789
		 *    } );
790
		 */
791
		this.fnSortListener = function( nNode, iColumn, fnCallback )
792
		{
793
			this.api( true ).order.listener( nNode, iColumn, fnCallback );
794
		};
795
		
796
		
797
		/**
798
		 * Update a table cell or row - this method will accept either a single value to
799
		 * update the cell with, an array of values with one element for each column or
800
		 * an object in the same format as the original data source. The function is
801
		 * self-referencing in order to make the multi column updates easier.
802
		 *  @param {object|array|string} mData Data to update the cell/row with
803
		 *  @param {node|int} mRow TR element you want to update or the aoData index
804
		 *  @param {int} [iColumn] The column to update, give as null or undefined to
805
		 *    update a whole row.
806
		 *  @param {bool} [bRedraw=true] Redraw the table or not
807
		 *  @param {bool} [bAction=true] Perform pre-draw actions or not
808
		 *  @returns {int} 0 on success, 1 on error
809
		 *  @dtopt API
810
		 *  @deprecated Since v1.10
811
		 *
812
		 *  @example
813
		 *    $(document).ready(function() {
814
		 *      var oTable = $('#example').dataTable();
815
		 *      oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell
816
		 *      oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], $('tbody tr')[0] ); // Row
817
		 *    } );
818
		 */
819
		this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction )
820
		{
821
			var api = this.api( true );
822
		
823
			if ( iColumn === undefined || iColumn === null ) {
824
				api.row( mRow ).data( mData );
825
			}
826
			else {
827
				api.cell( mRow, iColumn ).data( mData );
828
			}
829
		
830
			if ( bAction === undefined || bAction ) {
831
				api.columns.adjust();
832
			}
833
		
834
			if ( bRedraw === undefined || bRedraw ) {
835
				api.draw();
836
			}
837
			return 0;
838
		};
839
		
840
		
841
		/**
842
		 * Provide a common method for plug-ins to check the version of DataTables being used, in order
843
		 * to ensure compatibility.
844
		 *  @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the
845
		 *    formats "X" and "X.Y" are also acceptable.
846
		 *  @returns {boolean} true if this version of DataTables is greater or equal to the required
847
		 *    version, or false if this version of DataTales is not suitable
848
		 *  @method
849
		 *  @dtopt API
850
		 *  @deprecated Since v1.10
851
		 *
852
		 *  @example
853
		 *    $(document).ready(function() {
854
		 *      var oTable = $('#example').dataTable();
855
		 *      alert( oTable.fnVersionCheck( '1.9.0' ) );
856
		 *    } );
857
		 */
858
		this.fnVersionCheck = _ext.fnVersionCheck;
859
		
860

861
		var _that = this;
862
		var emptyInit = options === undefined;
863
		var len = this.length;
864

865
		if ( emptyInit ) {
866
			options = {};
867
		}
868

869
		this.oApi = this.internal = _ext.internal;
870

871
		// Extend with old style plug-in API methods
872
		for ( var fn in DataTable.ext.internal ) {
873
			if ( fn ) {
874
				this[fn] = _fnExternApiFunc(fn);
875
			}
876
		}
877

878
		this.each(function() {
879
			// For each initialisation we want to give it a clean initialisation
880
			// object that can be bashed around
881
			var o = {};
882
			var oInit = len > 1 ? // optimisation for single table case
883
				_fnExtend( o, options, true ) :
884
				options;
885

886
			/*global oInit,_that,emptyInit*/
887
			var i=0, iLen, j, jLen, k, kLen;
888
			var sId = this.getAttribute( 'id' );
889
			var bInitHandedOff = false;
890
			var defaults = DataTable.defaults;
891
			var $this = $(this);
892
			
893
			
894
			/* Sanity check */
895
			if ( this.nodeName.toLowerCase() != 'table' )
896
			{
897
				_fnLog( null, 0, 'Non-table node initialisation ('+this.nodeName+')', 2 );
898
				return;
899
			}
900
			
901
			/* Backwards compatibility for the defaults */
902
			_fnCompatOpts( defaults );
903
			_fnCompatCols( defaults.column );
904
			
905
			/* Convert the camel-case defaults to Hungarian */
906
			_fnCamelToHungarian( defaults, defaults, true );
907
			_fnCamelToHungarian( defaults.column, defaults.column, true );
908
			
909
			/* Setting up the initialisation object */
910
			_fnCamelToHungarian( defaults, $.extend( oInit, $this.data() ), true );
911
			
912
			
913
			
914
			/* Check to see if we are re-initialising a table */
915
			var allSettings = DataTable.settings;
916
			for ( i=0, iLen=allSettings.length ; i<iLen ; i++ )
917
			{
918
				var s = allSettings[i];
919
			
920
				/* Base check on table node */
921
				if (
922
					s.nTable == this ||
923
					(s.nTHead && s.nTHead.parentNode == this) ||
924
					(s.nTFoot && s.nTFoot.parentNode == this)
925
				) {
926
					var bRetrieve = oInit.bRetrieve !== undefined ? oInit.bRetrieve : defaults.bRetrieve;
927
					var bDestroy = oInit.bDestroy !== undefined ? oInit.bDestroy : defaults.bDestroy;
928
			
929
					if ( emptyInit || bRetrieve )
930
					{
931
						return s.oInstance;
932
					}
933
					else if ( bDestroy )
934
					{
935
						s.oInstance.fnDestroy();
936
						break;
937
					}
938
					else
939
					{
940
						_fnLog( s, 0, 'Cannot reinitialise DataTable', 3 );
941
						return;
942
					}
943
				}
944
			
945
				/* If the element we are initialising has the same ID as a table which was previously
946
				 * initialised, but the table nodes don't match (from before) then we destroy the old
947
				 * instance by simply deleting it. This is under the assumption that the table has been
948
				 * destroyed by other methods. Anyone using non-id selectors will need to do this manually
949
				 */
950
				if ( s.sTableId == this.id )
951
				{
952
					allSettings.splice( i, 1 );
953
					break;
954
				}
955
			}
956
			
957
			/* Ensure the table has an ID - required for accessibility */
958
			if ( sId === null || sId === "" )
959
			{
960
				sId = "DataTables_Table_"+(DataTable.ext._unique++);
961
				this.id = sId;
962
			}
963
			
964
			/* Create the settings object for this table and set some of the default parameters */
965
			var oSettings = $.extend( true, {}, DataTable.models.oSettings, {
966
				"sDestroyWidth": $this[0].style.width,
967
				"sInstance":     sId,
968
				"sTableId":      sId
969
			} );
970
			oSettings.nTable = this;
971
			oSettings.oApi   = _that.internal;
972
			oSettings.oInit  = oInit;
973
			
974
			allSettings.push( oSettings );
975
			
976
			// Need to add the instance after the instance after the settings object has been added
977
			// to the settings array, so we can self reference the table instance if more than one
978
			oSettings.oInstance = (_that.length===1) ? _that : $this.dataTable();
979
			
980
			// Backwards compatibility, before we apply all the defaults
981
			_fnCompatOpts( oInit );
982
			_fnLanguageCompat( oInit.oLanguage );
983
			
984
			// If the length menu is given, but the init display length is not, use the length menu
985
			if ( oInit.aLengthMenu && ! oInit.iDisplayLength )
986
			{
987
				oInit.iDisplayLength = Array.isArray( oInit.aLengthMenu[0] ) ?
988
					oInit.aLengthMenu[0][0] : oInit.aLengthMenu[0];
989
			}
990
			
991
			// Apply the defaults and init options to make a single init object will all
992
			// options defined from defaults and instance options.
993
			oInit = _fnExtend( $.extend( true, {}, defaults ), oInit );
994
			
995
			
996
			// Map the initialisation options onto the settings object
997
			_fnMap( oSettings.oFeatures, oInit, [
998
				"bPaginate",
999
				"bLengthChange",
1000
				"bFilter",
1001
				"bSort",
1002
				"bSortMulti",
1003
				"bInfo",
1004
				"bProcessing",
1005
				"bAutoWidth",
1006
				"bSortClasses",
1007
				"bServerSide",
1008
				"bDeferRender"
1009
			] );
1010
			_fnMap( oSettings, oInit, [
1011
				"asStripeClasses",
1012
				"ajax",
1013
				"fnServerData",
1014
				"fnFormatNumber",
1015
				"sServerMethod",
1016
				"aaSorting",
1017
				"aaSortingFixed",
1018
				"aLengthMenu",
1019
				"sPaginationType",
1020
				"sAjaxSource",
1021
				"sAjaxDataProp",
1022
				"iStateDuration",
1023
				"sDom",
1024
				"bSortCellsTop",
1025
				"iTabIndex",
1026
				"fnStateLoadCallback",
1027
				"fnStateSaveCallback",
1028
				"renderer",
1029
				"searchDelay",
1030
				"rowId",
1031
				[ "iCookieDuration", "iStateDuration" ], // backwards compat
1032
				[ "oSearch", "oPreviousSearch" ],
1033
				[ "aoSearchCols", "aoPreSearchCols" ],
1034
				[ "iDisplayLength", "_iDisplayLength" ]
1035
			] );
1036
			_fnMap( oSettings.oScroll, oInit, [
1037
				[ "sScrollX", "sX" ],
1038
				[ "sScrollXInner", "sXInner" ],
1039
				[ "sScrollY", "sY" ],
1040
				[ "bScrollCollapse", "bCollapse" ]
1041
			] );
1042
			_fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" );
1043
			
1044
			/* Callback functions which are array driven */
1045
			_fnCallbackReg( oSettings, 'aoDrawCallback',       oInit.fnDrawCallback,      'user' );
1046
			_fnCallbackReg( oSettings, 'aoServerParams',       oInit.fnServerParams,      'user' );
1047
			_fnCallbackReg( oSettings, 'aoStateSaveParams',    oInit.fnStateSaveParams,   'user' );
1048
			_fnCallbackReg( oSettings, 'aoStateLoadParams',    oInit.fnStateLoadParams,   'user' );
1049
			_fnCallbackReg( oSettings, 'aoStateLoaded',        oInit.fnStateLoaded,       'user' );
1050
			_fnCallbackReg( oSettings, 'aoRowCallback',        oInit.fnRowCallback,       'user' );
1051
			_fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow,        'user' );
1052
			_fnCallbackReg( oSettings, 'aoHeaderCallback',     oInit.fnHeaderCallback,    'user' );
1053
			_fnCallbackReg( oSettings, 'aoFooterCallback',     oInit.fnFooterCallback,    'user' );
1054
			_fnCallbackReg( oSettings, 'aoInitComplete',       oInit.fnInitComplete,      'user' );
1055
			_fnCallbackReg( oSettings, 'aoPreDrawCallback',    oInit.fnPreDrawCallback,   'user' );
1056
			
1057
			oSettings.rowIdFn = _fnGetObjectDataFn( oInit.rowId );
1058
			
1059
			/* Browser support detection */
1060
			_fnBrowserDetect( oSettings );
1061
			
1062
			var oClasses = oSettings.oClasses;
1063
			
1064
			$.extend( oClasses, DataTable.ext.classes, oInit.oClasses );
1065
			$this.addClass( oClasses.sTable );
1066
			
1067
			
1068
			if ( oSettings.iInitDisplayStart === undefined )
1069
			{
1070
				/* Display start point, taking into account the save saving */
1071
				oSettings.iInitDisplayStart = oInit.iDisplayStart;
1072
				oSettings._iDisplayStart = oInit.iDisplayStart;
1073
			}
1074
			
1075
			if ( oInit.iDeferLoading !== null )
1076
			{
1077
				oSettings.bDeferLoading = true;
1078
				var tmp = Array.isArray( oInit.iDeferLoading );
1079
				oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading;
1080
				oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading;
1081
			}
1082
			
1083
			/* Language definitions */
1084
			var oLanguage = oSettings.oLanguage;
1085
			$.extend( true, oLanguage, oInit.oLanguage );
1086
			
1087
			if ( oLanguage.sUrl )
1088
			{
1089
				/* Get the language definitions from a file - because this Ajax call makes the language
1090
				 * get async to the remainder of this function we use bInitHandedOff to indicate that
1091
				 * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor
1092
				 */
1093
				$.ajax( {
1094
					dataType: 'json',
1095
					url: oLanguage.sUrl,
1096
					success: function ( json ) {
1097
						_fnCamelToHungarian( defaults.oLanguage, json );
1098
						_fnLanguageCompat( json );
1099
						$.extend( true, oLanguage, json );
1100
			
1101
						_fnCallbackFire( oSettings, null, 'i18n', [oSettings]);
1102
						_fnInitialise( oSettings );
1103
					},
1104
					error: function () {
1105
						// Error occurred loading language file, continue on as best we can
1106
						_fnInitialise( oSettings );
1107
					}
1108
				} );
1109
				bInitHandedOff = true;
1110
			}
1111
			else {
1112
				_fnCallbackFire( oSettings, null, 'i18n', [oSettings]);
1113
			}
1114
			
1115
			/*
1116
			 * Stripes
1117
			 */
1118
			if ( oInit.asStripeClasses === null )
1119
			{
1120
				oSettings.asStripeClasses =[
1121
					oClasses.sStripeOdd,
1122
					oClasses.sStripeEven
1123
				];
1124
			}
1125
			
1126
			/* Remove row stripe classes if they are already on the table row */
1127
			var stripeClasses = oSettings.asStripeClasses;
1128
			var rowOne = $this.children('tbody').find('tr').eq(0);
1129
			if ( $.inArray( true, $.map( stripeClasses, function(el, i) {
1130
				return rowOne.hasClass(el);
1131
			} ) ) !== -1 ) {
1132
				$('tbody tr', this).removeClass( stripeClasses.join(' ') );
1133
				oSettings.asDestroyStripes = stripeClasses.slice();
1134
			}
1135
			
1136
			/*
1137
			 * Columns
1138
			 * See if we should load columns automatically or use defined ones
1139
			 */
1140
			var anThs = [];
1141
			var aoColumnsInit;
1142
			var nThead = this.getElementsByTagName('thead');
1143
			if ( nThead.length !== 0 )
1144
			{
1145
				_fnDetectHeader( oSettings.aoHeader, nThead[0] );
1146
				anThs = _fnGetUniqueThs( oSettings );
1147
			}
1148
			
1149
			/* If not given a column array, generate one with nulls */
1150
			if ( oInit.aoColumns === null )
1151
			{
1152
				aoColumnsInit = [];
1153
				for ( i=0, iLen=anThs.length ; i<iLen ; i++ )
1154
				{
1155
					aoColumnsInit.push( null );
1156
				}
1157
			}
1158
			else
1159
			{
1160
				aoColumnsInit = oInit.aoColumns;
1161
			}
1162
			
1163
			/* Add the columns */
1164
			for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ )
1165
			{
1166
				_fnAddColumn( oSettings, anThs ? anThs[i] : null );
1167
			}
1168
			
1169
			/* Apply the column definitions */
1170
			_fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) {
1171
				_fnColumnOptions( oSettings, iCol, oDef );
1172
			} );
1173
			
1174
			/* HTML5 attribute detection - build an mData object automatically if the
1175
			 * attributes are found
1176
			 */
1177
			if ( rowOne.length ) {
1178
				var a = function ( cell, name ) {
1179
					return cell.getAttribute( 'data-'+name ) !== null ? name : null;
1180
				};
1181
			
1182
				$( rowOne[0] ).children('th, td').each( function (i, cell) {
1183
					var col = oSettings.aoColumns[i];
1184
			
1185
					if ( col.mData === i ) {
1186
						var sort = a( cell, 'sort' ) || a( cell, 'order' );
1187
						var filter = a( cell, 'filter' ) || a( cell, 'search' );
1188
			
1189
						if ( sort !== null || filter !== null ) {
1190
							col.mData = {
1191
								_:      i+'.display',
1192
								sort:   sort !== null   ? i+'.@data-'+sort   : undefined,
1193
								type:   sort !== null   ? i+'.@data-'+sort   : undefined,
1194
								filter: filter !== null ? i+'.@data-'+filter : undefined
1195
							};
1196
			
1197
							_fnColumnOptions( oSettings, i );
1198
						}
1199
					}
1200
				} );
1201
			}
1202
			
1203
			var features = oSettings.oFeatures;
1204
			var loadedInit = function () {
1205
				/*
1206
				 * Sorting
1207
				 * @todo For modularisation (1.11) this needs to do into a sort start up handler
1208
				 */
1209
			
1210
				// If aaSorting is not defined, then we use the first indicator in asSorting
1211
				// in case that has been altered, so the default sort reflects that option
1212
				if ( oInit.aaSorting === undefined ) {
1213
					var sorting = oSettings.aaSorting;
1214
					for ( i=0, iLen=sorting.length ; i<iLen ; i++ ) {
1215
						sorting[i][1] = oSettings.aoColumns[ i ].asSorting[0];
1216
					}
1217
				}
1218
			
1219
				/* Do a first pass on the sorting classes (allows any size changes to be taken into
1220
				 * account, and also will apply sorting disabled classes if disabled
1221
				 */
1222
				_fnSortingClasses( oSettings );
1223
			
1224
				if ( features.bSort ) {
1225
					_fnCallbackReg( oSettings, 'aoDrawCallback', function () {
1226
						if ( oSettings.bSorted ) {
1227
							var aSort = _fnSortFlatten( oSettings );
1228
							var sortedColumns = {};
1229
			
1230
							$.each( aSort, function (i, val) {
1231
								sortedColumns[ val.src ] = val.dir;
1232
							} );
1233
			
1234
							_fnCallbackFire( oSettings, null, 'order', [oSettings, aSort, sortedColumns] );
1235
							_fnSortAria( oSettings );
1236
						}
1237
					} );
1238
				}
1239
			
1240
				_fnCallbackReg( oSettings, 'aoDrawCallback', function () {
1241
					if ( oSettings.bSorted || _fnDataSource( oSettings ) === 'ssp' || features.bDeferRender ) {
1242
						_fnSortingClasses( oSettings );
1243
					}
1244
				}, 'sc' );
1245
			
1246
			
1247
				/*
1248
				 * Final init
1249
				 * Cache the header, body and footer as required, creating them if needed
1250
				 */
1251
			
1252
				// Work around for Webkit bug 83867 - store the caption-side before removing from doc
1253
				var captions = $this.children('caption').each( function () {
1254
					this._captionSide = $(this).css('caption-side');
1255
				} );
1256
			
1257
				var thead = $this.children('thead');
1258
				if ( thead.length === 0 ) {
1259
					thead = $('<thead/>').appendTo($this);
1260
				}
1261
				oSettings.nTHead = thead[0];
1262
			
1263
				var tbody = $this.children('tbody');
1264
				if ( tbody.length === 0 ) {
1265
					tbody = $('<tbody/>').insertAfter(thead);
1266
				}
1267
				oSettings.nTBody = tbody[0];
1268
			
1269
				var tfoot = $this.children('tfoot');
1270
				if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") ) {
1271
					// If we are a scrolling table, and no footer has been given, then we need to create
1272
					// a tfoot element for the caption element to be appended to
1273
					tfoot = $('<tfoot/>').appendTo($this);
1274
				}
1275
			
1276
				if ( tfoot.length === 0 || tfoot.children().length === 0 ) {
1277
					$this.addClass( oClasses.sNoFooter );
1278
				}
1279
				else if ( tfoot.length > 0 ) {
1280
					oSettings.nTFoot = tfoot[0];
1281
					_fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );
1282
				}
1283
			
1284
				/* Check if there is data passing into the constructor */
1285
				if ( oInit.aaData ) {
1286
					for ( i=0 ; i<oInit.aaData.length ; i++ ) {
1287
						_fnAddData( oSettings, oInit.aaData[ i ] );
1288
					}
1289
				}
1290
				else if ( oSettings.bDeferLoading || _fnDataSource( oSettings ) == 'dom' ) {
1291
					/* Grab the data from the page - only do this when deferred loading or no Ajax
1292
					 * source since there is no point in reading the DOM data if we are then going
1293
					 * to replace it with Ajax data
1294
					 */
1295
					_fnAddTr( oSettings, $(oSettings.nTBody).children('tr') );
1296
				}
1297
			
1298
				/* Copy the data index array */
1299
				oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
1300
			
1301
				/* Initialisation complete - table can be drawn */
1302
				oSettings.bInitialised = true;
1303
			
1304
				/* Check if we need to initialise the table (it might not have been handed off to the
1305
				 * language processor)
1306
				 */
1307
				if ( bInitHandedOff === false ) {
1308
					_fnInitialise( oSettings );
1309
				}
1310
			};
1311
			
1312
			/* Must be done after everything which can be overridden by the state saving! */
1313
			_fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' );
1314
			
1315
			if ( oInit.bStateSave )
1316
			{
1317
				features.bStateSave = true;
1318
				_fnLoadState( oSettings, oInit, loadedInit );
1319
			}
1320
			else {
1321
				loadedInit();
1322
			}
1323
			
1324
		} );
1325
		_that = null;
1326
		return this;
1327
	};
1328

1329
	
1330
	/*
1331
	 * It is useful to have variables which are scoped locally so only the
1332
	 * DataTables functions can access them and they don't leak into global space.
1333
	 * At the same time these functions are often useful over multiple files in the
1334
	 * core and API, so we list, or at least document, all variables which are used
1335
	 * by DataTables as private variables here. This also ensures that there is no
1336
	 * clashing of variable names and that they can easily referenced for reuse.
1337
	 */
1338
	
1339
	
1340
	// Defined else where
1341
	//  _selector_run
1342
	//  _selector_opts
1343
	//  _selector_first
1344
	//  _selector_row_indexes
1345
	
1346
	var _ext; // DataTable.ext
1347
	var _Api; // DataTable.Api
1348
	var _api_register; // DataTable.Api.register
1349
	var _api_registerPlural; // DataTable.Api.registerPlural
1350
	
1351
	var _re_dic = {};
1352
	var _re_new_lines = /[\r\n\u2028]/g;
1353
	var _re_html = /<.*?>/g;
1354
	
1355
	// This is not strict ISO8601 - Date.parse() is quite lax, although
1356
	// implementations differ between browsers.
1357
	var _re_date = /^\d{2,4}[\.\/\-]\d{1,2}[\.\/\-]\d{1,2}([T ]{1}\d{1,2}[:\.]\d{2}([\.:]\d{2})?)?$/;
1358
	
1359
	// Escape regular expression special characters
1360
	var _re_escape_regex = new RegExp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' );
1361
	
1362
	// http://en.wikipedia.org/wiki/Foreign_exchange_market
1363
	// - \u20BD - Russian ruble.
1364
	// - \u20a9 - South Korean Won
1365
	// - \u20BA - Turkish Lira
1366
	// - \u20B9 - Indian Rupee
1367
	// - R - Brazil (R$) and South Africa
1368
	// - fr - Swiss Franc
1369
	// - kr - Swedish krona, Norwegian krone and Danish krone
1370
	// - \u2009 is thin space and \u202F is narrow no-break space, both used in many
1371
	// - Ƀ - Bitcoin
1372
	// - Ξ - Ethereum
1373
	//   standards as thousands separators.
1374
	var _re_formatted_numeric = /['\u00A0,$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfkɃΞ]/gi;
1375
	
1376
	
1377
	var _empty = function ( d ) {
1378
		return !d || d === true || d === '-' ? true : false;
1379
	};
1380
	
1381
	
1382
	var _intVal = function ( s ) {
1383
		var integer = parseInt( s, 10 );
1384
		return !isNaN(integer) && isFinite(s) ? integer : null;
1385
	};
1386
	
1387
	// Convert from a formatted number with characters other than `.` as the
1388
	// decimal place, to a Javascript number
1389
	var _numToDecimal = function ( num, decimalPoint ) {
1390
		// Cache created regular expressions for speed as this function is called often
1391
		if ( ! _re_dic[ decimalPoint ] ) {
1392
			_re_dic[ decimalPoint ] = new RegExp( _fnEscapeRegex( decimalPoint ), 'g' );
1393
		}
1394
		return typeof num === 'string' && decimalPoint !== '.' ?
1395
			num.replace( /\./g, '' ).replace( _re_dic[ decimalPoint ], '.' ) :
1396
			num;
1397
	};
1398
	
1399
	
1400
	var _isNumber = function ( d, decimalPoint, formatted ) {
1401
		var strType = typeof d === 'string';
1402
	
1403
		// If empty return immediately so there must be a number if it is a
1404
		// formatted string (this stops the string "k", or "kr", etc being detected
1405
		// as a formatted number for currency
1406
		if ( _empty( d ) ) {
1407
			return true;
1408
		}
1409
	
1410
		if ( decimalPoint && strType ) {
1411
			d = _numToDecimal( d, decimalPoint );
1412
		}
1413
	
1414
		if ( formatted && strType ) {
1415
			d = d.replace( _re_formatted_numeric, '' );
1416
		}
1417
	
1418
		return !isNaN( parseFloat(d) ) && isFinite( d );
1419
	};
1420
	
1421
	
1422
	// A string without HTML in it can be considered to be HTML still
1423
	var _isHtml = function ( d ) {
1424
		return _empty( d ) || typeof d === 'string';
1425
	};
1426
	
1427
	
1428
	var _htmlNumeric = function ( d, decimalPoint, formatted ) {
1429
		if ( _empty( d ) ) {
1430
			return true;
1431
		}
1432
	
1433
		var html = _isHtml( d );
1434
		return ! html ?
1435
			null :
1436
			_isNumber( _stripHtml( d ), decimalPoint, formatted ) ?
1437
				true :
1438
				null;
1439
	};
1440
	
1441
	
1442
	var _pluck = function ( a, prop, prop2 ) {
1443
		var out = [];
1444
		var i=0, ien=a.length;
1445
	
1446
		// Could have the test in the loop for slightly smaller code, but speed
1447
		// is essential here
1448
		if ( prop2 !== undefined ) {
1449
			for ( ; i<ien ; i++ ) {
1450
				if ( a[i] && a[i][ prop ] ) {
1451
					out.push( a[i][ prop ][ prop2 ] );
1452
				}
1453
			}
1454
		}
1455
		else {
1456
			for ( ; i<ien ; i++ ) {
1457
				if ( a[i] ) {
1458
					out.push( a[i][ prop ] );
1459
				}
1460
			}
1461
		}
1462
	
1463
		return out;
1464
	};
1465
	
1466
	
1467
	// Basically the same as _pluck, but rather than looping over `a` we use `order`
1468
	// as the indexes to pick from `a`
1469
	var _pluck_order = function ( a, order, prop, prop2 )
1470
	{
1471
		var out = [];
1472
		var i=0, ien=order.length;
1473
	
1474
		// Could have the test in the loop for slightly smaller code, but speed
1475
		// is essential here
1476
		if ( prop2 !== undefined ) {
1477
			for ( ; i<ien ; i++ ) {
1478
				if ( a[ order[i] ][ prop ] ) {
1479
					out.push( a[ order[i] ][ prop ][ prop2 ] );
1480
				}
1481
			}
1482
		}
1483
		else {
1484
			for ( ; i<ien ; i++ ) {
1485
				out.push( a[ order[i] ][ prop ] );
1486
			}
1487
		}
1488
	
1489
		return out;
1490
	};
1491
	
1492
	
1493
	var _range = function ( len, start )
1494
	{
1495
		var out = [];
1496
		var end;
1497
	
1498
		if ( start === undefined ) {
1499
			start = 0;
1500
			end = len;
1501
		}
1502
		else {
1503
			end = start;
1504
			start = len;
1505
		}
1506
	
1507
		for ( var i=start ; i<end ; i++ ) {
1508
			out.push( i );
1509
		}
1510
	
1511
		return out;
1512
	};
1513
	
1514
	
1515
	var _removeEmpty = function ( a )
1516
	{
1517
		var out = [];
1518
	
1519
		for ( var i=0, ien=a.length ; i<ien ; i++ ) {
1520
			if ( a[i] ) { // careful - will remove all falsy values!
1521
				out.push( a[i] );
1522
			}
1523
		}
1524
	
1525
		return out;
1526
	};
1527
	
1528
	
1529
	var _stripHtml = function ( d ) {
1530
		return d.replace( _re_html, '' );
1531
	};
1532
	
1533
	
1534
	/**
1535
	 * Determine if all values in the array are unique. This means we can short
1536
	 * cut the _unique method at the cost of a single loop. A sorted array is used
1537
	 * to easily check the values.
1538
	 *
1539
	 * @param  {array} src Source array
1540
	 * @return {boolean} true if all unique, false otherwise
1541
	 * @ignore
1542
	 */
1543
	var _areAllUnique = function ( src ) {
1544
		if ( src.length < 2 ) {
1545
			return true;
1546
		}
1547
	
1548
		var sorted = src.slice().sort();
1549
		var last = sorted[0];
1550
	
1551
		for ( var i=1, ien=sorted.length ; i<ien ; i++ ) {
1552
			if ( sorted[i] === last ) {
1553
				return false;
1554
			}
1555
	
1556
			last = sorted[i];
1557
		}
1558
	
1559
		return true;
1560
	};
1561
	
1562
	
1563
	/**
1564
	 * Find the unique elements in a source array.
1565
	 *
1566
	 * @param  {array} src Source array
1567
	 * @return {array} Array of unique items
1568
	 * @ignore
1569
	 */
1570
	var _unique = function ( src )
1571
	{
1572
		if ( _areAllUnique( src ) ) {
1573
			return src.slice();
1574
		}
1575
	
1576
		// A faster unique method is to use object keys to identify used values,
1577
		// but this doesn't work with arrays or objects, which we must also
1578
		// consider. See jsperf.com/compare-array-unique-versions/4 for more
1579
		// information.
1580
		var
1581
			out = [],
1582
			val,
1583
			i, ien=src.length,
1584
			j, k=0;
1585
	
1586
		again: for ( i=0 ; i<ien ; i++ ) {
1587
			val = src[i];
1588
	
1589
			for ( j=0 ; j<k ; j++ ) {
1590
				if ( out[j] === val ) {
1591
					continue again;
1592
				}
1593
			}
1594
	
1595
			out.push( val );
1596
			k++;
1597
		}
1598
	
1599
		return out;
1600
	};
1601
	
1602
	// Surprisingly this is faster than [].concat.apply
1603
	// https://jsperf.com/flatten-an-array-loop-vs-reduce/2
1604
	var _flatten = function (out, val) {
1605
		if (Array.isArray(val)) {
1606
			for (var i=0 ; i<val.length ; i++) {
1607
				_flatten(out, val[i]);
1608
			}
1609
		}
1610
		else {
1611
			out.push(val);
1612
		}
1613
	  
1614
		return out;
1615
	}
1616
	
1617
	var _includes = function (search, start) {
1618
		if (start === undefined) {
1619
			start = 0;
1620
		}
1621
	
1622
		return this.indexOf(search, start) !== -1;	
1623
	};
1624
	
1625
	// Array.isArray polyfill.
1626
	// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
1627
	if (! Array.isArray) {
1628
	    Array.isArray = function(arg) {
1629
	        return Object.prototype.toString.call(arg) === '[object Array]';
1630
	    };
1631
	}
1632
	
1633
	if (! Array.prototype.includes) {
1634
		Array.prototype.includes = _includes;
1635
	}
1636
	
1637
	// .trim() polyfill
1638
	// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trim
1639
	if (!String.prototype.trim) {
1640
	  String.prototype.trim = function () {
1641
	    return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
1642
	  };
1643
	}
1644
	
1645
	if (! String.prototype.includes) {
1646
		String.prototype.includes = _includes;
1647
	}
1648
	
1649
	/**
1650
	 * DataTables utility methods
1651
	 * 
1652
	 * This namespace provides helper methods that DataTables uses internally to
1653
	 * create a DataTable, but which are not exclusively used only for DataTables.
1654
	 * These methods can be used by extension authors to save the duplication of
1655
	 * code.
1656
	 *
1657
	 *  @namespace
1658
	 */
1659
	DataTable.util = {
1660
		/**
1661
		 * Throttle the calls to a function. Arguments and context are maintained
1662
		 * for the throttled function.
1663
		 *
1664
		 * @param {function} fn Function to be called
1665
		 * @param {integer} freq Call frequency in mS
1666
		 * @return {function} Wrapped function
1667
		 */
1668
		throttle: function ( fn, freq ) {
1669
			var
1670
				frequency = freq !== undefined ? freq : 200,
1671
				last,
1672
				timer;
1673
	
1674
			return function () {
1675
				var
1676
					that = this,
1677
					now  = +new Date(),
1678
					args = arguments;
1679
	
1680
				if ( last && now < last + frequency ) {
1681
					clearTimeout( timer );
1682
	
1683
					timer = setTimeout( function () {
1684
						last = undefined;
1685
						fn.apply( that, args );
1686
					}, frequency );
1687
				}
1688
				else {
1689
					last = now;
1690
					fn.apply( that, args );
1691
				}
1692
			};
1693
		},
1694
	
1695
	
1696
		/**
1697
		 * Escape a string such that it can be used in a regular expression
1698
		 *
1699
		 *  @param {string} val string to escape
1700
		 *  @returns {string} escaped string
1701
		 */
1702
		escapeRegex: function ( val ) {
1703
			return val.replace( _re_escape_regex, '\\$1' );
1704
		},
1705
	
1706
		/**
1707
		 * Create a function that will write to a nested object or array
1708
		 * @param {*} source JSON notation string
1709
		 * @returns Write function
1710
		 */
1711
		set: function ( source ) {
1712
			if ( $.isPlainObject( source ) ) {
1713
				/* Unlike get, only the underscore (global) option is used for for
1714
				 * setting data since we don't know the type here. This is why an object
1715
				 * option is not documented for `mData` (which is read/write), but it is
1716
				 * for `mRender` which is read only.
1717
				 */
1718
				return DataTable.util.set( source._ );
1719
			}
1720
			else if ( source === null ) {
1721
				// Nothing to do when the data source is null
1722
				return function () {};
1723
			}
1724
			else if ( typeof source === 'function' ) {
1725
				return function (data, val, meta) {
1726
					source( data, 'set', val, meta );
1727
				};
1728
			}
1729
			else if ( typeof source === 'string' && (source.indexOf('.') !== -1 ||
1730
					  source.indexOf('[') !== -1 || source.indexOf('(') !== -1) )
1731
			{
1732
				// Like the get, we need to get data from a nested object
1733
				var setData = function (data, val, src) {
1734
					var a = _fnSplitObjNotation( src ), b;
1735
					var aLast = a[a.length-1];
1736
					var arrayNotation, funcNotation, o, innerSrc;
1737
		
1738
					for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ ) {
1739
						// Protect against prototype pollution
1740
						if (a[i] === '__proto__' || a[i] === 'constructor') {
1741
							throw new Error('Cannot set prototype values');
1742
						}
1743
		
1744
						// Check if we are dealing with an array notation request
1745
						arrayNotation = a[i].match(__reArray);
1746
						funcNotation = a[i].match(__reFn);
1747
		
1748
						if ( arrayNotation ) {
1749
							a[i] = a[i].replace(__reArray, '');
1750
							data[ a[i] ] = [];
1751
		
1752
							// Get the remainder of the nested object to set so we can recurse
1753
							b = a.slice();
1754
							b.splice( 0, i+1 );
1755
							innerSrc = b.join('.');
1756
		
1757
							// Traverse each entry in the array setting the properties requested
1758
							if ( Array.isArray( val ) ) {
1759
								for ( var j=0, jLen=val.length ; j<jLen ; j++ ) {
1760
									o = {};
1761
									setData( o, val[j], innerSrc );
1762
									data[ a[i] ].push( o );
1763
								}
1764
							}
1765
							else {
1766
								// We've been asked to save data to an array, but it
1767
								// isn't array data to be saved. Best that can be done
1768
								// is to just save the value.
1769
								data[ a[i] ] = val;
1770
							}
1771
		
1772
							// The inner call to setData has already traversed through the remainder
1773
							// of the source and has set the data, thus we can exit here
1774
							return;
1775
						}
1776
						else if ( funcNotation ) {
1777
							// Function call
1778
							a[i] = a[i].replace(__reFn, '');
1779
							data = data[ a[i] ]( val );
1780
						}
1781
		
1782
						// If the nested object doesn't currently exist - since we are
1783
						// trying to set the value - create it
1784
						if ( data[ a[i] ] === null || data[ a[i] ] === undefined ) {
1785
							data[ a[i] ] = {};
1786
						}
1787
						data = data[ a[i] ];
1788
					}
1789
		
1790
					// Last item in the input - i.e, the actual set
1791
					if ( aLast.match(__reFn ) ) {
1792
						// Function call
1793
						data = data[ aLast.replace(__reFn, '') ]( val );
1794
					}
1795
					else {
1796
						// If array notation is used, we just want to strip it and use the property name
1797
						// and assign the value. If it isn't used, then we get the result we want anyway
1798
						data[ aLast.replace(__reArray, '') ] = val;
1799
					}
1800
				};
1801
		
1802
				return function (data, val) { // meta is also passed in, but not used
1803
					return setData( data, val, source );
1804
				};
1805
			}
1806
			else {
1807
				// Array or flat object mapping
1808
				return function (data, val) { // meta is also passed in, but not used
1809
					data[source] = val;
1810
				};
1811
			}
1812
		},
1813
	
1814
		/**
1815
		 * Create a function that will read nested objects from arrays, based on JSON notation
1816
		 * @param {*} source JSON notation string
1817
		 * @returns Value read
1818
		 */
1819
		get: function ( source ) {
1820
			if ( $.isPlainObject( source ) ) {
1821
				// Build an object of get functions, and wrap them in a single call
1822
				var o = {};
1823
				$.each( source, function (key, val) {
1824
					if ( val ) {
1825
						o[key] = DataTable.util.get( val );
1826
					}
1827
				} );
1828
		
1829
				return function (data, type, row, meta) {
1830
					var t = o[type] || o._;
1831
					return t !== undefined ?
1832
						t(data, type, row, meta) :
1833
						data;
1834
				};
1835
			}
1836
			else if ( source === null ) {
1837
				// Give an empty string for rendering / sorting etc
1838
				return function (data) { // type, row and meta also passed, but not used
1839
					return data;
1840
				};
1841
			}
1842
			else if ( typeof source === 'function' ) {
1843
				return function (data, type, row, meta) {
1844
					return source( data, type, row, meta );
1845
				};
1846
			}
1847
			else if ( typeof source === 'string' && (source.indexOf('.') !== -1 ||
1848
					  source.indexOf('[') !== -1 || source.indexOf('(') !== -1) )
1849
			{
1850
				/* If there is a . in the source string then the data source is in a
1851
				 * nested object so we loop over the data for each level to get the next
1852
				 * level down. On each loop we test for undefined, and if found immediately
1853
				 * return. This allows entire objects to be missing and sDefaultContent to
1854
				 * be used if defined, rather than throwing an error
1855
				 */
1856
				var fetchData = function (data, type, src) {
1857
					var arrayNotation, funcNotation, out, innerSrc;
1858
		
1859
					if ( src !== "" ) {
1860
						var a = _fnSplitObjNotation( src );
1861
		
1862
						for ( var i=0, iLen=a.length ; i<iLen ; i++ ) {
1863
							// Check if we are dealing with special notation
1864
							arrayNotation = a[i].match(__reArray);
1865
							funcNotation = a[i].match(__reFn);
1866
		
1867
							if ( arrayNotation ) {
1868
								// Array notation
1869
								a[i] = a[i].replace(__reArray, '');
1870
		
1871
								// Condition allows simply [] to be passed in
1872
								if ( a[i] !== "" ) {
1873
									data = data[ a[i] ];
1874
								}
1875
								out = [];
1876
		
1877
								// Get the remainder of the nested object to get
1878
								a.splice( 0, i+1 );
1879
								innerSrc = a.join('.');
1880
		
1881
								// Traverse each entry in the array getting the properties requested
1882
								if ( Array.isArray( data ) ) {
1883
									for ( var j=0, jLen=data.length ; j<jLen ; j++ ) {
1884
										out.push( fetchData( data[j], type, innerSrc ) );
1885
									}
1886
								}
1887
		
1888
								// If a string is given in between the array notation indicators, that
1889
								// is used to join the strings together, otherwise an array is returned
1890
								var join = arrayNotation[0].substring(1, arrayNotation[0].length-1);
1891
								data = (join==="") ? out : out.join(join);
1892
		
1893
								// The inner call to fetchData has already traversed through the remainder
1894
								// of the source requested, so we exit from the loop
1895
								break;
1896
							}
1897
							else if ( funcNotation ) {
1898
								// Function call
1899
								a[i] = a[i].replace(__reFn, '');
1900
								data = data[ a[i] ]();
1901
								continue;
1902
							}
1903
		
1904
							if ( data === null || data[ a[i] ] === undefined ) {
1905
								return undefined;
1906
							}
1907
	
1908
							data = data[ a[i] ];
1909
						}
1910
					}
1911
		
1912
					return data;
1913
				};
1914
		
1915
				return function (data, type) { // row and meta also passed, but not used
1916
					return fetchData( data, type, source );
1917
				};
1918
			}
1919
			else {
1920
				// Array or flat object mapping
1921
				return function (data, type) { // row and meta also passed, but not used
1922
					return data[source];
1923
				};
1924
			}
1925
		}
1926
	};
1927
	
1928
	
1929
	
1930
	/**
1931
	 * Create a mapping object that allows camel case parameters to be looked up
1932
	 * for their Hungarian counterparts. The mapping is stored in a private
1933
	 * parameter called `_hungarianMap` which can be accessed on the source object.
1934
	 *  @param {object} o
1935
	 *  @memberof DataTable#oApi
1936
	 */
1937
	function _fnHungarianMap ( o )
1938
	{
1939
		var
1940
			hungarian = 'a aa ai ao as b fn i m o s ',
1941
			match,
1942
			newKey,
1943
			map = {};
1944
	
1945
		$.each( o, function (key, val) {
1946
			match = key.match(/^([^A-Z]+?)([A-Z])/);
1947
	
1948
			if ( match && hungarian.indexOf(match[1]+' ') !== -1 )
1949
			{
1950
				newKey = key.replace( match[0], match[2].toLowerCase() );
1951
				map[ newKey ] = key;
1952
	
1953
				if ( match[1] === 'o' )
1954
				{
1955
					_fnHungarianMap( o[key] );
1956
				}
1957
			}
1958
		} );
1959
	
1960
		o._hungarianMap = map;
1961
	}
1962
	
1963
	
1964
	/**
1965
	 * Convert from camel case parameters to Hungarian, based on a Hungarian map
1966
	 * created by _fnHungarianMap.
1967
	 *  @param {object} src The model object which holds all parameters that can be
1968
	 *    mapped.
1969
	 *  @param {object} user The object to convert from camel case to Hungarian.
1970
	 *  @param {boolean} force When set to `true`, properties which already have a
1971
	 *    Hungarian value in the `user` object will be overwritten. Otherwise they
1972
	 *    won't be.
1973
	 *  @memberof DataTable#oApi
1974
	 */
1975
	function _fnCamelToHungarian ( src, user, force )
1976
	{
1977
		if ( ! src._hungarianMap ) {
1978
			_fnHungarianMap( src );
1979
		}
1980
	
1981
		var hungarianKey;
1982
	
1983
		$.each( user, function (key, val) {
1984
			hungarianKey = src._hungarianMap[ key ];
1985
	
1986
			if ( hungarianKey !== undefined && (force || user[hungarianKey] === undefined) )
1987
			{
1988
				// For objects, we need to buzz down into the object to copy parameters
1989
				if ( hungarianKey.charAt(0) === 'o' )
1990
				{
1991
					// Copy the camelCase options over to the hungarian
1992
					if ( ! user[ hungarianKey ] ) {
1993
						user[ hungarianKey ] = {};
1994
					}
1995
					$.extend( true, user[hungarianKey], user[key] );
1996
	
1997
					_fnCamelToHungarian( src[hungarianKey], user[hungarianKey], force );
1998
				}
1999
				else {
2000
					user[hungarianKey] = user[ key ];
2001
				}
2002
			}
2003
		} );
2004
	}
2005
	
2006
	
2007
	/**
2008
	 * Language compatibility - when certain options are given, and others aren't, we
2009
	 * need to duplicate the values over, in order to provide backwards compatibility
2010
	 * with older language files.
2011
	 *  @param {object} oSettings dataTables settings object
2012
	 *  @memberof DataTable#oApi
2013
	 */
2014
	function _fnLanguageCompat( lang )
2015
	{
2016
		// Note the use of the Hungarian notation for the parameters in this method as
2017
		// this is called after the mapping of camelCase to Hungarian
2018
		var defaults = DataTable.defaults.oLanguage;
2019
	
2020
		// Default mapping
2021
		var defaultDecimal = defaults.sDecimal;
2022
		if ( defaultDecimal ) {
2023
			_addNumericSort( defaultDecimal );
2024
		}
2025
	
2026
		if ( lang ) {
2027
			var zeroRecords = lang.sZeroRecords;
2028
	
2029
			// Backwards compatibility - if there is no sEmptyTable given, then use the same as
2030
			// sZeroRecords - assuming that is given.
2031
			if ( ! lang.sEmptyTable && zeroRecords &&
2032
				defaults.sEmptyTable === "No data available in table" )
2033
			{
2034
				_fnMap( lang, lang, 'sZeroRecords', 'sEmptyTable' );
2035
			}
2036
	
2037
			// Likewise with loading records
2038
			if ( ! lang.sLoadingRecords && zeroRecords &&
2039
				defaults.sLoadingRecords === "Loading..." )
2040
			{
2041
				_fnMap( lang, lang, 'sZeroRecords', 'sLoadingRecords' );
2042
			}
2043
	
2044
			// Old parameter name of the thousands separator mapped onto the new
2045
			if ( lang.sInfoThousands ) {
2046
				lang.sThousands = lang.sInfoThousands;
2047
			}
2048
	
2049
			var decimal = lang.sDecimal;
2050
			if ( decimal && defaultDecimal !== decimal ) {
2051
				_addNumericSort( decimal );
2052
			}
2053
		}
2054
	}
2055
	
2056
	
2057
	/**
2058
	 * Map one parameter onto another
2059
	 *  @param {object} o Object to map
2060
	 *  @param {*} knew The new parameter name
2061
	 *  @param {*} old The old parameter name
2062
	 */
2063
	var _fnCompatMap = function ( o, knew, old ) {
2064
		if ( o[ knew ] !== undefined ) {
2065
			o[ old ] = o[ knew ];
2066
		}
2067
	};
2068
	
2069
	
2070
	/**
2071
	 * Provide backwards compatibility for the main DT options. Note that the new
2072
	 * options are mapped onto the old parameters, so this is an external interface
2073
	 * change only.
2074
	 *  @param {object} init Object to map
2075
	 */
2076
	function _fnCompatOpts ( init )
2077
	{
2078
		_fnCompatMap( init, 'ordering',      'bSort' );
2079
		_fnCompatMap( init, 'orderMulti',    'bSortMulti' );
2080
		_fnCompatMap( init, 'orderClasses',  'bSortClasses' );
2081
		_fnCompatMap( init, 'orderCellsTop', 'bSortCellsTop' );
2082
		_fnCompatMap( init, 'order',         'aaSorting' );
2083
		_fnCompatMap( init, 'orderFixed',    'aaSortingFixed' );
2084
		_fnCompatMap( init, 'paging',        'bPaginate' );
2085
		_fnCompatMap( init, 'pagingType',    'sPaginationType' );
2086
		_fnCompatMap( init, 'pageLength',    'iDisplayLength' );
2087
		_fnCompatMap( init, 'searching',     'bFilter' );
2088
	
2089
		// Boolean initialisation of x-scrolling
2090
		if ( typeof init.sScrollX === 'boolean' ) {
2091
			init.sScrollX = init.sScrollX ? '100%' : '';
2092
		}
2093
		if ( typeof init.scrollX === 'boolean' ) {
2094
			init.scrollX = init.scrollX ? '100%' : '';
2095
		}
2096
	
2097
		// Column search objects are in an array, so it needs to be converted
2098
		// element by element
2099
		var searchCols = init.aoSearchCols;
2100
	
2101
		if ( searchCols ) {
2102
			for ( var i=0, ien=searchCols.length ; i<ien ; i++ ) {
2103
				if ( searchCols[i] ) {
2104
					_fnCamelToHungarian( DataTable.models.oSearch, searchCols[i] );
2105
				}
2106
			}
2107
		}
2108
	}
2109
	
2110
	
2111
	/**
2112
	 * Provide backwards compatibility for column options. Note that the new options
2113
	 * are mapped onto the old parameters, so this is an external interface change
2114
	 * only.
2115
	 *  @param {object} init Object to map
2116
	 */
2117
	function _fnCompatCols ( init )
2118
	{
2119
		_fnCompatMap( init, 'orderable',     'bSortable' );
2120
		_fnCompatMap( init, 'orderData',     'aDataSort' );
2121
		_fnCompatMap( init, 'orderSequence', 'asSorting' );
2122
		_fnCompatMap( init, 'orderDataType', 'sortDataType' );
2123
	
2124
		// orderData can be given as an integer
2125
		var dataSort = init.aDataSort;
2126
		if ( typeof dataSort === 'number' && ! Array.isArray( dataSort ) ) {
2127
			init.aDataSort = [ dataSort ];
2128
		}
2129
	}
2130
	
2131
	
2132
	/**
2133
	 * Browser feature detection for capabilities, quirks
2134
	 *  @param {object} settings dataTables settings object
2135
	 *  @memberof DataTable#oApi
2136
	 */
2137
	function _fnBrowserDetect( settings )
2138
	{
2139
		// We don't need to do this every time DataTables is constructed, the values
2140
		// calculated are specific to the browser and OS configuration which we
2141
		// don't expect to change between initialisations
2142
		if ( ! DataTable.__browser ) {
2143
			var browser = {};
2144
			DataTable.__browser = browser;
2145
	
2146
			// Scrolling feature / quirks detection
2147
			var n = $('<div/>')
2148
				.css( {
2149
					position: 'fixed',
2150
					top: 0,
2151
					left: $(window).scrollLeft()*-1, // allow for scrolling
2152
					height: 1,
2153
					width: 1,
2154
					overflow: 'hidden'
2155
				} )
2156
				.append(
2157
					$('<div/>')
2158
						.css( {
2159
							position: 'absolute',
2160
							top: 1,
2161
							left: 1,
2162
							width: 100,
2163
							overflow: 'scroll'
2164
						} )
2165
						.append(
2166
							$('<div/>')
2167
								.css( {
2168
									width: '100%',
2169
									height: 10
2170
								} )
2171
						)
2172
				)
2173
				.appendTo( 'body' );
2174
	
2175
			var outer = n.children();
2176
			var inner = outer.children();
2177
	
2178
			// Numbers below, in order, are:
2179
			// inner.offsetWidth, inner.clientWidth, outer.offsetWidth, outer.clientWidth
2180
			//
2181
			// IE6 XP:                           100 100 100  83
2182
			// IE7 Vista:                        100 100 100  83
2183
			// IE 8+ Windows:                     83  83 100  83
2184
			// Evergreen Windows:                 83  83 100  83
2185
			// Evergreen Mac with scrollbars:     85  85 100  85
2186
			// Evergreen Mac without scrollbars: 100 100 100 100
2187
	
2188
			// Get scrollbar width
2189
			browser.barWidth = outer[0].offsetWidth - outer[0].clientWidth;
2190
	
2191
			// IE6/7 will oversize a width 100% element inside a scrolling element, to
2192
			// include the width of the scrollbar, while other browsers ensure the inner
2193
			// element is contained without forcing scrolling
2194
			browser.bScrollOversize = inner[0].offsetWidth === 100 && outer[0].clientWidth !== 100;
2195
	
2196
			// In rtl text layout, some browsers (most, but not all) will place the
2197
			// scrollbar on the left, rather than the right.
2198
			browser.bScrollbarLeft = Math.round( inner.offset().left ) !== 1;
2199
	
2200
			// IE8- don't provide height and width for getBoundingClientRect
2201
			browser.bBounding = n[0].getBoundingClientRect().width ? true : false;
2202
	
2203
			n.remove();
2204
		}
2205
	
2206
		$.extend( settings.oBrowser, DataTable.__browser );
2207
		settings.oScroll.iBarWidth = DataTable.__browser.barWidth;
2208
	}
2209
	
2210
	
2211
	/**
2212
	 * Array.prototype reduce[Right] method, used for browsers which don't support
2213
	 * JS 1.6. Done this way to reduce code size, since we iterate either way
2214
	 *  @param {object} settings dataTables settings object
2215
	 *  @memberof DataTable#oApi
2216
	 */
2217
	function _fnReduce ( that, fn, init, start, end, inc )
2218
	{
2219
		var
2220
			i = start,
2221
			value,
2222
			isSet = false;
2223
	
2224
		if ( init !== undefined ) {
2225
			value = init;
2226
			isSet = true;
2227
		}
2228
	
2229
		while ( i !== end ) {
2230
			if ( ! that.hasOwnProperty(i) ) {
2231
				continue;
2232
			}
2233
	
2234
			value = isSet ?
2235
				fn( value, that[i], i, that ) :
2236
				that[i];
2237
	
2238
			isSet = true;
2239
			i += inc;
2240
		}
2241
	
2242
		return value;
2243
	}
2244
	
2245
	/**
2246
	 * Add a column to the list used for the table with default values
2247
	 *  @param {object} oSettings dataTables settings object
2248
	 *  @param {node} nTh The th element for this column
2249
	 *  @memberof DataTable#oApi
2250
	 */
2251
	function _fnAddColumn( oSettings, nTh )
2252
	{
2253
		// Add column to aoColumns array
2254
		var oDefaults = DataTable.defaults.column;
2255
		var iCol = oSettings.aoColumns.length;
2256
		var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {
2257
			"nTh": nTh ? nTh : document.createElement('th'),
2258
			"sTitle":    oDefaults.sTitle    ? oDefaults.sTitle    : nTh ? nTh.innerHTML : '',
2259
			"aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],
2260
			"mData": oDefaults.mData ? oDefaults.mData : iCol,
2261
			idx: iCol
2262
		} );
2263
		oSettings.aoColumns.push( oCol );
2264
	
2265
		// Add search object for column specific search. Note that the `searchCols[ iCol ]`
2266
		// passed into extend can be undefined. This allows the user to give a default
2267
		// with only some of the parameters defined, and also not give a default
2268
		var searchCols = oSettings.aoPreSearchCols;
2269
		searchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] );
2270
	
2271
		// Use the default column options function to initialise classes etc
2272
		_fnColumnOptions( oSettings, iCol, $(nTh).data() );
2273
	}
2274
	
2275
	
2276
	/**
2277
	 * Apply options for a column
2278
	 *  @param {object} oSettings dataTables settings object
2279
	 *  @param {int} iCol column index to consider
2280
	 *  @param {object} oOptions object with sType, bVisible and bSearchable etc
2281
	 *  @memberof DataTable#oApi
2282
	 */
2283
	function _fnColumnOptions( oSettings, iCol, oOptions )
2284
	{
2285
		var oCol = oSettings.aoColumns[ iCol ];
2286
		var oClasses = oSettings.oClasses;
2287
		var th = $(oCol.nTh);
2288
	
2289
		// Try to get width information from the DOM. We can't get it from CSS
2290
		// as we'd need to parse the CSS stylesheet. `width` option can override
2291
		if ( ! oCol.sWidthOrig ) {
2292
			// Width attribute
2293
			oCol.sWidthOrig = th.attr('width') || null;
2294
	
2295
			// Style attribute
2296
			var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/);
2297
			if ( t ) {
2298
				oCol.sWidthOrig = t[1];
2299
			}
2300
		}
2301
	
2302
		/* User specified column options */
2303
		if ( oOptions !== undefined && oOptions !== null )
2304
		{
2305
			// Backwards compatibility
2306
			_fnCompatCols( oOptions );
2307
	
2308
			// Map camel case parameters to their Hungarian counterparts
2309
			_fnCamelToHungarian( DataTable.defaults.column, oOptions, true );
2310
	
2311
			/* Backwards compatibility for mDataProp */
2312
			if ( oOptions.mDataProp !== undefined && !oOptions.mData )
2313
			{
2314
				oOptions.mData = oOptions.mDataProp;
2315
			}
2316
	
2317
			if ( oOptions.sType )
2318
			{
2319
				oCol._sManualType = oOptions.sType;
2320
			}
2321
	
2322
			// `class` is a reserved word in Javascript, so we need to provide
2323
			// the ability to use a valid name for the camel case input
2324
			if ( oOptions.className && ! oOptions.sClass )
2325
			{
2326
				oOptions.sClass = oOptions.className;
2327
			}
2328
			if ( oOptions.sClass ) {
2329
				th.addClass( oOptions.sClass );
2330
			}
2331
	
2332
			$.extend( oCol, oOptions );
2333
			_fnMap( oCol, oOptions, "sWidth", "sWidthOrig" );
2334
	
2335
			/* iDataSort to be applied (backwards compatibility), but aDataSort will take
2336
			 * priority if defined
2337
			 */
2338
			if ( oOptions.iDataSort !== undefined )
2339
			{
2340
				oCol.aDataSort = [ oOptions.iDataSort ];
2341
			}
2342
			_fnMap( oCol, oOptions, "aDataSort" );
2343
		}
2344
	
2345
		/* Cache the data get and set functions for speed */
2346
		var mDataSrc = oCol.mData;
2347
		var mData = _fnGetObjectDataFn( mDataSrc );
2348
		var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null;
2349
	
2350
		var attrTest = function( src ) {
2351
			return typeof src === 'string' && src.indexOf('@') !== -1;
2352
		};
2353
		oCol._bAttrSrc = $.isPlainObject( mDataSrc ) && (
2354
			attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter)
2355
		);
2356
		oCol._setter = null;
2357
	
2358
		oCol.fnGetData = function (rowData, type, meta) {
2359
			var innerData = mData( rowData, type, undefined, meta );
2360
	
2361
			return mRender && type ?
2362
				mRender( innerData, type, rowData, meta ) :
2363
				innerData;
2364
		};
2365
		oCol.fnSetData = function ( rowData, val, meta ) {
2366
			return _fnSetObjectDataFn( mDataSrc )( rowData, val, meta );
2367
		};
2368
	
2369
		// Indicate if DataTables should read DOM data as an object or array
2370
		// Used in _fnGetRowElements
2371
		if ( typeof mDataSrc !== 'number' ) {
2372
			oSettings._rowReadObject = true;
2373
		}
2374
	
2375
		/* Feature sorting overrides column specific when off */
2376
		if ( !oSettings.oFeatures.bSort )
2377
		{
2378
			oCol.bSortable = false;
2379
			th.addClass( oClasses.sSortableNone ); // Have to add class here as order event isn't called
2380
		}
2381
	
2382
		/* Check that the class assignment is correct for sorting */
2383
		var bAsc = $.inArray('asc', oCol.asSorting) !== -1;
2384
		var bDesc = $.inArray('desc', oCol.asSorting) !== -1;
2385
		if ( !oCol.bSortable || (!bAsc && !bDesc) )
2386
		{
2387
			oCol.sSortingClass = oClasses.sSortableNone;
2388
			oCol.sSortingClassJUI = "";
2389
		}
2390
		else if ( bAsc && !bDesc )
2391
		{
2392
			oCol.sSortingClass = oClasses.sSortableAsc;
2393
			oCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed;
2394
		}
2395
		else if ( !bAsc && bDesc )
2396
		{
2397
			oCol.sSortingClass = oClasses.sSortableDesc;
2398
			oCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed;
2399
		}
2400
		else
2401
		{
2402
			oCol.sSortingClass = oClasses.sSortable;
2403
			oCol.sSortingClassJUI = oClasses.sSortJUI;
2404
		}
2405
	}
2406
	
2407
	
2408
	/**
2409
	 * Adjust the table column widths for new data. Note: you would probably want to
2410
	 * do a redraw after calling this function!
2411
	 *  @param {object} settings dataTables settings object
2412
	 *  @memberof DataTable#oApi
2413
	 */
2414
	function _fnAdjustColumnSizing ( settings )
2415
	{
2416
		/* Not interested in doing column width calculation if auto-width is disabled */
2417
		if ( settings.oFeatures.bAutoWidth !== false )
2418
		{
2419
			var columns = settings.aoColumns;
2420
	
2421
			_fnCalculateColumnWidths( settings );
2422
			for ( var i=0 , iLen=columns.length ; i<iLen ; i++ )
2423
			{
2424
				columns[i].nTh.style.width = columns[i].sWidth;
2425
			}
2426
		}
2427
	
2428
		var scroll = settings.oScroll;
2429
		if ( scroll.sY !== '' || scroll.sX !== '')
2430
		{
2431
			_fnScrollDraw( settings );
2432
		}
2433
	
2434
		_fnCallbackFire( settings, null, 'column-sizing', [settings] );
2435
	}
2436
	
2437
	
2438
	/**
2439
	 * Convert the index of a visible column to the index in the data array (take account
2440
	 * of hidden columns)
2441
	 *  @param {object} oSettings dataTables settings object
2442
	 *  @param {int} iMatch Visible column index to lookup
2443
	 *  @returns {int} i the data index
2444
	 *  @memberof DataTable#oApi
2445
	 */
2446
	function _fnVisibleToColumnIndex( oSettings, iMatch )
2447
	{
2448
		var aiVis = _fnGetColumns( oSettings, 'bVisible' );
2449
	
2450
		return typeof aiVis[iMatch] === 'number' ?
2451
			aiVis[iMatch] :
2452
			null;
2453
	}
2454
	
2455
	
2456
	/**
2457
	 * Convert the index of an index in the data array and convert it to the visible
2458
	 *   column index (take account of hidden columns)
2459
	 *  @param {int} iMatch Column index to lookup
2460
	 *  @param {object} oSettings dataTables settings object
2461
	 *  @returns {int} i the data index
2462
	 *  @memberof DataTable#oApi
2463
	 */
2464
	function _fnColumnIndexToVisible( oSettings, iMatch )
2465
	{
2466
		var aiVis = _fnGetColumns( oSettings, 'bVisible' );
2467
		var iPos = $.inArray( iMatch, aiVis );
2468
	
2469
		return iPos !== -1 ? iPos : null;
2470
	}
2471
	
2472
	
2473
	/**
2474
	 * Get the number of visible columns
2475
	 *  @param {object} oSettings dataTables settings object
2476
	 *  @returns {int} i the number of visible columns
2477
	 *  @memberof DataTable#oApi
2478
	 */
2479
	function _fnVisbleColumns( oSettings )
2480
	{
2481
		var vis = 0;
2482
	
2483
		// No reduce in IE8, use a loop for now
2484
		$.each( oSettings.aoColumns, function ( i, col ) {
2485
			if ( col.bVisible && $(col.nTh).css('display') !== 'none' ) {
2486
				vis++;
2487
			}
2488
		} );
2489
	
2490
		return vis;
2491
	}
2492
	
2493
	
2494
	/**
2495
	 * Get an array of column indexes that match a given property
2496
	 *  @param {object} oSettings dataTables settings object
2497
	 *  @param {string} sParam Parameter in aoColumns to look for - typically
2498
	 *    bVisible or bSearchable
2499
	 *  @returns {array} Array of indexes with matched properties
2500
	 *  @memberof DataTable#oApi
2501
	 */
2502
	function _fnGetColumns( oSettings, sParam )
2503
	{
2504
		var a = [];
2505
	
2506
		$.map( oSettings.aoColumns, function(val, i) {
2507
			if ( val[sParam] ) {
2508
				a.push( i );
2509
			}
2510
		} );
2511
	
2512
		return a;
2513
	}
2514
	
2515
	
2516
	/**
2517
	 * Calculate the 'type' of a column
2518
	 *  @param {object} settings dataTables settings object
2519
	 *  @memberof DataTable#oApi
2520
	 */
2521
	function _fnColumnTypes ( settings )
2522
	{
2523
		var columns = settings.aoColumns;
2524
		var data = settings.aoData;
2525
		var types = DataTable.ext.type.detect;
2526
		var i, ien, j, jen, k, ken;
2527
		var col, cell, detectedType, cache;
2528
	
2529
		// For each column, spin over the 
2530
		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
2531
			col = columns[i];
2532
			cache = [];
2533
	
2534
			if ( ! col.sType && col._sManualType ) {
2535
				col.sType = col._sManualType;
2536
			}
2537
			else if ( ! col.sType ) {
2538
				for ( j=0, jen=types.length ; j<jen ; j++ ) {
2539
					for ( k=0, ken=data.length ; k<ken ; k++ ) {
2540
						// Use a cache array so we only need to get the type data
2541
						// from the formatter once (when using multiple detectors)
2542
						if ( cache[k] === undefined ) {
2543
							cache[k] = _fnGetCellData( settings, k, i, 'type' );
2544
						}
2545
	
2546
						detectedType = types[j]( cache[k], settings );
2547
	
2548
						// If null, then this type can't apply to this column, so
2549
						// rather than testing all cells, break out. There is an
2550
						// exception for the last type which is `html`. We need to
2551
						// scan all rows since it is possible to mix string and HTML
2552
						// types
2553
						if ( ! detectedType && j !== types.length-1 ) {
2554
							break;
2555
						}
2556
	
2557
						// Only a single match is needed for html type since it is
2558
						// bottom of the pile and very similar to string - but it
2559
						// must not be empty
2560
						if ( detectedType === 'html' && ! _empty(cache[k]) ) {
2561
							break;
2562
						}
2563
					}
2564
	
2565
					// Type is valid for all data points in the column - use this
2566
					// type
2567
					if ( detectedType ) {
2568
						col.sType = detectedType;
2569
						break;
2570
					}
2571
				}
2572
	
2573
				// Fall back - if no type was detected, always use string
2574
				if ( ! col.sType ) {
2575
					col.sType = 'string';
2576
				}
2577
			}
2578
		}
2579
	}
2580
	
2581
	
2582
	/**
2583
	 * Take the column definitions and static columns arrays and calculate how
2584
	 * they relate to column indexes. The callback function will then apply the
2585
	 * definition found for a column to a suitable configuration object.
2586
	 *  @param {object} oSettings dataTables settings object
2587
	 *  @param {array} aoColDefs The aoColumnDefs array that is to be applied
2588
	 *  @param {array} aoCols The aoColumns array that defines columns individually
2589
	 *  @param {function} fn Callback function - takes two parameters, the calculated
2590
	 *    column index and the definition for that column.
2591
	 *  @memberof DataTable#oApi
2592
	 */
2593
	function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )
2594
	{
2595
		var i, iLen, j, jLen, k, kLen, def;
2596
		var columns = oSettings.aoColumns;
2597
	
2598
		// Column definitions with aTargets
2599
		if ( aoColDefs )
2600
		{
2601
			/* Loop over the definitions array - loop in reverse so first instance has priority */
2602
			for ( i=aoColDefs.length-1 ; i>=0 ; i-- )
2603
			{
2604
				def = aoColDefs[i];
2605
	
2606
				/* Each definition can target multiple columns, as it is an array */
2607
				var aTargets = def.targets !== undefined ?
2608
					def.targets :
2609
					def.aTargets;
2610
	
2611
				if ( ! Array.isArray( aTargets ) )
2612
				{
2613
					aTargets = [ aTargets ];
2614
				}
2615
	
2616
				for ( j=0, jLen=aTargets.length ; j<jLen ; j++ )
2617
				{
2618
					if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 )
2619
					{
2620
						/* Add columns that we don't yet know about */
2621
						while( columns.length <= aTargets[j] )
2622
						{
2623
							_fnAddColumn( oSettings );
2624
						}
2625
	
2626
						/* Integer, basic index */
2627
						fn( aTargets[j], def );
2628
					}
2629
					else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 )
2630
					{
2631
						/* Negative integer, right to left column counting */
2632
						fn( columns.length+aTargets[j], def );
2633
					}
2634
					else if ( typeof aTargets[j] === 'string' )
2635
					{
2636
						/* Class name matching on TH element */
2637
						for ( k=0, kLen=columns.length ; k<kLen ; k++ )
2638
						{
2639
							if ( aTargets[j] == "_all" ||
2640
							     $(columns[k].nTh).hasClass( aTargets[j] ) )
2641
							{
2642
								fn( k, def );
2643
							}
2644
						}
2645
					}
2646
				}
2647
			}
2648
		}
2649
	
2650
		// Statically defined columns array
2651
		if ( aoCols )
2652
		{
2653
			for ( i=0, iLen=aoCols.length ; i<iLen ; i++ )
2654
			{
2655
				fn( i, aoCols[i] );
2656
			}
2657
		}
2658
	}
2659
	
2660
	/**
2661
	 * Add a data array to the table, creating DOM node etc. This is the parallel to
2662
	 * _fnGatherData, but for adding rows from a Javascript source, rather than a
2663
	 * DOM source.
2664
	 *  @param {object} oSettings dataTables settings object
2665
	 *  @param {array} aData data array to be added
2666
	 *  @param {node} [nTr] TR element to add to the table - optional. If not given,
2667
	 *    DataTables will create a row automatically
2668
	 *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
2669
	 *    if nTr is.
2670
	 *  @returns {int} >=0 if successful (index of new aoData entry), -1 if failed
2671
	 *  @memberof DataTable#oApi
2672
	 */
2673
	function _fnAddData ( oSettings, aDataIn, nTr, anTds )
2674
	{
2675
		/* Create the object for storing information about this new row */
2676
		var iRow = oSettings.aoData.length;
2677
		var oData = $.extend( true, {}, DataTable.models.oRow, {
2678
			src: nTr ? 'dom' : 'data',
2679
			idx: iRow
2680
		} );
2681
	
2682
		oData._aData = aDataIn;
2683
		oSettings.aoData.push( oData );
2684
	
2685
		/* Create the cells */
2686
		var nTd, sThisType;
2687
		var columns = oSettings.aoColumns;
2688
	
2689
		// Invalidate the column types as the new data needs to be revalidated
2690
		for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
2691
		{
2692
			columns[i].sType = null;
2693
		}
2694
	
2695
		/* Add to the display array */
2696
		oSettings.aiDisplayMaster.push( iRow );
2697
	
2698
		var id = oSettings.rowIdFn( aDataIn );
2699
		if ( id !== undefined ) {
2700
			oSettings.aIds[ id ] = oData;
2701
		}
2702
	
2703
		/* Create the DOM information, or register it if already present */
2704
		if ( nTr || ! oSettings.oFeatures.bDeferRender )
2705
		{
2706
			_fnCreateTr( oSettings, iRow, nTr, anTds );
2707
		}
2708
	
2709
		return iRow;
2710
	}
2711
	
2712
	
2713
	/**
2714
	 * Add one or more TR elements to the table. Generally we'd expect to
2715
	 * use this for reading data from a DOM sourced table, but it could be
2716
	 * used for an TR element. Note that if a TR is given, it is used (i.e.
2717
	 * it is not cloned).
2718
	 *  @param {object} settings dataTables settings object
2719
	 *  @param {array|node|jQuery} trs The TR element(s) to add to the table
2720
	 *  @returns {array} Array of indexes for the added rows
2721
	 *  @memberof DataTable#oApi
2722
	 */
2723
	function _fnAddTr( settings, trs )
2724
	{
2725
		var row;
2726
	
2727
		// Allow an individual node to be passed in
2728
		if ( ! (trs instanceof $) ) {
2729
			trs = $(trs);
2730
		}
2731
	
2732
		return trs.map( function (i, el) {
2733
			row = _fnGetRowElements( settings, el );
2734
			return _fnAddData( settings, row.data, el, row.cells );
2735
		} );
2736
	}
2737
	
2738
	
2739
	/**
2740
	 * Take a TR element and convert it to an index in aoData
2741
	 *  @param {object} oSettings dataTables settings object
2742
	 *  @param {node} n the TR element to find
2743
	 *  @returns {int} index if the node is found, null if not
2744
	 *  @memberof DataTable#oApi
2745
	 */
2746
	function _fnNodeToDataIndex( oSettings, n )
2747
	{
2748
		return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null;
2749
	}
2750
	
2751
	
2752
	/**
2753
	 * Take a TD element and convert it into a column data index (not the visible index)
2754
	 *  @param {object} oSettings dataTables settings object
2755
	 *  @param {int} iRow The row number the TD/TH can be found in
2756
	 *  @param {node} n The TD/TH element to find
2757
	 *  @returns {int} index if the node is found, -1 if not
2758
	 *  @memberof DataTable#oApi
2759
	 */
2760
	function _fnNodeToColumnIndex( oSettings, iRow, n )
2761
	{
2762
		return $.inArray( n, oSettings.aoData[ iRow ].anCells );
2763
	}
2764
	
2765
	
2766
	/**
2767
	 * Get the data for a given cell from the internal cache, taking into account data mapping
2768
	 *  @param {object} settings dataTables settings object
2769
	 *  @param {int} rowIdx aoData row id
2770
	 *  @param {int} colIdx Column index
2771
	 *  @param {string} type data get type ('display', 'type' 'filter|search' 'sort|order')
2772
	 *  @returns {*} Cell data
2773
	 *  @memberof DataTable#oApi
2774
	 */
2775
	function _fnGetCellData( settings, rowIdx, colIdx, type )
2776
	{
2777
		if (type === 'search') {
2778
			type = 'filter';
2779
		}
2780
		else if (type === 'order') {
2781
			type = 'sort';
2782
		}
2783
	
2784
		var draw           = settings.iDraw;
2785
		var col            = settings.aoColumns[colIdx];
2786
		var rowData        = settings.aoData[rowIdx]._aData;
2787
		var defaultContent = col.sDefaultContent;
2788
		var cellData       = col.fnGetData( rowData, type, {
2789
			settings: settings,
2790
			row:      rowIdx,
2791
			col:      colIdx
2792
		} );
2793
	
2794
		if ( cellData === undefined ) {
2795
			if ( settings.iDrawError != draw && defaultContent === null ) {
2796
				_fnLog( settings, 0, "Requested unknown parameter "+
2797
					(typeof col.mData=='function' ? '{function}' : "'"+col.mData+"'")+
2798
					" for row "+rowIdx+", column "+colIdx, 4 );
2799
				settings.iDrawError = draw;
2800
			}
2801
			return defaultContent;
2802
		}
2803
	
2804
		// When the data source is null and a specific data type is requested (i.e.
2805
		// not the original data), we can use default column data
2806
		if ( (cellData === rowData || cellData === null) && defaultContent !== null && type !== undefined ) {
2807
			cellData = defaultContent;
2808
		}
2809
		else if ( typeof cellData === 'function' ) {
2810
			// If the data source is a function, then we run it and use the return,
2811
			// executing in the scope of the data object (for instances)
2812
			return cellData.call( rowData );
2813
		}
2814
	
2815
		if ( cellData === null && type === 'display' ) {
2816
			return '';
2817
		}
2818
	
2819
		if ( type === 'filter' ) {
2820
			var fomatters = DataTable.ext.type.search;
2821
	
2822
			if ( fomatters[ col.sType ] ) {
2823
				cellData = fomatters[ col.sType ]( cellData );
2824
			}
2825
		}
2826
	
2827
		return cellData;
2828
	}
2829
	
2830
	
2831
	/**
2832
	 * Set the value for a specific cell, into the internal data cache
2833
	 *  @param {object} settings dataTables settings object
2834
	 *  @param {int} rowIdx aoData row id
2835
	 *  @param {int} colIdx Column index
2836
	 *  @param {*} val Value to set
2837
	 *  @memberof DataTable#oApi
2838
	 */
2839
	function _fnSetCellData( settings, rowIdx, colIdx, val )
2840
	{
2841
		var col     = settings.aoColumns[colIdx];
2842
		var rowData = settings.aoData[rowIdx]._aData;
2843
	
2844
		col.fnSetData( rowData, val, {
2845
			settings: settings,
2846
			row:      rowIdx,
2847
			col:      colIdx
2848
		}  );
2849
	}
2850
	
2851
	
2852
	// Private variable that is used to match action syntax in the data property object
2853
	var __reArray = /\[.*?\]$/;
2854
	var __reFn = /\(\)$/;
2855
	
2856
	/**
2857
	 * Split string on periods, taking into account escaped periods
2858
	 * @param  {string} str String to split
2859
	 * @return {array} Split string
2860
	 */
2861
	function _fnSplitObjNotation( str )
2862
	{
2863
		return $.map( str.match(/(\\.|[^\.])+/g) || [''], function ( s ) {
2864
			return s.replace(/\\\./g, '.');
2865
		} );
2866
	}
2867
	
2868
	
2869
	/**
2870
	 * Return a function that can be used to get data from a source object, taking
2871
	 * into account the ability to use nested objects as a source
2872
	 *  @param {string|int|function} mSource The data source for the object
2873
	 *  @returns {function} Data get function
2874
	 *  @memberof DataTable#oApi
2875
	 */
2876
	var _fnGetObjectDataFn = DataTable.util.get;
2877
	
2878
	
2879
	/**
2880
	 * Return a function that can be used to set data from a source object, taking
2881
	 * into account the ability to use nested objects as a source
2882
	 *  @param {string|int|function} mSource The data source for the object
2883
	 *  @returns {function} Data set function
2884
	 *  @memberof DataTable#oApi
2885
	 */
2886
	var _fnSetObjectDataFn = DataTable.util.set;
2887
	
2888
	
2889
	/**
2890
	 * Return an array with the full table data
2891
	 *  @param {object} oSettings dataTables settings object
2892
	 *  @returns array {array} aData Master data array
2893
	 *  @memberof DataTable#oApi
2894
	 */
2895
	function _fnGetDataMaster ( settings )
2896
	{
2897
		return _pluck( settings.aoData, '_aData' );
2898
	}
2899
	
2900
	
2901
	/**
2902
	 * Nuke the table
2903
	 *  @param {object} oSettings dataTables settings object
2904
	 *  @memberof DataTable#oApi
2905
	 */
2906
	function _fnClearTable( settings )
2907
	{
2908
		settings.aoData.length = 0;
2909
		settings.aiDisplayMaster.length = 0;
2910
		settings.aiDisplay.length = 0;
2911
		settings.aIds = {};
2912
	}
2913
	
2914
	
2915
	 /**
2916
	 * Take an array of integers (index array) and remove a target integer (value - not
2917
	 * the key!)
2918
	 *  @param {array} a Index array to target
2919
	 *  @param {int} iTarget value to find
2920
	 *  @memberof DataTable#oApi
2921
	 */
2922
	function _fnDeleteIndex( a, iTarget, splice )
2923
	{
2924
		var iTargetIndex = -1;
2925
	
2926
		for ( var i=0, iLen=a.length ; i<iLen ; i++ )
2927
		{
2928
			if ( a[i] == iTarget )
2929
			{
2930
				iTargetIndex = i;
2931
			}
2932
			else if ( a[i] > iTarget )
2933
			{
2934
				a[i]--;
2935
			}
2936
		}
2937
	
2938
		if ( iTargetIndex != -1 && splice === undefined )
2939
		{
2940
			a.splice( iTargetIndex, 1 );
2941
		}
2942
	}
2943
	
2944
	
2945
	/**
2946
	 * Mark cached data as invalid such that a re-read of the data will occur when
2947
	 * the cached data is next requested. Also update from the data source object.
2948
	 *
2949
	 * @param {object} settings DataTables settings object
2950
	 * @param {int}    rowIdx   Row index to invalidate
2951
	 * @param {string} [src]    Source to invalidate from: undefined, 'auto', 'dom'
2952
	 *     or 'data'
2953
	 * @param {int}    [colIdx] Column index to invalidate. If undefined the whole
2954
	 *     row will be invalidated
2955
	 * @memberof DataTable#oApi
2956
	 *
2957
	 * @todo For the modularisation of v1.11 this will need to become a callback, so
2958
	 *   the sort and filter methods can subscribe to it. That will required
2959
	 *   initialisation options for sorting, which is why it is not already baked in
2960
	 */
2961
	function _fnInvalidate( settings, rowIdx, src, colIdx )
2962
	{
2963
		var row = settings.aoData[ rowIdx ];
2964
		var i, ien;
2965
		var cellWrite = function ( cell, col ) {
2966
			// This is very frustrating, but in IE if you just write directly
2967
			// to innerHTML, and elements that are overwritten are GC'ed,
2968
			// even if there is a reference to them elsewhere
2969
			while ( cell.childNodes.length ) {
2970
				cell.removeChild( cell.firstChild );
2971
			}
2972
	
2973
			cell.innerHTML = _fnGetCellData( settings, rowIdx, col, 'display' );
2974
		};
2975
	
2976
		// Are we reading last data from DOM or the data object?
2977
		if ( src === 'dom' || ((! src || src === 'auto') && row.src === 'dom') ) {
2978
			// Read the data from the DOM
2979
			row._aData = _fnGetRowElements(
2980
					settings, row, colIdx, colIdx === undefined ? undefined : row._aData
2981
				)
2982
				.data;
2983
		}
2984
		else {
2985
			// Reading from data object, update the DOM
2986
			var cells = row.anCells;
2987
	
2988
			if ( cells ) {
2989
				if ( colIdx !== undefined ) {
2990
					cellWrite( cells[colIdx], colIdx );
2991
				}
2992
				else {
2993
					for ( i=0, ien=cells.length ; i<ien ; i++ ) {
2994
						cellWrite( cells[i], i );
2995
					}
2996
				}
2997
			}
2998
		}
2999
	
3000
		// For both row and cell invalidation, the cached data for sorting and
3001
		// filtering is nulled out
3002
		row._aSortData = null;
3003
		row._aFilterData = null;
3004
	
3005
		// Invalidate the type for a specific column (if given) or all columns since
3006
		// the data might have changed
3007
		var cols = settings.aoColumns;
3008
		if ( colIdx !== undefined ) {
3009
			cols[ colIdx ].sType = null;
3010
		}
3011
		else {
3012
			for ( i=0, ien=cols.length ; i<ien ; i++ ) {
3013
				cols[i].sType = null;
3014
			}
3015
	
3016
			// Update DataTables special `DT_*` attributes for the row
3017
			_fnRowAttributes( settings, row );
3018
		}
3019
	}
3020
	
3021
	
3022
	/**
3023
	 * Build a data source object from an HTML row, reading the contents of the
3024
	 * cells that are in the row.
3025
	 *
3026
	 * @param {object} settings DataTables settings object
3027
	 * @param {node|object} TR element from which to read data or existing row
3028
	 *   object from which to re-read the data from the cells
3029
	 * @param {int} [colIdx] Optional column index
3030
	 * @param {array|object} [d] Data source object. If `colIdx` is given then this
3031
	 *   parameter should also be given and will be used to write the data into.
3032
	 *   Only the column in question will be written
3033
	 * @returns {object} Object with two parameters: `data` the data read, in
3034
	 *   document order, and `cells` and array of nodes (they can be useful to the
3035
	 *   caller, so rather than needing a second traversal to get them, just return
3036
	 *   them from here).
3037
	 * @memberof DataTable#oApi
3038
	 */
3039
	function _fnGetRowElements( settings, row, colIdx, d )
3040
	{
3041
		var
3042
			tds = [],
3043
			td = row.firstChild,
3044
			name, col, o, i=0, contents,
3045
			columns = settings.aoColumns,
3046
			objectRead = settings._rowReadObject;
3047
	
3048
		// Allow the data object to be passed in, or construct
3049
		d = d !== undefined ?
3050
			d :
3051
			objectRead ?
3052
				{} :
3053
				[];
3054
	
3055
		var attr = function ( str, td  ) {
3056
			if ( typeof str === 'string' ) {
3057
				var idx = str.indexOf('@');
3058
	
3059
				if ( idx !== -1 ) {
3060
					var attr = str.substring( idx+1 );
3061
					var setter = _fnSetObjectDataFn( str );
3062
					setter( d, td.getAttribute( attr ) );
3063
				}
3064
			}
3065
		};
3066
	
3067
		// Read data from a cell and store into the data object
3068
		var cellProcess = function ( cell ) {
3069
			if ( colIdx === undefined || colIdx === i ) {
3070
				col = columns[i];
3071
				contents = (cell.innerHTML).trim();
3072
	
3073
				if ( col && col._bAttrSrc ) {
3074
					var setter = _fnSetObjectDataFn( col.mData._ );
3075
					setter( d, contents );
3076
	
3077
					attr( col.mData.sort, cell );
3078
					attr( col.mData.type, cell );
3079
					attr( col.mData.filter, cell );
3080
				}
3081
				else {
3082
					// Depending on the `data` option for the columns the data can
3083
					// be read to either an object or an array.
3084
					if ( objectRead ) {
3085
						if ( ! col._setter ) {
3086
							// Cache the setter function
3087
							col._setter = _fnSetObjectDataFn( col.mData );
3088
						}
3089
						col._setter( d, contents );
3090
					}
3091
					else {
3092
						d[i] = contents;
3093
					}
3094
				}
3095
			}
3096
	
3097
			i++;
3098
		};
3099
	
3100
		if ( td ) {
3101
			// `tr` element was passed in
3102
			while ( td ) {
3103
				name = td.nodeName.toUpperCase();
3104
	
3105
				if ( name == "TD" || name == "TH" ) {
3106
					cellProcess( td );
3107
					tds.push( td );
3108
				}
3109
	
3110
				td = td.nextSibling;
3111
			}
3112
		}
3113
		else {
3114
			// Existing row object passed in
3115
			tds = row.anCells;
3116
	
3117
			for ( var j=0, jen=tds.length ; j<jen ; j++ ) {
3118
				cellProcess( tds[j] );
3119
			}
3120
		}
3121
	
3122
		// Read the ID from the DOM if present
3123
		var rowNode = row.firstChild ? row : row.nTr;
3124
	
3125
		if ( rowNode ) {
3126
			var id = rowNode.getAttribute( 'id' );
3127
	
3128
			if ( id ) {
3129
				_fnSetObjectDataFn( settings.rowId )( d, id );
3130
			}
3131
		}
3132
	
3133
		return {
3134
			data: d,
3135
			cells: tds
3136
		};
3137
	}
3138
	/**
3139
	 * Create a new TR element (and it's TD children) for a row
3140
	 *  @param {object} oSettings dataTables settings object
3141
	 *  @param {int} iRow Row to consider
3142
	 *  @param {node} [nTrIn] TR element to add to the table - optional. If not given,
3143
	 *    DataTables will create a row automatically
3144
	 *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
3145
	 *    if nTr is.
3146
	 *  @memberof DataTable#oApi
3147
	 */
3148
	function _fnCreateTr ( oSettings, iRow, nTrIn, anTds )
3149
	{
3150
		var
3151
			row = oSettings.aoData[iRow],
3152
			rowData = row._aData,
3153
			cells = [],
3154
			nTr, nTd, oCol,
3155
			i, iLen, create;
3156
	
3157
		if ( row.nTr === null )
3158
		{
3159
			nTr = nTrIn || document.createElement('tr');
3160
	
3161
			row.nTr = nTr;
3162
			row.anCells = cells;
3163
	
3164
			/* Use a private property on the node to allow reserve mapping from the node
3165
			 * to the aoData array for fast look up
3166
			 */
3167
			nTr._DT_RowIndex = iRow;
3168
	
3169
			/* Special parameters can be given by the data source to be used on the row */
3170
			_fnRowAttributes( oSettings, row );
3171
	
3172
			/* Process each column */
3173
			for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
3174
			{
3175
				oCol = oSettings.aoColumns[i];
3176
				create = nTrIn ? false : true;
3177
	
3178
				nTd = create ? document.createElement( oCol.sCellType ) : anTds[i];
3179
				nTd._DT_CellIndex = {
3180
					row: iRow,
3181
					column: i
3182
				};
3183
				
3184
				cells.push( nTd );
3185
	
3186
				// Need to create the HTML if new, or if a rendering function is defined
3187
				if ( create || ((oCol.mRender || oCol.mData !== i) &&
3188
					 (!$.isPlainObject(oCol.mData) || oCol.mData._ !== i+'.display')
3189
				)) {
3190
					nTd.innerHTML = _fnGetCellData( oSettings, iRow, i, 'display' );
3191
				}
3192
	
3193
				/* Add user defined class */
3194
				if ( oCol.sClass )
3195
				{
3196
					nTd.className += ' '+oCol.sClass;
3197
				}
3198
	
3199
				// Visibility - add or remove as required
3200
				if ( oCol.bVisible && ! nTrIn )
3201
				{
3202
					nTr.appendChild( nTd );
3203
				}
3204
				else if ( ! oCol.bVisible && nTrIn )
3205
				{
3206
					nTd.parentNode.removeChild( nTd );
3207
				}
3208
	
3209
				if ( oCol.fnCreatedCell )
3210
				{
3211
					oCol.fnCreatedCell.call( oSettings.oInstance,
3212
						nTd, _fnGetCellData( oSettings, iRow, i ), rowData, iRow, i
3213
					);
3214
				}
3215
			}
3216
	
3217
			_fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow, cells] );
3218
		}
3219
	}
3220
	
3221
	
3222
	/**
3223
	 * Add attributes to a row based on the special `DT_*` parameters in a data
3224
	 * source object.
3225
	 *  @param {object} settings DataTables settings object
3226
	 *  @param {object} DataTables row object for the row to be modified
3227
	 *  @memberof DataTable#oApi
3228
	 */
3229
	function _fnRowAttributes( settings, row )
3230
	{
3231
		var tr = row.nTr;
3232
		var data = row._aData;
3233
	
3234
		if ( tr ) {
3235
			var id = settings.rowIdFn( data );
3236
	
3237
			if ( id ) {
3238
				tr.id = id;
3239
			}
3240
	
3241
			if ( data.DT_RowClass ) {
3242
				// Remove any classes added by DT_RowClass before
3243
				var a = data.DT_RowClass.split(' ');
3244
				row.__rowc = row.__rowc ?
3245
					_unique( row.__rowc.concat( a ) ) :
3246
					a;
3247
	
3248
				$(tr)
3249
					.removeClass( row.__rowc.join(' ') )
3250
					.addClass( data.DT_RowClass );
3251
			}
3252
	
3253
			if ( data.DT_RowAttr ) {
3254
				$(tr).attr( data.DT_RowAttr );
3255
			}
3256
	
3257
			if ( data.DT_RowData ) {
3258
				$(tr).data( data.DT_RowData );
3259
			}
3260
		}
3261
	}
3262
	
3263
	
3264
	/**
3265
	 * Create the HTML header for the table
3266
	 *  @param {object} oSettings dataTables settings object
3267
	 *  @memberof DataTable#oApi
3268
	 */
3269
	function _fnBuildHead( oSettings )
3270
	{
3271
		var i, ien, cell, row, column;
3272
		var thead = oSettings.nTHead;
3273
		var tfoot = oSettings.nTFoot;
3274
		var createHeader = $('th, td', thead).length === 0;
3275
		var classes = oSettings.oClasses;
3276
		var columns = oSettings.aoColumns;
3277
	
3278
		if ( createHeader ) {
3279
			row = $('<tr/>').appendTo( thead );
3280
		}
3281
	
3282
		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
3283
			column = columns[i];
3284
			cell = $( column.nTh ).addClass( column.sClass );
3285
	
3286
			if ( createHeader ) {
3287
				cell.appendTo( row );
3288
			}
3289
	
3290
			// 1.11 move into sorting
3291
			if ( oSettings.oFeatures.bSort ) {
3292
				cell.addClass( column.sSortingClass );
3293
	
3294
				if ( column.bSortable !== false ) {
3295
					cell
3296
						.attr( 'tabindex', oSettings.iTabIndex )
3297
						.attr( 'aria-controls', oSettings.sTableId );
3298
	
3299
					_fnSortAttachListener( oSettings, column.nTh, i );
3300
				}
3301
			}
3302
	
3303
			if ( column.sTitle != cell[0].innerHTML ) {
3304
				cell.html( column.sTitle );
3305
			}
3306
	
3307
			_fnRenderer( oSettings, 'header' )(
3308
				oSettings, cell, column, classes
3309
			);
3310
		}
3311
	
3312
		if ( createHeader ) {
3313
			_fnDetectHeader( oSettings.aoHeader, thead );
3314
		}
3315
	
3316
		/* Deal with the footer - add classes if required */
3317
		$(thead).children('tr').children('th, td').addClass( classes.sHeaderTH );
3318
		$(tfoot).children('tr').children('th, td').addClass( classes.sFooterTH );
3319
	
3320
		// Cache the footer cells. Note that we only take the cells from the first
3321
		// row in the footer. If there is more than one row the user wants to
3322
		// interact with, they need to use the table().foot() method. Note also this
3323
		// allows cells to be used for multiple columns using colspan
3324
		if ( tfoot !== null ) {
3325
			var cells = oSettings.aoFooter[0];
3326
	
3327
			for ( i=0, ien=cells.length ; i<ien ; i++ ) {
3328
				column = columns[i];
3329
				column.nTf = cells[i].cell;
3330
	
3331
				if ( column.sClass ) {
3332
					$(column.nTf).addClass( column.sClass );
3333
				}
3334
			}
3335
		}
3336
	}
3337
	
3338
	
3339
	/**
3340
	 * Draw the header (or footer) element based on the column visibility states. The
3341
	 * methodology here is to use the layout array from _fnDetectHeader, modified for
3342
	 * the instantaneous column visibility, to construct the new layout. The grid is
3343
	 * traversed over cell at a time in a rows x columns grid fashion, although each
3344
	 * cell insert can cover multiple elements in the grid - which is tracks using the
3345
	 * aApplied array. Cell inserts in the grid will only occur where there isn't
3346
	 * already a cell in that position.
3347
	 *  @param {object} oSettings dataTables settings object
3348
	 *  @param array {objects} aoSource Layout array from _fnDetectHeader
3349
	 *  @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,
3350
	 *  @memberof DataTable#oApi
3351
	 */
3352
	function _fnDrawHead( oSettings, aoSource, bIncludeHidden )
3353
	{
3354
		var i, iLen, j, jLen, k, kLen, n, nLocalTr;
3355
		var aoLocal = [];
3356
		var aApplied = [];
3357
		var iColumns = oSettings.aoColumns.length;
3358
		var iRowspan, iColspan;
3359
	
3360
		if ( ! aoSource )
3361
		{
3362
			return;
3363
		}
3364
	
3365
		if (  bIncludeHidden === undefined )
3366
		{
3367
			bIncludeHidden = false;
3368
		}
3369
	
3370
		/* Make a copy of the master layout array, but without the visible columns in it */
3371
		for ( i=0, iLen=aoSource.length ; i<iLen ; i++ )
3372
		{
3373
			aoLocal[i] = aoSource[i].slice();
3374
			aoLocal[i].nTr = aoSource[i].nTr;
3375
	
3376
			/* Remove any columns which are currently hidden */
3377
			for ( j=iColumns-1 ; j>=0 ; j-- )
3378
			{
3379
				if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden )
3380
				{
3381
					aoLocal[i].splice( j, 1 );
3382
				}
3383
			}
3384
	
3385
			/* Prep the applied array - it needs an element for each row */
3386
			aApplied.push( [] );
3387
		}
3388
	
3389
		for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ )
3390
		{
3391
			nLocalTr = aoLocal[i].nTr;
3392
	
3393
			/* All cells are going to be replaced, so empty out the row */
3394
			if ( nLocalTr )
3395
			{
3396
				while( (n = nLocalTr.firstChild) )
3397
				{
3398
					nLocalTr.removeChild( n );
3399
				}
3400
			}
3401
	
3402
			for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ )
3403
			{
3404
				iRowspan = 1;
3405
				iColspan = 1;
3406
	
3407
				/* Check to see if there is already a cell (row/colspan) covering our target
3408
				 * insert point. If there is, then there is nothing to do.
3409
				 */
3410
				if ( aApplied[i][j] === undefined )
3411
				{
3412
					nLocalTr.appendChild( aoLocal[i][j].cell );
3413
					aApplied[i][j] = 1;
3414
	
3415
					/* Expand the cell to cover as many rows as needed */
3416
					while ( aoLocal[i+iRowspan] !== undefined &&
3417
					        aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell )
3418
					{
3419
						aApplied[i+iRowspan][j] = 1;
3420
						iRowspan++;
3421
					}
3422
	
3423
					/* Expand the cell to cover as many columns as needed */
3424
					while ( aoLocal[i][j+iColspan] !== undefined &&
3425
					        aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell )
3426
					{
3427
						/* Must update the applied array over the rows for the columns */
3428
						for ( k=0 ; k<iRowspan ; k++ )
3429
						{
3430
							aApplied[i+k][j+iColspan] = 1;
3431
						}
3432
						iColspan++;
3433
					}
3434
	
3435
					/* Do the actual expansion in the DOM */
3436
					$(aoLocal[i][j].cell)
3437
						.attr('rowspan', iRowspan)
3438
						.attr('colspan', iColspan);
3439
				}
3440
			}
3441
		}
3442
	}
3443
	
3444
	
3445
	/**
3446
	 * Insert the required TR nodes into the table for display
3447
	 *  @param {object} oSettings dataTables settings object
3448
	 *  @param ajaxComplete true after ajax call to complete rendering
3449
	 *  @memberof DataTable#oApi
3450
	 */
3451
	function _fnDraw( oSettings, ajaxComplete )
3452
	{
3453
		// Allow for state saving and a custom start position
3454
		_fnStart( oSettings );
3455
	
3456
		/* Provide a pre-callback function which can be used to cancel the draw is false is returned */
3457
		var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] );
3458
		if ( $.inArray( false, aPreDraw ) !== -1 )
3459
		{
3460
			_fnProcessingDisplay( oSettings, false );
3461
			return;
3462
		}
3463
	
3464
		var anRows = [];
3465
		var iRowCount = 0;
3466
		var asStripeClasses = oSettings.asStripeClasses;
3467
		var iStripes = asStripeClasses.length;
3468
		var oLang = oSettings.oLanguage;
3469
		var bServerSide = _fnDataSource( oSettings ) == 'ssp';
3470
		var aiDisplay = oSettings.aiDisplay;
3471
		var iDisplayStart = oSettings._iDisplayStart;
3472
		var iDisplayEnd = oSettings.fnDisplayEnd();
3473
	
3474
		oSettings.bDrawing = true;
3475
	
3476
		/* Server-side processing draw intercept */
3477
		if ( oSettings.bDeferLoading )
3478
		{
3479
			oSettings.bDeferLoading = false;
3480
			oSettings.iDraw++;
3481
			_fnProcessingDisplay( oSettings, false );
3482
		}
3483
		else if ( !bServerSide )
3484
		{
3485
			oSettings.iDraw++;
3486
		}
3487
		else if ( !oSettings.bDestroying && !ajaxComplete)
3488
		{
3489
			_fnAjaxUpdate( oSettings );
3490
			return;
3491
		}
3492
	
3493
		if ( aiDisplay.length !== 0 )
3494
		{
3495
			var iStart = bServerSide ? 0 : iDisplayStart;
3496
			var iEnd = bServerSide ? oSettings.aoData.length : iDisplayEnd;
3497
	
3498
			for ( var j=iStart ; j<iEnd ; j++ )
3499
			{
3500
				var iDataIndex = aiDisplay[j];
3501
				var aoData = oSettings.aoData[ iDataIndex ];
3502
				if ( aoData.nTr === null )
3503
				{
3504
					_fnCreateTr( oSettings, iDataIndex );
3505
				}
3506
	
3507
				var nRow = aoData.nTr;
3508
	
3509
				/* Remove the old striping classes and then add the new one */
3510
				if ( iStripes !== 0 )
3511
				{
3512
					var sStripe = asStripeClasses[ iRowCount % iStripes ];
3513
					if ( aoData._sRowStripe != sStripe )
3514
					{
3515
						$(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe );
3516
						aoData._sRowStripe = sStripe;
3517
					}
3518
				}
3519
	
3520
				// Row callback functions - might want to manipulate the row
3521
				// iRowCount and j are not currently documented. Are they at all
3522
				// useful?
3523
				_fnCallbackFire( oSettings, 'aoRowCallback', null,
3524
					[nRow, aoData._aData, iRowCount, j, iDataIndex] );
3525
	
3526
				anRows.push( nRow );
3527
				iRowCount++;
3528
			}
3529
		}
3530
		else
3531
		{
3532
			/* Table is empty - create a row with an empty message in it */
3533
			var sZero = oLang.sZeroRecords;
3534
			if ( oSettings.iDraw == 1 &&  _fnDataSource( oSettings ) == 'ajax' )
3535
			{
3536
				sZero = oLang.sLoadingRecords;
3537
			}
3538
			else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 )
3539
			{
3540
				sZero = oLang.sEmptyTable;
3541
			}
3542
	
3543
			anRows[ 0 ] = $( '<tr/>', { 'class': iStripes ? asStripeClasses[0] : '' } )
3544
				.append( $('<td />', {
3545
					'valign':  'top',
3546
					'colSpan': _fnVisbleColumns( oSettings ),
3547
					'class':   oSettings.oClasses.sRowEmpty
3548
				} ).html( sZero ) )[0];
3549
		}
3550
	
3551
		/* Header and footer callbacks */
3552
		_fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0],
3553
			_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
3554
	
3555
		_fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0],
3556
			_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
3557
	
3558
		var body = $(oSettings.nTBody);
3559
	
3560
		body.children().detach();
3561
		body.append( $(anRows) );
3562
	
3563
		/* Call all required callback functions for the end of a draw */
3564
		_fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] );
3565
	
3566
		/* Draw is complete, sorting and filtering must be as well */
3567
		oSettings.bSorted = false;
3568
		oSettings.bFiltered = false;
3569
		oSettings.bDrawing = false;
3570
	}
3571
	
3572
	
3573
	/**
3574
	 * Redraw the table - taking account of the various features which are enabled
3575
	 *  @param {object} oSettings dataTables settings object
3576
	 *  @param {boolean} [holdPosition] Keep the current paging position. By default
3577
	 *    the paging is reset to the first page
3578
	 *  @memberof DataTable#oApi
3579
	 */
3580
	function _fnReDraw( settings, holdPosition )
3581
	{
3582
		var
3583
			features = settings.oFeatures,
3584
			sort     = features.bSort,
3585
			filter   = features.bFilter;
3586
	
3587
		if ( sort ) {
3588
			_fnSort( settings );
3589
		}
3590
	
3591
		if ( filter ) {
3592
			_fnFilterComplete( settings, settings.oPreviousSearch );
3593
		}
3594
		else {
3595
			// No filtering, so we want to just use the display master
3596
			settings.aiDisplay = settings.aiDisplayMaster.slice();
3597
		}
3598
	
3599
		if ( holdPosition !== true ) {
3600
			settings._iDisplayStart = 0;
3601
		}
3602
	
3603
		// Let any modules know about the draw hold position state (used by
3604
		// scrolling internally)
3605
		settings._drawHold = holdPosition;
3606
	
3607
		_fnDraw( settings );
3608
	
3609
		settings._drawHold = false;
3610
	}
3611
	
3612
	
3613
	/**
3614
	 * Add the options to the page HTML for the table
3615
	 *  @param {object} oSettings dataTables settings object
3616
	 *  @memberof DataTable#oApi
3617
	 */
3618
	function _fnAddOptionsHtml ( oSettings )
3619
	{
3620
		var classes = oSettings.oClasses;
3621
		var table = $(oSettings.nTable);
3622
		var holding = $('<div/>').insertBefore( table ); // Holding element for speed
3623
		var features = oSettings.oFeatures;
3624
	
3625
		// All DataTables are wrapped in a div
3626
		var insert = $('<div/>', {
3627
			id:      oSettings.sTableId+'_wrapper',
3628
			'class': classes.sWrapper + (oSettings.nTFoot ? '' : ' '+classes.sNoFooter)
3629
		} );
3630
	
3631
		oSettings.nHolding = holding[0];
3632
		oSettings.nTableWrapper = insert[0];
3633
		oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;
3634
	
3635
		/* Loop over the user set positioning and place the elements as needed */
3636
		var aDom = oSettings.sDom.split('');
3637
		var featureNode, cOption, nNewNode, cNext, sAttr, j;
3638
		for ( var i=0 ; i<aDom.length ; i++ )
3639
		{
3640
			featureNode = null;
3641
			cOption = aDom[i];
3642
	
3643
			if ( cOption == '<' )
3644
			{
3645
				/* New container div */
3646
				nNewNode = $('<div/>')[0];
3647
	
3648
				/* Check to see if we should append an id and/or a class name to the container */
3649
				cNext = aDom[i+1];
3650
				if ( cNext == "'" || cNext == '"' )
3651
				{
3652
					sAttr = "";
3653
					j = 2;
3654
					while ( aDom[i+j] != cNext )
3655
					{
3656
						sAttr += aDom[i+j];
3657
						j++;
3658
					}
3659
	
3660
					/* Replace jQuery UI constants @todo depreciated */
3661
					if ( sAttr == "H" )
3662
					{
3663
						sAttr = classes.sJUIHeader;
3664
					}
3665
					else if ( sAttr == "F" )
3666
					{
3667
						sAttr = classes.sJUIFooter;
3668
					}
3669
	
3670
					/* The attribute can be in the format of "#id.class", "#id" or "class" This logic
3671
					 * breaks the string into parts and applies them as needed
3672
					 */
3673
					if ( sAttr.indexOf('.') != -1 )
3674
					{
3675
						var aSplit = sAttr.split('.');
3676
						nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);
3677
						nNewNode.className = aSplit[1];
3678
					}
3679
					else if ( sAttr.charAt(0) == "#" )
3680
					{
3681
						nNewNode.id = sAttr.substr(1, sAttr.length-1);
3682
					}
3683
					else
3684
					{
3685
						nNewNode.className = sAttr;
3686
					}
3687
	
3688
					i += j; /* Move along the position array */
3689
				}
3690
	
3691
				insert.append( nNewNode );
3692
				insert = $(nNewNode);
3693
			}
3694
			else if ( cOption == '>' )
3695
			{
3696
				/* End container div */
3697
				insert = insert.parent();
3698
			}
3699
			// @todo Move options into their own plugins?
3700
			else if ( cOption == 'l' && features.bPaginate && features.bLengthChange )
3701
			{
3702
				/* Length */
3703
				featureNode = _fnFeatureHtmlLength( oSettings );
3704
			}
3705
			else if ( cOption == 'f' && features.bFilter )
3706
			{
3707
				/* Filter */
3708
				featureNode = _fnFeatureHtmlFilter( oSettings );
3709
			}
3710
			else if ( cOption == 'r' && features.bProcessing )
3711
			{
3712
				/* pRocessing */
3713
				featureNode = _fnFeatureHtmlProcessing( oSettings );
3714
			}
3715
			else if ( cOption == 't' )
3716
			{
3717
				/* Table */
3718
				featureNode = _fnFeatureHtmlTable( oSettings );
3719
			}
3720
			else if ( cOption ==  'i' && features.bInfo )
3721
			{
3722
				/* Info */
3723
				featureNode = _fnFeatureHtmlInfo( oSettings );
3724
			}
3725
			else if ( cOption == 'p' && features.bPaginate )
3726
			{
3727
				/* Pagination */
3728
				featureNode = _fnFeatureHtmlPaginate( oSettings );
3729
			}
3730
			else if ( DataTable.ext.feature.length !== 0 )
3731
			{
3732
				/* Plug-in features */
3733
				var aoFeatures = DataTable.ext.feature;
3734
				for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )
3735
				{
3736
					if ( cOption == aoFeatures[k].cFeature )
3737
					{
3738
						featureNode = aoFeatures[k].fnInit( oSettings );
3739
						break;
3740
					}
3741
				}
3742
			}
3743
	
3744
			/* Add to the 2D features array */
3745
			if ( featureNode )
3746
			{
3747
				var aanFeatures = oSettings.aanFeatures;
3748
	
3749
				if ( ! aanFeatures[cOption] )
3750
				{
3751
					aanFeatures[cOption] = [];
3752
				}
3753
	
3754
				aanFeatures[cOption].push( featureNode );
3755
				insert.append( featureNode );
3756
			}
3757
		}
3758
	
3759
		/* Built our DOM structure - replace the holding div with what we want */
3760
		holding.replaceWith( insert );
3761
		oSettings.nHolding = null;
3762
	}
3763
	
3764
	
3765
	/**
3766
	 * Use the DOM source to create up an array of header cells. The idea here is to
3767
	 * create a layout grid (array) of rows x columns, which contains a reference
3768
	 * to the cell that that point in the grid (regardless of col/rowspan), such that
3769
	 * any column / row could be removed and the new grid constructed
3770
	 *  @param array {object} aLayout Array to store the calculated layout in
3771
	 *  @param {node} nThead The header/footer element for the table
3772
	 *  @memberof DataTable#oApi
3773
	 */
3774
	function _fnDetectHeader ( aLayout, nThead )
3775
	{
3776
		var nTrs = $(nThead).children('tr');
3777
		var nTr, nCell;
3778
		var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan;
3779
		var bUnique;
3780
		var fnShiftCol = function ( a, i, j ) {
3781
			var k = a[i];
3782
	                while ( k[j] ) {
3783
				j++;
3784
			}
3785
			return j;
3786
		};
3787
	
3788
		aLayout.splice( 0, aLayout.length );
3789
	
3790
		/* We know how many rows there are in the layout - so prep it */
3791
		for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
3792
		{
3793
			aLayout.push( [] );
3794
		}
3795
	
3796
		/* Calculate a layout array */
3797
		for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
3798
		{
3799
			nTr = nTrs[i];
3800
			iColumn = 0;
3801
	
3802
			/* For every cell in the row... */
3803
			nCell = nTr.firstChild;
3804
			while ( nCell ) {
3805
				if ( nCell.nodeName.toUpperCase() == "TD" ||
3806
				     nCell.nodeName.toUpperCase() == "TH" )
3807
				{
3808
					/* Get the col and rowspan attributes from the DOM and sanitise them */
3809
					iColspan = nCell.getAttribute('colspan') * 1;
3810
					iRowspan = nCell.getAttribute('rowspan') * 1;
3811
					iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan;
3812
					iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan;
3813
	
3814
					/* There might be colspan cells already in this row, so shift our target
3815
					 * accordingly
3816
					 */
3817
					iColShifted = fnShiftCol( aLayout, i, iColumn );
3818
	
3819
					/* Cache calculation for unique columns */
3820
					bUnique = iColspan === 1 ? true : false;
3821
	
3822
					/* If there is col / rowspan, copy the information into the layout grid */
3823
					for ( l=0 ; l<iColspan ; l++ )
3824
					{
3825
						for ( k=0 ; k<iRowspan ; k++ )
3826
						{
3827
							aLayout[i+k][iColShifted+l] = {
3828
								"cell": nCell,
3829
								"unique": bUnique
3830
							};
3831
							aLayout[i+k].nTr = nTr;
3832
						}
3833
					}
3834
				}
3835
				nCell = nCell.nextSibling;
3836
			}
3837
		}
3838
	}
3839
	
3840
	
3841
	/**
3842
	 * Get an array of unique th elements, one for each column
3843
	 *  @param {object} oSettings dataTables settings object
3844
	 *  @param {node} nHeader automatically detect the layout from this node - optional
3845
	 *  @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional
3846
	 *  @returns array {node} aReturn list of unique th's
3847
	 *  @memberof DataTable#oApi
3848
	 */
3849
	function _fnGetUniqueThs ( oSettings, nHeader, aLayout )
3850
	{
3851
		var aReturn = [];
3852
		if ( !aLayout )
3853
		{
3854
			aLayout = oSettings.aoHeader;
3855
			if ( nHeader )
3856
			{
3857
				aLayout = [];
3858
				_fnDetectHeader( aLayout, nHeader );
3859
			}
3860
		}
3861
	
3862
		for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ )
3863
		{
3864
			for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ )
3865
			{
3866
				if ( aLayout[i][j].unique &&
3867
					 (!aReturn[j] || !oSettings.bSortCellsTop) )
3868
				{
3869
					aReturn[j] = aLayout[i][j].cell;
3870
				}
3871
			}
3872
		}
3873
	
3874
		return aReturn;
3875
	}
3876
	
3877
	/**
3878
	 * Set the start position for draw
3879
	 *  @param {object} oSettings dataTables settings object
3880
	 */
3881
	function _fnStart( oSettings )
3882
	{
3883
		var bServerSide = _fnDataSource( oSettings ) == 'ssp';
3884
		var iInitDisplayStart = oSettings.iInitDisplayStart;
3885
	
3886
		// Check and see if we have an initial draw position from state saving
3887
		if ( iInitDisplayStart !== undefined && iInitDisplayStart !== -1 )
3888
		{
3889
			oSettings._iDisplayStart = bServerSide ?
3890
				iInitDisplayStart :
3891
				iInitDisplayStart >= oSettings.fnRecordsDisplay() ?
3892
					0 :
3893
					iInitDisplayStart;
3894
	
3895
			oSettings.iInitDisplayStart = -1;
3896
		}
3897
	}
3898
	
3899
	/**
3900
	 * Create an Ajax call based on the table's settings, taking into account that
3901
	 * parameters can have multiple forms, and backwards compatibility.
3902
	 *
3903
	 * @param {object} oSettings dataTables settings object
3904
	 * @param {array} data Data to send to the server, required by
3905
	 *     DataTables - may be augmented by developer callbacks
3906
	 * @param {function} fn Callback function to run when data is obtained
3907
	 */
3908
	function _fnBuildAjax( oSettings, data, fn )
3909
	{
3910
		// Compatibility with 1.9-, allow fnServerData and event to manipulate
3911
		_fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [data] );
3912
	
3913
		// Convert to object based for 1.10+ if using the old array scheme which can
3914
		// come from server-side processing or serverParams
3915
		if ( data && Array.isArray(data) ) {
3916
			var tmp = {};
3917
			var rbracket = /(.*?)\[\]$/;
3918
	
3919
			$.each( data, function (key, val) {
3920
				var match = val.name.match(rbracket);
3921
	
3922
				if ( match ) {
3923
					// Support for arrays
3924
					var name = match[0];
3925
	
3926
					if ( ! tmp[ name ] ) {
3927
						tmp[ name ] = [];
3928
					}
3929
					tmp[ name ].push( val.value );
3930
				}
3931
				else {
3932
					tmp[val.name] = val.value;
3933
				}
3934
			} );
3935
			data = tmp;
3936
		}
3937
	
3938
		var ajaxData;
3939
		var ajax = oSettings.ajax;
3940
		var instance = oSettings.oInstance;
3941
		var callback = function ( json ) {
3942
			var status = oSettings.jqXHR
3943
				? oSettings.jqXHR.status
3944
				: null;
3945
	
3946
			if ( json === null || (typeof status === 'number' && status == 204 ) ) {
3947
				json = {};
3948
				_fnAjaxDataSrc( oSettings, json, [] );
3949
			}
3950
	
3951
			var error = json.error || json.sError;
3952
			if ( error ) {
3953
				_fnLog( oSettings, 0, error );
3954
			}
3955
	
3956
			oSettings.json = json;
3957
	
3958
			_fnCallbackFire( oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR] );
3959
			fn( json );
3960
		};
3961
	
3962
		if ( $.isPlainObject( ajax ) && ajax.data )
3963
		{
3964
			ajaxData = ajax.data;
3965
	
3966
			var newData = typeof ajaxData === 'function' ?
3967
				ajaxData( data, oSettings ) :  // fn can manipulate data or return
3968
				ajaxData;                      // an object object or array to merge
3969
	
3970
			// If the function returned something, use that alone
3971
			data = typeof ajaxData === 'function' && newData ?
3972
				newData :
3973
				$.extend( true, data, newData );
3974
	
3975
			// Remove the data property as we've resolved it already and don't want
3976
			// jQuery to do it again (it is restored at the end of the function)
3977
			delete ajax.data;
3978
		}
3979
	
3980
		var baseAjax = {
3981
			"data": data,
3982
			"success": callback,
3983
			"dataType": "json",
3984
			"cache": false,
3985
			"type": oSettings.sServerMethod,
3986
			"error": function (xhr, error, thrown) {
3987
				var ret = _fnCallbackFire( oSettings, null, 'xhr', [oSettings, null, oSettings.jqXHR] );
3988
	
3989
				if ( $.inArray( true, ret ) === -1 ) {
3990
					if ( error == "parsererror" ) {
3991
						_fnLog( oSettings, 0, 'Invalid JSON response', 1 );
3992
					}
3993
					else if ( xhr.readyState === 4 ) {
3994
						_fnLog( oSettings, 0, 'Ajax error', 7 );
3995
					}
3996
				}
3997
	
3998
				_fnProcessingDisplay( oSettings, false );
3999
			}
4000
		};
4001
	
4002
		// Store the data submitted for the API
4003
		oSettings.oAjaxData = data;
4004
	
4005
		// Allow plug-ins and external processes to modify the data
4006
		_fnCallbackFire( oSettings, null, 'preXhr', [oSettings, data] );
4007
	
4008
		if ( oSettings.fnServerData )
4009
		{
4010
			// DataTables 1.9- compatibility
4011
			oSettings.fnServerData.call( instance,
4012
				oSettings.sAjaxSource,
4013
				$.map( data, function (val, key) { // Need to convert back to 1.9 trad format
4014
					return { name: key, value: val };
4015
				} ),
4016
				callback,
4017
				oSettings
4018
			);
4019
		}
4020
		else if ( oSettings.sAjaxSource || typeof ajax === 'string' )
4021
		{
4022
			// DataTables 1.9- compatibility
4023
			oSettings.jqXHR = $.ajax( $.extend( baseAjax, {
4024
				url: ajax || oSettings.sAjaxSource
4025
			} ) );
4026
		}
4027
		else if ( typeof ajax === 'function' )
4028
		{
4029
			// Is a function - let the caller define what needs to be done
4030
			oSettings.jqXHR = ajax.call( instance, data, callback, oSettings );
4031
		}
4032
		else
4033
		{
4034
			// Object to extend the base settings
4035
			oSettings.jqXHR = $.ajax( $.extend( baseAjax, ajax ) );
4036
	
4037
			// Restore for next time around
4038
			ajax.data = ajaxData;
4039
		}
4040
	}
4041
	
4042
	
4043
	/**
4044
	 * Update the table using an Ajax call
4045
	 *  @param {object} settings dataTables settings object
4046
	 *  @returns {boolean} Block the table drawing or not
4047
	 *  @memberof DataTable#oApi
4048
	 */
4049
	function _fnAjaxUpdate( settings )
4050
	{
4051
		settings.iDraw++;
4052
		_fnProcessingDisplay( settings, true );
4053
	
4054
		_fnBuildAjax(
4055
			settings,
4056
			_fnAjaxParameters( settings ),
4057
			function(json) {
4058
				_fnAjaxUpdateDraw( settings, json );
4059
			}
4060
		);
4061
	}
4062
	
4063
	
4064
	/**
4065
	 * Build up the parameters in an object needed for a server-side processing
4066
	 * request. Note that this is basically done twice, is different ways - a modern
4067
	 * method which is used by default in DataTables 1.10 which uses objects and
4068
	 * arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if
4069
	 * the sAjaxSource option is used in the initialisation, or the legacyAjax
4070
	 * option is set.
4071
	 *  @param {object} oSettings dataTables settings object
4072
	 *  @returns {bool} block the table drawing or not
4073
	 *  @memberof DataTable#oApi
4074
	 */
4075
	function _fnAjaxParameters( settings )
4076
	{
4077
		var
4078
			columns = settings.aoColumns,
4079
			columnCount = columns.length,
4080
			features = settings.oFeatures,
4081
			preSearch = settings.oPreviousSearch,
4082
			preColSearch = settings.aoPreSearchCols,
4083
			i, data = [], dataProp, column, columnSearch,
4084
			sort = _fnSortFlatten( settings ),
4085
			displayStart = settings._iDisplayStart,
4086
			displayLength = features.bPaginate !== false ?
4087
				settings._iDisplayLength :
4088
				-1;
4089
	
4090
		var param = function ( name, value ) {
4091
			data.push( { 'name': name, 'value': value } );
4092
		};
4093
	
4094
		// DataTables 1.9- compatible method
4095
		param( 'sEcho',          settings.iDraw );
4096
		param( 'iColumns',       columnCount );
4097
		param( 'sColumns',       _pluck( columns, 'sName' ).join(',') );
4098
		param( 'iDisplayStart',  displayStart );
4099
		param( 'iDisplayLength', displayLength );
4100
	
4101
		// DataTables 1.10+ method
4102
		var d = {
4103
			draw:    settings.iDraw,
4104
			columns: [],
4105
			order:   [],
4106
			start:   displayStart,
4107
			length:  displayLength,
4108
			search:  {
4109
				value: preSearch.sSearch,
4110
				regex: preSearch.bRegex
4111
			}
4112
		};
4113
	
4114
		for ( i=0 ; i<columnCount ; i++ ) {
4115
			column = columns[i];
4116
			columnSearch = preColSearch[i];
4117
			dataProp = typeof column.mData=="function" ? 'function' : column.mData ;
4118
	
4119
			d.columns.push( {
4120
				data:       dataProp,
4121
				name:       column.sName,
4122
				searchable: column.bSearchable,
4123
				orderable:  column.bSortable,
4124
				search:     {
4125
					value: columnSearch.sSearch,
4126
					regex: columnSearch.bRegex
4127
				}
4128
			} );
4129
	
4130
			param( "mDataProp_"+i, dataProp );
4131
	
4132
			if ( features.bFilter ) {
4133
				param( 'sSearch_'+i,     columnSearch.sSearch );
4134
				param( 'bRegex_'+i,      columnSearch.bRegex );
4135
				param( 'bSearchable_'+i, column.bSearchable );
4136
			}
4137
	
4138
			if ( features.bSort ) {
4139
				param( 'bSortable_'+i, column.bSortable );
4140
			}
4141
		}
4142
	
4143
		if ( features.bFilter ) {
4144
			param( 'sSearch', preSearch.sSearch );
4145
			param( 'bRegex', preSearch.bRegex );
4146
		}
4147
	
4148
		if ( features.bSort ) {
4149
			$.each( sort, function ( i, val ) {
4150
				d.order.push( { column: val.col, dir: val.dir } );
4151
	
4152
				param( 'iSortCol_'+i, val.col );
4153
				param( 'sSortDir_'+i, val.dir );
4154
			} );
4155
	
4156
			param( 'iSortingCols', sort.length );
4157
		}
4158
	
4159
		// If the legacy.ajax parameter is null, then we automatically decide which
4160
		// form to use, based on sAjaxSource
4161
		var legacy = DataTable.ext.legacy.ajax;
4162
		if ( legacy === null ) {
4163
			return settings.sAjaxSource ? data : d;
4164
		}
4165
	
4166
		// Otherwise, if legacy has been specified then we use that to decide on the
4167
		// form
4168
		return legacy ? data : d;
4169
	}
4170
	
4171
	
4172
	/**
4173
	 * Data the data from the server (nuking the old) and redraw the table
4174
	 *  @param {object} oSettings dataTables settings object
4175
	 *  @param {object} json json data return from the server.
4176
	 *  @param {string} json.sEcho Tracking flag for DataTables to match requests
4177
	 *  @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering
4178
	 *  @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering
4179
	 *  @param {array} json.aaData The data to display on this page
4180
	 *  @param {string} [json.sColumns] Column ordering (sName, comma separated)
4181
	 *  @memberof DataTable#oApi
4182
	 */
4183
	function _fnAjaxUpdateDraw ( settings, json )
4184
	{
4185
		// v1.10 uses camelCase variables, while 1.9 uses Hungarian notation.
4186
		// Support both
4187
		var compat = function ( old, modern ) {
4188
			return json[old] !== undefined ? json[old] : json[modern];
4189
		};
4190
	
4191
		var data = _fnAjaxDataSrc( settings, json );
4192
		var draw            = compat( 'sEcho',                'draw' );
4193
		var recordsTotal    = compat( 'iTotalRecords',        'recordsTotal' );
4194
		var recordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' );
4195
	
4196
		if ( draw !== undefined ) {
4197
			// Protect against out of sequence returns
4198
			if ( draw*1 < settings.iDraw ) {
4199
				return;
4200
			}
4201
			settings.iDraw = draw * 1;
4202
		}
4203
	
4204
		// No data in returned object, so rather than an array, we show an empty table
4205
		if ( ! data ) {
4206
			data = [];
4207
		}
4208
	
4209
		_fnClearTable( settings );
4210
		settings._iRecordsTotal   = parseInt(recordsTotal, 10);
4211
		settings._iRecordsDisplay = parseInt(recordsFiltered, 10);
4212
	
4213
		for ( var i=0, ien=data.length ; i<ien ; i++ ) {
4214
			_fnAddData( settings, data[i] );
4215
		}
4216
		settings.aiDisplay = settings.aiDisplayMaster.slice();
4217
	
4218
		_fnDraw( settings, true );
4219
	
4220
		if ( ! settings._bInitComplete ) {
4221
			_fnInitComplete( settings, json );
4222
		}
4223
	
4224
		_fnProcessingDisplay( settings, false );
4225
	}
4226
	
4227
	
4228
	/**
4229
	 * Get the data from the JSON data source to use for drawing a table. Using
4230
	 * `_fnGetObjectDataFn` allows the data to be sourced from a property of the
4231
	 * source object, or from a processing function.
4232
	 *  @param {object} oSettings dataTables settings object
4233
	 *  @param  {object} json Data source object / array from the server
4234
	 *  @return {array} Array of data to use
4235
	 */
4236
	 function _fnAjaxDataSrc ( oSettings, json, write )
4237
	 {
4238
		var dataSrc = $.isPlainObject( oSettings.ajax ) && oSettings.ajax.dataSrc !== undefined ?
4239
			oSettings.ajax.dataSrc :
4240
			oSettings.sAjaxDataProp; // Compatibility with 1.9-.
4241
	
4242
		if ( ! write ) {
4243
			if ( dataSrc === 'data' ) {
4244
				// If the default, then we still want to support the old style, and safely ignore
4245
				// it if possible
4246
				return json.aaData || json[dataSrc];
4247
			}
4248
	
4249
			return dataSrc !== "" ?
4250
				_fnGetObjectDataFn( dataSrc )( json ) :
4251
				json;
4252
		}
4253
	
4254
		// set
4255
		_fnSetObjectDataFn( dataSrc )( json, write );
4256
	}
4257
	
4258
	/**
4259
	 * Generate the node required for filtering text
4260
	 *  @returns {node} Filter control element
4261
	 *  @param {object} oSettings dataTables settings object
4262
	 *  @memberof DataTable#oApi
4263
	 */
4264
	function _fnFeatureHtmlFilter ( settings )
4265
	{
4266
		var classes = settings.oClasses;
4267
		var tableId = settings.sTableId;
4268
		var language = settings.oLanguage;
4269
		var previousSearch = settings.oPreviousSearch;
4270
		var features = settings.aanFeatures;
4271
		var input = '<input type="search" class="'+classes.sFilterInput+'"/>';
4272
	
4273
		var str = language.sSearch;
4274
		str = str.match(/_INPUT_/) ?
4275
			str.replace('_INPUT_', input) :
4276
			str+input;
4277
	
4278
		var filter = $('<div/>', {
4279
				'id': ! features.f ? tableId+'_filter' : null,
4280
				'class': classes.sFilter
4281
			} )
4282
			.append( $('<label/>' ).append( str ) );
4283
	
4284
		var searchFn = function(event) {
4285
			/* Update all other filter input elements for the new display */
4286
			var n = features.f;
4287
			var val = !this.value ? "" : this.value; // mental IE8 fix :-(
4288
			if(previousSearch.return && event.key !== "Enter") {
4289
				return;
4290
			}
4291
			/* Now do the filter */
4292
			if ( val != previousSearch.sSearch ) {
4293
				_fnFilterComplete( settings, {
4294
					"sSearch": val,
4295
					"bRegex": previousSearch.bRegex,
4296
					"bSmart": previousSearch.bSmart ,
4297
					"bCaseInsensitive": previousSearch.bCaseInsensitive,
4298
					"return": previousSearch.return
4299
				} );
4300
	
4301
				// Need to redraw, without resorting
4302
				settings._iDisplayStart = 0;
4303
				_fnDraw( settings );
4304
			}
4305
		};
4306
	
4307
		var searchDelay = settings.searchDelay !== null ?
4308
			settings.searchDelay :
4309
			_fnDataSource( settings ) === 'ssp' ?
4310
				400 :
4311
				0;
4312
	
4313
		var jqFilter = $('input', filter)
4314
			.val( previousSearch.sSearch )
4315
			.attr( 'placeholder', language.sSearchPlaceholder )
4316
			.on(
4317
				'keyup.DT search.DT input.DT paste.DT cut.DT',
4318
				searchDelay ?
4319
					_fnThrottle( searchFn, searchDelay ) :
4320
					searchFn
4321
			)
4322
			.on( 'mouseup', function(e) {
4323
				// Edge fix! Edge 17 does not trigger anything other than mouse events when clicking
4324
				// on the clear icon (Edge bug 17584515). This is safe in other browsers as `searchFn`
4325
				// checks the value to see if it has changed. In other browsers it won't have.
4326
				setTimeout( function () {
4327
					searchFn.call(jqFilter[0], e);
4328
				}, 10);
4329
			} )
4330
			.on( 'keypress.DT', function(e) {
4331
				/* Prevent form submission */
4332
				if ( e.keyCode == 13 ) {
4333
					return false;
4334
				}
4335
			} )
4336
			.attr('aria-controls', tableId);
4337
	
4338
		// Update the input elements whenever the table is filtered
4339
		$(settings.nTable).on( 'search.dt.DT', function ( ev, s ) {
4340
			if ( settings === s ) {
4341
				// IE9 throws an 'unknown error' if document.activeElement is used
4342
				// inside an iframe or frame...
4343
				try {
4344
					if ( jqFilter[0] !== document.activeElement ) {
4345
						jqFilter.val( previousSearch.sSearch );
4346
					}
4347
				}
4348
				catch ( e ) {}
4349
			}
4350
		} );
4351
	
4352
		return filter[0];
4353
	}
4354
	
4355
	
4356
	/**
4357
	 * Filter the table using both the global filter and column based filtering
4358
	 *  @param {object} oSettings dataTables settings object
4359
	 *  @param {object} oSearch search information
4360
	 *  @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)
4361
	 *  @memberof DataTable#oApi
4362
	 */
4363
	function _fnFilterComplete ( oSettings, oInput, iForce )
4364
	{
4365
		var oPrevSearch = oSettings.oPreviousSearch;
4366
		var aoPrevSearch = oSettings.aoPreSearchCols;
4367
		var fnSaveFilter = function ( oFilter ) {
4368
			/* Save the filtering values */
4369
			oPrevSearch.sSearch = oFilter.sSearch;
4370
			oPrevSearch.bRegex = oFilter.bRegex;
4371
			oPrevSearch.bSmart = oFilter.bSmart;
4372
			oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive;
4373
			oPrevSearch.return = oFilter.return;
4374
		};
4375
		var fnRegex = function ( o ) {
4376
			// Backwards compatibility with the bEscapeRegex option
4377
			return o.bEscapeRegex !== undefined ? !o.bEscapeRegex : o.bRegex;
4378
		};
4379
	
4380
		// Resolve any column types that are unknown due to addition or invalidation
4381
		// @todo As per sort - can this be moved into an event handler?
4382
		_fnColumnTypes( oSettings );
4383
	
4384
		/* In server-side processing all filtering is done by the server, so no point hanging around here */
4385
		if ( _fnDataSource( oSettings ) != 'ssp' )
4386
		{
4387
			/* Global filter */
4388
			_fnFilter( oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive, oInput.return );
4389
			fnSaveFilter( oInput );
4390
	
4391
			/* Now do the individual column filter */
4392
			for ( var i=0 ; i<aoPrevSearch.length ; i++ )
4393
			{
4394
				_fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, fnRegex(aoPrevSearch[i]),
4395
					aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive );
4396
			}
4397
	
4398
			/* Custom filtering */
4399
			_fnFilterCustom( oSettings );
4400
		}
4401
		else
4402
		{
4403
			fnSaveFilter( oInput );
4404
		}
4405
	
4406
		/* Tell the draw function we have been filtering */
4407
		oSettings.bFiltered = true;
4408
		_fnCallbackFire( oSettings, null, 'search', [oSettings] );
4409
	}
4410
	
4411
	
4412
	/**
4413
	 * Apply custom filtering functions
4414
	 *  @param {object} oSettings dataTables settings object
4415
	 *  @memberof DataTable#oApi
4416
	 */
4417
	function _fnFilterCustom( settings )
4418
	{
4419
		var filters = DataTable.ext.search;
4420
		var displayRows = settings.aiDisplay;
4421
		var row, rowIdx;
4422
	
4423
		for ( var i=0, ien=filters.length ; i<ien ; i++ ) {
4424
			var rows = [];
4425
	
4426
			// Loop over each row and see if it should be included
4427
			for ( var j=0, jen=displayRows.length ; j<jen ; j++ ) {
4428
				rowIdx = displayRows[ j ];
4429
				row = settings.aoData[ rowIdx ];
4430
	
4431
				if ( filters[i]( settings, row._aFilterData, rowIdx, row._aData, j ) ) {
4432
					rows.push( rowIdx );
4433
				}
4434
			}
4435
	
4436
			// So the array reference doesn't break set the results into the
4437
			// existing array
4438
			displayRows.length = 0;
4439
			$.merge( displayRows, rows );
4440
		}
4441
	}
4442
	
4443
	
4444
	/**
4445
	 * Filter the table on a per-column basis
4446
	 *  @param {object} oSettings dataTables settings object
4447
	 *  @param {string} sInput string to filter on
4448
	 *  @param {int} iColumn column to filter
4449
	 *  @param {bool} bRegex treat search string as a regular expression or not
4450
	 *  @param {bool} bSmart use smart filtering or not
4451
	 *  @param {bool} bCaseInsensitive Do case insensitive matching or not
4452
	 *  @memberof DataTable#oApi
4453
	 */
4454
	function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, caseInsensitive )
4455
	{
4456
		if ( searchStr === '' ) {
4457
			return;
4458
		}
4459
	
4460
		var data;
4461
		var out = [];
4462
		var display = settings.aiDisplay;
4463
		var rpSearch = _fnFilterCreateSearch( searchStr, regex, smart, caseInsensitive );
4464
	
4465
		for ( var i=0 ; i<display.length ; i++ ) {
4466
			data = settings.aoData[ display[i] ]._aFilterData[ colIdx ];
4467
	
4468
			if ( rpSearch.test( data ) ) {
4469
				out.push( display[i] );
4470
			}
4471
		}
4472
	
4473
		settings.aiDisplay = out;
4474
	}
4475
	
4476
	
4477
	/**
4478
	 * Filter the data table based on user input and draw the table
4479
	 *  @param {object} settings dataTables settings object
4480
	 *  @param {string} input string to filter on
4481
	 *  @param {int} force optional - force a research of the master array (1) or not (undefined or 0)
4482
	 *  @param {bool} regex treat as a regular expression or not
4483
	 *  @param {bool} smart perform smart filtering or not
4484
	 *  @param {bool} caseInsensitive Do case insensitive matching or not
4485
	 *  @memberof DataTable#oApi
4486
	 */
4487
	function _fnFilter( settings, input, force, regex, smart, caseInsensitive )
4488
	{
4489
		var rpSearch = _fnFilterCreateSearch( input, regex, smart, caseInsensitive );
4490
		var prevSearch = settings.oPreviousSearch.sSearch;
4491
		var displayMaster = settings.aiDisplayMaster;
4492
		var display, invalidated, i;
4493
		var filtered = [];
4494
	
4495
		// Need to take account of custom filtering functions - always filter
4496
		if ( DataTable.ext.search.length !== 0 ) {
4497
			force = true;
4498
		}
4499
	
4500
		// Check if any of the rows were invalidated
4501
		invalidated = _fnFilterData( settings );
4502
	
4503
		// If the input is blank - we just want the full data set
4504
		if ( input.length <= 0 ) {
4505
			settings.aiDisplay = displayMaster.slice();
4506
		}
4507
		else {
4508
			// New search - start from the master array
4509
			if ( invalidated ||
4510
				 force ||
4511
				 regex ||
4512
				 prevSearch.length > input.length ||
4513
				 input.indexOf(prevSearch) !== 0 ||
4514
				 settings.bSorted // On resort, the display master needs to be
4515
				                  // re-filtered since indexes will have changed
4516
			) {
4517
				settings.aiDisplay = displayMaster.slice();
4518
			}
4519
	
4520
			// Search the display array
4521
			display = settings.aiDisplay;
4522
	
4523
			for ( i=0 ; i<display.length ; i++ ) {
4524
				if ( rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) {
4525
					filtered.push( display[i] );
4526
				}
4527
			}
4528
	
4529
			settings.aiDisplay = filtered;
4530
		}
4531
	}
4532
	
4533
	
4534
	/**
4535
	 * Build a regular expression object suitable for searching a table
4536
	 *  @param {string} sSearch string to search for
4537
	 *  @param {bool} bRegex treat as a regular expression or not
4538
	 *  @param {bool} bSmart perform smart filtering or not
4539
	 *  @param {bool} bCaseInsensitive Do case insensitive matching or not
4540
	 *  @returns {RegExp} constructed object
4541
	 *  @memberof DataTable#oApi
4542
	 */
4543
	function _fnFilterCreateSearch( search, regex, smart, caseInsensitive )
4544
	{
4545
		search = regex ?
4546
			search :
4547
			_fnEscapeRegex( search );
4548
		
4549
		if ( smart ) {
4550
			/* For smart filtering we want to allow the search to work regardless of
4551
			 * word order. We also want double quoted text to be preserved, so word
4552
			 * order is important - a la google. So this is what we want to
4553
			 * generate:
4554
			 * 
4555
			 * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$
4556
			 */
4557
			var a = $.map( search.match( /"[^"]+"|[^ ]+/g ) || [''], function ( word ) {
4558
				if ( word.charAt(0) === '"' ) {
4559
					var m = word.match( /^"(.*)"$/ );
4560
					word = m ? m[1] : word;
4561
				}
4562
	
4563
				return word.replace('"', '');
4564
			} );
4565
	
4566
			search = '^(?=.*?'+a.join( ')(?=.*?' )+').*$';
4567
		}
4568
	
4569
		return new RegExp( search, caseInsensitive ? 'i' : '' );
4570
	}
4571
	
4572
	
4573
	/**
4574
	 * Escape a string such that it can be used in a regular expression
4575
	 *  @param {string} sVal string to escape
4576
	 *  @returns {string} escaped string
4577
	 *  @memberof DataTable#oApi
4578
	 */
4579
	var _fnEscapeRegex = DataTable.util.escapeRegex;
4580
	
4581
	var __filter_div = $('<div>')[0];
4582
	var __filter_div_textContent = __filter_div.textContent !== undefined;
4583
	
4584
	// Update the filtering data for each row if needed (by invalidation or first run)
4585
	function _fnFilterData ( settings )
4586
	{
4587
		var columns = settings.aoColumns;
4588
		var column;
4589
		var i, j, ien, jen, filterData, cellData, row;
4590
		var wasInvalidated = false;
4591
	
4592
		for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
4593
			row = settings.aoData[i];
4594
	
4595
			if ( ! row._aFilterData ) {
4596
				filterData = [];
4597
	
4598
				for ( j=0, jen=columns.length ; j<jen ; j++ ) {
4599
					column = columns[j];
4600
	
4601
					if ( column.bSearchable ) {
4602
						cellData = _fnGetCellData( settings, i, j, 'filter' );
4603
	
4604
						// Search in DataTables 1.10 is string based. In 1.11 this
4605
						// should be altered to also allow strict type checking.
4606
						if ( cellData === null ) {
4607
							cellData = '';
4608
						}
4609
	
4610
						if ( typeof cellData !== 'string' && cellData.toString ) {
4611
							cellData = cellData.toString();
4612
						}
4613
					}
4614
					else {
4615
						cellData = '';
4616
					}
4617
	
4618
					// If it looks like there is an HTML entity in the string,
4619
					// attempt to decode it so sorting works as expected. Note that
4620
					// we could use a single line of jQuery to do this, but the DOM
4621
					// method used here is much faster http://jsperf.com/html-decode
4622
					if ( cellData.indexOf && cellData.indexOf('&') !== -1 ) {
4623
						__filter_div.innerHTML = cellData;
4624
						cellData = __filter_div_textContent ?
4625
							__filter_div.textContent :
4626
							__filter_div.innerText;
4627
					}
4628
	
4629
					if ( cellData.replace ) {
4630
						cellData = cellData.replace(/[\r\n\u2028]/g, '');
4631
					}
4632
	
4633
					filterData.push( cellData );
4634
				}
4635
	
4636
				row._aFilterData = filterData;
4637
				row._sFilterRow = filterData.join('  ');
4638
				wasInvalidated = true;
4639
			}
4640
		}
4641
	
4642
		return wasInvalidated;
4643
	}
4644
	
4645
	
4646
	/**
4647
	 * Convert from the internal Hungarian notation to camelCase for external
4648
	 * interaction
4649
	 *  @param {object} obj Object to convert
4650
	 *  @returns {object} Inverted object
4651
	 *  @memberof DataTable#oApi
4652
	 */
4653
	function _fnSearchToCamel ( obj )
4654
	{
4655
		return {
4656
			search:          obj.sSearch,
4657
			smart:           obj.bSmart,
4658
			regex:           obj.bRegex,
4659
			caseInsensitive: obj.bCaseInsensitive
4660
		};
4661
	}
4662
	
4663
	
4664
	
4665
	/**
4666
	 * Convert from camelCase notation to the internal Hungarian. We could use the
4667
	 * Hungarian convert function here, but this is cleaner
4668
	 *  @param {object} obj Object to convert
4669
	 *  @returns {object} Inverted object
4670
	 *  @memberof DataTable#oApi
4671
	 */
4672
	function _fnSearchToHung ( obj )
4673
	{
4674
		return {
4675
			sSearch:          obj.search,
4676
			bSmart:           obj.smart,
4677
			bRegex:           obj.regex,
4678
			bCaseInsensitive: obj.caseInsensitive
4679
		};
4680
	}
4681
	
4682
	/**
4683
	 * Generate the node required for the info display
4684
	 *  @param {object} oSettings dataTables settings object
4685
	 *  @returns {node} Information element
4686
	 *  @memberof DataTable#oApi
4687
	 */
4688
	function _fnFeatureHtmlInfo ( settings )
4689
	{
4690
		var
4691
			tid = settings.sTableId,
4692
			nodes = settings.aanFeatures.i,
4693
			n = $('<div/>', {
4694
				'class': settings.oClasses.sInfo,
4695
				'id': ! nodes ? tid+'_info' : null
4696
			} );
4697
	
4698
		if ( ! nodes ) {
4699
			// Update display on each draw
4700
			settings.aoDrawCallback.push( {
4701
				"fn": _fnUpdateInfo,
4702
				"sName": "information"
4703
			} );
4704
	
4705
			n
4706
				.attr( 'role', 'status' )
4707
				.attr( 'aria-live', 'polite' );
4708
	
4709
			// Table is described by our info div
4710
			$(settings.nTable).attr( 'aria-describedby', tid+'_info' );
4711
		}
4712
	
4713
		return n[0];
4714
	}
4715
	
4716
	
4717
	/**
4718
	 * Update the information elements in the display
4719
	 *  @param {object} settings dataTables settings object
4720
	 *  @memberof DataTable#oApi
4721
	 */
4722
	function _fnUpdateInfo ( settings )
4723
	{
4724
		/* Show information about the table */
4725
		var nodes = settings.aanFeatures.i;
4726
		if ( nodes.length === 0 ) {
4727
			return;
4728
		}
4729
	
4730
		var
4731
			lang  = settings.oLanguage,
4732
			start = settings._iDisplayStart+1,
4733
			end   = settings.fnDisplayEnd(),
4734
			max   = settings.fnRecordsTotal(),
4735
			total = settings.fnRecordsDisplay(),
4736
			out   = total ?
4737
				lang.sInfo :
4738
				lang.sInfoEmpty;
4739
	
4740
		if ( total !== max ) {
4741
			/* Record set after filtering */
4742
			out += ' ' + lang.sInfoFiltered;
4743
		}
4744
	
4745
		// Convert the macros
4746
		out += lang.sInfoPostFix;
4747
		out = _fnInfoMacros( settings, out );
4748
	
4749
		var callback = lang.fnInfoCallback;
4750
		if ( callback !== null ) {
4751
			out = callback.call( settings.oInstance,
4752
				settings, start, end, max, total, out
4753
			);
4754
		}
4755
	
4756
		$(nodes).html( out );
4757
	}
4758
	
4759
	
4760
	function _fnInfoMacros ( settings, str )
4761
	{
4762
		// When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
4763
		// internally
4764
		var
4765
			formatter  = settings.fnFormatNumber,
4766
			start      = settings._iDisplayStart+1,
4767
			len        = settings._iDisplayLength,
4768
			vis        = settings.fnRecordsDisplay(),
4769
			all        = len === -1;
4770
	
4771
		return str.
4772
			replace(/_START_/g, formatter.call( settings, start ) ).
4773
			replace(/_END_/g,   formatter.call( settings, settings.fnDisplayEnd() ) ).
4774
			replace(/_MAX_/g,   formatter.call( settings, settings.fnRecordsTotal() ) ).
4775
			replace(/_TOTAL_/g, formatter.call( settings, vis ) ).
4776
			replace(/_PAGE_/g,  formatter.call( settings, all ? 1 : Math.ceil( start / len ) ) ).
4777
			replace(/_PAGES_/g, formatter.call( settings, all ? 1 : Math.ceil( vis / len ) ) );
4778
	}
4779
	
4780
	
4781
	
4782
	/**
4783
	 * Draw the table for the first time, adding all required features
4784
	 *  @param {object} settings dataTables settings object
4785
	 *  @memberof DataTable#oApi
4786
	 */
4787
	function _fnInitialise ( settings )
4788
	{
4789
		var i, iLen, iAjaxStart=settings.iInitDisplayStart;
4790
		var columns = settings.aoColumns, column;
4791
		var features = settings.oFeatures;
4792
		var deferLoading = settings.bDeferLoading; // value modified by the draw
4793
	
4794
		/* Ensure that the table data is fully initialised */
4795
		if ( ! settings.bInitialised ) {
4796
			setTimeout( function(){ _fnInitialise( settings ); }, 200 );
4797
			return;
4798
		}
4799
	
4800
		/* Show the display HTML options */
4801
		_fnAddOptionsHtml( settings );
4802
	
4803
		/* Build and draw the header / footer for the table */
4804
		_fnBuildHead( settings );
4805
		_fnDrawHead( settings, settings.aoHeader );
4806
		_fnDrawHead( settings, settings.aoFooter );
4807
	
4808
		/* Okay to show that something is going on now */
4809
		_fnProcessingDisplay( settings, true );
4810
	
4811
		/* Calculate sizes for columns */
4812
		if ( features.bAutoWidth ) {
4813
			_fnCalculateColumnWidths( settings );
4814
		}
4815
	
4816
		for ( i=0, iLen=columns.length ; i<iLen ; i++ ) {
4817
			column = columns[i];
4818
	
4819
			if ( column.sWidth ) {
4820
				column.nTh.style.width = _fnStringToCss( column.sWidth );
4821
			}
4822
		}
4823
	
4824
		_fnCallbackFire( settings, null, 'preInit', [settings] );
4825
	
4826
		// If there is default sorting required - let's do it. The sort function
4827
		// will do the drawing for us. Otherwise we draw the table regardless of the
4828
		// Ajax source - this allows the table to look initialised for Ajax sourcing
4829
		// data (show 'loading' message possibly)
4830
		_fnReDraw( settings );
4831
	
4832
		// Server-side processing init complete is done by _fnAjaxUpdateDraw
4833
		var dataSrc = _fnDataSource( settings );
4834
		if ( dataSrc != 'ssp' || deferLoading ) {
4835
			// if there is an ajax source load the data
4836
			if ( dataSrc == 'ajax' ) {
4837
				_fnBuildAjax( settings, [], function(json) {
4838
					var aData = _fnAjaxDataSrc( settings, json );
4839
	
4840
					// Got the data - add it to the table
4841
					for ( i=0 ; i<aData.length ; i++ ) {
4842
						_fnAddData( settings, aData[i] );
4843
					}
4844
	
4845
					// Reset the init display for cookie saving. We've already done
4846
					// a filter, and therefore cleared it before. So we need to make
4847
					// it appear 'fresh'
4848
					settings.iInitDisplayStart = iAjaxStart;
4849
	
4850
					_fnReDraw( settings );
4851
	
4852
					_fnProcessingDisplay( settings, false );
4853
					_fnInitComplete( settings, json );
4854
				}, settings );
4855
			}
4856
			else {
4857
				_fnProcessingDisplay( settings, false );
4858
				_fnInitComplete( settings );
4859
			}
4860
		}
4861
	}
4862
	
4863
	
4864
	/**
4865
	 * Draw the table for the first time, adding all required features
4866
	 *  @param {object} oSettings dataTables settings object
4867
	 *  @param {object} [json] JSON from the server that completed the table, if using Ajax source
4868
	 *    with client-side processing (optional)
4869
	 *  @memberof DataTable#oApi
4870
	 */
4871
	function _fnInitComplete ( settings, json )
4872
	{
4873
		settings._bInitComplete = true;
4874
	
4875
		// When data was added after the initialisation (data or Ajax) we need to
4876
		// calculate the column sizing
4877
		if ( json || settings.oInit.aaData ) {
4878
			_fnAdjustColumnSizing( settings );
4879
		}
4880
	
4881
		_fnCallbackFire( settings, null, 'plugin-init', [settings, json] );
4882
		_fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] );
4883
	}
4884
	
4885
	
4886
	function _fnLengthChange ( settings, val )
4887
	{
4888
		var len = parseInt( val, 10 );
4889
		settings._iDisplayLength = len;
4890
	
4891
		_fnLengthOverflow( settings );
4892
	
4893
		// Fire length change event
4894
		_fnCallbackFire( settings, null, 'length', [settings, len] );
4895
	}
4896
	
4897
	
4898
	/**
4899
	 * Generate the node required for user display length changing
4900
	 *  @param {object} settings dataTables settings object
4901
	 *  @returns {node} Display length feature node
4902
	 *  @memberof DataTable#oApi
4903
	 */
4904
	function _fnFeatureHtmlLength ( settings )
4905
	{
4906
		var
4907
			classes  = settings.oClasses,
4908
			tableId  = settings.sTableId,
4909
			menu     = settings.aLengthMenu,
4910
			d2       = Array.isArray( menu[0] ),
4911
			lengths  = d2 ? menu[0] : menu,
4912
			language = d2 ? menu[1] : menu;
4913
	
4914
		var select = $('<select/>', {
4915
			'name':          tableId+'_length',
4916
			'aria-controls': tableId,
4917
			'class':         classes.sLengthSelect
4918
		} );
4919
	
4920
		for ( var i=0, ien=lengths.length ; i<ien ; i++ ) {
4921
			select[0][ i ] = new Option(
4922
				typeof language[i] === 'number' ?
4923
					settings.fnFormatNumber( language[i] ) :
4924
					language[i],
4925
				lengths[i]
4926
			);
4927
		}
4928
	
4929
		var div = $('<div><label/></div>').addClass( classes.sLength );
4930
		if ( ! settings.aanFeatures.l ) {
4931
			div[0].id = tableId+'_length';
4932
		}
4933
	
4934
		div.children().append(
4935
			settings.oLanguage.sLengthMenu.replace( '_MENU_', select[0].outerHTML )
4936
		);
4937
	
4938
		// Can't use `select` variable as user might provide their own and the
4939
		// reference is broken by the use of outerHTML
4940
		$('select', div)
4941
			.val( settings._iDisplayLength )
4942
			.on( 'change.DT', function(e) {
4943
				_fnLengthChange( settings, $(this).val() );
4944
				_fnDraw( settings );
4945
			} );
4946
	
4947
		// Update node value whenever anything changes the table's length
4948
		$(settings.nTable).on( 'length.dt.DT', function (e, s, len) {
4949
			if ( settings === s ) {
4950
				$('select', div).val( len );
4951
			}
4952
		} );
4953
	
4954
		return div[0];
4955
	}
4956
	
4957
	
4958
	
4959
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
4960
	 * Note that most of the paging logic is done in
4961
	 * DataTable.ext.pager
4962
	 */
4963
	
4964
	/**
4965
	 * Generate the node required for default pagination
4966
	 *  @param {object} oSettings dataTables settings object
4967
	 *  @returns {node} Pagination feature node
4968
	 *  @memberof DataTable#oApi
4969
	 */
4970
	function _fnFeatureHtmlPaginate ( settings )
4971
	{
4972
		var
4973
			type   = settings.sPaginationType,
4974
			plugin = DataTable.ext.pager[ type ],
4975
			modern = typeof plugin === 'function',
4976
			redraw = function( settings ) {
4977
				_fnDraw( settings );
4978
			},
4979
			node = $('<div/>').addClass( settings.oClasses.sPaging + type )[0],
4980
			features = settings.aanFeatures;
4981
	
4982
		if ( ! modern ) {
4983
			plugin.fnInit( settings, node, redraw );
4984
		}
4985
	
4986
		/* Add a draw callback for the pagination on first instance, to update the paging display */
4987
		if ( ! features.p )
4988
		{
4989
			node.id = settings.sTableId+'_paginate';
4990
	
4991
			settings.aoDrawCallback.push( {
4992
				"fn": function( settings ) {
4993
					if ( modern ) {
4994
						var
4995
							start      = settings._iDisplayStart,
4996
							len        = settings._iDisplayLength,
4997
							visRecords = settings.fnRecordsDisplay(),
4998
							all        = len === -1,
4999
							page = all ? 0 : Math.ceil( start / len ),
5000
							pages = all ? 1 : Math.ceil( visRecords / len ),
5001
							buttons = plugin(page, pages),
5002
							i, ien;
5003
	
5004
						for ( i=0, ien=features.p.length ; i<ien ; i++ ) {
5005
							_fnRenderer( settings, 'pageButton' )(
5006
								settings, features.p[i], i, buttons, page, pages
5007
							);
5008
						}
5009
					}
5010
					else {
5011
						plugin.fnUpdate( settings, redraw );
5012
					}
5013
				},
5014
				"sName": "pagination"
5015
			} );
5016
		}
5017
	
5018
		return node;
5019
	}
5020
	
5021
	
5022
	/**
5023
	 * Alter the display settings to change the page
5024
	 *  @param {object} settings DataTables settings object
5025
	 *  @param {string|int} action Paging action to take: "first", "previous",
5026
	 *    "next" or "last" or page number to jump to (integer)
5027
	 *  @param [bool] redraw Automatically draw the update or not
5028
	 *  @returns {bool} true page has changed, false - no change
5029
	 *  @memberof DataTable#oApi
5030
	 */
5031
	function _fnPageChange ( settings, action, redraw )
5032
	{
5033
		var
5034
			start     = settings._iDisplayStart,
5035
			len       = settings._iDisplayLength,
5036
			records   = settings.fnRecordsDisplay();
5037
	
5038
		if ( records === 0 || len === -1 )
5039
		{
5040
			start = 0;
5041
		}
5042
		else if ( typeof action === "number" )
5043
		{
5044
			start = action * len;
5045
	
5046
			if ( start > records )
5047
			{
5048
				start = 0;
5049
			}
5050
		}
5051
		else if ( action == "first" )
5052
		{
5053
			start = 0;
5054
		}
5055
		else if ( action == "previous" )
5056
		{
5057
			start = len >= 0 ?
5058
				start - len :
5059
				0;
5060
	
5061
			if ( start < 0 )
5062
			{
5063
			  start = 0;
5064
			}
5065
		}
5066
		else if ( action == "next" )
5067
		{
5068
			if ( start + len < records )
5069
			{
5070
				start += len;
5071
			}
5072
		}
5073
		else if ( action == "last" )
5074
		{
5075
			start = Math.floor( (records-1) / len) * len;
5076
		}
5077
		else
5078
		{
5079
			_fnLog( settings, 0, "Unknown paging action: "+action, 5 );
5080
		}
5081
	
5082
		var changed = settings._iDisplayStart !== start;
5083
		settings._iDisplayStart = start;
5084
	
5085
		if ( changed ) {
5086
			_fnCallbackFire( settings, null, 'page', [settings] );
5087
	
5088
			if ( redraw ) {
5089
				_fnDraw( settings );
5090
			}
5091
		}
5092
	
5093
		return changed;
5094
	}
5095
	
5096
	
5097
	
5098
	/**
5099
	 * Generate the node required for the processing node
5100
	 *  @param {object} settings dataTables settings object
5101
	 *  @returns {node} Processing element
5102
	 *  @memberof DataTable#oApi
5103
	 */
5104
	function _fnFeatureHtmlProcessing ( settings )
5105
	{
5106
		return $('<div/>', {
5107
				'id': ! settings.aanFeatures.r ? settings.sTableId+'_processing' : null,
5108
				'class': settings.oClasses.sProcessing
5109
			} )
5110
			.html( settings.oLanguage.sProcessing )
5111
			.insertBefore( settings.nTable )[0];
5112
	}
5113
	
5114
	
5115
	/**
5116
	 * Display or hide the processing indicator
5117
	 *  @param {object} settings dataTables settings object
5118
	 *  @param {bool} show Show the processing indicator (true) or not (false)
5119
	 *  @memberof DataTable#oApi
5120
	 */
5121
	function _fnProcessingDisplay ( settings, show )
5122
	{
5123
		if ( settings.oFeatures.bProcessing ) {
5124
			$(settings.aanFeatures.r).css( 'display', show ? 'block' : 'none' );
5125
		}
5126
	
5127
		_fnCallbackFire( settings, null, 'processing', [settings, show] );
5128
	}
5129
	
5130
	/**
5131
	 * Add any control elements for the table - specifically scrolling
5132
	 *  @param {object} settings dataTables settings object
5133
	 *  @returns {node} Node to add to the DOM
5134
	 *  @memberof DataTable#oApi
5135
	 */
5136
	function _fnFeatureHtmlTable ( settings )
5137
	{
5138
		var table = $(settings.nTable);
5139
	
5140
		// Scrolling from here on in
5141
		var scroll = settings.oScroll;
5142
	
5143
		if ( scroll.sX === '' && scroll.sY === '' ) {
5144
			return settings.nTable;
5145
		}
5146
	
5147
		var scrollX = scroll.sX;
5148
		var scrollY = scroll.sY;
5149
		var classes = settings.oClasses;
5150
		var caption = table.children('caption');
5151
		var captionSide = caption.length ? caption[0]._captionSide : null;
5152
		var headerClone = $( table[0].cloneNode(false) );
5153
		var footerClone = $( table[0].cloneNode(false) );
5154
		var footer = table.children('tfoot');
5155
		var _div = '<div/>';
5156
		var size = function ( s ) {
5157
			return !s ? null : _fnStringToCss( s );
5158
		};
5159
	
5160
		if ( ! footer.length ) {
5161
			footer = null;
5162
		}
5163
	
5164
		/*
5165
		 * The HTML structure that we want to generate in this function is:
5166
		 *  div - scroller
5167
		 *    div - scroll head
5168
		 *      div - scroll head inner
5169
		 *        table - scroll head table
5170
		 *          thead - thead
5171
		 *    div - scroll body
5172
		 *      table - table (master table)
5173
		 *        thead - thead clone for sizing
5174
		 *        tbody - tbody
5175
		 *    div - scroll foot
5176
		 *      div - scroll foot inner
5177
		 *        table - scroll foot table
5178
		 *          tfoot - tfoot
5179
		 */
5180
		var scroller = $( _div, { 'class': classes.sScrollWrapper } )
5181
			.append(
5182
				$(_div, { 'class': classes.sScrollHead } )
5183
					.css( {
5184
						overflow: 'hidden',
5185
						position: 'relative',
5186
						border: 0,
5187
						width: scrollX ? size(scrollX) : '100%'
5188
					} )
5189
					.append(
5190
						$(_div, { 'class': classes.sScrollHeadInner } )
5191
							.css( {
5192
								'box-sizing': 'content-box',
5193
								width: scroll.sXInner || '100%'
5194
							} )
5195
							.append(
5196
								headerClone
5197
									.removeAttr('id')
5198
									.css( 'margin-left', 0 )
5199
									.append( captionSide === 'top' ? caption : null )
5200
									.append(
5201
										table.children('thead')
5202
									)
5203
							)
5204
					)
5205
			)
5206
			.append(
5207
				$(_div, { 'class': classes.sScrollBody } )
5208
					.css( {
5209
						position: 'relative',
5210
						overflow: 'auto',
5211
						width: size( scrollX )
5212
					} )
5213
					.append( table )
5214
			);
5215
	
5216
		if ( footer ) {
5217
			scroller.append(
5218
				$(_div, { 'class': classes.sScrollFoot } )
5219
					.css( {
5220
						overflow: 'hidden',
5221
						border: 0,
5222
						width: scrollX ? size(scrollX) : '100%'
5223
					} )
5224
					.append(
5225
						$(_div, { 'class': classes.sScrollFootInner } )
5226
							.append(
5227
								footerClone
5228
									.removeAttr('id')
5229
									.css( 'margin-left', 0 )
5230
									.append( captionSide === 'bottom' ? caption : null )
5231
									.append(
5232
										table.children('tfoot')
5233
									)
5234
							)
5235
					)
5236
			);
5237
		}
5238
	
5239
		var children = scroller.children();
5240
		var scrollHead = children[0];
5241
		var scrollBody = children[1];
5242
		var scrollFoot = footer ? children[2] : null;
5243
	
5244
		// When the body is scrolled, then we also want to scroll the headers
5245
		if ( scrollX ) {
5246
			$(scrollBody).on( 'scroll.DT', function (e) {
5247
				var scrollLeft = this.scrollLeft;
5248
	
5249
				scrollHead.scrollLeft = scrollLeft;
5250
	
5251
				if ( footer ) {
5252
					scrollFoot.scrollLeft = scrollLeft;
5253
				}
5254
			} );
5255
		}
5256
	
5257
		$(scrollBody).css('max-height', scrollY);
5258
		if (! scroll.bCollapse) {
5259
			$(scrollBody).css('height', scrollY);
5260
		}
5261
	
5262
		settings.nScrollHead = scrollHead;
5263
		settings.nScrollBody = scrollBody;
5264
		settings.nScrollFoot = scrollFoot;
5265
	
5266
		// On redraw - align columns
5267
		settings.aoDrawCallback.push( {
5268
			"fn": _fnScrollDraw,
5269
			"sName": "scrolling"
5270
		} );
5271
	
5272
		return scroller[0];
5273
	}
5274
	
5275
	
5276
	
5277
	/**
5278
	 * Update the header, footer and body tables for resizing - i.e. column
5279
	 * alignment.
5280
	 *
5281
	 * Welcome to the most horrible function DataTables. The process that this
5282
	 * function follows is basically:
5283
	 *   1. Re-create the table inside the scrolling div
5284
	 *   2. Take live measurements from the DOM
5285
	 *   3. Apply the measurements to align the columns
5286
	 *   4. Clean up
5287
	 *
5288
	 *  @param {object} settings dataTables settings object
5289
	 *  @memberof DataTable#oApi
5290
	 */
5291
	function _fnScrollDraw ( settings )
5292
	{
5293
		// Given that this is such a monster function, a lot of variables are use
5294
		// to try and keep the minimised size as small as possible
5295
		var
5296
			scroll         = settings.oScroll,
5297
			scrollX        = scroll.sX,
5298
			scrollXInner   = scroll.sXInner,
5299
			scrollY        = scroll.sY,
5300
			barWidth       = scroll.iBarWidth,
5301
			divHeader      = $(settings.nScrollHead),
5302
			divHeaderStyle = divHeader[0].style,
5303
			divHeaderInner = divHeader.children('div'),
5304
			divHeaderInnerStyle = divHeaderInner[0].style,
5305
			divHeaderTable = divHeaderInner.children('table'),
5306
			divBodyEl      = settings.nScrollBody,
5307
			divBody        = $(divBodyEl),
5308
			divBodyStyle   = divBodyEl.style,
5309
			divFooter      = $(settings.nScrollFoot),
5310
			divFooterInner = divFooter.children('div'),
5311
			divFooterTable = divFooterInner.children('table'),
5312
			header         = $(settings.nTHead),
5313
			table          = $(settings.nTable),
5314
			tableEl        = table[0],
5315
			tableStyle     = tableEl.style,
5316
			footer         = settings.nTFoot ? $(settings.nTFoot) : null,
5317
			browser        = settings.oBrowser,
5318
			ie67           = browser.bScrollOversize,
5319
			dtHeaderCells  = _pluck( settings.aoColumns, 'nTh' ),
5320
			headerTrgEls, footerTrgEls,
5321
			headerSrcEls, footerSrcEls,
5322
			headerCopy, footerCopy,
5323
			headerWidths=[], footerWidths=[],
5324
			headerContent=[], footerContent=[],
5325
			idx, correction, sanityWidth,
5326
			zeroOut = function(nSizer) {
5327
				var style = nSizer.style;
5328
				style.paddingTop = "0";
5329
				style.paddingBottom = "0";
5330
				style.borderTopWidth = "0";
5331
				style.borderBottomWidth = "0";
5332
				style.height = 0;
5333
			};
5334
	
5335
		// If the scrollbar visibility has changed from the last draw, we need to
5336
		// adjust the column sizes as the table width will have changed to account
5337
		// for the scrollbar
5338
		var scrollBarVis = divBodyEl.scrollHeight > divBodyEl.clientHeight;
5339
		
5340
		if ( settings.scrollBarVis !== scrollBarVis && settings.scrollBarVis !== undefined ) {
5341
			settings.scrollBarVis = scrollBarVis;
5342
			_fnAdjustColumnSizing( settings );
5343
			return; // adjust column sizing will call this function again
5344
		}
5345
		else {
5346
			settings.scrollBarVis = scrollBarVis;
5347
		}
5348
	
5349
		/*
5350
		 * 1. Re-create the table inside the scrolling div
5351
		 */
5352
	
5353
		// Remove the old minimised thead and tfoot elements in the inner table
5354
		table.children('thead, tfoot').remove();
5355
	
5356
		if ( footer ) {
5357
			footerCopy = footer.clone().prependTo( table );
5358
			footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized
5359
			footerSrcEls = footerCopy.find('tr');
5360
		}
5361
	
5362
		// Clone the current header and footer elements and then place it into the inner table
5363
		headerCopy = header.clone().prependTo( table );
5364
		headerTrgEls = header.find('tr'); // original header is in its own table
5365
		headerSrcEls = headerCopy.find('tr');
5366
		headerCopy.find('th, td').removeAttr('tabindex');
5367
	
5368
	
5369
		/*
5370
		 * 2. Take live measurements from the DOM - do not alter the DOM itself!
5371
		 */
5372
	
5373
		// Remove old sizing and apply the calculated column widths
5374
		// Get the unique column headers in the newly created (cloned) header. We want to apply the
5375
		// calculated sizes to this header
5376
		if ( ! scrollX )
5377
		{
5378
			divBodyStyle.width = '100%';
5379
			divHeader[0].style.width = '100%';
5380
		}
5381
	
5382
		$.each( _fnGetUniqueThs( settings, headerCopy ), function ( i, el ) {
5383
			idx = _fnVisibleToColumnIndex( settings, i );
5384
			el.style.width = settings.aoColumns[idx].sWidth;
5385
		} );
5386
	
5387
		if ( footer ) {
5388
			_fnApplyToChildren( function(n) {
5389
				n.style.width = "";
5390
			}, footerSrcEls );
5391
		}
5392
	
5393
		// Size the table as a whole
5394
		sanityWidth = table.outerWidth();
5395
		if ( scrollX === "" ) {
5396
			// No x scrolling
5397
			tableStyle.width = "100%";
5398
	
5399
			// IE7 will make the width of the table when 100% include the scrollbar
5400
			// - which is shouldn't. When there is a scrollbar we need to take this
5401
			// into account.
5402
			if ( ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight ||
5403
				divBody.css('overflow-y') == "scroll")
5404
			) {
5405
				tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth);
5406
			}
5407
	
5408
			// Recalculate the sanity width
5409
			sanityWidth = table.outerWidth();
5410
		}
5411
		else if ( scrollXInner !== "" ) {
5412
			// legacy x scroll inner has been given - use it
5413
			tableStyle.width = _fnStringToCss(scrollXInner);
5414
	
5415
			// Recalculate the sanity width
5416
			sanityWidth = table.outerWidth();
5417
		}
5418
	
5419
		// Hidden header should have zero height, so remove padding and borders. Then
5420
		// set the width based on the real headers
5421
	
5422
		// Apply all styles in one pass
5423
		_fnApplyToChildren( zeroOut, headerSrcEls );
5424
	
5425
		// Read all widths in next pass
5426
		_fnApplyToChildren( function(nSizer) {
5427
			var style = window.getComputedStyle ?
5428
				window.getComputedStyle(nSizer).width :
5429
				_fnStringToCss( $(nSizer).width() );
5430
	
5431
			headerContent.push( nSizer.innerHTML );
5432
			headerWidths.push( style );
5433
		}, headerSrcEls );
5434
	
5435
		// Apply all widths in final pass
5436
		_fnApplyToChildren( function(nToSize, i) {
5437
			nToSize.style.width = headerWidths[i];
5438
		}, headerTrgEls );
5439
	
5440
		$(headerSrcEls).height(0);
5441
	
5442
		/* Same again with the footer if we have one */
5443
		if ( footer )
5444
		{
5445
			_fnApplyToChildren( zeroOut, footerSrcEls );
5446
	
5447
			_fnApplyToChildren( function(nSizer) {
5448
				footerContent.push( nSizer.innerHTML );
5449
				footerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
5450
			}, footerSrcEls );
5451
	
5452
			_fnApplyToChildren( function(nToSize, i) {
5453
				nToSize.style.width = footerWidths[i];
5454
			}, footerTrgEls );
5455
	
5456
			$(footerSrcEls).height(0);
5457
		}
5458
	
5459
	
5460
		/*
5461
		 * 3. Apply the measurements
5462
		 */
5463
	
5464
		// "Hide" the header and footer that we used for the sizing. We need to keep
5465
		// the content of the cell so that the width applied to the header and body
5466
		// both match, but we want to hide it completely. We want to also fix their
5467
		// width to what they currently are
5468
		_fnApplyToChildren( function(nSizer, i) {
5469
			nSizer.innerHTML = '<div class="dataTables_sizing">'+headerContent[i]+'</div>';
5470
			nSizer.childNodes[0].style.height = "0";
5471
			nSizer.childNodes[0].style.overflow = "hidden";
5472
			nSizer.style.width = headerWidths[i];
5473
		}, headerSrcEls );
5474
	
5475
		if ( footer )
5476
		{
5477
			_fnApplyToChildren( function(nSizer, i) {
5478
				nSizer.innerHTML = '<div class="dataTables_sizing">'+footerContent[i]+'</div>';
5479
				nSizer.childNodes[0].style.height = "0";
5480
				nSizer.childNodes[0].style.overflow = "hidden";
5481
				nSizer.style.width = footerWidths[i];
5482
			}, footerSrcEls );
5483
		}
5484
	
5485
		// Sanity check that the table is of a sensible width. If not then we are going to get
5486
		// misalignment - try to prevent this by not allowing the table to shrink below its min width
5487
		if ( Math.round(table.outerWidth()) < Math.round(sanityWidth) )
5488
		{
5489
			// The min width depends upon if we have a vertical scrollbar visible or not */
5490
			correction = ((divBodyEl.scrollHeight > divBodyEl.offsetHeight ||
5491
				divBody.css('overflow-y') == "scroll")) ?
5492
					sanityWidth+barWidth :
5493
					sanityWidth;
5494
	
5495
			// IE6/7 are a law unto themselves...
5496
			if ( ie67 && (divBodyEl.scrollHeight >
5497
				divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll")
5498
			) {
5499
				tableStyle.width = _fnStringToCss( correction-barWidth );
5500
			}
5501
	
5502
			// And give the user a warning that we've stopped the table getting too small
5503
			if ( scrollX === "" || scrollXInner !== "" ) {
5504
				_fnLog( settings, 1, 'Possible column misalignment', 6 );
5505
			}
5506
		}
5507
		else
5508
		{
5509
			correction = '100%';
5510
		}
5511
	
5512
		// Apply to the container elements
5513
		divBodyStyle.width = _fnStringToCss( correction );
5514
		divHeaderStyle.width = _fnStringToCss( correction );
5515
	
5516
		if ( footer ) {
5517
			settings.nScrollFoot.style.width = _fnStringToCss( correction );
5518
		}
5519
	
5520
	
5521
		/*
5522
		 * 4. Clean up
5523
		 */
5524
		if ( ! scrollY ) {
5525
			/* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
5526
			 * the scrollbar height from the visible display, rather than adding it on. We need to
5527
			 * set the height in order to sort this. Don't want to do it in any other browsers.
5528
			 */
5529
			if ( ie67 ) {
5530
				divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+barWidth );
5531
			}
5532
		}
5533
	
5534
		/* Finally set the width's of the header and footer tables */
5535
		var iOuterWidth = table.outerWidth();
5536
		divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth );
5537
		divHeaderInnerStyle.width = _fnStringToCss( iOuterWidth );
5538
	
5539
		// Figure out if there are scrollbar present - if so then we need a the header and footer to
5540
		// provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
5541
		var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll";
5542
		var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' );
5543
		divHeaderInnerStyle[ padding ] = bScrolling ? barWidth+"px" : "0px";
5544
	
5545
		if ( footer ) {
5546
			divFooterTable[0].style.width = _fnStringToCss( iOuterWidth );
5547
			divFooterInner[0].style.width = _fnStringToCss( iOuterWidth );
5548
			divFooterInner[0].style[padding] = bScrolling ? barWidth+"px" : "0px";
5549
		}
5550
	
5551
		// Correct DOM ordering for colgroup - comes before the thead
5552
		table.children('colgroup').insertBefore( table.children('thead') );
5553
	
5554
		/* Adjust the position of the header in case we loose the y-scrollbar */
5555
		divBody.trigger('scroll');
5556
	
5557
		// If sorting or filtering has occurred, jump the scrolling back to the top
5558
		// only if we aren't holding the position
5559
		if ( (settings.bSorted || settings.bFiltered) && ! settings._drawHold ) {
5560
			divBodyEl.scrollTop = 0;
5561
		}
5562
	}
5563
	
5564
	
5565
	
5566
	/**
5567
	 * Apply a given function to the display child nodes of an element array (typically
5568
	 * TD children of TR rows
5569
	 *  @param {function} fn Method to apply to the objects
5570
	 *  @param array {nodes} an1 List of elements to look through for display children
5571
	 *  @param array {nodes} an2 Another list (identical structure to the first) - optional
5572
	 *  @memberof DataTable#oApi
5573
	 */
5574
	function _fnApplyToChildren( fn, an1, an2 )
5575
	{
5576
		var index=0, i=0, iLen=an1.length;
5577
		var nNode1, nNode2;
5578
	
5579
		while ( i < iLen ) {
5580
			nNode1 = an1[i].firstChild;
5581
			nNode2 = an2 ? an2[i].firstChild : null;
5582
	
5583
			while ( nNode1 ) {
5584
				if ( nNode1.nodeType === 1 ) {
5585
					if ( an2 ) {
5586
						fn( nNode1, nNode2, index );
5587
					}
5588
					else {
5589
						fn( nNode1, index );
5590
					}
5591
	
5592
					index++;
5593
				}
5594
	
5595
				nNode1 = nNode1.nextSibling;
5596
				nNode2 = an2 ? nNode2.nextSibling : null;
5597
			}
5598
	
5599
			i++;
5600
		}
5601
	}
5602
	
5603
	
5604
	
5605
	var __re_html_remove = /<.*?>/g;
5606
	
5607
	
5608
	/**
5609
	 * Calculate the width of columns for the table
5610
	 *  @param {object} oSettings dataTables settings object
5611
	 *  @memberof DataTable#oApi
5612
	 */
5613
	function _fnCalculateColumnWidths ( oSettings )
5614
	{
5615
		var
5616
			table = oSettings.nTable,
5617
			columns = oSettings.aoColumns,
5618
			scroll = oSettings.oScroll,
5619
			scrollY = scroll.sY,
5620
			scrollX = scroll.sX,
5621
			scrollXInner = scroll.sXInner,
5622
			columnCount = columns.length,
5623
			visibleColumns = _fnGetColumns( oSettings, 'bVisible' ),
5624
			headerCells = $('th', oSettings.nTHead),
5625
			tableWidthAttr = table.getAttribute('width'), // from DOM element
5626
			tableContainer = table.parentNode,
5627
			userInputs = false,
5628
			i, column, columnIdx, width, outerWidth,
5629
			browser = oSettings.oBrowser,
5630
			ie67 = browser.bScrollOversize;
5631
	
5632
		var styleWidth = table.style.width;
5633
		if ( styleWidth && styleWidth.indexOf('%') !== -1 ) {
5634
			tableWidthAttr = styleWidth;
5635
		}
5636
	
5637
		/* Convert any user input sizes into pixel sizes */
5638
		for ( i=0 ; i<visibleColumns.length ; i++ ) {
5639
			column = columns[ visibleColumns[i] ];
5640
	
5641
			if ( column.sWidth !== null ) {
5642
				column.sWidth = _fnConvertToWidth( column.sWidthOrig, tableContainer );
5643
	
5644
				userInputs = true;
5645
			}
5646
		}
5647
	
5648
		/* If the number of columns in the DOM equals the number that we have to
5649
		 * process in DataTables, then we can use the offsets that are created by
5650
		 * the web- browser. No custom sizes can be set in order for this to happen,
5651
		 * nor scrolling used
5652
		 */
5653
		if ( ie67 || ! userInputs && ! scrollX && ! scrollY &&
5654
		     columnCount == _fnVisbleColumns( oSettings ) &&
5655
		     columnCount == headerCells.length
5656
		) {
5657
			for ( i=0 ; i<columnCount ; i++ ) {
5658
				var colIdx = _fnVisibleToColumnIndex( oSettings, i );
5659
	
5660
				if ( colIdx !== null ) {
5661
					columns[ colIdx ].sWidth = _fnStringToCss( headerCells.eq(i).width() );
5662
				}
5663
			}
5664
		}
5665
		else
5666
		{
5667
			// Otherwise construct a single row, worst case, table with the widest
5668
			// node in the data, assign any user defined widths, then insert it into
5669
			// the DOM and allow the browser to do all the hard work of calculating
5670
			// table widths
5671
			var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table
5672
				.css( 'visibility', 'hidden' )
5673
				.removeAttr( 'id' );
5674
	
5675
			// Clean up the table body
5676
			tmpTable.find('tbody tr').remove();
5677
			var tr = $('<tr/>').appendTo( tmpTable.find('tbody') );
5678
	
5679
			// Clone the table header and footer - we can't use the header / footer
5680
			// from the cloned table, since if scrolling is active, the table's
5681
			// real header and footer are contained in different table tags
5682
			tmpTable.find('thead, tfoot').remove();
5683
			tmpTable
5684
				.append( $(oSettings.nTHead).clone() )
5685
				.append( $(oSettings.nTFoot).clone() );
5686
	
5687
			// Remove any assigned widths from the footer (from scrolling)
5688
			tmpTable.find('tfoot th, tfoot td').css('width', '');
5689
	
5690
			// Apply custom sizing to the cloned header
5691
			headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] );
5692
	
5693
			for ( i=0 ; i<visibleColumns.length ; i++ ) {
5694
				column = columns[ visibleColumns[i] ];
5695
	
5696
				headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ?
5697
					_fnStringToCss( column.sWidthOrig ) :
5698
					'';
5699
	
5700
				// For scrollX we need to force the column width otherwise the
5701
				// browser will collapse it. If this width is smaller than the
5702
				// width the column requires, then it will have no effect
5703
				if ( column.sWidthOrig && scrollX ) {
5704
					$( headerCells[i] ).append( $('<div/>').css( {
5705
						width: column.sWidthOrig,
5706
						margin: 0,
5707
						padding: 0,
5708
						border: 0,
5709
						height: 1
5710
					} ) );
5711
				}
5712
			}
5713
	
5714
			// Find the widest cell for each column and put it into the table
5715
			if ( oSettings.aoData.length ) {
5716
				for ( i=0 ; i<visibleColumns.length ; i++ ) {
5717
					columnIdx = visibleColumns[i];
5718
					column = columns[ columnIdx ];
5719
	
5720
					$( _fnGetWidestNode( oSettings, columnIdx ) )
5721
						.clone( false )
5722
						.append( column.sContentPadding )
5723
						.appendTo( tr );
5724
				}
5725
			}
5726
	
5727
			// Tidy the temporary table - remove name attributes so there aren't
5728
			// duplicated in the dom (radio elements for example)
5729
			$('[name]', tmpTable).removeAttr('name');
5730
	
5731
			// Table has been built, attach to the document so we can work with it.
5732
			// A holding element is used, positioned at the top of the container
5733
			// with minimal height, so it has no effect on if the container scrolls
5734
			// or not. Otherwise it might trigger scrolling when it actually isn't
5735
			// needed
5736
			var holder = $('<div/>').css( scrollX || scrollY ?
5737
					{
5738
						position: 'absolute',
5739
						top: 0,
5740
						left: 0,
5741
						height: 1,
5742
						right: 0,
5743
						overflow: 'hidden'
5744
					} :
5745
					{}
5746
				)
5747
				.append( tmpTable )
5748
				.appendTo( tableContainer );
5749
	
5750
			// When scrolling (X or Y) we want to set the width of the table as 
5751
			// appropriate. However, when not scrolling leave the table width as it
5752
			// is. This results in slightly different, but I think correct behaviour
5753
			if ( scrollX && scrollXInner ) {
5754
				tmpTable.width( scrollXInner );
5755
			}
5756
			else if ( scrollX ) {
5757
				tmpTable.css( 'width', 'auto' );
5758
				tmpTable.removeAttr('width');
5759
	
5760
				// If there is no width attribute or style, then allow the table to
5761
				// collapse
5762
				if ( tmpTable.width() < tableContainer.clientWidth && tableWidthAttr ) {
5763
					tmpTable.width( tableContainer.clientWidth );
5764
				}
5765
			}
5766
			else if ( scrollY ) {
5767
				tmpTable.width( tableContainer.clientWidth );
5768
			}
5769
			else if ( tableWidthAttr ) {
5770
				tmpTable.width( tableWidthAttr );
5771
			}
5772
	
5773
			// Get the width of each column in the constructed table - we need to
5774
			// know the inner width (so it can be assigned to the other table's
5775
			// cells) and the outer width so we can calculate the full width of the
5776
			// table. This is safe since DataTables requires a unique cell for each
5777
			// column, but if ever a header can span multiple columns, this will
5778
			// need to be modified.
5779
			var total = 0;
5780
			for ( i=0 ; i<visibleColumns.length ; i++ ) {
5781
				var cell = $(headerCells[i]);
5782
				var border = cell.outerWidth() - cell.width();
5783
	
5784
				// Use getBounding... where possible (not IE8-) because it can give
5785
				// sub-pixel accuracy, which we then want to round up!
5786
				var bounding = browser.bBounding ?
5787
					Math.ceil( headerCells[i].getBoundingClientRect().width ) :
5788
					cell.outerWidth();
5789
	
5790
				// Total is tracked to remove any sub-pixel errors as the outerWidth
5791
				// of the table might not equal the total given here (IE!).
5792
				total += bounding;
5793
	
5794
				// Width for each column to use
5795
				columns[ visibleColumns[i] ].sWidth = _fnStringToCss( bounding - border );
5796
			}
5797
	
5798
			table.style.width = _fnStringToCss( total );
5799
	
5800
			// Finished with the table - ditch it
5801
			holder.remove();
5802
		}
5803
	
5804
		// If there is a width attr, we want to attach an event listener which
5805
		// allows the table sizing to automatically adjust when the window is
5806
		// resized. Use the width attr rather than CSS, since we can't know if the
5807
		// CSS is a relative value or absolute - DOM read is always px.
5808
		if ( tableWidthAttr ) {
5809
			table.style.width = _fnStringToCss( tableWidthAttr );
5810
		}
5811
	
5812
		if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) {
5813
			var bindResize = function () {
5814
				$(window).on('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {
5815
					_fnAdjustColumnSizing( oSettings );
5816
				} ) );
5817
			};
5818
	
5819
			// IE6/7 will crash if we bind a resize event handler on page load.
5820
			// To be removed in 1.11 which drops IE6/7 support
5821
			if ( ie67 ) {
5822
				setTimeout( bindResize, 1000 );
5823
			}
5824
			else {
5825
				bindResize();
5826
			}
5827
	
5828
			oSettings._reszEvt = true;
5829
		}
5830
	}
5831
	
5832
	
5833
	/**
5834
	 * Throttle the calls to a function. Arguments and context are maintained for
5835
	 * the throttled function
5836
	 *  @param {function} fn Function to be called
5837
	 *  @param {int} [freq=200] call frequency in mS
5838
	 *  @returns {function} wrapped function
5839
	 *  @memberof DataTable#oApi
5840
	 */
5841
	var _fnThrottle = DataTable.util.throttle;
5842
	
5843
	
5844
	/**
5845
	 * Convert a CSS unit width to pixels (e.g. 2em)
5846
	 *  @param {string} width width to be converted
5847
	 *  @param {node} parent parent to get the with for (required for relative widths) - optional
5848
	 *  @returns {int} width in pixels
5849
	 *  @memberof DataTable#oApi
5850
	 */
5851
	function _fnConvertToWidth ( width, parent )
5852
	{
5853
		if ( ! width ) {
5854
			return 0;
5855
		}
5856
	
5857
		var n = $('<div/>')
5858
			.css( 'width', _fnStringToCss( width ) )
5859
			.appendTo( parent || document.body );
5860
	
5861
		var val = n[0].offsetWidth;
5862
		n.remove();
5863
	
5864
		return val;
5865
	}
5866
	
5867
	
5868
	/**
5869
	 * Get the widest node
5870
	 *  @param {object} settings dataTables settings object
5871
	 *  @param {int} colIdx column of interest
5872
	 *  @returns {node} widest table node
5873
	 *  @memberof DataTable#oApi
5874
	 */
5875
	function _fnGetWidestNode( settings, colIdx )
5876
	{
5877
		var idx = _fnGetMaxLenString( settings, colIdx );
5878
		if ( idx < 0 ) {
5879
			return null;
5880
		}
5881
	
5882
		var data = settings.aoData[ idx ];
5883
		return ! data.nTr ? // Might not have been created when deferred rendering
5884
			$('<td/>').html( _fnGetCellData( settings, idx, colIdx, 'display' ) )[0] :
5885
			data.anCells[ colIdx ];
5886
	}
5887
	
5888
	
5889
	/**
5890
	 * Get the maximum strlen for each data column
5891
	 *  @param {object} settings dataTables settings object
5892
	 *  @param {int} colIdx column of interest
5893
	 *  @returns {string} max string length for each column
5894
	 *  @memberof DataTable#oApi
5895
	 */
5896
	function _fnGetMaxLenString( settings, colIdx )
5897
	{
5898
		var s, max=-1, maxIdx = -1;
5899
	
5900
		for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
5901
			s = _fnGetCellData( settings, i, colIdx, 'display' )+'';
5902
			s = s.replace( __re_html_remove, '' );
5903
			s = s.replace( /&nbsp;/g, ' ' );
5904
	
5905
			if ( s.length > max ) {
5906
				max = s.length;
5907
				maxIdx = i;
5908
			}
5909
		}
5910
	
5911
		return maxIdx;
5912
	}
5913
	
5914
	
5915
	/**
5916
	 * Append a CSS unit (only if required) to a string
5917
	 *  @param {string} value to css-ify
5918
	 *  @returns {string} value with css unit
5919
	 *  @memberof DataTable#oApi
5920
	 */
5921
	function _fnStringToCss( s )
5922
	{
5923
		if ( s === null ) {
5924
			return '0px';
5925
		}
5926
	
5927
		if ( typeof s == 'number' ) {
5928
			return s < 0 ?
5929
				'0px' :
5930
				s+'px';
5931
		}
5932
	
5933
		// Check it has a unit character already
5934
		return s.match(/\d$/) ?
5935
			s+'px' :
5936
			s;
5937
	}
5938
	
5939
	
5940
	
5941
	function _fnSortFlatten ( settings )
5942
	{
5943
		var
5944
			i, iLen, k, kLen,
5945
			aSort = [],
5946
			aiOrig = [],
5947
			aoColumns = settings.aoColumns,
5948
			aDataSort, iCol, sType, srcCol,
5949
			fixed = settings.aaSortingFixed,
5950
			fixedObj = $.isPlainObject( fixed ),
5951
			nestedSort = [],
5952
			add = function ( a ) {
5953
				if ( a.length && ! Array.isArray( a[0] ) ) {
5954
					// 1D array
5955
					nestedSort.push( a );
5956
				}
5957
				else {
5958
					// 2D array
5959
					$.merge( nestedSort, a );
5960
				}
5961
			};
5962
	
5963
		// Build the sort array, with pre-fix and post-fix options if they have been
5964
		// specified
5965
		if ( Array.isArray( fixed ) ) {
5966
			add( fixed );
5967
		}
5968
	
5969
		if ( fixedObj && fixed.pre ) {
5970
			add( fixed.pre );
5971
		}
5972
	
5973
		add( settings.aaSorting );
5974
	
5975
		if (fixedObj && fixed.post ) {
5976
			add( fixed.post );
5977
		}
5978
	
5979
		for ( i=0 ; i<nestedSort.length ; i++ )
5980
		{
5981
			srcCol = nestedSort[i][0];
5982
			aDataSort = aoColumns[ srcCol ].aDataSort;
5983
	
5984
			for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ )
5985
			{
5986
				iCol = aDataSort[k];
5987
				sType = aoColumns[ iCol ].sType || 'string';
5988
	
5989
				if ( nestedSort[i]._idx === undefined ) {
5990
					nestedSort[i]._idx = $.inArray( nestedSort[i][1], aoColumns[iCol].asSorting );
5991
				}
5992
	
5993
				aSort.push( {
5994
					src:       srcCol,
5995
					col:       iCol,
5996
					dir:       nestedSort[i][1],
5997
					index:     nestedSort[i]._idx,
5998
					type:      sType,
5999
					formatter: DataTable.ext.type.order[ sType+"-pre" ]
6000
				} );
6001
			}
6002
		}
6003
	
6004
		return aSort;
6005
	}
6006
	
6007
	/**
6008
	 * Change the order of the table
6009
	 *  @param {object} oSettings dataTables settings object
6010
	 *  @memberof DataTable#oApi
6011
	 *  @todo This really needs split up!
6012
	 */
6013
	function _fnSort ( oSettings )
6014
	{
6015
		var
6016
			i, ien, iLen, j, jLen, k, kLen,
6017
			sDataType, nTh,
6018
			aiOrig = [],
6019
			oExtSort = DataTable.ext.type.order,
6020
			aoData = oSettings.aoData,
6021
			aoColumns = oSettings.aoColumns,
6022
			aDataSort, data, iCol, sType, oSort,
6023
			formatters = 0,
6024
			sortCol,
6025
			displayMaster = oSettings.aiDisplayMaster,
6026
			aSort;
6027
	
6028
		// Resolve any column types that are unknown due to addition or invalidation
6029
		// @todo Can this be moved into a 'data-ready' handler which is called when
6030
		//   data is going to be used in the table?
6031
		_fnColumnTypes( oSettings );
6032
	
6033
		aSort = _fnSortFlatten( oSettings );
6034
	
6035
		for ( i=0, ien=aSort.length ; i<ien ; i++ ) {
6036
			sortCol = aSort[i];
6037
	
6038
			// Track if we can use the fast sort algorithm
6039
			if ( sortCol.formatter ) {
6040
				formatters++;
6041
			}
6042
	
6043
			// Load the data needed for the sort, for each cell
6044
			_fnSortData( oSettings, sortCol.col );
6045
		}
6046
	
6047
		/* No sorting required if server-side or no sorting array */
6048
		if ( _fnDataSource( oSettings ) != 'ssp' && aSort.length !== 0 )
6049
		{
6050
			// Create a value - key array of the current row positions such that we can use their
6051
			// current position during the sort, if values match, in order to perform stable sorting
6052
			for ( i=0, iLen=displayMaster.length ; i<iLen ; i++ ) {
6053
				aiOrig[ displayMaster[i] ] = i;
6054
			}
6055
	
6056
			/* Do the sort - here we want multi-column sorting based on a given data source (column)
6057
			 * and sorting function (from oSort) in a certain direction. It's reasonably complex to
6058
			 * follow on it's own, but this is what we want (example two column sorting):
6059
			 *  fnLocalSorting = function(a,b){
6060
			 *    var iTest;
6061
			 *    iTest = oSort['string-asc']('data11', 'data12');
6062
			 *      if (iTest !== 0)
6063
			 *        return iTest;
6064
			 *    iTest = oSort['numeric-desc']('data21', 'data22');
6065
			 *    if (iTest !== 0)
6066
			 *      return iTest;
6067
			 *    return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
6068
			 *  }
6069
			 * Basically we have a test for each sorting column, if the data in that column is equal,
6070
			 * test the next column. If all columns match, then we use a numeric sort on the row
6071
			 * positions in the original data array to provide a stable sort.
6072
			 *
6073
			 * Note - I know it seems excessive to have two sorting methods, but the first is around
6074
			 * 15% faster, so the second is only maintained for backwards compatibility with sorting
6075
			 * methods which do not have a pre-sort formatting function.
6076
			 */
6077
			if ( formatters === aSort.length ) {
6078
				// All sort types have formatting functions
6079
				displayMaster.sort( function ( a, b ) {
6080
					var
6081
						x, y, k, test, sort,
6082
						len=aSort.length,
6083
						dataA = aoData[a]._aSortData,
6084
						dataB = aoData[b]._aSortData;
6085
	
6086
					for ( k=0 ; k<len ; k++ ) {
6087
						sort = aSort[k];
6088
	
6089
						x = dataA[ sort.col ];
6090
						y = dataB[ sort.col ];
6091
	
6092
						test = x<y ? -1 : x>y ? 1 : 0;
6093
						if ( test !== 0 ) {
6094
							return sort.dir === 'asc' ? test : -test;
6095
						}
6096
					}
6097
	
6098
					x = aiOrig[a];
6099
					y = aiOrig[b];
6100
					return x<y ? -1 : x>y ? 1 : 0;
6101
				} );
6102
			}
6103
			else {
6104
				// Depreciated - remove in 1.11 (providing a plug-in option)
6105
				// Not all sort types have formatting methods, so we have to call their sorting
6106
				// methods.
6107
				displayMaster.sort( function ( a, b ) {
6108
					var
6109
						x, y, k, l, test, sort, fn,
6110
						len=aSort.length,
6111
						dataA = aoData[a]._aSortData,
6112
						dataB = aoData[b]._aSortData;
6113
	
6114
					for ( k=0 ; k<len ; k++ ) {
6115
						sort = aSort[k];
6116
	
6117
						x = dataA[ sort.col ];
6118
						y = dataB[ sort.col ];
6119
	
6120
						fn = oExtSort[ sort.type+"-"+sort.dir ] || oExtSort[ "string-"+sort.dir ];
6121
						test = fn( x, y );
6122
						if ( test !== 0 ) {
6123
							return test;
6124
						}
6125
					}
6126
	
6127
					x = aiOrig[a];
6128
					y = aiOrig[b];
6129
					return x<y ? -1 : x>y ? 1 : 0;
6130
				} );
6131
			}
6132
		}
6133
	
6134
		/* Tell the draw function that we have sorted the data */
6135
		oSettings.bSorted = true;
6136
	}
6137
	
6138
	
6139
	function _fnSortAria ( settings )
6140
	{
6141
		var label;
6142
		var nextSort;
6143
		var columns = settings.aoColumns;
6144
		var aSort = _fnSortFlatten( settings );
6145
		var oAria = settings.oLanguage.oAria;
6146
	
6147
		// ARIA attributes - need to loop all columns, to update all (removing old
6148
		// attributes as needed)
6149
		for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
6150
		{
6151
			var col = columns[i];
6152
			var asSorting = col.asSorting;
6153
			var sTitle = col.ariaTitle || col.sTitle.replace( /<.*?>/g, "" );
6154
			var th = col.nTh;
6155
	
6156
			// IE7 is throwing an error when setting these properties with jQuery's
6157
			// attr() and removeAttr() methods...
6158
			th.removeAttribute('aria-sort');
6159
	
6160
			/* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
6161
			if ( col.bSortable ) {
6162
				if ( aSort.length > 0 && aSort[0].col == i ) {
6163
					th.setAttribute('aria-sort', aSort[0].dir=="asc" ? "ascending" : "descending" );
6164
					nextSort = asSorting[ aSort[0].index+1 ] || asSorting[0];
6165
				}
6166
				else {
6167
					nextSort = asSorting[0];
6168
				}
6169
	
6170
				label = sTitle + ( nextSort === "asc" ?
6171
					oAria.sSortAscending :
6172
					oAria.sSortDescending
6173
				);
6174
			}
6175
			else {
6176
				label = sTitle;
6177
			}
6178
	
6179
			th.setAttribute('aria-label', label);
6180
		}
6181
	}
6182
	
6183
	
6184
	/**
6185
	 * Function to run on user sort request
6186
	 *  @param {object} settings dataTables settings object
6187
	 *  @param {node} attachTo node to attach the handler to
6188
	 *  @param {int} colIdx column sorting index
6189
	 *  @param {boolean} [append=false] Append the requested sort to the existing
6190
	 *    sort if true (i.e. multi-column sort)
6191
	 *  @param {function} [callback] callback function
6192
	 *  @memberof DataTable#oApi
6193
	 */
6194
	function _fnSortListener ( settings, colIdx, append, callback )
6195
	{
6196
		var col = settings.aoColumns[ colIdx ];
6197
		var sorting = settings.aaSorting;
6198
		var asSorting = col.asSorting;
6199
		var nextSortIdx;
6200
		var next = function ( a, overflow ) {
6201
			var idx = a._idx;
6202
			if ( idx === undefined ) {
6203
				idx = $.inArray( a[1], asSorting );
6204
			}
6205
	
6206
			return idx+1 < asSorting.length ?
6207
				idx+1 :
6208
				overflow ?
6209
					null :
6210
					0;
6211
		};
6212
	
6213
		// Convert to 2D array if needed
6214
		if ( typeof sorting[0] === 'number' ) {
6215
			sorting = settings.aaSorting = [ sorting ];
6216
		}
6217
	
6218
		// If appending the sort then we are multi-column sorting
6219
		if ( append && settings.oFeatures.bSortMulti ) {
6220
			// Are we already doing some kind of sort on this column?
6221
			var sortIdx = $.inArray( colIdx, _pluck(sorting, '0') );
6222
	
6223
			if ( sortIdx !== -1 ) {
6224
				// Yes, modify the sort
6225
				nextSortIdx = next( sorting[sortIdx], true );
6226
	
6227
				if ( nextSortIdx === null && sorting.length === 1 ) {
6228
					nextSortIdx = 0; // can't remove sorting completely
6229
				}
6230
	
6231
				if ( nextSortIdx === null ) {
6232
					sorting.splice( sortIdx, 1 );
6233
				}
6234
				else {
6235
					sorting[sortIdx][1] = asSorting[ nextSortIdx ];
6236
					sorting[sortIdx]._idx = nextSortIdx;
6237
				}
6238
			}
6239
			else {
6240
				// No sort on this column yet
6241
				sorting.push( [ colIdx, asSorting[0], 0 ] );
6242
				sorting[sorting.length-1]._idx = 0;
6243
			}
6244
		}
6245
		else if ( sorting.length && sorting[0][0] == colIdx ) {
6246
			// Single column - already sorting on this column, modify the sort
6247
			nextSortIdx = next( sorting[0] );
6248
	
6249
			sorting.length = 1;
6250
			sorting[0][1] = asSorting[ nextSortIdx ];
6251
			sorting[0]._idx = nextSortIdx;
6252
		}
6253
		else {
6254
			// Single column - sort only on this column
6255
			sorting.length = 0;
6256
			sorting.push( [ colIdx, asSorting[0] ] );
6257
			sorting[0]._idx = 0;
6258
		}
6259
	
6260
		// Run the sort by calling a full redraw
6261
		_fnReDraw( settings );
6262
	
6263
		// callback used for async user interaction
6264
		if ( typeof callback == 'function' ) {
6265
			callback( settings );
6266
		}
6267
	}
6268
	
6269
	
6270
	/**
6271
	 * Attach a sort handler (click) to a node
6272
	 *  @param {object} settings dataTables settings object
6273
	 *  @param {node} attachTo node to attach the handler to
6274
	 *  @param {int} colIdx column sorting index
6275
	 *  @param {function} [callback] callback function
6276
	 *  @memberof DataTable#oApi
6277
	 */
6278
	function _fnSortAttachListener ( settings, attachTo, colIdx, callback )
6279
	{
6280
		var col = settings.aoColumns[ colIdx ];
6281
	
6282
		_fnBindAction( attachTo, {}, function (e) {
6283
			/* If the column is not sortable - don't to anything */
6284
			if ( col.bSortable === false ) {
6285
				return;
6286
			}
6287
	
6288
			// If processing is enabled use a timeout to allow the processing
6289
			// display to be shown - otherwise to it synchronously
6290
			if ( settings.oFeatures.bProcessing ) {
6291
				_fnProcessingDisplay( settings, true );
6292
	
6293
				setTimeout( function() {
6294
					_fnSortListener( settings, colIdx, e.shiftKey, callback );
6295
	
6296
					// In server-side processing, the draw callback will remove the
6297
					// processing display
6298
					if ( _fnDataSource( settings ) !== 'ssp' ) {
6299
						_fnProcessingDisplay( settings, false );
6300
					}
6301
				}, 0 );
6302
			}
6303
			else {
6304
				_fnSortListener( settings, colIdx, e.shiftKey, callback );
6305
			}
6306
		} );
6307
	}
6308
	
6309
	
6310
	/**
6311
	 * Set the sorting classes on table's body, Note: it is safe to call this function
6312
	 * when bSort and bSortClasses are false
6313
	 *  @param {object} oSettings dataTables settings object
6314
	 *  @memberof DataTable#oApi
6315
	 */
6316
	function _fnSortingClasses( settings )
6317
	{
6318
		var oldSort = settings.aLastSort;
6319
		var sortClass = settings.oClasses.sSortColumn;
6320
		var sort = _fnSortFlatten( settings );
6321
		var features = settings.oFeatures;
6322
		var i, ien, colIdx;
6323
	
6324
		if ( features.bSort && features.bSortClasses ) {
6325
			// Remove old sorting classes
6326
			for ( i=0, ien=oldSort.length ; i<ien ; i++ ) {
6327
				colIdx = oldSort[i].src;
6328
	
6329
				// Remove column sorting
6330
				$( _pluck( settings.aoData, 'anCells', colIdx ) )
6331
					.removeClass( sortClass + (i<2 ? i+1 : 3) );
6332
			}
6333
	
6334
			// Add new column sorting
6335
			for ( i=0, ien=sort.length ; i<ien ; i++ ) {
6336
				colIdx = sort[i].src;
6337
	
6338
				$( _pluck( settings.aoData, 'anCells', colIdx ) )
6339
					.addClass( sortClass + (i<2 ? i+1 : 3) );
6340
			}
6341
		}
6342
	
6343
		settings.aLastSort = sort;
6344
	}
6345
	
6346
	
6347
	// Get the data to sort a column, be it from cache, fresh (populating the
6348
	// cache), or from a sort formatter
6349
	function _fnSortData( settings, idx )
6350
	{
6351
		// Custom sorting function - provided by the sort data type
6352
		var column = settings.aoColumns[ idx ];
6353
		var customSort = DataTable.ext.order[ column.sSortDataType ];
6354
		var customData;
6355
	
6356
		if ( customSort ) {
6357
			customData = customSort.call( settings.oInstance, settings, idx,
6358
				_fnColumnIndexToVisible( settings, idx )
6359
			);
6360
		}
6361
	
6362
		// Use / populate cache
6363
		var row, cellData;
6364
		var formatter = DataTable.ext.type.order[ column.sType+"-pre" ];
6365
	
6366
		for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
6367
			row = settings.aoData[i];
6368
	
6369
			if ( ! row._aSortData ) {
6370
				row._aSortData = [];
6371
			}
6372
	
6373
			if ( ! row._aSortData[idx] || customSort ) {
6374
				cellData = customSort ?
6375
					customData[i] : // If there was a custom sort function, use data from there
6376
					_fnGetCellData( settings, i, idx, 'sort' );
6377
	
6378
				row._aSortData[ idx ] = formatter ?
6379
					formatter( cellData ) :
6380
					cellData;
6381
			}
6382
		}
6383
	}
6384
	
6385
	
6386
	
6387
	/**
6388
	 * Save the state of a table
6389
	 *  @param {object} oSettings dataTables settings object
6390
	 *  @memberof DataTable#oApi
6391
	 */
6392
	function _fnSaveState ( settings )
6393
	{
6394
		if (settings._bLoadingState) {
6395
			return;
6396
		}
6397
	
6398
		/* Store the interesting variables */
6399
		var state = {
6400
			time:    +new Date(),
6401
			start:   settings._iDisplayStart,
6402
			length:  settings._iDisplayLength,
6403
			order:   $.extend( true, [], settings.aaSorting ),
6404
			search:  _fnSearchToCamel( settings.oPreviousSearch ),
6405
			columns: $.map( settings.aoColumns, function ( col, i ) {
6406
				return {
6407
					visible: col.bVisible,
6408
					search: _fnSearchToCamel( settings.aoPreSearchCols[i] )
6409
				};
6410
			} )
6411
		};
6412
	
6413
		settings.oSavedState = state;
6414
		_fnCallbackFire( settings, "aoStateSaveParams", 'stateSaveParams', [settings, state] );
6415
		
6416
		if ( settings.oFeatures.bStateSave && !settings.bDestroying )
6417
		{
6418
			settings.fnStateSaveCallback.call( settings.oInstance, settings, state );
6419
		}	
6420
	}
6421
	
6422
	
6423
	/**
6424
	 * Attempt to load a saved table state
6425
	 *  @param {object} oSettings dataTables settings object
6426
	 *  @param {object} oInit DataTables init object so we can override settings
6427
	 *  @param {function} callback Callback to execute when the state has been loaded
6428
	 *  @memberof DataTable#oApi
6429
	 */
6430
	function _fnLoadState ( settings, oInit, callback )
6431
	{
6432
		if ( ! settings.oFeatures.bStateSave ) {
6433
			callback();
6434
			return;
6435
		}
6436
	
6437
		var loaded = function(state) {
6438
			_fnImplementState(settings, state, callback);
6439
		}
6440
	
6441
		var state = settings.fnStateLoadCallback.call( settings.oInstance, settings, loaded );
6442
	
6443
		if ( state !== undefined ) {
6444
			_fnImplementState( settings, state, callback );
6445
		}
6446
		// otherwise, wait for the loaded callback to be executed
6447
	
6448
		return true;
6449
	}
6450
	
6451
	function _fnImplementState ( settings, s, callback) {
6452
		var i, ien;
6453
		var columns = settings.aoColumns;
6454
		settings._bLoadingState = true;
6455
	
6456
		// When StateRestore was introduced the state could now be implemented at any time
6457
		// Not just initialisation. To do this an api instance is required in some places
6458
		var api = settings._bInitComplete ? new DataTable.Api(settings) : null;
6459
	
6460
		if ( ! s || ! s.time ) {
6461
			settings._bLoadingState = false;
6462
			callback();
6463
			return;
6464
		}
6465
	
6466
		// Allow custom and plug-in manipulation functions to alter the saved data set and
6467
		// cancelling of loading by returning false
6468
		var abStateLoad = _fnCallbackFire( settings, 'aoStateLoadParams', 'stateLoadParams', [settings, s] );
6469
		if ( $.inArray( false, abStateLoad ) !== -1 ) {
6470
			settings._bLoadingState = false;
6471
			callback();
6472
			return;
6473
		}
6474
	
6475
		// Reject old data
6476
		var duration = settings.iStateDuration;
6477
		if ( duration > 0 && s.time < +new Date() - (duration*1000) ) {
6478
			settings._bLoadingState = false;
6479
			callback();
6480
			return;
6481
		}
6482
	
6483
		// Number of columns have changed - all bets are off, no restore of settings
6484
		if ( s.columns && columns.length !== s.columns.length ) {
6485
			settings._bLoadingState = false;
6486
			callback();
6487
			return;
6488
		}
6489
	
6490
		// Store the saved state so it might be accessed at any time
6491
		settings.oLoadedState = $.extend( true, {}, s );
6492
	
6493
		// Restore key features - todo - for 1.11 this needs to be done by
6494
		// subscribed events
6495
		if ( s.start !== undefined ) {
6496
			if(api === null) {
6497
				settings._iDisplayStart    = s.start;
6498
				settings.iInitDisplayStart = s.start;
6499
			}
6500
			else {
6501
				_fnPageChange(settings, s.start/s.length);
6502
	
6503
			}
6504
		}
6505
		if ( s.length !== undefined ) {
6506
			settings._iDisplayLength   = s.length;
6507
		}
6508
	
6509
		// Order
6510
		if ( s.order !== undefined ) {
6511
			settings.aaSorting = [];
6512
			$.each( s.order, function ( i, col ) {
6513
				settings.aaSorting.push( col[0] >= columns.length ?
6514
					[ 0, col[1] ] :
6515
					col
6516
				);
6517
			} );
6518
		}
6519
	
6520
		// Search
6521
		if ( s.search !== undefined ) {
6522
			$.extend( settings.oPreviousSearch, _fnSearchToHung( s.search ) );
6523
		}
6524
	
6525
		// Columns
6526
		if ( s.columns ) {
6527
			for ( i=0, ien=s.columns.length ; i<ien ; i++ ) {
6528
				var col = s.columns[i];
6529
	
6530
				// Visibility
6531
				if ( col.visible !== undefined ) {
6532
					// If the api is defined, the table has been initialised so we need to use it rather than internal settings
6533
					if (api) {
6534
						// Don't redraw the columns on every iteration of this loop, we will do this at the end instead
6535
						api.column(i).visible(col.visible, false);
6536
					}
6537
					else {
6538
						columns[i].bVisible = col.visible;
6539
					}
6540
				}
6541
	
6542
				// Search
6543
				if ( col.search !== undefined ) {
6544
					$.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) );
6545
				}
6546
			}
6547
			
6548
			// If the api is defined then we need to adjust the columns once the visibility has been changed
6549
			if (api) {
6550
				api.columns.adjust();
6551
			}
6552
		}
6553
	
6554
		settings._bLoadingState = false;
6555
		_fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, s] );
6556
		callback();
6557
	};
6558
	
6559
	
6560
	/**
6561
	 * Return the settings object for a particular table
6562
	 *  @param {node} table table we are using as a dataTable
6563
	 *  @returns {object} Settings object - or null if not found
6564
	 *  @memberof DataTable#oApi
6565
	 */
6566
	function _fnSettingsFromNode ( table )
6567
	{
6568
		var settings = DataTable.settings;
6569
		var idx = $.inArray( table, _pluck( settings, 'nTable' ) );
6570
	
6571
		return idx !== -1 ?
6572
			settings[ idx ] :
6573
			null;
6574
	}
6575
	
6576
	
6577
	/**
6578
	 * Log an error message
6579
	 *  @param {object} settings dataTables settings object
6580
	 *  @param {int} level log error messages, or display them to the user
6581
	 *  @param {string} msg error message
6582
	 *  @param {int} tn Technical note id to get more information about the error.
6583
	 *  @memberof DataTable#oApi
6584
	 */
6585
	function _fnLog( settings, level, msg, tn )
6586
	{
6587
		msg = 'DataTables warning: '+
6588
			(settings ? 'table id='+settings.sTableId+' - ' : '')+msg;
6589
	
6590
		if ( tn ) {
6591
			msg += '. For more information about this error, please see '+
6592
			'http://datatables.net/tn/'+tn;
6593
		}
6594
	
6595
		if ( ! level  ) {
6596
			// Backwards compatibility pre 1.10
6597
			var ext = DataTable.ext;
6598
			var type = ext.sErrMode || ext.errMode;
6599
	
6600
			if ( settings ) {
6601
				_fnCallbackFire( settings, null, 'error', [ settings, tn, msg ] );
6602
			}
6603
	
6604
			if ( type == 'alert' ) {
6605
				alert( msg );
6606
			}
6607
			else if ( type == 'throw' ) {
6608
				throw new Error(msg);
6609
			}
6610
			else if ( typeof type == 'function' ) {
6611
				type( settings, tn, msg );
6612
			}
6613
		}
6614
		else if ( window.console && console.log ) {
6615
			console.log( msg );
6616
		}
6617
	}
6618
	
6619
	
6620
	/**
6621
	 * See if a property is defined on one object, if so assign it to the other object
6622
	 *  @param {object} ret target object
6623
	 *  @param {object} src source object
6624
	 *  @param {string} name property
6625
	 *  @param {string} [mappedName] name to map too - optional, name used if not given
6626
	 *  @memberof DataTable#oApi
6627
	 */
6628
	function _fnMap( ret, src, name, mappedName )
6629
	{
6630
		if ( Array.isArray( name ) ) {
6631
			$.each( name, function (i, val) {
6632
				if ( Array.isArray( val ) ) {
6633
					_fnMap( ret, src, val[0], val[1] );
6634
				}
6635
				else {
6636
					_fnMap( ret, src, val );
6637
				}
6638
			} );
6639
	
6640
			return;
6641
		}
6642
	
6643
		if ( mappedName === undefined ) {
6644
			mappedName = name;
6645
		}
6646
	
6647
		if ( src[name] !== undefined ) {
6648
			ret[mappedName] = src[name];
6649
		}
6650
	}
6651
	
6652
	
6653
	/**
6654
	 * Extend objects - very similar to jQuery.extend, but deep copy objects, and
6655
	 * shallow copy arrays. The reason we need to do this, is that we don't want to
6656
	 * deep copy array init values (such as aaSorting) since the dev wouldn't be
6657
	 * able to override them, but we do want to deep copy arrays.
6658
	 *  @param {object} out Object to extend
6659
	 *  @param {object} extender Object from which the properties will be applied to
6660
	 *      out
6661
	 *  @param {boolean} breakRefs If true, then arrays will be sliced to take an
6662
	 *      independent copy with the exception of the `data` or `aaData` parameters
6663
	 *      if they are present. This is so you can pass in a collection to
6664
	 *      DataTables and have that used as your data source without breaking the
6665
	 *      references
6666
	 *  @returns {object} out Reference, just for convenience - out === the return.
6667
	 *  @memberof DataTable#oApi
6668
	 *  @todo This doesn't take account of arrays inside the deep copied objects.
6669
	 */
6670
	function _fnExtend( out, extender, breakRefs )
6671
	{
6672
		var val;
6673
	
6674
		for ( var prop in extender ) {
6675
			if ( extender.hasOwnProperty(prop) ) {
6676
				val = extender[prop];
6677
	
6678
				if ( $.isPlainObject( val ) ) {
6679
					if ( ! $.isPlainObject( out[prop] ) ) {
6680
						out[prop] = {};
6681
					}
6682
					$.extend( true, out[prop], val );
6683
				}
6684
				else if ( breakRefs && prop !== 'data' && prop !== 'aaData' && Array.isArray(val) ) {
6685
					out[prop] = val.slice();
6686
				}
6687
				else {
6688
					out[prop] = val;
6689
				}
6690
			}
6691
		}
6692
	
6693
		return out;
6694
	}
6695
	
6696
	
6697
	/**
6698
	 * Bind an event handers to allow a click or return key to activate the callback.
6699
	 * This is good for accessibility since a return on the keyboard will have the
6700
	 * same effect as a click, if the element has focus.
6701
	 *  @param {element} n Element to bind the action to
6702
	 *  @param {object} oData Data object to pass to the triggered function
6703
	 *  @param {function} fn Callback function for when the event is triggered
6704
	 *  @memberof DataTable#oApi
6705
	 */
6706
	function _fnBindAction( n, oData, fn )
6707
	{
6708
		$(n)
6709
			.on( 'click.DT', oData, function (e) {
6710
					$(n).trigger('blur'); // Remove focus outline for mouse users
6711
					fn(e);
6712
				} )
6713
			.on( 'keypress.DT', oData, function (e){
6714
					if ( e.which === 13 ) {
6715
						e.preventDefault();
6716
						fn(e);
6717
					}
6718
				} )
6719
			.on( 'selectstart.DT', function () {
6720
					/* Take the brutal approach to cancelling text selection */
6721
					return false;
6722
				} );
6723
	}
6724
	
6725
	
6726
	/**
6727
	 * Register a callback function. Easily allows a callback function to be added to
6728
	 * an array store of callback functions that can then all be called together.
6729
	 *  @param {object} oSettings dataTables settings object
6730
	 *  @param {string} sStore Name of the array storage for the callbacks in oSettings
6731
	 *  @param {function} fn Function to be called back
6732
	 *  @param {string} sName Identifying name for the callback (i.e. a label)
6733
	 *  @memberof DataTable#oApi
6734
	 */
6735
	function _fnCallbackReg( oSettings, sStore, fn, sName )
6736
	{
6737
		if ( fn )
6738
		{
6739
			oSettings[sStore].push( {
6740
				"fn": fn,
6741
				"sName": sName
6742
			} );
6743
		}
6744
	}
6745
	
6746
	
6747
	/**
6748
	 * Fire callback functions and trigger events. Note that the loop over the
6749
	 * callback array store is done backwards! Further note that you do not want to
6750
	 * fire off triggers in time sensitive applications (for example cell creation)
6751
	 * as its slow.
6752
	 *  @param {object} settings dataTables settings object
6753
	 *  @param {string} callbackArr Name of the array storage for the callbacks in
6754
	 *      oSettings
6755
	 *  @param {string} eventName Name of the jQuery custom event to trigger. If
6756
	 *      null no trigger is fired
6757
	 *  @param {array} args Array of arguments to pass to the callback function /
6758
	 *      trigger
6759
	 *  @memberof DataTable#oApi
6760
	 */
6761
	function _fnCallbackFire( settings, callbackArr, eventName, args )
6762
	{
6763
		var ret = [];
6764
	
6765
		if ( callbackArr ) {
6766
			ret = $.map( settings[callbackArr].slice().reverse(), function (val, i) {
6767
				return val.fn.apply( settings.oInstance, args );
6768
			} );
6769
		}
6770
	
6771
		if ( eventName !== null ) {
6772
			var e = $.Event( eventName+'.dt' );
6773
	
6774
			$(settings.nTable).trigger( e, args );
6775
	
6776
			ret.push( e.result );
6777
		}
6778
	
6779
		return ret;
6780
	}
6781
	
6782
	
6783
	function _fnLengthOverflow ( settings )
6784
	{
6785
		var
6786
			start = settings._iDisplayStart,
6787
			end = settings.fnDisplayEnd(),
6788
			len = settings._iDisplayLength;
6789
	
6790
		/* If we have space to show extra rows (backing up from the end point - then do so */
6791
		if ( start >= end )
6792
		{
6793
			start = end - len;
6794
		}
6795
	
6796
		// Keep the start record on the current page
6797
		start -= (start % len);
6798
	
6799
		if ( len === -1 || start < 0 )
6800
		{
6801
			start = 0;
6802
		}
6803
	
6804
		settings._iDisplayStart = start;
6805
	}
6806
	
6807
	
6808
	function _fnRenderer( settings, type )
6809
	{
6810
		var renderer = settings.renderer;
6811
		var host = DataTable.ext.renderer[type];
6812
	
6813
		if ( $.isPlainObject( renderer ) && renderer[type] ) {
6814
			// Specific renderer for this type. If available use it, otherwise use
6815
			// the default.
6816
			return host[renderer[type]] || host._;
6817
		}
6818
		else if ( typeof renderer === 'string' ) {
6819
			// Common renderer - if there is one available for this type use it,
6820
			// otherwise use the default
6821
			return host[renderer] || host._;
6822
		}
6823
	
6824
		// Use the default
6825
		return host._;
6826
	}
6827
	
6828
	
6829
	/**
6830
	 * Detect the data source being used for the table. Used to simplify the code
6831
	 * a little (ajax) and to make it compress a little smaller.
6832
	 *
6833
	 *  @param {object} settings dataTables settings object
6834
	 *  @returns {string} Data source
6835
	 *  @memberof DataTable#oApi
6836
	 */
6837
	function _fnDataSource ( settings )
6838
	{
6839
		if ( settings.oFeatures.bServerSide ) {
6840
			return 'ssp';
6841
		}
6842
		else if ( settings.ajax || settings.sAjaxSource ) {
6843
			return 'ajax';
6844
		}
6845
		return 'dom';
6846
	}
6847
	
6848

6849
	
6850
	
6851
	/**
6852
	 * Computed structure of the DataTables API, defined by the options passed to
6853
	 * `DataTable.Api.register()` when building the API.
6854
	 *
6855
	 * The structure is built in order to speed creation and extension of the Api
6856
	 * objects since the extensions are effectively pre-parsed.
6857
	 *
6858
	 * The array is an array of objects with the following structure, where this
6859
	 * base array represents the Api prototype base:
6860
	 *
6861
	 *     [
6862
	 *       {
6863
	 *         name:      'data'                -- string   - Property name
6864
	 *         val:       function () {},       -- function - Api method (or undefined if just an object
6865
	 *         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
6866
	 *         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
6867
	 *       },
6868
	 *       {
6869
	 *         name:     'row'
6870
	 *         val:       {},
6871
	 *         methodExt: [ ... ],
6872
	 *         propExt:   [
6873
	 *           {
6874
	 *             name:      'data'
6875
	 *             val:       function () {},
6876
	 *             methodExt: [ ... ],
6877
	 *             propExt:   [ ... ]
6878
	 *           },
6879
	 *           ...
6880
	 *         ]
6881
	 *       }
6882
	 *     ]
6883
	 *
6884
	 * @type {Array}
6885
	 * @ignore
6886
	 */
6887
	var __apiStruct = [];
6888
	
6889
	
6890
	/**
6891
	 * `Array.prototype` reference.
6892
	 *
6893
	 * @type object
6894
	 * @ignore
6895
	 */
6896
	var __arrayProto = Array.prototype;
6897
	
6898
	
6899
	/**
6900
	 * Abstraction for `context` parameter of the `Api` constructor to allow it to
6901
	 * take several different forms for ease of use.
6902
	 *
6903
	 * Each of the input parameter types will be converted to a DataTables settings
6904
	 * object where possible.
6905
	 *
6906
	 * @param  {string|node|jQuery|object} mixed DataTable identifier. Can be one
6907
	 *   of:
6908
	 *
6909
	 *   * `string` - jQuery selector. Any DataTables' matching the given selector
6910
	 *     with be found and used.
6911
	 *   * `node` - `TABLE` node which has already been formed into a DataTable.
6912
	 *   * `jQuery` - A jQuery object of `TABLE` nodes.
6913
	 *   * `object` - DataTables settings object
6914
	 *   * `DataTables.Api` - API instance
6915
	 * @return {array|null} Matching DataTables settings objects. `null` or
6916
	 *   `undefined` is returned if no matching DataTable is found.
6917
	 * @ignore
6918
	 */
6919
	var _toSettings = function ( mixed )
6920
	{
6921
		var idx, jq;
6922
		var settings = DataTable.settings;
6923
		var tables = $.map( settings, function (el, i) {
6924
			return el.nTable;
6925
		} );
6926
	
6927
		if ( ! mixed ) {
6928
			return [];
6929
		}
6930
		else if ( mixed.nTable && mixed.oApi ) {
6931
			// DataTables settings object
6932
			return [ mixed ];
6933
		}
6934
		else if ( mixed.nodeName && mixed.nodeName.toLowerCase() === 'table' ) {
6935
			// Table node
6936
			idx = $.inArray( mixed, tables );
6937
			return idx !== -1 ? [ settings[idx] ] : null;
6938
		}
6939
		else if ( mixed && typeof mixed.settings === 'function' ) {
6940
			return mixed.settings().toArray();
6941
		}
6942
		else if ( typeof mixed === 'string' ) {
6943
			// jQuery selector
6944
			jq = $(mixed);
6945
		}
6946
		else if ( mixed instanceof $ ) {
6947
			// jQuery object (also DataTables instance)
6948
			jq = mixed;
6949
		}
6950
	
6951
		if ( jq ) {
6952
			return jq.map( function(i) {
6953
				idx = $.inArray( this, tables );
6954
				return idx !== -1 ? settings[idx] : null;
6955
			} ).toArray();
6956
		}
6957
	};
6958
	
6959
	
6960
	/**
6961
	 * DataTables API class - used to control and interface with  one or more
6962
	 * DataTables enhanced tables.
6963
	 *
6964
	 * The API class is heavily based on jQuery, presenting a chainable interface
6965
	 * that you can use to interact with tables. Each instance of the API class has
6966
	 * a "context" - i.e. the tables that it will operate on. This could be a single
6967
	 * table, all tables on a page or a sub-set thereof.
6968
	 *
6969
	 * Additionally the API is designed to allow you to easily work with the data in
6970
	 * the tables, retrieving and manipulating it as required. This is done by
6971
	 * presenting the API class as an array like interface. The contents of the
6972
	 * array depend upon the actions requested by each method (for example
6973
	 * `rows().nodes()` will return an array of nodes, while `rows().data()` will
6974
	 * return an array of objects or arrays depending upon your table's
6975
	 * configuration). The API object has a number of array like methods (`push`,
6976
	 * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`,
6977
	 * `unique` etc) to assist your working with the data held in a table.
6978
	 *
6979
	 * Most methods (those which return an Api instance) are chainable, which means
6980
	 * the return from a method call also has all of the methods available that the
6981
	 * top level object had. For example, these two calls are equivalent:
6982
	 *
6983
	 *     // Not chained
6984
	 *     api.row.add( {...} );
6985
	 *     api.draw();
6986
	 *
6987
	 *     // Chained
6988
	 *     api.row.add( {...} ).draw();
6989
	 *
6990
	 * @class DataTable.Api
6991
	 * @param {array|object|string|jQuery} context DataTable identifier. This is
6992
	 *   used to define which DataTables enhanced tables this API will operate on.
6993
	 *   Can be one of:
6994
	 *
6995
	 *   * `string` - jQuery selector. Any DataTables' matching the given selector
6996
	 *     with be found and used.
6997
	 *   * `node` - `TABLE` node which has already been formed into a DataTable.
6998
	 *   * `jQuery` - A jQuery object of `TABLE` nodes.
6999
	 *   * `object` - DataTables settings object
7000
	 * @param {array} [data] Data to initialise the Api instance with.
7001
	 *
7002
	 * @example
7003
	 *   // Direct initialisation during DataTables construction
7004
	 *   var api = $('#example').DataTable();
7005
	 *
7006
	 * @example
7007
	 *   // Initialisation using a DataTables jQuery object
7008
	 *   var api = $('#example').dataTable().api();
7009
	 *
7010
	 * @example
7011
	 *   // Initialisation as a constructor
7012
	 *   var api = new $.fn.DataTable.Api( 'table.dataTable' );
7013
	 */
7014
	_Api = function ( context, data )
7015
	{
7016
		if ( ! (this instanceof _Api) ) {
7017
			return new _Api( context, data );
7018
		}
7019
	
7020
		var settings = [];
7021
		var ctxSettings = function ( o ) {
7022
			var a = _toSettings( o );
7023
			if ( a ) {
7024
				settings.push.apply( settings, a );
7025
			}
7026
		};
7027
	
7028
		if ( Array.isArray( context ) ) {
7029
			for ( var i=0, ien=context.length ; i<ien ; i++ ) {
7030
				ctxSettings( context[i] );
7031
			}
7032
		}
7033
		else {
7034
			ctxSettings( context );
7035
		}
7036
	
7037
		// Remove duplicates
7038
		this.context = _unique( settings );
7039
	
7040
		// Initial data
7041
		if ( data ) {
7042
			$.merge( this, data );
7043
		}
7044
	
7045
		// selector
7046
		this.selector = {
7047
			rows: null,
7048
			cols: null,
7049
			opts: null
7050
		};
7051
	
7052
		_Api.extend( this, this, __apiStruct );
7053
	};
7054
	
7055
	DataTable.Api = _Api;
7056
	
7057
	// Don't destroy the existing prototype, just extend it. Required for jQuery 2's
7058
	// isPlainObject.
7059
	$.extend( _Api.prototype, {
7060
		any: function ()
7061
		{
7062
			return this.count() !== 0;
7063
		},
7064
	
7065
	
7066
		concat:  __arrayProto.concat,
7067
	
7068
	
7069
		context: [], // array of table settings objects
7070
	
7071
	
7072
		count: function ()
7073
		{
7074
			return this.flatten().length;
7075
		},
7076
	
7077
	
7078
		each: function ( fn )
7079
		{
7080
			for ( var i=0, ien=this.length ; i<ien; i++ ) {
7081
				fn.call( this, this[i], i, this );
7082
			}
7083
	
7084
			return this;
7085
		},
7086
	
7087
	
7088
		eq: function ( idx )
7089
		{
7090
			var ctx = this.context;
7091
	
7092
			return ctx.length > idx ?
7093
				new _Api( ctx[idx], this[idx] ) :
7094
				null;
7095
		},
7096
	
7097
	
7098
		filter: function ( fn )
7099
		{
7100
			var a = [];
7101
	
7102
			if ( __arrayProto.filter ) {
7103
				a = __arrayProto.filter.call( this, fn, this );
7104
			}
7105
			else {
7106
				// Compatibility for browsers without EMCA-252-5 (JS 1.6)
7107
				for ( var i=0, ien=this.length ; i<ien ; i++ ) {
7108
					if ( fn.call( this, this[i], i, this ) ) {
7109
						a.push( this[i] );
7110
					}
7111
				}
7112
			}
7113
	
7114
			return new _Api( this.context, a );
7115
		},
7116
	
7117
	
7118
		flatten: function ()
7119
		{
7120
			var a = [];
7121
			return new _Api( this.context, a.concat.apply( a, this.toArray() ) );
7122
		},
7123
	
7124
	
7125
		join:    __arrayProto.join,
7126
	
7127
	
7128
		indexOf: __arrayProto.indexOf || function (obj, start)
7129
		{
7130
			for ( var i=(start || 0), ien=this.length ; i<ien ; i++ ) {
7131
				if ( this[i] === obj ) {
7132
					return i;
7133
				}
7134
			}
7135
			return -1;
7136
		},
7137
	
7138
		iterator: function ( flatten, type, fn, alwaysNew ) {
7139
			var
7140
				a = [], ret,
7141
				i, ien, j, jen,
7142
				context = this.context,
7143
				rows, items, item,
7144
				selector = this.selector;
7145
	
7146
			// Argument shifting
7147
			if ( typeof flatten === 'string' ) {
7148
				alwaysNew = fn;
7149
				fn = type;
7150
				type = flatten;
7151
				flatten = false;
7152
			}
7153
	
7154
			for ( i=0, ien=context.length ; i<ien ; i++ ) {
7155
				var apiInst = new _Api( context[i] );
7156
	
7157
				if ( type === 'table' ) {
7158
					ret = fn.call( apiInst, context[i], i );
7159
	
7160
					if ( ret !== undefined ) {
7161
						a.push( ret );
7162
					}
7163
				}
7164
				else if ( type === 'columns' || type === 'rows' ) {
7165
					// this has same length as context - one entry for each table
7166
					ret = fn.call( apiInst, context[i], this[i], i );
7167
	
7168
					if ( ret !== undefined ) {
7169
						a.push( ret );
7170
					}
7171
				}
7172
				else if ( type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell' ) {
7173
					// columns and rows share the same structure.
7174
					// 'this' is an array of column indexes for each context
7175
					items = this[i];
7176
	
7177
					if ( type === 'column-rows' ) {
7178
						rows = _selector_row_indexes( context[i], selector.opts );
7179
					}
7180
	
7181
					for ( j=0, jen=items.length ; j<jen ; j++ ) {
7182
						item = items[j];
7183
	
7184
						if ( type === 'cell' ) {
7185
							ret = fn.call( apiInst, context[i], item.row, item.column, i, j );
7186
						}
7187
						else {
7188
							ret = fn.call( apiInst, context[i], item, i, j, rows );
7189
						}
7190
	
7191
						if ( ret !== undefined ) {
7192
							a.push( ret );
7193
						}
7194
					}
7195
				}
7196
			}
7197
	
7198
			if ( a.length || alwaysNew ) {
7199
				var api = new _Api( context, flatten ? a.concat.apply( [], a ) : a );
7200
				var apiSelector = api.selector;
7201
				apiSelector.rows = selector.rows;
7202
				apiSelector.cols = selector.cols;
7203
				apiSelector.opts = selector.opts;
7204
				return api;
7205
			}
7206
			return this;
7207
		},
7208
	
7209
	
7210
		lastIndexOf: __arrayProto.lastIndexOf || function (obj, start)
7211
		{
7212
			// Bit cheeky...
7213
			return this.indexOf.apply( this.toArray.reverse(), arguments );
7214
		},
7215
	
7216
	
7217
		length:  0,
7218
	
7219
	
7220
		map: function ( fn )
7221
		{
7222
			var a = [];
7223
	
7224
			if ( __arrayProto.map ) {
7225
				a = __arrayProto.map.call( this, fn, this );
7226
			}
7227
			else {
7228
				// Compatibility for browsers without EMCA-252-5 (JS 1.6)
7229
				for ( var i=0, ien=this.length ; i<ien ; i++ ) {
7230
					a.push( fn.call( this, this[i], i ) );
7231
				}
7232
			}
7233
	
7234
			return new _Api( this.context, a );
7235
		},
7236
	
7237
	
7238
		pluck: function ( prop )
7239
		{
7240
			return this.map( function ( el ) {
7241
				return el[ prop ];
7242
			} );
7243
		},
7244
	
7245
		pop:     __arrayProto.pop,
7246
	
7247
	
7248
		push:    __arrayProto.push,
7249
	
7250
	
7251
		// Does not return an API instance
7252
		reduce: __arrayProto.reduce || function ( fn, init )
7253
		{
7254
			return _fnReduce( this, fn, init, 0, this.length, 1 );
7255
		},
7256
	
7257
	
7258
		reduceRight: __arrayProto.reduceRight || function ( fn, init )
7259
		{
7260
			return _fnReduce( this, fn, init, this.length-1, -1, -1 );
7261
		},
7262
	
7263
	
7264
		reverse: __arrayProto.reverse,
7265
	
7266
	
7267
		// Object with rows, columns and opts
7268
		selector: null,
7269
	
7270
	
7271
		shift:   __arrayProto.shift,
7272
	
7273
	
7274
		slice: function () {
7275
			return new _Api( this.context, this );
7276
		},
7277
	
7278
	
7279
		sort:    __arrayProto.sort, // ? name - order?
7280
	
7281
	
7282
		splice:  __arrayProto.splice,
7283
	
7284
	
7285
		toArray: function ()
7286
		{
7287
			return __arrayProto.slice.call( this );
7288
		},
7289
	
7290
	
7291
		to$: function ()
7292
		{
7293
			return $( this );
7294
		},
7295
	
7296
	
7297
		toJQuery: function ()
7298
		{
7299
			return $( this );
7300
		},
7301
	
7302
	
7303
		unique: function ()
7304
		{
7305
			return new _Api( this.context, _unique(this) );
7306
		},
7307
	
7308
	
7309
		unshift: __arrayProto.unshift
7310
	} );
7311
	
7312
	
7313
	_Api.extend = function ( scope, obj, ext )
7314
	{
7315
		// Only extend API instances and static properties of the API
7316
		if ( ! ext.length || ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) {
7317
			return;
7318
		}
7319
	
7320
		var
7321
			i, ien,
7322
			struct,
7323
			methodScoping = function ( scope, fn, struc ) {
7324
				return function () {
7325
					var ret = fn.apply( scope, arguments );
7326
	
7327
					// Method extension
7328
					_Api.extend( ret, ret, struc.methodExt );
7329
					return ret;
7330
				};
7331
			};
7332
	
7333
		for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7334
			struct = ext[i];
7335
	
7336
			// Value
7337
			obj[ struct.name ] = struct.type === 'function' ?
7338
				methodScoping( scope, struct.val, struct ) :
7339
				struct.type === 'object' ?
7340
					{} :
7341
					struct.val;
7342
	
7343
			obj[ struct.name ].__dt_wrapper = true;
7344
	
7345
			// Property extension
7346
			_Api.extend( scope, obj[ struct.name ], struct.propExt );
7347
		}
7348
	};
7349
	
7350
	
7351
	// @todo - Is there need for an augment function?
7352
	// _Api.augment = function ( inst, name )
7353
	// {
7354
	// 	// Find src object in the structure from the name
7355
	// 	var parts = name.split('.');
7356
	
7357
	// 	_Api.extend( inst, obj );
7358
	// };
7359
	
7360
	
7361
	//     [
7362
	//       {
7363
	//         name:      'data'                -- string   - Property name
7364
	//         val:       function () {},       -- function - Api method (or undefined if just an object
7365
	//         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
7366
	//         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
7367
	//       },
7368
	//       {
7369
	//         name:     'row'
7370
	//         val:       {},
7371
	//         methodExt: [ ... ],
7372
	//         propExt:   [
7373
	//           {
7374
	//             name:      'data'
7375
	//             val:       function () {},
7376
	//             methodExt: [ ... ],
7377
	//             propExt:   [ ... ]
7378
	//           },
7379
	//           ...
7380
	//         ]
7381
	//       }
7382
	//     ]
7383
	
7384
	_Api.register = _api_register = function ( name, val )
7385
	{
7386
		if ( Array.isArray( name ) ) {
7387
			for ( var j=0, jen=name.length ; j<jen ; j++ ) {
7388
				_Api.register( name[j], val );
7389
			}
7390
			return;
7391
		}
7392
	
7393
		var
7394
			i, ien,
7395
			heir = name.split('.'),
7396
			struct = __apiStruct,
7397
			key, method;
7398
	
7399
		var find = function ( src, name ) {
7400
			for ( var i=0, ien=src.length ; i<ien ; i++ ) {
7401
				if ( src[i].name === name ) {
7402
					return src[i];
7403
				}
7404
			}
7405
			return null;
7406
		};
7407
	
7408
		for ( i=0, ien=heir.length ; i<ien ; i++ ) {
7409
			method = heir[i].indexOf('()') !== -1;
7410
			key = method ?
7411
				heir[i].replace('()', '') :
7412
				heir[i];
7413
	
7414
			var src = find( struct, key );
7415
			if ( ! src ) {
7416
				src = {
7417
					name:      key,
7418
					val:       {},
7419
					methodExt: [],
7420
					propExt:   [],
7421
					type:      'object'
7422
				};
7423
				struct.push( src );
7424
			}
7425
	
7426
			if ( i === ien-1 ) {
7427
				src.val = val;
7428
				src.type = typeof val === 'function' ?
7429
					'function' :
7430
					$.isPlainObject( val ) ?
7431
						'object' :
7432
						'other';
7433
			}
7434
			else {
7435
				struct = method ?
7436
					src.methodExt :
7437
					src.propExt;
7438
			}
7439
		}
7440
	};
7441
	
7442
	_Api.registerPlural = _api_registerPlural = function ( pluralName, singularName, val ) {
7443
		_Api.register( pluralName, val );
7444
	
7445
		_Api.register( singularName, function () {
7446
			var ret = val.apply( this, arguments );
7447
	
7448
			if ( ret === this ) {
7449
				// Returned item is the API instance that was passed in, return it
7450
				return this;
7451
			}
7452
			else if ( ret instanceof _Api ) {
7453
				// New API instance returned, want the value from the first item
7454
				// in the returned array for the singular result.
7455
				return ret.length ?
7456
					Array.isArray( ret[0] ) ?
7457
						new _Api( ret.context, ret[0] ) : // Array results are 'enhanced'
7458
						ret[0] :
7459
					undefined;
7460
			}
7461
	
7462
			// Non-API return - just fire it back
7463
			return ret;
7464
		} );
7465
	};
7466
	
7467
	
7468
	/**
7469
	 * Selector for HTML tables. Apply the given selector to the give array of
7470
	 * DataTables settings objects.
7471
	 *
7472
	 * @param {string|integer} [selector] jQuery selector string or integer
7473
	 * @param  {array} Array of DataTables settings objects to be filtered
7474
	 * @return {array}
7475
	 * @ignore
7476
	 */
7477
	var __table_selector = function ( selector, a )
7478
	{
7479
		if ( Array.isArray(selector) ) {
7480
			return $.map( selector, function (item) {
7481
				return __table_selector(item, a);
7482
			} );
7483
		}
7484
	
7485
		// Integer is used to pick out a table by index
7486
		if ( typeof selector === 'number' ) {
7487
			return [ a[ selector ] ];
7488
		}
7489
	
7490
		// Perform a jQuery selector on the table nodes
7491
		var nodes = $.map( a, function (el, i) {
7492
			return el.nTable;
7493
		} );
7494
	
7495
		return $(nodes)
7496
			.filter( selector )
7497
			.map( function (i) {
7498
				// Need to translate back from the table node to the settings
7499
				var idx = $.inArray( this, nodes );
7500
				return a[ idx ];
7501
			} )
7502
			.toArray();
7503
	};
7504
	
7505
	
7506
	
7507
	/**
7508
	 * Context selector for the API's context (i.e. the tables the API instance
7509
	 * refers to.
7510
	 *
7511
	 * @name    DataTable.Api#tables
7512
	 * @param {string|integer} [selector] Selector to pick which tables the iterator
7513
	 *   should operate on. If not given, all tables in the current context are
7514
	 *   used. This can be given as a jQuery selector (for example `':gt(0)'`) to
7515
	 *   select multiple tables or as an integer to select a single table.
7516
	 * @returns {DataTable.Api} Returns a new API instance if a selector is given.
7517
	 */
7518
	_api_register( 'tables()', function ( selector ) {
7519
		// A new instance is created if there was a selector specified
7520
		return selector !== undefined && selector !== null ?
7521
			new _Api( __table_selector( selector, this.context ) ) :
7522
			this;
7523
	} );
7524
	
7525
	
7526
	_api_register( 'table()', function ( selector ) {
7527
		var tables = this.tables( selector );
7528
		var ctx = tables.context;
7529
	
7530
		// Truncate to the first matched table
7531
		return ctx.length ?
7532
			new _Api( ctx[0] ) :
7533
			tables;
7534
	} );
7535
	
7536
	
7537
	_api_registerPlural( 'tables().nodes()', 'table().node()' , function () {
7538
		return this.iterator( 'table', function ( ctx ) {
7539
			return ctx.nTable;
7540
		}, 1 );
7541
	} );
7542
	
7543
	
7544
	_api_registerPlural( 'tables().body()', 'table().body()' , function () {
7545
		return this.iterator( 'table', function ( ctx ) {
7546
			return ctx.nTBody;
7547
		}, 1 );
7548
	} );
7549
	
7550
	
7551
	_api_registerPlural( 'tables().header()', 'table().header()' , function () {
7552
		return this.iterator( 'table', function ( ctx ) {
7553
			return ctx.nTHead;
7554
		}, 1 );
7555
	} );
7556
	
7557
	
7558
	_api_registerPlural( 'tables().footer()', 'table().footer()' , function () {
7559
		return this.iterator( 'table', function ( ctx ) {
7560
			return ctx.nTFoot;
7561
		}, 1 );
7562
	} );
7563
	
7564
	
7565
	_api_registerPlural( 'tables().containers()', 'table().container()' , function () {
7566
		return this.iterator( 'table', function ( ctx ) {
7567
			return ctx.nTableWrapper;
7568
		}, 1 );
7569
	} );
7570
	
7571
	
7572
	
7573
	/**
7574
	 * Redraw the tables in the current context.
7575
	 */
7576
	_api_register( 'draw()', function ( paging ) {
7577
		return this.iterator( 'table', function ( settings ) {
7578
			if ( paging === 'page' ) {
7579
				_fnDraw( settings );
7580
			}
7581
			else {
7582
				if ( typeof paging === 'string' ) {
7583
					paging = paging === 'full-hold' ?
7584
						false :
7585
						true;
7586
				}
7587
	
7588
				_fnReDraw( settings, paging===false );
7589
			}
7590
		} );
7591
	} );
7592
	
7593
	
7594
	
7595
	/**
7596
	 * Get the current page index.
7597
	 *
7598
	 * @return {integer} Current page index (zero based)
7599
	 *//**
7600
	 * Set the current page.
7601
	 *
7602
	 * Note that if you attempt to show a page which does not exist, DataTables will
7603
	 * not throw an error, but rather reset the paging.
7604
	 *
7605
	 * @param {integer|string} action The paging action to take. This can be one of:
7606
	 *  * `integer` - The page index to jump to
7607
	 *  * `string` - An action to take:
7608
	 *    * `first` - Jump to first page.
7609
	 *    * `next` - Jump to the next page
7610
	 *    * `previous` - Jump to previous page
7611
	 *    * `last` - Jump to the last page.
7612
	 * @returns {DataTables.Api} this
7613
	 */
7614
	_api_register( 'page()', function ( action ) {
7615
		if ( action === undefined ) {
7616
			return this.page.info().page; // not an expensive call
7617
		}
7618
	
7619
		// else, have an action to take on all tables
7620
		return this.iterator( 'table', function ( settings ) {
7621
			_fnPageChange( settings, action );
7622
		} );
7623
	} );
7624
	
7625
	
7626
	/**
7627
	 * Paging information for the first table in the current context.
7628
	 *
7629
	 * If you require paging information for another table, use the `table()` method
7630
	 * with a suitable selector.
7631
	 *
7632
	 * @return {object} Object with the following properties set:
7633
	 *  * `page` - Current page index (zero based - i.e. the first page is `0`)
7634
	 *  * `pages` - Total number of pages
7635
	 *  * `start` - Display index for the first record shown on the current page
7636
	 *  * `end` - Display index for the last record shown on the current page
7637
	 *  * `length` - Display length (number of records). Note that generally `start
7638
	 *    + length = end`, but this is not always true, for example if there are
7639
	 *    only 2 records to show on the final page, with a length of 10.
7640
	 *  * `recordsTotal` - Full data set length
7641
	 *  * `recordsDisplay` - Data set length once the current filtering criterion
7642
	 *    are applied.
7643
	 */
7644
	_api_register( 'page.info()', function ( action ) {
7645
		if ( this.context.length === 0 ) {
7646
			return undefined;
7647
		}
7648
	
7649
		var
7650
			settings   = this.context[0],
7651
			start      = settings._iDisplayStart,
7652
			len        = settings.oFeatures.bPaginate ? settings._iDisplayLength : -1,
7653
			visRecords = settings.fnRecordsDisplay(),
7654
			all        = len === -1;
7655
	
7656
		return {
7657
			"page":           all ? 0 : Math.floor( start / len ),
7658
			"pages":          all ? 1 : Math.ceil( visRecords / len ),
7659
			"start":          start,
7660
			"end":            settings.fnDisplayEnd(),
7661
			"length":         len,
7662
			"recordsTotal":   settings.fnRecordsTotal(),
7663
			"recordsDisplay": visRecords,
7664
			"serverSide":     _fnDataSource( settings ) === 'ssp'
7665
		};
7666
	} );
7667
	
7668
	
7669
	/**
7670
	 * Get the current page length.
7671
	 *
7672
	 * @return {integer} Current page length. Note `-1` indicates that all records
7673
	 *   are to be shown.
7674
	 *//**
7675
	 * Set the current page length.
7676
	 *
7677
	 * @param {integer} Page length to set. Use `-1` to show all records.
7678
	 * @returns {DataTables.Api} this
7679
	 */
7680
	_api_register( 'page.len()', function ( len ) {
7681
		// Note that we can't call this function 'length()' because `length`
7682
		// is a Javascript property of functions which defines how many arguments
7683
		// the function expects.
7684
		if ( len === undefined ) {
7685
			return this.context.length !== 0 ?
7686
				this.context[0]._iDisplayLength :
7687
				undefined;
7688
		}
7689
	
7690
		// else, set the page length
7691
		return this.iterator( 'table', function ( settings ) {
7692
			_fnLengthChange( settings, len );
7693
		} );
7694
	} );
7695
	
7696
	
7697
	
7698
	var __reload = function ( settings, holdPosition, callback ) {
7699
		// Use the draw event to trigger a callback
7700
		if ( callback ) {
7701
			var api = new _Api( settings );
7702
	
7703
			api.one( 'draw', function () {
7704
				callback( api.ajax.json() );
7705
			} );
7706
		}
7707
	
7708
		if ( _fnDataSource( settings ) == 'ssp' ) {
7709
			_fnReDraw( settings, holdPosition );
7710
		}
7711
		else {
7712
			_fnProcessingDisplay( settings, true );
7713
	
7714
			// Cancel an existing request
7715
			var xhr = settings.jqXHR;
7716
			if ( xhr && xhr.readyState !== 4 ) {
7717
				xhr.abort();
7718
			}
7719
	
7720
			// Trigger xhr
7721
			_fnBuildAjax( settings, [], function( json ) {
7722
				_fnClearTable( settings );
7723
	
7724
				var data = _fnAjaxDataSrc( settings, json );
7725
				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7726
					_fnAddData( settings, data[i] );
7727
				}
7728
	
7729
				_fnReDraw( settings, holdPosition );
7730
				_fnProcessingDisplay( settings, false );
7731
			} );
7732
		}
7733
	};
7734
	
7735
	
7736
	/**
7737
	 * Get the JSON response from the last Ajax request that DataTables made to the
7738
	 * server. Note that this returns the JSON from the first table in the current
7739
	 * context.
7740
	 *
7741
	 * @return {object} JSON received from the server.
7742
	 */
7743
	_api_register( 'ajax.json()', function () {
7744
		var ctx = this.context;
7745
	
7746
		if ( ctx.length > 0 ) {
7747
			return ctx[0].json;
7748
		}
7749
	
7750
		// else return undefined;
7751
	} );
7752
	
7753
	
7754
	/**
7755
	 * Get the data submitted in the last Ajax request
7756
	 */
7757
	_api_register( 'ajax.params()', function () {
7758
		var ctx = this.context;
7759
	
7760
		if ( ctx.length > 0 ) {
7761
			return ctx[0].oAjaxData;
7762
		}
7763
	
7764
		// else return undefined;
7765
	} );
7766
	
7767
	
7768
	/**
7769
	 * Reload tables from the Ajax data source. Note that this function will
7770
	 * automatically re-draw the table when the remote data has been loaded.
7771
	 *
7772
	 * @param {boolean} [reset=true] Reset (default) or hold the current paging
7773
	 *   position. A full re-sort and re-filter is performed when this method is
7774
	 *   called, which is why the pagination reset is the default action.
7775
	 * @returns {DataTables.Api} this
7776
	 */
7777
	_api_register( 'ajax.reload()', function ( callback, resetPaging ) {
7778
		return this.iterator( 'table', function (settings) {
7779
			__reload( settings, resetPaging===false, callback );
7780
		} );
7781
	} );
7782
	
7783
	
7784
	/**
7785
	 * Get the current Ajax URL. Note that this returns the URL from the first
7786
	 * table in the current context.
7787
	 *
7788
	 * @return {string} Current Ajax source URL
7789
	 *//**
7790
	 * Set the Ajax URL. Note that this will set the URL for all tables in the
7791
	 * current context.
7792
	 *
7793
	 * @param {string} url URL to set.
7794
	 * @returns {DataTables.Api} this
7795
	 */
7796
	_api_register( 'ajax.url()', function ( url ) {
7797
		var ctx = this.context;
7798
	
7799
		if ( url === undefined ) {
7800
			// get
7801
			if ( ctx.length === 0 ) {
7802
				return undefined;
7803
			}
7804
			ctx = ctx[0];
7805
	
7806
			return ctx.ajax ?
7807
				$.isPlainObject( ctx.ajax ) ?
7808
					ctx.ajax.url :
7809
					ctx.ajax :
7810
				ctx.sAjaxSource;
7811
		}
7812
	
7813
		// set
7814
		return this.iterator( 'table', function ( settings ) {
7815
			if ( $.isPlainObject( settings.ajax ) ) {
7816
				settings.ajax.url = url;
7817
			}
7818
			else {
7819
				settings.ajax = url;
7820
			}
7821
			// No need to consider sAjaxSource here since DataTables gives priority
7822
			// to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any
7823
			// value of `sAjaxSource` redundant.
7824
		} );
7825
	} );
7826
	
7827
	
7828
	/**
7829
	 * Load data from the newly set Ajax URL. Note that this method is only
7830
	 * available when `ajax.url()` is used to set a URL. Additionally, this method
7831
	 * has the same effect as calling `ajax.reload()` but is provided for
7832
	 * convenience when setting a new URL. Like `ajax.reload()` it will
7833
	 * automatically redraw the table once the remote data has been loaded.
7834
	 *
7835
	 * @returns {DataTables.Api} this
7836
	 */
7837
	_api_register( 'ajax.url().load()', function ( callback, resetPaging ) {
7838
		// Same as a reload, but makes sense to present it for easy access after a
7839
		// url change
7840
		return this.iterator( 'table', function ( ctx ) {
7841
			__reload( ctx, resetPaging===false, callback );
7842
		} );
7843
	} );
7844
	
7845
	
7846
	
7847
	
7848
	var _selector_run = function ( type, selector, selectFn, settings, opts )
7849
	{
7850
		var
7851
			out = [], res,
7852
			a, i, ien, j, jen,
7853
			selectorType = typeof selector;
7854
	
7855
		// Can't just check for isArray here, as an API or jQuery instance might be
7856
		// given with their array like look
7857
		if ( ! selector || selectorType === 'string' || selectorType === 'function' || selector.length === undefined ) {
7858
			selector = [ selector ];
7859
		}
7860
	
7861
		for ( i=0, ien=selector.length ; i<ien ; i++ ) {
7862
			// Only split on simple strings - complex expressions will be jQuery selectors
7863
			a = selector[i] && selector[i].split && ! selector[i].match(/[\[\(:]/) ?
7864
				selector[i].split(',') :
7865
				[ selector[i] ];
7866
	
7867
			for ( j=0, jen=a.length ; j<jen ; j++ ) {
7868
				res = selectFn( typeof a[j] === 'string' ? (a[j]).trim() : a[j] );
7869
	
7870
				if ( res && res.length ) {
7871
					out = out.concat( res );
7872
				}
7873
			}
7874
		}
7875
	
7876
		// selector extensions
7877
		var ext = _ext.selector[ type ];
7878
		if ( ext.length ) {
7879
			for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7880
				out = ext[i]( settings, opts, out );
7881
			}
7882
		}
7883
	
7884
		return _unique( out );
7885
	};
7886
	
7887
	
7888
	var _selector_opts = function ( opts )
7889
	{
7890
		if ( ! opts ) {
7891
			opts = {};
7892
		}
7893
	
7894
		// Backwards compatibility for 1.9- which used the terminology filter rather
7895
		// than search
7896
		if ( opts.filter && opts.search === undefined ) {
7897
			opts.search = opts.filter;
7898
		}
7899
	
7900
		return $.extend( {
7901
			search: 'none',
7902
			order: 'current',
7903
			page: 'all'
7904
		}, opts );
7905
	};
7906
	
7907
	
7908
	var _selector_first = function ( inst )
7909
	{
7910
		// Reduce the API instance to the first item found
7911
		for ( var i=0, ien=inst.length ; i<ien ; i++ ) {
7912
			if ( inst[i].length > 0 ) {
7913
				// Assign the first element to the first item in the instance
7914
				// and truncate the instance and context
7915
				inst[0] = inst[i];
7916
				inst[0].length = 1;
7917
				inst.length = 1;
7918
				inst.context = [ inst.context[i] ];
7919
	
7920
				return inst;
7921
			}
7922
		}
7923
	
7924
		// Not found - return an empty instance
7925
		inst.length = 0;
7926
		return inst;
7927
	};
7928
	
7929
	
7930
	var _selector_row_indexes = function ( settings, opts )
7931
	{
7932
		var
7933
			i, ien, tmp, a=[],
7934
			displayFiltered = settings.aiDisplay,
7935
			displayMaster = settings.aiDisplayMaster;
7936
	
7937
		var
7938
			search = opts.search,  // none, applied, removed
7939
			order  = opts.order,   // applied, current, index (original - compatibility with 1.9)
7940
			page   = opts.page;    // all, current
7941
	
7942
		if ( _fnDataSource( settings ) == 'ssp' ) {
7943
			// In server-side processing mode, most options are irrelevant since
7944
			// rows not shown don't exist and the index order is the applied order
7945
			// Removed is a special case - for consistency just return an empty
7946
			// array
7947
			return search === 'removed' ?
7948
				[] :
7949
				_range( 0, displayMaster.length );
7950
		}
7951
		else if ( page == 'current' ) {
7952
			// Current page implies that order=current and filter=applied, since it is
7953
			// fairly senseless otherwise, regardless of what order and search actually
7954
			// are
7955
			for ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i<ien ; i++ ) {
7956
				a.push( displayFiltered[i] );
7957
			}
7958
		}
7959
		else if ( order == 'current' || order == 'applied' ) {
7960
			if ( search == 'none') {
7961
				a = displayMaster.slice();
7962
			}
7963
			else if ( search == 'applied' ) {
7964
				a = displayFiltered.slice();
7965
			}
7966
			else if ( search == 'removed' ) {
7967
				// O(n+m) solution by creating a hash map
7968
				var displayFilteredMap = {};
7969
	
7970
				for ( var i=0, ien=displayFiltered.length ; i<ien ; i++ ) {
7971
					displayFilteredMap[displayFiltered[i]] = null;
7972
				}
7973
	
7974
				a = $.map( displayMaster, function (el) {
7975
					return ! displayFilteredMap.hasOwnProperty(el) ?
7976
						el :
7977
						null;
7978
				} );
7979
			}
7980
		}
7981
		else if ( order == 'index' || order == 'original' ) {
7982
			for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
7983
				if ( search == 'none' ) {
7984
					a.push( i );
7985
				}
7986
				else { // applied | removed
7987
					tmp = $.inArray( i, displayFiltered );
7988
	
7989
					if ((tmp === -1 && search == 'removed') ||
7990
						(tmp >= 0   && search == 'applied') )
7991
					{
7992
						a.push( i );
7993
					}
7994
				}
7995
			}
7996
		}
7997
	
7998
		return a;
7999
	};
8000
	
8001
	
8002
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
8003
	 * Rows
8004
	 *
8005
	 * {}          - no selector - use all available rows
8006
	 * {integer}   - row aoData index
8007
	 * {node}      - TR node
8008
	 * {string}    - jQuery selector to apply to the TR elements
8009
	 * {array}     - jQuery array of nodes, or simply an array of TR nodes
8010
	 *
8011
	 */
8012
	var __row_selector = function ( settings, selector, opts )
8013
	{
8014
		var rows;
8015
		var run = function ( sel ) {
8016
			var selInt = _intVal( sel );
8017
			var i, ien;
8018
			var aoData = settings.aoData;
8019
	
8020
			// Short cut - selector is a number and no options provided (default is
8021
			// all records, so no need to check if the index is in there, since it
8022
			// must be - dev error if the index doesn't exist).
8023
			if ( selInt !== null && ! opts ) {
8024
				return [ selInt ];
8025
			}
8026
	
8027
			if ( ! rows ) {
8028
				rows = _selector_row_indexes( settings, opts );
8029
			}
8030
	
8031
			if ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) {
8032
				// Selector - integer
8033
				return [ selInt ];
8034
			}
8035
			else if ( sel === null || sel === undefined || sel === '' ) {
8036
				// Selector - none
8037
				return rows;
8038
			}
8039
	
8040
			// Selector - function
8041
			if ( typeof sel === 'function' ) {
8042
				return $.map( rows, function (idx) {
8043
					var row = aoData[ idx ];
8044
					return sel( idx, row._aData, row.nTr ) ? idx : null;
8045
				} );
8046
			}
8047
	
8048
			// Selector - node
8049
			if ( sel.nodeName ) {
8050
				var rowIdx = sel._DT_RowIndex;  // Property added by DT for fast lookup
8051
				var cellIdx = sel._DT_CellIndex;
8052
	
8053
				if ( rowIdx !== undefined ) {
8054
					// Make sure that the row is actually still present in the table
8055
					return aoData[ rowIdx ] && aoData[ rowIdx ].nTr === sel ?
8056
						[ rowIdx ] :
8057
						[];
8058
				}
8059
				else if ( cellIdx ) {
8060
					return aoData[ cellIdx.row ] && aoData[ cellIdx.row ].nTr === sel.parentNode ?
8061
						[ cellIdx.row ] :
8062
						[];
8063
				}
8064
				else {
8065
					var host = $(sel).closest('*[data-dt-row]');
8066
					return host.length ?
8067
						[ host.data('dt-row') ] :
8068
						[];
8069
				}
8070
			}
8071
	
8072
			// ID selector. Want to always be able to select rows by id, regardless
8073
			// of if the tr element has been created or not, so can't rely upon
8074
			// jQuery here - hence a custom implementation. This does not match
8075
			// Sizzle's fast selector or HTML4 - in HTML5 the ID can be anything,
8076
			// but to select it using a CSS selector engine (like Sizzle or
8077
			// querySelect) it would need to need to be escaped for some characters.
8078
			// DataTables simplifies this for row selectors since you can select
8079
			// only a row. A # indicates an id any anything that follows is the id -
8080
			// unescaped.
8081
			if ( typeof sel === 'string' && sel.charAt(0) === '#' ) {
8082
				// get row index from id
8083
				var rowObj = settings.aIds[ sel.replace( /^#/, '' ) ];
8084
				if ( rowObj !== undefined ) {
8085
					return [ rowObj.idx ];
8086
				}
8087
	
8088
				// need to fall through to jQuery in case there is DOM id that
8089
				// matches
8090
			}
8091
			
8092
			// Get nodes in the order from the `rows` array with null values removed
8093
			var nodes = _removeEmpty(
8094
				_pluck_order( settings.aoData, rows, 'nTr' )
8095
			);
8096
	
8097
			// Selector - jQuery selector string, array of nodes or jQuery object/
8098
			// As jQuery's .filter() allows jQuery objects to be passed in filter,
8099
			// it also allows arrays, so this will cope with all three options
8100
			return $(nodes)
8101
				.filter( sel )
8102
				.map( function () {
8103
					return this._DT_RowIndex;
8104
				} )
8105
				.toArray();
8106
		};
8107
	
8108
		return _selector_run( 'row', selector, run, settings, opts );
8109
	};
8110
	
8111
	
8112
	_api_register( 'rows()', function ( selector, opts ) {
8113
		// argument shifting
8114
		if ( selector === undefined ) {
8115
			selector = '';
8116
		}
8117
		else if ( $.isPlainObject( selector ) ) {
8118
			opts = selector;
8119
			selector = '';
8120
		}
8121
	
8122
		opts = _selector_opts( opts );
8123
	
8124
		var inst = this.iterator( 'table', function ( settings ) {
8125
			return __row_selector( settings, selector, opts );
8126
		}, 1 );
8127
	
8128
		// Want argument shifting here and in __row_selector?
8129
		inst.selector.rows = selector;
8130
		inst.selector.opts = opts;
8131
	
8132
		return inst;
8133
	} );
8134
	
8135
	_api_register( 'rows().nodes()', function () {
8136
		return this.iterator( 'row', function ( settings, row ) {
8137
			return settings.aoData[ row ].nTr || undefined;
8138
		}, 1 );
8139
	} );
8140
	
8141
	_api_register( 'rows().data()', function () {
8142
		return this.iterator( true, 'rows', function ( settings, rows ) {
8143
			return _pluck_order( settings.aoData, rows, '_aData' );
8144
		}, 1 );
8145
	} );
8146
	
8147
	_api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) {
8148
		return this.iterator( 'row', function ( settings, row ) {
8149
			var r = settings.aoData[ row ];
8150
			return type === 'search' ? r._aFilterData : r._aSortData;
8151
		}, 1 );
8152
	} );
8153
	
8154
	_api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) {
8155
		return this.iterator( 'row', function ( settings, row ) {
8156
			_fnInvalidate( settings, row, src );
8157
		} );
8158
	} );
8159
	
8160
	_api_registerPlural( 'rows().indexes()', 'row().index()', function () {
8161
		return this.iterator( 'row', function ( settings, row ) {
8162
			return row;
8163
		}, 1 );
8164
	} );
8165
	
8166
	_api_registerPlural( 'rows().ids()', 'row().id()', function ( hash ) {
8167
		var a = [];
8168
		var context = this.context;
8169
	
8170
		// `iterator` will drop undefined values, but in this case we want them
8171
		for ( var i=0, ien=context.length ; i<ien ; i++ ) {
8172
			for ( var j=0, jen=this[i].length ; j<jen ; j++ ) {
8173
				var id = context[i].rowIdFn( context[i].aoData[ this[i][j] ]._aData );
8174
				a.push( (hash === true ? '#' : '' )+ id );
8175
			}
8176
		}
8177
	
8178
		return new _Api( context, a );
8179
	} );
8180
	
8181
	_api_registerPlural( 'rows().remove()', 'row().remove()', function () {
8182
		var that = this;
8183
	
8184
		this.iterator( 'row', function ( settings, row, thatIdx ) {
8185
			var data = settings.aoData;
8186
			var rowData = data[ row ];
8187
			var i, ien, j, jen;
8188
			var loopRow, loopCells;
8189
	
8190
			data.splice( row, 1 );
8191
	
8192
			// Update the cached indexes
8193
			for ( i=0, ien=data.length ; i<ien ; i++ ) {
8194
				loopRow = data[i];
8195
				loopCells = loopRow.anCells;
8196
	
8197
				// Rows
8198
				if ( loopRow.nTr !== null ) {
8199
					loopRow.nTr._DT_RowIndex = i;
8200
				}
8201
	
8202
				// Cells
8203
				if ( loopCells !== null ) {
8204
					for ( j=0, jen=loopCells.length ; j<jen ; j++ ) {
8205
						loopCells[j]._DT_CellIndex.row = i;
8206
					}
8207
				}
8208
			}
8209
	
8210
			// Delete from the display arrays
8211
			_fnDeleteIndex( settings.aiDisplayMaster, row );
8212
			_fnDeleteIndex( settings.aiDisplay, row );
8213
			_fnDeleteIndex( that[ thatIdx ], row, false ); // maintain local indexes
8214
	
8215
			// For server-side processing tables - subtract the deleted row from the count
8216
			if ( settings._iRecordsDisplay > 0 ) {
8217
				settings._iRecordsDisplay--;
8218
			}
8219
	
8220
			// Check for an 'overflow' they case for displaying the table
8221
			_fnLengthOverflow( settings );
8222
	
8223
			// Remove the row's ID reference if there is one
8224
			var id = settings.rowIdFn( rowData._aData );
8225
			if ( id !== undefined ) {
8226
				delete settings.aIds[ id ];
8227
			}
8228
		} );
8229
	
8230
		this.iterator( 'table', function ( settings ) {
8231
			for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
8232
				settings.aoData[i].idx = i;
8233
			}
8234
		} );
8235
	
8236
		return this;
8237
	} );
8238
	
8239
	
8240
	_api_register( 'rows.add()', function ( rows ) {
8241
		var newRows = this.iterator( 'table', function ( settings ) {
8242
				var row, i, ien;
8243
				var out = [];
8244
	
8245
				for ( i=0, ien=rows.length ; i<ien ; i++ ) {
8246
					row = rows[i];
8247
	
8248
					if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
8249
						out.push( _fnAddTr( settings, row )[0] );
8250
					}
8251
					else {
8252
						out.push( _fnAddData( settings, row ) );
8253
					}
8254
				}
8255
	
8256
				return out;
8257
			}, 1 );
8258
	
8259
		// Return an Api.rows() extended instance, so rows().nodes() etc can be used
8260
		var modRows = this.rows( -1 );
8261
		modRows.pop();
8262
		$.merge( modRows, newRows );
8263
	
8264
		return modRows;
8265
	} );
8266
	
8267
	
8268
	
8269
	
8270
	
8271
	/**
8272
	 *
8273
	 */
8274
	_api_register( 'row()', function ( selector, opts ) {
8275
		return _selector_first( this.rows( selector, opts ) );
8276
	} );
8277
	
8278
	
8279
	_api_register( 'row().data()', function ( data ) {
8280
		var ctx = this.context;
8281
	
8282
		if ( data === undefined ) {
8283
			// Get
8284
			return ctx.length && this.length ?
8285
				ctx[0].aoData[ this[0] ]._aData :
8286
				undefined;
8287
		}
8288
	
8289
		// Set
8290
		var row = ctx[0].aoData[ this[0] ];
8291
		row._aData = data;
8292
	
8293
		// If the DOM has an id, and the data source is an array
8294
		if ( Array.isArray( data ) && row.nTr && row.nTr.id ) {
8295
			_fnSetObjectDataFn( ctx[0].rowId )( data, row.nTr.id );
8296
		}
8297
	
8298
		// Automatically invalidate
8299
		_fnInvalidate( ctx[0], this[0], 'data' );
8300
	
8301
		return this;
8302
	} );
8303
	
8304
	
8305
	_api_register( 'row().node()', function () {
8306
		var ctx = this.context;
8307
	
8308
		return ctx.length && this.length ?
8309
			ctx[0].aoData[ this[0] ].nTr || null :
8310
			null;
8311
	} );
8312
	
8313
	
8314
	_api_register( 'row.add()', function ( row ) {
8315
		// Allow a jQuery object to be passed in - only a single row is added from
8316
		// it though - the first element in the set
8317
		if ( row instanceof $ && row.length ) {
8318
			row = row[0];
8319
		}
8320
	
8321
		var rows = this.iterator( 'table', function ( settings ) {
8322
			if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
8323
				return _fnAddTr( settings, row )[0];
8324
			}
8325
			return _fnAddData( settings, row );
8326
		} );
8327
	
8328
		// Return an Api.rows() extended instance, with the newly added row selected
8329
		return this.row( rows[0] );
8330
	} );
8331
	
8332
	
8333
	$(document).on('plugin-init.dt', function (e, context) {
8334
		var api = new _Api( context );
8335
		api.on( 'stateSaveParams', function ( e, settings, data ) {
8336
			var indexes = api.rows().iterator( 'row', function ( settings, idx ) {
8337
				return settings.aoData[idx]._detailsShow ? idx : undefined;
8338
			});
8339
	
8340
			data.childRows = api.rows( indexes ).ids( true ).toArray();
8341
		})
8342
	
8343
		var loaded = api.state.loaded();
8344
	
8345
		if ( loaded && loaded.childRows ) {
8346
			api.rows( loaded.childRows ).every( function () {
8347
				_fnCallbackFire( context, null, 'requestChild', [ this ] )
8348
			})
8349
		}
8350
	})
8351
	
8352
	var __details_add = function ( ctx, row, data, klass )
8353
	{
8354
		// Convert to array of TR elements
8355
		var rows = [];
8356
		var addRow = function ( r, k ) {
8357
			// Recursion to allow for arrays of jQuery objects
8358
			if ( Array.isArray( r ) || r instanceof $ ) {
8359
				for ( var i=0, ien=r.length ; i<ien ; i++ ) {
8360
					addRow( r[i], k );
8361
				}
8362
				return;
8363
			}
8364
	
8365
			// If we get a TR element, then just add it directly - up to the dev
8366
			// to add the correct number of columns etc
8367
			if ( r.nodeName && r.nodeName.toLowerCase() === 'tr' ) {
8368
				rows.push( r );
8369
			}
8370
			else {
8371
				// Otherwise create a row with a wrapper
8372
				var created = $('<tr><td></td></tr>').addClass( k );
8373
				$('td', created)
8374
					.addClass( k )
8375
					.html( r )
8376
					[0].colSpan = _fnVisbleColumns( ctx );
8377
	
8378
				rows.push( created[0] );
8379
			}
8380
		};
8381
	
8382
		addRow( data, klass );
8383
	
8384
		if ( row._details ) {
8385
			row._details.detach();
8386
		}
8387
	
8388
		row._details = $(rows);
8389
	
8390
		// If the children were already shown, that state should be retained
8391
		if ( row._detailsShow ) {
8392
			row._details.insertAfter( row.nTr );
8393
		}
8394
	};
8395
	
8396
	
8397
	var __details_remove = function ( api, idx )
8398
	{
8399
		var ctx = api.context;
8400
	
8401
		if ( ctx.length ) {
8402
			var row = ctx[0].aoData[ idx !== undefined ? idx : api[0] ];
8403
	
8404
			if ( row && row._details ) {
8405
				row._details.remove();
8406
	
8407
				row._detailsShow = undefined;
8408
				row._details = undefined;
8409
				$( row.nTr ).removeClass( 'dt-hasChild' );
8410
				_fnSaveState( ctx[0] );
8411
			}
8412
		}
8413
	};
8414
	
8415
	
8416
	var __details_display = function ( api, show ) {
8417
		var ctx = api.context;
8418
	
8419
		if ( ctx.length && api.length ) {
8420
			var row = ctx[0].aoData[ api[0] ];
8421
	
8422
			if ( row._details ) {
8423
				row._detailsShow = show;
8424
	
8425
				if ( show ) {
8426
					row._details.insertAfter( row.nTr );
8427
					$( row.nTr ).addClass( 'dt-hasChild' );
8428
				}
8429
				else {
8430
					row._details.detach();
8431
					$( row.nTr ).removeClass( 'dt-hasChild' );
8432
				}
8433
	
8434
				_fnCallbackFire( ctx[0], null, 'childRow', [ show, api.row( api[0] ) ] )
8435
	
8436
				__details_events( ctx[0] );
8437
				_fnSaveState( ctx[0] );
8438
			}
8439
		}
8440
	};
8441
	
8442
	
8443
	var __details_events = function ( settings )
8444
	{
8445
		var api = new _Api( settings );
8446
		var namespace = '.dt.DT_details';
8447
		var drawEvent = 'draw'+namespace;
8448
		var colvisEvent = 'column-visibility'+namespace;
8449
		var destroyEvent = 'destroy'+namespace;
8450
		var data = settings.aoData;
8451
	
8452
		api.off( drawEvent +' '+ colvisEvent +' '+ destroyEvent );
8453
	
8454
		if ( _pluck( data, '_details' ).length > 0 ) {
8455
			// On each draw, insert the required elements into the document
8456
			api.on( drawEvent, function ( e, ctx ) {
8457
				if ( settings !== ctx ) {
8458
					return;
8459
				}
8460
	
8461
				api.rows( {page:'current'} ).eq(0).each( function (idx) {
8462
					// Internal data grab
8463
					var row = data[ idx ];
8464
	
8465
					if ( row._detailsShow ) {
8466
						row._details.insertAfter( row.nTr );
8467
					}
8468
				} );
8469
			} );
8470
	
8471
			// Column visibility change - update the colspan
8472
			api.on( colvisEvent, function ( e, ctx, idx, vis ) {
8473
				if ( settings !== ctx ) {
8474
					return;
8475
				}
8476
	
8477
				// Update the colspan for the details rows (note, only if it already has
8478
				// a colspan)
8479
				var row, visible = _fnVisbleColumns( ctx );
8480
	
8481
				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
8482
					row = data[i];
8483
	
8484
					if ( row._details ) {
8485
						row._details.children('td[colspan]').attr('colspan', visible );
8486
					}
8487
				}
8488
			} );
8489
	
8490
			// Table destroyed - nuke any child rows
8491
			api.on( destroyEvent, function ( e, ctx ) {
8492
				if ( settings !== ctx ) {
8493
					return;
8494
				}
8495
	
8496
				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
8497
					if ( data[i]._details ) {
8498
						__details_remove( api, i );
8499
					}
8500
				}
8501
			} );
8502
		}
8503
	};
8504
	
8505
	// Strings for the method names to help minification
8506
	var _emp = '';
8507
	var _child_obj = _emp+'row().child';
8508
	var _child_mth = _child_obj+'()';
8509
	
8510
	// data can be:
8511
	//  tr
8512
	//  string
8513
	//  jQuery or array of any of the above
8514
	_api_register( _child_mth, function ( data, klass ) {
8515
		var ctx = this.context;
8516
	
8517
		if ( data === undefined ) {
8518
			// get
8519
			return ctx.length && this.length ?
8520
				ctx[0].aoData[ this[0] ]._details :
8521
				undefined;
8522
		}
8523
		else if ( data === true ) {
8524
			// show
8525
			this.child.show();
8526
		}
8527
		else if ( data === false ) {
8528
			// remove
8529
			__details_remove( this );
8530
		}
8531
		else if ( ctx.length && this.length ) {
8532
			// set
8533
			__details_add( ctx[0], ctx[0].aoData[ this[0] ], data, klass );
8534
		}
8535
	
8536
		return this;
8537
	} );
8538
	
8539
	
8540
	_api_register( [
8541
		_child_obj+'.show()',
8542
		_child_mth+'.show()' // only when `child()` was called with parameters (without
8543
	], function ( show ) {   // it returns an object and this method is not executed)
8544
		__details_display( this, true );
8545
		return this;
8546
	} );
8547
	
8548
	
8549
	_api_register( [
8550
		_child_obj+'.hide()',
8551
		_child_mth+'.hide()' // only when `child()` was called with parameters (without
8552
	], function () {         // it returns an object and this method is not executed)
8553
		__details_display( this, false );
8554
		return this;
8555
	} );
8556
	
8557
	
8558
	_api_register( [
8559
		_child_obj+'.remove()',
8560
		_child_mth+'.remove()' // only when `child()` was called with parameters (without
8561
	], function () {           // it returns an object and this method is not executed)
8562
		__details_remove( this );
8563
		return this;
8564
	} );
8565
	
8566
	
8567
	_api_register( _child_obj+'.isShown()', function () {
8568
		var ctx = this.context;
8569
	
8570
		if ( ctx.length && this.length ) {
8571
			// _detailsShown as false or undefined will fall through to return false
8572
			return ctx[0].aoData[ this[0] ]._detailsShow || false;
8573
		}
8574
		return false;
8575
	} );
8576
	
8577
	
8578
	
8579
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
8580
	 * Columns
8581
	 *
8582
	 * {integer}           - column index (>=0 count from left, <0 count from right)
8583
	 * "{integer}:visIdx"  - visible column index (i.e. translate to column index)  (>=0 count from left, <0 count from right)
8584
	 * "{integer}:visible" - alias for {integer}:visIdx  (>=0 count from left, <0 count from right)
8585
	 * "{string}:name"     - column name
8586
	 * "{string}"          - jQuery selector on column header nodes
8587
	 *
8588
	 */
8589
	
8590
	// can be an array of these items, comma separated list, or an array of comma
8591
	// separated lists
8592
	
8593
	var __re_column_selector = /^([^:]+):(name|visIdx|visible)$/;
8594
	
8595
	
8596
	// r1 and r2 are redundant - but it means that the parameters match for the
8597
	// iterator callback in columns().data()
8598
	var __columnData = function ( settings, column, r1, r2, rows ) {
8599
		var a = [];
8600
		for ( var row=0, ien=rows.length ; row<ien ; row++ ) {
8601
			a.push( _fnGetCellData( settings, rows[row], column ) );
8602
		}
8603
		return a;
8604
	};
8605
	
8606
	
8607
	var __column_selector = function ( settings, selector, opts )
8608
	{
8609
		var
8610
			columns = settings.aoColumns,
8611
			names = _pluck( columns, 'sName' ),
8612
			nodes = _pluck( columns, 'nTh' );
8613
	
8614
		var run = function ( s ) {
8615
			var selInt = _intVal( s );
8616
	
8617
			// Selector - all
8618
			if ( s === '' ) {
8619
				return _range( columns.length );
8620
			}
8621
	
8622
			// Selector - index
8623
			if ( selInt !== null ) {
8624
				return [ selInt >= 0 ?
8625
					selInt : // Count from left
8626
					columns.length + selInt // Count from right (+ because its a negative value)
8627
				];
8628
			}
8629
	
8630
			// Selector = function
8631
			if ( typeof s === 'function' ) {
8632
				var rows = _selector_row_indexes( settings, opts );
8633
	
8634
				return $.map( columns, function (col, idx) {
8635
					return s(
8636
							idx,
8637
							__columnData( settings, idx, 0, 0, rows ),
8638
							nodes[ idx ]
8639
						) ? idx : null;
8640
				} );
8641
			}
8642
	
8643
			// jQuery or string selector
8644
			var match = typeof s === 'string' ?
8645
				s.match( __re_column_selector ) :
8646
				'';
8647
	
8648
			if ( match ) {
8649
				switch( match[2] ) {
8650
					case 'visIdx':
8651
					case 'visible':
8652
						var idx = parseInt( match[1], 10 );
8653
						// Visible index given, convert to column index
8654
						if ( idx < 0 ) {
8655
							// Counting from the right
8656
							var visColumns = $.map( columns, function (col,i) {
8657
								return col.bVisible ? i : null;
8658
							} );
8659
							return [ visColumns[ visColumns.length + idx ] ];
8660
						}
8661
						// Counting from the left
8662
						return [ _fnVisibleToColumnIndex( settings, idx ) ];
8663
	
8664
					case 'name':
8665
						// match by name. `names` is column index complete and in order
8666
						return $.map( names, function (name, i) {
8667
							return name === match[1] ? i : null;
8668
						} );
8669
	
8670
					default:
8671
						return [];
8672
				}
8673
			}
8674
	
8675
			// Cell in the table body
8676
			if ( s.nodeName && s._DT_CellIndex ) {
8677
				return [ s._DT_CellIndex.column ];
8678
			}
8679
	
8680
			// jQuery selector on the TH elements for the columns
8681
			var jqResult = $( nodes )
8682
				.filter( s )
8683
				.map( function () {
8684
					return $.inArray( this, nodes ); // `nodes` is column index complete and in order
8685
				} )
8686
				.toArray();
8687
	
8688
			if ( jqResult.length || ! s.nodeName ) {
8689
				return jqResult;
8690
			}
8691
	
8692
			// Otherwise a node which might have a `dt-column` data attribute, or be
8693
			// a child or such an element
8694
			var host = $(s).closest('*[data-dt-column]');
8695
			return host.length ?
8696
				[ host.data('dt-column') ] :
8697
				[];
8698
		};
8699
	
8700
		return _selector_run( 'column', selector, run, settings, opts );
8701
	};
8702
	
8703
	
8704
	var __setColumnVis = function ( settings, column, vis ) {
8705
		var
8706
			cols = settings.aoColumns,
8707
			col  = cols[ column ],
8708
			data = settings.aoData,
8709
			row, cells, i, ien, tr;
8710
	
8711
		// Get
8712
		if ( vis === undefined ) {
8713
			return col.bVisible;
8714
		}
8715
	
8716
		// Set
8717
		// No change
8718
		if ( col.bVisible === vis ) {
8719
			return;
8720
		}
8721
	
8722
		if ( vis ) {
8723
			// Insert column
8724
			// Need to decide if we should use appendChild or insertBefore
8725
			var insertBefore = $.inArray( true, _pluck(cols, 'bVisible'), column+1 );
8726
	
8727
			for ( i=0, ien=data.length ; i<ien ; i++ ) {
8728
				tr = data[i].nTr;
8729
				cells = data[i].anCells;
8730
	
8731
				if ( tr ) {
8732
					// insertBefore can act like appendChild if 2nd arg is null
8733
					tr.insertBefore( cells[ column ], cells[ insertBefore ] || null );
8734
				}
8735
			}
8736
		}
8737
		else {
8738
			// Remove column
8739
			$( _pluck( settings.aoData, 'anCells', column ) ).detach();
8740
		}
8741
	
8742
		// Common actions
8743
		col.bVisible = vis;
8744
	};
8745
	
8746
	
8747
	_api_register( 'columns()', function ( selector, opts ) {
8748
		// argument shifting
8749
		if ( selector === undefined ) {
8750
			selector = '';
8751
		}
8752
		else if ( $.isPlainObject( selector ) ) {
8753
			opts = selector;
8754
			selector = '';
8755
		}
8756
	
8757
		opts = _selector_opts( opts );
8758
	
8759
		var inst = this.iterator( 'table', function ( settings ) {
8760
			return __column_selector( settings, selector, opts );
8761
		}, 1 );
8762
	
8763
		// Want argument shifting here and in _row_selector?
8764
		inst.selector.cols = selector;
8765
		inst.selector.opts = opts;
8766
	
8767
		return inst;
8768
	} );
8769
	
8770
	_api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) {
8771
		return this.iterator( 'column', function ( settings, column ) {
8772
			return settings.aoColumns[column].nTh;
8773
		}, 1 );
8774
	} );
8775
	
8776
	_api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) {
8777
		return this.iterator( 'column', function ( settings, column ) {
8778
			return settings.aoColumns[column].nTf;
8779
		}, 1 );
8780
	} );
8781
	
8782
	_api_registerPlural( 'columns().data()', 'column().data()', function () {
8783
		return this.iterator( 'column-rows', __columnData, 1 );
8784
	} );
8785
	
8786
	_api_registerPlural( 'columns().dataSrc()', 'column().dataSrc()', function () {
8787
		return this.iterator( 'column', function ( settings, column ) {
8788
			return settings.aoColumns[column].mData;
8789
		}, 1 );
8790
	} );
8791
	
8792
	_api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) {
8793
		return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8794
			return _pluck_order( settings.aoData, rows,
8795
				type === 'search' ? '_aFilterData' : '_aSortData', column
8796
			);
8797
		}, 1 );
8798
	} );
8799
	
8800
	_api_registerPlural( 'columns().nodes()', 'column().nodes()', function () {
8801
		return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8802
			return _pluck_order( settings.aoData, rows, 'anCells', column ) ;
8803
		}, 1 );
8804
	} );
8805
	
8806
	_api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis, calc ) {
8807
		var that = this;
8808
		var ret = this.iterator( 'column', function ( settings, column ) {
8809
			if ( vis === undefined ) {
8810
				return settings.aoColumns[ column ].bVisible;
8811
			} // else
8812
			__setColumnVis( settings, column, vis );
8813
		} );
8814
	
8815
		// Group the column visibility changes
8816
		if ( vis !== undefined ) {
8817
			this.iterator( 'table', function ( settings ) {
8818
				// Redraw the header after changes
8819
				_fnDrawHead( settings, settings.aoHeader );
8820
				_fnDrawHead( settings, settings.aoFooter );
8821
		
8822
				// Update colspan for no records display. Child rows and extensions will use their own
8823
				// listeners to do this - only need to update the empty table item here
8824
				if ( ! settings.aiDisplay.length ) {
8825
					$(settings.nTBody).find('td[colspan]').attr('colspan', _fnVisbleColumns(settings));
8826
				}
8827
		
8828
				_fnSaveState( settings );
8829
	
8830
				// Second loop once the first is done for events
8831
				that.iterator( 'column', function ( settings, column ) {
8832
					_fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis, calc] );
8833
				} );
8834
	
8835
				if ( calc === undefined || calc ) {
8836
					that.columns.adjust();
8837
				}
8838
			});
8839
		}
8840
	
8841
		return ret;
8842
	} );
8843
	
8844
	_api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) {
8845
		return this.iterator( 'column', function ( settings, column ) {
8846
			return type === 'visible' ?
8847
				_fnColumnIndexToVisible( settings, column ) :
8848
				column;
8849
		}, 1 );
8850
	} );
8851
	
8852
	_api_register( 'columns.adjust()', function () {
8853
		return this.iterator( 'table', function ( settings ) {
8854
			_fnAdjustColumnSizing( settings );
8855
		}, 1 );
8856
	} );
8857
	
8858
	_api_register( 'column.index()', function ( type, idx ) {
8859
		if ( this.context.length !== 0 ) {
8860
			var ctx = this.context[0];
8861
	
8862
			if ( type === 'fromVisible' || type === 'toData' ) {
8863
				return _fnVisibleToColumnIndex( ctx, idx );
8864
			}
8865
			else if ( type === 'fromData' || type === 'toVisible' ) {
8866
				return _fnColumnIndexToVisible( ctx, idx );
8867
			}
8868
		}
8869
	} );
8870
	
8871
	_api_register( 'column()', function ( selector, opts ) {
8872
		return _selector_first( this.columns( selector, opts ) );
8873
	} );
8874
	
8875
	var __cell_selector = function ( settings, selector, opts )
8876
	{
8877
		var data = settings.aoData;
8878
		var rows = _selector_row_indexes( settings, opts );
8879
		var cells = _removeEmpty( _pluck_order( data, rows, 'anCells' ) );
8880
		var allCells = $(_flatten( [], cells ));
8881
		var row;
8882
		var columns = settings.aoColumns.length;
8883
		var a, i, ien, j, o, host;
8884
	
8885
		var run = function ( s ) {
8886
			var fnSelector = typeof s === 'function';
8887
	
8888
			if ( s === null || s === undefined || fnSelector ) {
8889
				// All cells and function selectors
8890
				a = [];
8891
	
8892
				for ( i=0, ien=rows.length ; i<ien ; i++ ) {
8893
					row = rows[i];
8894
	
8895
					for ( j=0 ; j<columns ; j++ ) {
8896
						o = {
8897
							row: row,
8898
							column: j
8899
						};
8900
	
8901
						if ( fnSelector ) {
8902
							// Selector - function
8903
							host = data[ row ];
8904
	
8905
							if ( s( o, _fnGetCellData(settings, row, j), host.anCells ? host.anCells[j] : null ) ) {
8906
								a.push( o );
8907
							}
8908
						}
8909
						else {
8910
							// Selector - all
8911
							a.push( o );
8912
						}
8913
					}
8914
				}
8915
	
8916
				return a;
8917
			}
8918
			
8919
			// Selector - index
8920
			if ( $.isPlainObject( s ) ) {
8921
				// Valid cell index and its in the array of selectable rows
8922
				return s.column !== undefined && s.row !== undefined && $.inArray( s.row, rows ) !== -1 ?
8923
					[s] :
8924
					[];
8925
			}
8926
	
8927
			// Selector - jQuery filtered cells
8928
			var jqResult = allCells
8929
				.filter( s )
8930
				.map( function (i, el) {
8931
					return { // use a new object, in case someone changes the values
8932
						row:    el._DT_CellIndex.row,
8933
						column: el._DT_CellIndex.column
8934
	 				};
8935
				} )
8936
				.toArray();
8937
	
8938
			if ( jqResult.length || ! s.nodeName ) {
8939
				return jqResult;
8940
			}
8941
	
8942
			// Otherwise the selector is a node, and there is one last option - the
8943
			// element might be a child of an element which has dt-row and dt-column
8944
			// data attributes
8945
			host = $(s).closest('*[data-dt-row]');
8946
			return host.length ?
8947
				[ {
8948
					row: host.data('dt-row'),
8949
					column: host.data('dt-column')
8950
				} ] :
8951
				[];
8952
		};
8953
	
8954
		return _selector_run( 'cell', selector, run, settings, opts );
8955
	};
8956
	
8957
	
8958
	
8959
	
8960
	_api_register( 'cells()', function ( rowSelector, columnSelector, opts ) {
8961
		// Argument shifting
8962
		if ( $.isPlainObject( rowSelector ) ) {
8963
			// Indexes
8964
			if ( rowSelector.row === undefined ) {
8965
				// Selector options in first parameter
8966
				opts = rowSelector;
8967
				rowSelector = null;
8968
			}
8969
			else {
8970
				// Cell index objects in first parameter
8971
				opts = columnSelector;
8972
				columnSelector = null;
8973
			}
8974
		}
8975
		if ( $.isPlainObject( columnSelector ) ) {
8976
			opts = columnSelector;
8977
			columnSelector = null;
8978
		}
8979
	
8980
		// Cell selector
8981
		if ( columnSelector === null || columnSelector === undefined ) {
8982
			return this.iterator( 'table', function ( settings ) {
8983
				return __cell_selector( settings, rowSelector, _selector_opts( opts ) );
8984
			} );
8985
		}
8986
	
8987
		// The default built in options need to apply to row and columns
8988
		var internalOpts = opts ? {
8989
			page: opts.page,
8990
			order: opts.order,
8991
			search: opts.search
8992
		} : {};
8993
	
8994
		// Row + column selector
8995
		var columns = this.columns( columnSelector, internalOpts );
8996
		var rows = this.rows( rowSelector, internalOpts );
8997
		var i, ien, j, jen;
8998
	
8999
		var cellsNoOpts = this.iterator( 'table', function ( settings, idx ) {
9000
			var a = [];
9001
	
9002
			for ( i=0, ien=rows[idx].length ; i<ien ; i++ ) {
9003
				for ( j=0, jen=columns[idx].length ; j<jen ; j++ ) {
9004
					a.push( {
9005
						row:    rows[idx][i],
9006
						column: columns[idx][j]
9007
					} );
9008
				}
9009
			}
9010
	
9011
			return a;
9012
		}, 1 );
9013
	
9014
		// There is currently only one extension which uses a cell selector extension
9015
		// It is a _major_ performance drag to run this if it isn't needed, so this is
9016
		// an extension specific check at the moment
9017
		var cells = opts && opts.selected ?
9018
			this.cells( cellsNoOpts, opts ) :
9019
			cellsNoOpts;
9020
	
9021
		$.extend( cells.selector, {
9022
			cols: columnSelector,
9023
			rows: rowSelector,
9024
			opts: opts
9025
		} );
9026
	
9027
		return cells;
9028
	} );
9029
	
9030
	
9031
	_api_registerPlural( 'cells().nodes()', 'cell().node()', function () {
9032
		return this.iterator( 'cell', function ( settings, row, column ) {
9033
			var data = settings.aoData[ row ];
9034
	
9035
			return data && data.anCells ?
9036
				data.anCells[ column ] :
9037
				undefined;
9038
		}, 1 );
9039
	} );
9040
	
9041
	
9042
	_api_register( 'cells().data()', function () {
9043
		return this.iterator( 'cell', function ( settings, row, column ) {
9044
			return _fnGetCellData( settings, row, column );
9045
		}, 1 );
9046
	} );
9047
	
9048
	
9049
	_api_registerPlural( 'cells().cache()', 'cell().cache()', function ( type ) {
9050
		type = type === 'search' ? '_aFilterData' : '_aSortData';
9051
	
9052
		return this.iterator( 'cell', function ( settings, row, column ) {
9053
			return settings.aoData[ row ][ type ][ column ];
9054
		}, 1 );
9055
	} );
9056
	
9057
	
9058
	_api_registerPlural( 'cells().render()', 'cell().render()', function ( type ) {
9059
		return this.iterator( 'cell', function ( settings, row, column ) {
9060
			return _fnGetCellData( settings, row, column, type );
9061
		}, 1 );
9062
	} );
9063
	
9064
	
9065
	_api_registerPlural( 'cells().indexes()', 'cell().index()', function () {
9066
		return this.iterator( 'cell', function ( settings, row, column ) {
9067
			return {
9068
				row: row,
9069
				column: column,
9070
				columnVisible: _fnColumnIndexToVisible( settings, column )
9071
			};
9072
		}, 1 );
9073
	} );
9074
	
9075
	
9076
	_api_registerPlural( 'cells().invalidate()', 'cell().invalidate()', function ( src ) {
9077
		return this.iterator( 'cell', function ( settings, row, column ) {
9078
			_fnInvalidate( settings, row, src, column );
9079
		} );
9080
	} );
9081
	
9082
	
9083
	
9084
	_api_register( 'cell()', function ( rowSelector, columnSelector, opts ) {
9085
		return _selector_first( this.cells( rowSelector, columnSelector, opts ) );
9086
	} );
9087
	
9088
	
9089
	_api_register( 'cell().data()', function ( data ) {
9090
		var ctx = this.context;
9091
		var cell = this[0];
9092
	
9093
		if ( data === undefined ) {
9094
			// Get
9095
			return ctx.length && cell.length ?
9096
				_fnGetCellData( ctx[0], cell[0].row, cell[0].column ) :
9097
				undefined;
9098
		}
9099
	
9100
		// Set
9101
		_fnSetCellData( ctx[0], cell[0].row, cell[0].column, data );
9102
		_fnInvalidate( ctx[0], cell[0].row, 'data', cell[0].column );
9103
	
9104
		return this;
9105
	} );
9106
	
9107
	
9108
	
9109
	/**
9110
	 * Get current ordering (sorting) that has been applied to the table.
9111
	 *
9112
	 * @returns {array} 2D array containing the sorting information for the first
9113
	 *   table in the current context. Each element in the parent array represents
9114
	 *   a column being sorted upon (i.e. multi-sorting with two columns would have
9115
	 *   2 inner arrays). The inner arrays may have 2 or 3 elements. The first is
9116
	 *   the column index that the sorting condition applies to, the second is the
9117
	 *   direction of the sort (`desc` or `asc`) and, optionally, the third is the
9118
	 *   index of the sorting order from the `column.sorting` initialisation array.
9119
	 *//**
9120
	 * Set the ordering for the table.
9121
	 *
9122
	 * @param {integer} order Column index to sort upon.
9123
	 * @param {string} direction Direction of the sort to be applied (`asc` or `desc`)
9124
	 * @returns {DataTables.Api} this
9125
	 *//**
9126
	 * Set the ordering for the table.
9127
	 *
9128
	 * @param {array} order 1D array of sorting information to be applied.
9129
	 * @param {array} [...] Optional additional sorting conditions
9130
	 * @returns {DataTables.Api} this
9131
	 *//**
9132
	 * Set the ordering for the table.
9133
	 *
9134
	 * @param {array} order 2D array of sorting information to be applied.
9135
	 * @returns {DataTables.Api} this
9136
	 */
9137
	_api_register( 'order()', function ( order, dir ) {
9138
		var ctx = this.context;
9139
	
9140
		if ( order === undefined ) {
9141
			// get
9142
			return ctx.length !== 0 ?
9143
				ctx[0].aaSorting :
9144
				undefined;
9145
		}
9146
	
9147
		// set
9148
		if ( typeof order === 'number' ) {
9149
			// Simple column / direction passed in
9150
			order = [ [ order, dir ] ];
9151
		}
9152
		else if ( order.length && ! Array.isArray( order[0] ) ) {
9153
			// Arguments passed in (list of 1D arrays)
9154
			order = Array.prototype.slice.call( arguments );
9155
		}
9156
		// otherwise a 2D array was passed in
9157
	
9158
		return this.iterator( 'table', function ( settings ) {
9159
			settings.aaSorting = order.slice();
9160
		} );
9161
	} );
9162
	
9163
	
9164
	/**
9165
	 * Attach a sort listener to an element for a given column
9166
	 *
9167
	 * @param {node|jQuery|string} node Identifier for the element(s) to attach the
9168
	 *   listener to. This can take the form of a single DOM node, a jQuery
9169
	 *   collection of nodes or a jQuery selector which will identify the node(s).
9170
	 * @param {integer} column the column that a click on this node will sort on
9171
	 * @param {function} [callback] callback function when sort is run
9172
	 * @returns {DataTables.Api} this
9173
	 */
9174
	_api_register( 'order.listener()', function ( node, column, callback ) {
9175
		return this.iterator( 'table', function ( settings ) {
9176
			_fnSortAttachListener( settings, node, column, callback );
9177
		} );
9178
	} );
9179
	
9180
	
9181
	_api_register( 'order.fixed()', function ( set ) {
9182
		if ( ! set ) {
9183
			var ctx = this.context;
9184
			var fixed = ctx.length ?
9185
				ctx[0].aaSortingFixed :
9186
				undefined;
9187
	
9188
			return Array.isArray( fixed ) ?
9189
				{ pre: fixed } :
9190
				fixed;
9191
		}
9192
	
9193
		return this.iterator( 'table', function ( settings ) {
9194
			settings.aaSortingFixed = $.extend( true, {}, set );
9195
		} );
9196
	} );
9197
	
9198
	
9199
	// Order by the selected column(s)
9200
	_api_register( [
9201
		'columns().order()',
9202
		'column().order()'
9203
	], function ( dir ) {
9204
		var that = this;
9205
	
9206
		return this.iterator( 'table', function ( settings, i ) {
9207
			var sort = [];
9208
	
9209
			$.each( that[i], function (j, col) {
9210
				sort.push( [ col, dir ] );
9211
			} );
9212
	
9213
			settings.aaSorting = sort;
9214
		} );
9215
	} );
9216
	
9217
	
9218
	
9219
	_api_register( 'search()', function ( input, regex, smart, caseInsen ) {
9220
		var ctx = this.context;
9221
	
9222
		if ( input === undefined ) {
9223
			// get
9224
			return ctx.length !== 0 ?
9225
				ctx[0].oPreviousSearch.sSearch :
9226
				undefined;
9227
		}
9228
	
9229
		// set
9230
		return this.iterator( 'table', function ( settings ) {
9231
			if ( ! settings.oFeatures.bFilter ) {
9232
				return;
9233
			}
9234
	
9235
			_fnFilterComplete( settings, $.extend( {}, settings.oPreviousSearch, {
9236
				"sSearch": input+"",
9237
				"bRegex":  regex === null ? false : regex,
9238
				"bSmart":  smart === null ? true  : smart,
9239
				"bCaseInsensitive": caseInsen === null ? true : caseInsen
9240
			} ), 1 );
9241
		} );
9242
	} );
9243
	
9244
	
9245
	_api_registerPlural(
9246
		'columns().search()',
9247
		'column().search()',
9248
		function ( input, regex, smart, caseInsen ) {
9249
			return this.iterator( 'column', function ( settings, column ) {
9250
				var preSearch = settings.aoPreSearchCols;
9251
	
9252
				if ( input === undefined ) {
9253
					// get
9254
					return preSearch[ column ].sSearch;
9255
				}
9256
	
9257
				// set
9258
				if ( ! settings.oFeatures.bFilter ) {
9259
					return;
9260
				}
9261
	
9262
				$.extend( preSearch[ column ], {
9263
					"sSearch": input+"",
9264
					"bRegex":  regex === null ? false : regex,
9265
					"bSmart":  smart === null ? true  : smart,
9266
					"bCaseInsensitive": caseInsen === null ? true : caseInsen
9267
				} );
9268
	
9269
				_fnFilterComplete( settings, settings.oPreviousSearch, 1 );
9270
			} );
9271
		}
9272
	);
9273
	
9274
	/*
9275
	 * State API methods
9276
	 */
9277
	
9278
	_api_register( 'state()', function () {
9279
		return this.context.length ?
9280
			this.context[0].oSavedState :
9281
			null;
9282
	} );
9283
	
9284
	
9285
	_api_register( 'state.clear()', function () {
9286
		return this.iterator( 'table', function ( settings ) {
9287
			// Save an empty object
9288
			settings.fnStateSaveCallback.call( settings.oInstance, settings, {} );
9289
		} );
9290
	} );
9291
	
9292
	
9293
	_api_register( 'state.loaded()', function () {
9294
		return this.context.length ?
9295
			this.context[0].oLoadedState :
9296
			null;
9297
	} );
9298
	
9299
	
9300
	_api_register( 'state.save()', function () {
9301
		return this.iterator( 'table', function ( settings ) {
9302
			_fnSaveState( settings );
9303
		} );
9304
	} );
9305
	
9306
	
9307
	
9308
	/**
9309
	 * Provide a common method for plug-ins to check the version of DataTables being
9310
	 * used, in order to ensure compatibility.
9311
	 *
9312
	 *  @param {string} version Version string to check for, in the format "X.Y.Z".
9313
	 *    Note that the formats "X" and "X.Y" are also acceptable.
9314
	 *  @returns {boolean} true if this version of DataTables is greater or equal to
9315
	 *    the required version, or false if this version of DataTales is not
9316
	 *    suitable
9317
	 *  @static
9318
	 *  @dtopt API-Static
9319
	 *
9320
	 *  @example
9321
	 *    alert( $.fn.dataTable.versionCheck( '1.9.0' ) );
9322
	 */
9323
	DataTable.versionCheck = DataTable.fnVersionCheck = function( version )
9324
	{
9325
		var aThis = DataTable.version.split('.');
9326
		var aThat = version.split('.');
9327
		var iThis, iThat;
9328
	
9329
		for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) {
9330
			iThis = parseInt( aThis[i], 10 ) || 0;
9331
			iThat = parseInt( aThat[i], 10 ) || 0;
9332
	
9333
			// Parts are the same, keep comparing
9334
			if (iThis === iThat) {
9335
				continue;
9336
			}
9337
	
9338
			// Parts are different, return immediately
9339
			return iThis > iThat;
9340
		}
9341
	
9342
		return true;
9343
	};
9344
	
9345
	
9346
	/**
9347
	 * Check if a `<table>` node is a DataTable table already or not.
9348
	 *
9349
	 *  @param {node|jquery|string} table Table node, jQuery object or jQuery
9350
	 *      selector for the table to test. Note that if more than more than one
9351
	 *      table is passed on, only the first will be checked
9352
	 *  @returns {boolean} true the table given is a DataTable, or false otherwise
9353
	 *  @static
9354
	 *  @dtopt API-Static
9355
	 *
9356
	 *  @example
9357
	 *    if ( ! $.fn.DataTable.isDataTable( '#example' ) ) {
9358
	 *      $('#example').dataTable();
9359
	 *    }
9360
	 */
9361
	DataTable.isDataTable = DataTable.fnIsDataTable = function ( table )
9362
	{
9363
		var t = $(table).get(0);
9364
		var is = false;
9365
	
9366
		if ( table instanceof DataTable.Api ) {
9367
			return true;
9368
		}
9369
	
9370
		$.each( DataTable.settings, function (i, o) {
9371
			var head = o.nScrollHead ? $('table', o.nScrollHead)[0] : null;
9372
			var foot = o.nScrollFoot ? $('table', o.nScrollFoot)[0] : null;
9373
	
9374
			if ( o.nTable === t || head === t || foot === t ) {
9375
				is = true;
9376
			}
9377
		} );
9378
	
9379
		return is;
9380
	};
9381
	
9382
	
9383
	/**
9384
	 * Get all DataTable tables that have been initialised - optionally you can
9385
	 * select to get only currently visible tables.
9386
	 *
9387
	 *  @param {boolean} [visible=false] Flag to indicate if you want all (default)
9388
	 *    or visible tables only.
9389
	 *  @returns {array} Array of `table` nodes (not DataTable instances) which are
9390
	 *    DataTables
9391
	 *  @static
9392
	 *  @dtopt API-Static
9393
	 *
9394
	 *  @example
9395
	 *    $.each( $.fn.dataTable.tables(true), function () {
9396
	 *      $(table).DataTable().columns.adjust();
9397
	 *    } );
9398
	 */
9399
	DataTable.tables = DataTable.fnTables = function ( visible )
9400
	{
9401
		var api = false;
9402
	
9403
		if ( $.isPlainObject( visible ) ) {
9404
			api = visible.api;
9405
			visible = visible.visible;
9406
		}
9407
	
9408
		var a = $.map( DataTable.settings, function (o) {
9409
			if ( !visible || (visible && $(o.nTable).is(':visible')) ) {
9410
				return o.nTable;
9411
			}
9412
		} );
9413
	
9414
		return api ?
9415
			new _Api( a ) :
9416
			a;
9417
	};
9418
	
9419
	
9420
	/**
9421
	 * Convert from camel case parameters to Hungarian notation. This is made public
9422
	 * for the extensions to provide the same ability as DataTables core to accept
9423
	 * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase
9424
	 * parameters.
9425
	 *
9426
	 *  @param {object} src The model object which holds all parameters that can be
9427
	 *    mapped.
9428
	 *  @param {object} user The object to convert from camel case to Hungarian.
9429
	 *  @param {boolean} force When set to `true`, properties which already have a
9430
	 *    Hungarian value in the `user` object will be overwritten. Otherwise they
9431
	 *    won't be.
9432
	 */
9433
	DataTable.camelToHungarian = _fnCamelToHungarian;
9434
	
9435
	
9436
	
9437
	/**
9438
	 *
9439
	 */
9440
	_api_register( '$()', function ( selector, opts ) {
9441
		var
9442
			rows   = this.rows( opts ).nodes(), // Get all rows
9443
			jqRows = $(rows);
9444
	
9445
		return $( [].concat(
9446
			jqRows.filter( selector ).toArray(),
9447
			jqRows.find( selector ).toArray()
9448
		) );
9449
	} );
9450
	
9451
	
9452
	// jQuery functions to operate on the tables
9453
	$.each( [ 'on', 'one', 'off' ], function (i, key) {
9454
		_api_register( key+'()', function ( /* event, handler */ ) {
9455
			var args = Array.prototype.slice.call(arguments);
9456
	
9457
			// Add the `dt` namespace automatically if it isn't already present
9458
			args[0] = $.map( args[0].split( /\s/ ), function ( e ) {
9459
				return ! e.match(/\.dt\b/) ?
9460
					e+'.dt' :
9461
					e;
9462
				} ).join( ' ' );
9463
	
9464
			var inst = $( this.tables().nodes() );
9465
			inst[key].apply( inst, args );
9466
			return this;
9467
		} );
9468
	} );
9469
	
9470
	
9471
	_api_register( 'clear()', function () {
9472
		return this.iterator( 'table', function ( settings ) {
9473
			_fnClearTable( settings );
9474
		} );
9475
	} );
9476
	
9477
	
9478
	_api_register( 'settings()', function () {
9479
		return new _Api( this.context, this.context );
9480
	} );
9481
	
9482
	
9483
	_api_register( 'init()', function () {
9484
		var ctx = this.context;
9485
		return ctx.length ? ctx[0].oInit : null;
9486
	} );
9487
	
9488
	
9489
	_api_register( 'data()', function () {
9490
		return this.iterator( 'table', function ( settings ) {
9491
			return _pluck( settings.aoData, '_aData' );
9492
		} ).flatten();
9493
	} );
9494
	
9495
	
9496
	_api_register( 'destroy()', function ( remove ) {
9497
		remove = remove || false;
9498
	
9499
		return this.iterator( 'table', function ( settings ) {
9500
			var orig      = settings.nTableWrapper.parentNode;
9501
			var classes   = settings.oClasses;
9502
			var table     = settings.nTable;
9503
			var tbody     = settings.nTBody;
9504
			var thead     = settings.nTHead;
9505
			var tfoot     = settings.nTFoot;
9506
			var jqTable   = $(table);
9507
			var jqTbody   = $(tbody);
9508
			var jqWrapper = $(settings.nTableWrapper);
9509
			var rows      = $.map( settings.aoData, function (r) { return r.nTr; } );
9510
			var i, ien;
9511
	
9512
			// Flag to note that the table is currently being destroyed - no action
9513
			// should be taken
9514
			settings.bDestroying = true;
9515
	
9516
			// Fire off the destroy callbacks for plug-ins etc
9517
			_fnCallbackFire( settings, "aoDestroyCallback", "destroy", [settings] );
9518
	
9519
			// If not being removed from the document, make all columns visible
9520
			if ( ! remove ) {
9521
				new _Api( settings ).columns().visible( true );
9522
			}
9523
	
9524
			// Blitz all `DT` namespaced events (these are internal events, the
9525
			// lowercase, `dt` events are user subscribed and they are responsible
9526
			// for removing them
9527
			jqWrapper.off('.DT').find(':not(tbody *)').off('.DT');
9528
			$(window).off('.DT-'+settings.sInstance);
9529
	
9530
			// When scrolling we had to break the table up - restore it
9531
			if ( table != thead.parentNode ) {
9532
				jqTable.children('thead').detach();
9533
				jqTable.append( thead );
9534
			}
9535
	
9536
			if ( tfoot && table != tfoot.parentNode ) {
9537
				jqTable.children('tfoot').detach();
9538
				jqTable.append( tfoot );
9539
			}
9540
	
9541
			settings.aaSorting = [];
9542
			settings.aaSortingFixed = [];
9543
			_fnSortingClasses( settings );
9544
	
9545
			$( rows ).removeClass( settings.asStripeClasses.join(' ') );
9546
	
9547
			$('th, td', thead).removeClass( classes.sSortable+' '+
9548
				classes.sSortableAsc+' '+classes.sSortableDesc+' '+classes.sSortableNone
9549
			);
9550
	
9551
			// Add the TR elements back into the table in their original order
9552
			jqTbody.children().detach();
9553
			jqTbody.append( rows );
9554
	
9555
			// Remove the DataTables generated nodes, events and classes
9556
			var removedMethod = remove ? 'remove' : 'detach';
9557
			jqTable[ removedMethod ]();
9558
			jqWrapper[ removedMethod ]();
9559
	
9560
			// If we need to reattach the table to the document
9561
			if ( ! remove && orig ) {
9562
				// insertBefore acts like appendChild if !arg[1]
9563
				orig.insertBefore( table, settings.nTableReinsertBefore );
9564
	
9565
				// Restore the width of the original table - was read from the style property,
9566
				// so we can restore directly to that
9567
				jqTable
9568
					.css( 'width', settings.sDestroyWidth )
9569
					.removeClass( classes.sTable );
9570
	
9571
				// If the were originally stripe classes - then we add them back here.
9572
				// Note this is not fool proof (for example if not all rows had stripe
9573
				// classes - but it's a good effort without getting carried away
9574
				ien = settings.asDestroyStripes.length;
9575
	
9576
				if ( ien ) {
9577
					jqTbody.children().each( function (i) {
9578
						$(this).addClass( settings.asDestroyStripes[i % ien] );
9579
					} );
9580
				}
9581
			}
9582
	
9583
			/* Remove the settings object from the settings array */
9584
			var idx = $.inArray( settings, DataTable.settings );
9585
			if ( idx !== -1 ) {
9586
				DataTable.settings.splice( idx, 1 );
9587
			}
9588
		} );
9589
	} );
9590
	
9591
	
9592
	// Add the `every()` method for rows, columns and cells in a compact form
9593
	$.each( [ 'column', 'row', 'cell' ], function ( i, type ) {
9594
		_api_register( type+'s().every()', function ( fn ) {
9595
			var opts = this.selector.opts;
9596
			var api = this;
9597
	
9598
			return this.iterator( type, function ( settings, arg1, arg2, arg3, arg4 ) {
9599
				// Rows and columns:
9600
				//  arg1 - index
9601
				//  arg2 - table counter
9602
				//  arg3 - loop counter
9603
				//  arg4 - undefined
9604
				// Cells:
9605
				//  arg1 - row index
9606
				//  arg2 - column index
9607
				//  arg3 - table counter
9608
				//  arg4 - loop counter
9609
				fn.call(
9610
					api[ type ](
9611
						arg1,
9612
						type==='cell' ? arg2 : opts,
9613
						type==='cell' ? opts : undefined
9614
					),
9615
					arg1, arg2, arg3, arg4
9616
				);
9617
			} );
9618
		} );
9619
	} );
9620
	
9621
	
9622
	// i18n method for extensions to be able to use the language object from the
9623
	// DataTable
9624
	_api_register( 'i18n()', function ( token, def, plural ) {
9625
		var ctx = this.context[0];
9626
		var resolved = _fnGetObjectDataFn( token )( ctx.oLanguage );
9627
	
9628
		if ( resolved === undefined ) {
9629
			resolved = def;
9630
		}
9631
	
9632
		if ( plural !== undefined && $.isPlainObject( resolved ) ) {
9633
			resolved = resolved[ plural ] !== undefined ?
9634
				resolved[ plural ] :
9635
				resolved._;
9636
		}
9637
	
9638
		return resolved.replace( '%d', plural ); // nb: plural might be undefined,
9639
	} );
9640
	/**
9641
	 * Version string for plug-ins to check compatibility. Allowed format is
9642
	 * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used
9643
	 * only for non-release builds. See http://semver.org/ for more information.
9644
	 *  @member
9645
	 *  @type string
9646
	 *  @default Version number
9647
	 */
9648
	DataTable.version = "1.11.4";
9649

9650
	/**
9651
	 * Private data store, containing all of the settings objects that are
9652
	 * created for the tables on a given page.
9653
	 *
9654
	 * Note that the `DataTable.settings` object is aliased to
9655
	 * `jQuery.fn.dataTableExt` through which it may be accessed and
9656
	 * manipulated, or `jQuery.fn.dataTable.settings`.
9657
	 *  @member
9658
	 *  @type array
9659
	 *  @default []
9660
	 *  @private
9661
	 */
9662
	DataTable.settings = [];
9663

9664
	/**
9665
	 * Object models container, for the various models that DataTables has
9666
	 * available to it. These models define the objects that are used to hold
9667
	 * the active state and configuration of the table.
9668
	 *  @namespace
9669
	 */
9670
	DataTable.models = {};
9671
	
9672
	
9673
	
9674
	/**
9675
	 * Template object for the way in which DataTables holds information about
9676
	 * search information for the global filter and individual column filters.
9677
	 *  @namespace
9678
	 */
9679
	DataTable.models.oSearch = {
9680
		/**
9681
		 * Flag to indicate if the filtering should be case insensitive or not
9682
		 *  @type boolean
9683
		 *  @default true
9684
		 */
9685
		"bCaseInsensitive": true,
9686
	
9687
		/**
9688
		 * Applied search term
9689
		 *  @type string
9690
		 *  @default <i>Empty string</i>
9691
		 */
9692
		"sSearch": "",
9693
	
9694
		/**
9695
		 * Flag to indicate if the search term should be interpreted as a
9696
		 * regular expression (true) or not (false) and therefore and special
9697
		 * regex characters escaped.
9698
		 *  @type boolean
9699
		 *  @default false
9700
		 */
9701
		"bRegex": false,
9702
	
9703
		/**
9704
		 * Flag to indicate if DataTables is to use its smart filtering or not.
9705
		 *  @type boolean
9706
		 *  @default true
9707
		 */
9708
		"bSmart": true,
9709
	
9710
		/**
9711
		 * Flag to indicate if DataTables should only trigger a search when
9712
		 * the return key is pressed.
9713
		 *  @type boolean
9714
		 *  @default false
9715
		 */
9716
		"return": false
9717
	};
9718
	
9719
	
9720
	
9721
	
9722
	/**
9723
	 * Template object for the way in which DataTables holds information about
9724
	 * each individual row. This is the object format used for the settings
9725
	 * aoData array.
9726
	 *  @namespace
9727
	 */
9728
	DataTable.models.oRow = {
9729
		/**
9730
		 * TR element for the row
9731
		 *  @type node
9732
		 *  @default null
9733
		 */
9734
		"nTr": null,
9735
	
9736
		/**
9737
		 * Array of TD elements for each row. This is null until the row has been
9738
		 * created.
9739
		 *  @type array nodes
9740
		 *  @default []
9741
		 */
9742
		"anCells": null,
9743
	
9744
		/**
9745
		 * Data object from the original data source for the row. This is either
9746
		 * an array if using the traditional form of DataTables, or an object if
9747
		 * using mData options. The exact type will depend on the passed in
9748
		 * data from the data source, or will be an array if using DOM a data
9749
		 * source.
9750
		 *  @type array|object
9751
		 *  @default []
9752
		 */
9753
		"_aData": [],
9754
	
9755
		/**
9756
		 * Sorting data cache - this array is ostensibly the same length as the
9757
		 * number of columns (although each index is generated only as it is
9758
		 * needed), and holds the data that is used for sorting each column in the
9759
		 * row. We do this cache generation at the start of the sort in order that
9760
		 * the formatting of the sort data need be done only once for each cell
9761
		 * per sort. This array should not be read from or written to by anything
9762
		 * other than the master sorting methods.
9763
		 *  @type array
9764
		 *  @default null
9765
		 *  @private
9766
		 */
9767
		"_aSortData": null,
9768
	
9769
		/**
9770
		 * Per cell filtering data cache. As per the sort data cache, used to
9771
		 * increase the performance of the filtering in DataTables
9772
		 *  @type array
9773
		 *  @default null
9774
		 *  @private
9775
		 */
9776
		"_aFilterData": null,
9777
	
9778
		/**
9779
		 * Filtering data cache. This is the same as the cell filtering cache, but
9780
		 * in this case a string rather than an array. This is easily computed with
9781
		 * a join on `_aFilterData`, but is provided as a cache so the join isn't
9782
		 * needed on every search (memory traded for performance)
9783
		 *  @type array
9784
		 *  @default null
9785
		 *  @private
9786
		 */
9787
		"_sFilterRow": null,
9788
	
9789
		/**
9790
		 * Cache of the class name that DataTables has applied to the row, so we
9791
		 * can quickly look at this variable rather than needing to do a DOM check
9792
		 * on className for the nTr property.
9793
		 *  @type string
9794
		 *  @default <i>Empty string</i>
9795
		 *  @private
9796
		 */
9797
		"_sRowStripe": "",
9798
	
9799
		/**
9800
		 * Denote if the original data source was from the DOM, or the data source
9801
		 * object. This is used for invalidating data, so DataTables can
9802
		 * automatically read data from the original source, unless uninstructed
9803
		 * otherwise.
9804
		 *  @type string
9805
		 *  @default null
9806
		 *  @private
9807
		 */
9808
		"src": null,
9809
	
9810
		/**
9811
		 * Index in the aoData array. This saves an indexOf lookup when we have the
9812
		 * object, but want to know the index
9813
		 *  @type integer
9814
		 *  @default -1
9815
		 *  @private
9816
		 */
9817
		"idx": -1
9818
	};
9819
	
9820
	
9821
	/**
9822
	 * Template object for the column information object in DataTables. This object
9823
	 * is held in the settings aoColumns array and contains all the information that
9824
	 * DataTables needs about each individual column.
9825
	 *
9826
	 * Note that this object is related to {@link DataTable.defaults.column}
9827
	 * but this one is the internal data store for DataTables's cache of columns.
9828
	 * It should NOT be manipulated outside of DataTables. Any configuration should
9829
	 * be done through the initialisation options.
9830
	 *  @namespace
9831
	 */
9832
	DataTable.models.oColumn = {
9833
		/**
9834
		 * Column index. This could be worked out on-the-fly with $.inArray, but it
9835
		 * is faster to just hold it as a variable
9836
		 *  @type integer
9837
		 *  @default null
9838
		 */
9839
		"idx": null,
9840
	
9841
		/**
9842
		 * A list of the columns that sorting should occur on when this column
9843
		 * is sorted. That this property is an array allows multi-column sorting
9844
		 * to be defined for a column (for example first name / last name columns
9845
		 * would benefit from this). The values are integers pointing to the
9846
		 * columns to be sorted on (typically it will be a single integer pointing
9847
		 * at itself, but that doesn't need to be the case).
9848
		 *  @type array
9849
		 */
9850
		"aDataSort": null,
9851
	
9852
		/**
9853
		 * Define the sorting directions that are applied to the column, in sequence
9854
		 * as the column is repeatedly sorted upon - i.e. the first value is used
9855
		 * as the sorting direction when the column if first sorted (clicked on).
9856
		 * Sort it again (click again) and it will move on to the next index.
9857
		 * Repeat until loop.
9858
		 *  @type array
9859
		 */
9860
		"asSorting": null,
9861
	
9862
		/**
9863
		 * Flag to indicate if the column is searchable, and thus should be included
9864
		 * in the filtering or not.
9865
		 *  @type boolean
9866
		 */
9867
		"bSearchable": null,
9868
	
9869
		/**
9870
		 * Flag to indicate if the column is sortable or not.
9871
		 *  @type boolean
9872
		 */
9873
		"bSortable": null,
9874
	
9875
		/**
9876
		 * Flag to indicate if the column is currently visible in the table or not
9877
		 *  @type boolean
9878
		 */
9879
		"bVisible": null,
9880
	
9881
		/**
9882
		 * Store for manual type assignment using the `column.type` option. This
9883
		 * is held in store so we can manipulate the column's `sType` property.
9884
		 *  @type string
9885
		 *  @default null
9886
		 *  @private
9887
		 */
9888
		"_sManualType": null,
9889
	
9890
		/**
9891
		 * Flag to indicate if HTML5 data attributes should be used as the data
9892
		 * source for filtering or sorting. True is either are.
9893
		 *  @type boolean
9894
		 *  @default false
9895
		 *  @private
9896
		 */
9897
		"_bAttrSrc": false,
9898
	
9899
		/**
9900
		 * Developer definable function that is called whenever a cell is created (Ajax source,
9901
		 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
9902
		 * allowing you to modify the DOM element (add background colour for example) when the
9903
		 * element is available.
9904
		 *  @type function
9905
		 *  @param {element} nTd The TD node that has been created
9906
		 *  @param {*} sData The Data for the cell
9907
		 *  @param {array|object} oData The data for the whole row
9908
		 *  @param {int} iRow The row index for the aoData data store
9909
		 *  @default null
9910
		 */
9911
		"fnCreatedCell": null,
9912
	
9913
		/**
9914
		 * Function to get data from a cell in a column. You should <b>never</b>
9915
		 * access data directly through _aData internally in DataTables - always use
9916
		 * the method attached to this property. It allows mData to function as
9917
		 * required. This function is automatically assigned by the column
9918
		 * initialisation method
9919
		 *  @type function
9920
		 *  @param {array|object} oData The data array/object for the array
9921
		 *    (i.e. aoData[]._aData)
9922
		 *  @param {string} sSpecific The specific data type you want to get -
9923
		 *    'display', 'type' 'filter' 'sort'
9924
		 *  @returns {*} The data for the cell from the given row's data
9925
		 *  @default null
9926
		 */
9927
		"fnGetData": null,
9928
	
9929
		/**
9930
		 * Function to set data for a cell in the column. You should <b>never</b>
9931
		 * set the data directly to _aData internally in DataTables - always use
9932
		 * this method. It allows mData to function as required. This function
9933
		 * is automatically assigned by the column initialisation method
9934
		 *  @type function
9935
		 *  @param {array|object} oData The data array/object for the array
9936
		 *    (i.e. aoData[]._aData)
9937
		 *  @param {*} sValue Value to set
9938
		 *  @default null
9939
		 */
9940
		"fnSetData": null,
9941
	
9942
		/**
9943
		 * Property to read the value for the cells in the column from the data
9944
		 * source array / object. If null, then the default content is used, if a
9945
		 * function is given then the return from the function is used.
9946
		 *  @type function|int|string|null
9947
		 *  @default null
9948
		 */
9949
		"mData": null,
9950
	
9951
		/**
9952
		 * Partner property to mData which is used (only when defined) to get
9953
		 * the data - i.e. it is basically the same as mData, but without the
9954
		 * 'set' option, and also the data fed to it is the result from mData.
9955
		 * This is the rendering method to match the data method of mData.
9956
		 *  @type function|int|string|null
9957
		 *  @default null
9958
		 */
9959
		"mRender": null,
9960
	
9961
		/**
9962
		 * Unique header TH/TD element for this column - this is what the sorting
9963
		 * listener is attached to (if sorting is enabled.)
9964
		 *  @type node
9965
		 *  @default null
9966
		 */
9967
		"nTh": null,
9968
	
9969
		/**
9970
		 * Unique footer TH/TD element for this column (if there is one). Not used
9971
		 * in DataTables as such, but can be used for plug-ins to reference the
9972
		 * footer for each column.
9973
		 *  @type node
9974
		 *  @default null
9975
		 */
9976
		"nTf": null,
9977
	
9978
		/**
9979
		 * The class to apply to all TD elements in the table's TBODY for the column
9980
		 *  @type string
9981
		 *  @default null
9982
		 */
9983
		"sClass": null,
9984
	
9985
		/**
9986
		 * When DataTables calculates the column widths to assign to each column,
9987
		 * it finds the longest string in each column and then constructs a
9988
		 * temporary table and reads the widths from that. The problem with this
9989
		 * is that "mmm" is much wider then "iiii", but the latter is a longer
9990
		 * string - thus the calculation can go wrong (doing it properly and putting
9991
		 * it into an DOM object and measuring that is horribly(!) slow). Thus as
9992
		 * a "work around" we provide this option. It will append its value to the
9993
		 * text that is found to be the longest string for the column - i.e. padding.
9994
		 *  @type string
9995
		 */
9996
		"sContentPadding": null,
9997
	
9998
		/**
9999
		 * Allows a default value to be given for a column's data, and will be used
10000
		 * whenever a null data source is encountered (this can be because mData
10001
		 * is set to null, or because the data source itself is null).
10002
		 *  @type string
10003
		 *  @default null
10004
		 */
10005
		"sDefaultContent": null,
10006
	
10007
		/**
10008
		 * Name for the column, allowing reference to the column by name as well as
10009
		 * by index (needs a lookup to work by name).
10010
		 *  @type string
10011
		 */
10012
		"sName": null,
10013
	
10014
		/**
10015
		 * Custom sorting data type - defines which of the available plug-ins in
10016
		 * afnSortData the custom sorting will use - if any is defined.
10017
		 *  @type string
10018
		 *  @default std
10019
		 */
10020
		"sSortDataType": 'std',
10021
	
10022
		/**
10023
		 * Class to be applied to the header element when sorting on this column
10024
		 *  @type string
10025
		 *  @default null
10026
		 */
10027
		"sSortingClass": null,
10028
	
10029
		/**
10030
		 * Class to be applied to the header element when sorting on this column -
10031
		 * when jQuery UI theming is used.
10032
		 *  @type string
10033
		 *  @default null
10034
		 */
10035
		"sSortingClassJUI": null,
10036
	
10037
		/**
10038
		 * Title of the column - what is seen in the TH element (nTh).
10039
		 *  @type string
10040
		 */
10041
		"sTitle": null,
10042
	
10043
		/**
10044
		 * Column sorting and filtering type
10045
		 *  @type string
10046
		 *  @default null
10047
		 */
10048
		"sType": null,
10049
	
10050
		/**
10051
		 * Width of the column
10052
		 *  @type string
10053
		 *  @default null
10054
		 */
10055
		"sWidth": null,
10056
	
10057
		/**
10058
		 * Width of the column when it was first "encountered"
10059
		 *  @type string
10060
		 *  @default null
10061
		 */
10062
		"sWidthOrig": null
10063
	};
10064
	
10065
	
10066
	/*
10067
	 * Developer note: The properties of the object below are given in Hungarian
10068
	 * notation, that was used as the interface for DataTables prior to v1.10, however
10069
	 * from v1.10 onwards the primary interface is camel case. In order to avoid
10070
	 * breaking backwards compatibility utterly with this change, the Hungarian
10071
	 * version is still, internally the primary interface, but is is not documented
10072
	 * - hence the @name tags in each doc comment. This allows a Javascript function
10073
	 * to create a map from Hungarian notation to camel case (going the other direction
10074
	 * would require each property to be listed, which would add around 3K to the size
10075
	 * of DataTables, while this method is about a 0.5K hit).
10076
	 *
10077
	 * Ultimately this does pave the way for Hungarian notation to be dropped
10078
	 * completely, but that is a massive amount of work and will break current
10079
	 * installs (therefore is on-hold until v2).
10080
	 */
10081
	
10082
	/**
10083
	 * Initialisation options that can be given to DataTables at initialisation
10084
	 * time.
10085
	 *  @namespace
10086
	 */
10087
	DataTable.defaults = {
10088
		/**
10089
		 * An array of data to use for the table, passed in at initialisation which
10090
		 * will be used in preference to any data which is already in the DOM. This is
10091
		 * particularly useful for constructing tables purely in Javascript, for
10092
		 * example with a custom Ajax call.
10093
		 *  @type array
10094
		 *  @default null
10095
		 *
10096
		 *  @dtopt Option
10097
		 *  @name DataTable.defaults.data
10098
		 *
10099
		 *  @example
10100
		 *    // Using a 2D array data source
10101
		 *    $(document).ready( function () {
10102
		 *      $('#example').dataTable( {
10103
		 *        "data": [
10104
		 *          ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
10105
		 *          ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
10106
		 *        ],
10107
		 *        "columns": [
10108
		 *          { "title": "Engine" },
10109
		 *          { "title": "Browser" },
10110
		 *          { "title": "Platform" },
10111
		 *          { "title": "Version" },
10112
		 *          { "title": "Grade" }
10113
		 *        ]
10114
		 *      } );
10115
		 *    } );
10116
		 *
10117
		 *  @example
10118
		 *    // Using an array of objects as a data source (`data`)
10119
		 *    $(document).ready( function () {
10120
		 *      $('#example').dataTable( {
10121
		 *        "data": [
10122
		 *          {
10123
		 *            "engine":   "Trident",
10124
		 *            "browser":  "Internet Explorer 4.0",
10125
		 *            "platform": "Win 95+",
10126
		 *            "version":  4,
10127
		 *            "grade":    "X"
10128
		 *          },
10129
		 *          {
10130
		 *            "engine":   "Trident",
10131
		 *            "browser":  "Internet Explorer 5.0",
10132
		 *            "platform": "Win 95+",
10133
		 *            "version":  5,
10134
		 *            "grade":    "C"
10135
		 *          }
10136
		 *        ],
10137
		 *        "columns": [
10138
		 *          { "title": "Engine",   "data": "engine" },
10139
		 *          { "title": "Browser",  "data": "browser" },
10140
		 *          { "title": "Platform", "data": "platform" },
10141
		 *          { "title": "Version",  "data": "version" },
10142
		 *          { "title": "Grade",    "data": "grade" }
10143
		 *        ]
10144
		 *      } );
10145
		 *    } );
10146
		 */
10147
		"aaData": null,
10148
	
10149
	
10150
		/**
10151
		 * If ordering is enabled, then DataTables will perform a first pass sort on
10152
		 * initialisation. You can define which column(s) the sort is performed
10153
		 * upon, and the sorting direction, with this variable. The `sorting` array
10154
		 * should contain an array for each column to be sorted initially containing
10155
		 * the column's index and a direction string ('asc' or 'desc').
10156
		 *  @type array
10157
		 *  @default [[0,'asc']]
10158
		 *
10159
		 *  @dtopt Option
10160
		 *  @name DataTable.defaults.order
10161
		 *
10162
		 *  @example
10163
		 *    // Sort by 3rd column first, and then 4th column
10164
		 *    $(document).ready( function() {
10165
		 *      $('#example').dataTable( {
10166
		 *        "order": [[2,'asc'], [3,'desc']]
10167
		 *      } );
10168
		 *    } );
10169
		 *
10170
		 *    // No initial sorting
10171
		 *    $(document).ready( function() {
10172
		 *      $('#example').dataTable( {
10173
		 *        "order": []
10174
		 *      } );
10175
		 *    } );
10176
		 */
10177
		"aaSorting": [[0,'asc']],
10178
	
10179
	
10180
		/**
10181
		 * This parameter is basically identical to the `sorting` parameter, but
10182
		 * cannot be overridden by user interaction with the table. What this means
10183
		 * is that you could have a column (visible or hidden) which the sorting
10184
		 * will always be forced on first - any sorting after that (from the user)
10185
		 * will then be performed as required. This can be useful for grouping rows
10186
		 * together.
10187
		 *  @type array
10188
		 *  @default null
10189
		 *
10190
		 *  @dtopt Option
10191
		 *  @name DataTable.defaults.orderFixed
10192
		 *
10193
		 *  @example
10194
		 *    $(document).ready( function() {
10195
		 *      $('#example').dataTable( {
10196
		 *        "orderFixed": [[0,'asc']]
10197
		 *      } );
10198
		 *    } )
10199
		 */
10200
		"aaSortingFixed": [],
10201
	
10202
	
10203
		/**
10204
		 * DataTables can be instructed to load data to display in the table from a
10205
		 * Ajax source. This option defines how that Ajax call is made and where to.
10206
		 *
10207
		 * The `ajax` property has three different modes of operation, depending on
10208
		 * how it is defined. These are:
10209
		 *
10210
		 * * `string` - Set the URL from where the data should be loaded from.
10211
		 * * `object` - Define properties for `jQuery.ajax`.
10212
		 * * `function` - Custom data get function
10213
		 *
10214
		 * `string`
10215
		 * --------
10216
		 *
10217
		 * As a string, the `ajax` property simply defines the URL from which
10218
		 * DataTables will load data.
10219
		 *
10220
		 * `object`
10221
		 * --------
10222
		 *
10223
		 * As an object, the parameters in the object are passed to
10224
		 * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control
10225
		 * of the Ajax request. DataTables has a number of default parameters which
10226
		 * you can override using this option. Please refer to the jQuery
10227
		 * documentation for a full description of the options available, although
10228
		 * the following parameters provide additional options in DataTables or
10229
		 * require special consideration:
10230
		 *
10231
		 * * `data` - As with jQuery, `data` can be provided as an object, but it
10232
		 *   can also be used as a function to manipulate the data DataTables sends
10233
		 *   to the server. The function takes a single parameter, an object of
10234
		 *   parameters with the values that DataTables has readied for sending. An
10235
		 *   object may be returned which will be merged into the DataTables
10236
		 *   defaults, or you can add the items to the object that was passed in and
10237
		 *   not return anything from the function. This supersedes `fnServerParams`
10238
		 *   from DataTables 1.9-.
10239
		 *
10240
		 * * `dataSrc` - By default DataTables will look for the property `data` (or
10241
		 *   `aaData` for compatibility with DataTables 1.9-) when obtaining data
10242
		 *   from an Ajax source or for server-side processing - this parameter
10243
		 *   allows that property to be changed. You can use Javascript dotted
10244
		 *   object notation to get a data source for multiple levels of nesting, or
10245
		 *   it my be used as a function. As a function it takes a single parameter,
10246
		 *   the JSON returned from the server, which can be manipulated as
10247
		 *   required, with the returned value being that used by DataTables as the
10248
		 *   data source for the table. This supersedes `sAjaxDataProp` from
10249
		 *   DataTables 1.9-.
10250
		 *
10251
		 * * `success` - Should not be overridden it is used internally in
10252
		 *   DataTables. To manipulate / transform the data returned by the server
10253
		 *   use `ajax.dataSrc`, or use `ajax` as a function (see below).
10254
		 *
10255
		 * `function`
10256
		 * ----------
10257
		 *
10258
		 * As a function, making the Ajax call is left up to yourself allowing
10259
		 * complete control of the Ajax request. Indeed, if desired, a method other
10260
		 * than Ajax could be used to obtain the required data, such as Web storage
10261
		 * or an AIR database.
10262
		 *
10263
		 * The function is given four parameters and no return is required. The
10264
		 * parameters are:
10265
		 *
10266
		 * 1. _object_ - Data to send to the server
10267
		 * 2. _function_ - Callback function that must be executed when the required
10268
		 *    data has been obtained. That data should be passed into the callback
10269
		 *    as the only parameter
10270
		 * 3. _object_ - DataTables settings object for the table
10271
		 *
10272
		 * Note that this supersedes `fnServerData` from DataTables 1.9-.
10273
		 *
10274
		 *  @type string|object|function
10275
		 *  @default null
10276
		 *
10277
		 *  @dtopt Option
10278
		 *  @name DataTable.defaults.ajax
10279
		 *  @since 1.10.0
10280
		 *
10281
		 * @example
10282
		 *   // Get JSON data from a file via Ajax.
10283
		 *   // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default).
10284
		 *   $('#example').dataTable( {
10285
		 *     "ajax": "data.json"
10286
		 *   } );
10287
		 *
10288
		 * @example
10289
		 *   // Get JSON data from a file via Ajax, using `dataSrc` to change
10290
		 *   // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`)
10291
		 *   $('#example').dataTable( {
10292
		 *     "ajax": {
10293
		 *       "url": "data.json",
10294
		 *       "dataSrc": "tableData"
10295
		 *     }
10296
		 *   } );
10297
		 *
10298
		 * @example
10299
		 *   // Get JSON data from a file via Ajax, using `dataSrc` to read data
10300
		 *   // from a plain array rather than an array in an object
10301
		 *   $('#example').dataTable( {
10302
		 *     "ajax": {
10303
		 *       "url": "data.json",
10304
		 *       "dataSrc": ""
10305
		 *     }
10306
		 *   } );
10307
		 *
10308
		 * @example
10309
		 *   // Manipulate the data returned from the server - add a link to data
10310
		 *   // (note this can, should, be done using `render` for the column - this
10311
		 *   // is just a simple example of how the data can be manipulated).
10312
		 *   $('#example').dataTable( {
10313
		 *     "ajax": {
10314
		 *       "url": "data.json",
10315
		 *       "dataSrc": function ( json ) {
10316
		 *         for ( var i=0, ien=json.length ; i<ien ; i++ ) {
10317
		 *           json[i][0] = '<a href="/message/'+json[i][0]+'>View message</a>';
10318
		 *         }
10319
		 *         return json;
10320
		 *       }
10321
		 *     }
10322
		 *   } );
10323
		 *
10324
		 * @example
10325
		 *   // Add data to the request
10326
		 *   $('#example').dataTable( {
10327
		 *     "ajax": {
10328
		 *       "url": "data.json",
10329
		 *       "data": function ( d ) {
10330
		 *         return {
10331
		 *           "extra_search": $('#extra').val()
10332
		 *         };
10333
		 *       }
10334
		 *     }
10335
		 *   } );
10336
		 *
10337
		 * @example
10338
		 *   // Send request as POST
10339
		 *   $('#example').dataTable( {
10340
		 *     "ajax": {
10341
		 *       "url": "data.json",
10342
		 *       "type": "POST"
10343
		 *     }
10344
		 *   } );
10345
		 *
10346
		 * @example
10347
		 *   // Get the data from localStorage (could interface with a form for
10348
		 *   // adding, editing and removing rows).
10349
		 *   $('#example').dataTable( {
10350
		 *     "ajax": function (data, callback, settings) {
10351
		 *       callback(
10352
		 *         JSON.parse( localStorage.getItem('dataTablesData') )
10353
		 *       );
10354
		 *     }
10355
		 *   } );
10356
		 */
10357
		"ajax": null,
10358
	
10359
	
10360
		/**
10361
		 * This parameter allows you to readily specify the entries in the length drop
10362
		 * down menu that DataTables shows when pagination is enabled. It can be
10363
		 * either a 1D array of options which will be used for both the displayed
10364
		 * option and the value, or a 2D array which will use the array in the first
10365
		 * position as the value, and the array in the second position as the
10366
		 * displayed options (useful for language strings such as 'All').
10367
		 *
10368
		 * Note that the `pageLength` property will be automatically set to the
10369
		 * first value given in this array, unless `pageLength` is also provided.
10370
		 *  @type array
10371
		 *  @default [ 10, 25, 50, 100 ]
10372
		 *
10373
		 *  @dtopt Option
10374
		 *  @name DataTable.defaults.lengthMenu
10375
		 *
10376
		 *  @example
10377
		 *    $(document).ready( function() {
10378
		 *      $('#example').dataTable( {
10379
		 *        "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
10380
		 *      } );
10381
		 *    } );
10382
		 */
10383
		"aLengthMenu": [ 10, 25, 50, 100 ],
10384
	
10385
	
10386
		/**
10387
		 * The `columns` option in the initialisation parameter allows you to define
10388
		 * details about the way individual columns behave. For a full list of
10389
		 * column options that can be set, please see
10390
		 * {@link DataTable.defaults.column}. Note that if you use `columns` to
10391
		 * define your columns, you must have an entry in the array for every single
10392
		 * column that you have in your table (these can be null if you don't which
10393
		 * to specify any options).
10394
		 *  @member
10395
		 *
10396
		 *  @name DataTable.defaults.column
10397
		 */
10398
		"aoColumns": null,
10399
	
10400
		/**
10401
		 * Very similar to `columns`, `columnDefs` allows you to target a specific
10402
		 * column, multiple columns, or all columns, using the `targets` property of
10403
		 * each object in the array. This allows great flexibility when creating
10404
		 * tables, as the `columnDefs` arrays can be of any length, targeting the
10405
		 * columns you specifically want. `columnDefs` may use any of the column
10406
		 * options available: {@link DataTable.defaults.column}, but it _must_
10407
		 * have `targets` defined in each object in the array. Values in the `targets`
10408
		 * array may be:
10409
		 *   <ul>
10410
		 *     <li>a string - class name will be matched on the TH for the column</li>
10411
		 *     <li>0 or a positive integer - column index counting from the left</li>
10412
		 *     <li>a negative integer - column index counting from the right</li>
10413
		 *     <li>the string "_all" - all columns (i.e. assign a default)</li>
10414
		 *   </ul>
10415
		 *  @member
10416
		 *
10417
		 *  @name DataTable.defaults.columnDefs
10418
		 */
10419
		"aoColumnDefs": null,
10420
	
10421
	
10422
		/**
10423
		 * Basically the same as `search`, this parameter defines the individual column
10424
		 * filtering state at initialisation time. The array must be of the same size
10425
		 * as the number of columns, and each element be an object with the parameters
10426
		 * `search` and `escapeRegex` (the latter is optional). 'null' is also
10427
		 * accepted and the default will be used.
10428
		 *  @type array
10429
		 *  @default []
10430
		 *
10431
		 *  @dtopt Option
10432
		 *  @name DataTable.defaults.searchCols
10433
		 *
10434
		 *  @example
10435
		 *    $(document).ready( function() {
10436
		 *      $('#example').dataTable( {
10437
		 *        "searchCols": [
10438
		 *          null,
10439
		 *          { "search": "My filter" },
10440
		 *          null,
10441
		 *          { "search": "^[0-9]", "escapeRegex": false }
10442
		 *        ]
10443
		 *      } );
10444
		 *    } )
10445
		 */
10446
		"aoSearchCols": [],
10447
	
10448
	
10449
		/**
10450
		 * An array of CSS classes that should be applied to displayed rows. This
10451
		 * array may be of any length, and DataTables will apply each class
10452
		 * sequentially, looping when required.
10453
		 *  @type array
10454
		 *  @default null <i>Will take the values determined by the `oClasses.stripe*`
10455
		 *    options</i>
10456
		 *
10457
		 *  @dtopt Option
10458
		 *  @name DataTable.defaults.stripeClasses
10459
		 *
10460
		 *  @example
10461
		 *    $(document).ready( function() {
10462
		 *      $('#example').dataTable( {
10463
		 *        "stripeClasses": [ 'strip1', 'strip2', 'strip3' ]
10464
		 *      } );
10465
		 *    } )
10466
		 */
10467
		"asStripeClasses": null,
10468
	
10469
	
10470
		/**
10471
		 * Enable or disable automatic column width calculation. This can be disabled
10472
		 * as an optimisation (it takes some time to calculate the widths) if the
10473
		 * tables widths are passed in using `columns`.
10474
		 *  @type boolean
10475
		 *  @default true
10476
		 *
10477
		 *  @dtopt Features
10478
		 *  @name DataTable.defaults.autoWidth
10479
		 *
10480
		 *  @example
10481
		 *    $(document).ready( function () {
10482
		 *      $('#example').dataTable( {
10483
		 *        "autoWidth": false
10484
		 *      } );
10485
		 *    } );
10486
		 */
10487
		"bAutoWidth": true,
10488
	
10489
	
10490
		/**
10491
		 * Deferred rendering can provide DataTables with a huge speed boost when you
10492
		 * are using an Ajax or JS data source for the table. This option, when set to
10493
		 * true, will cause DataTables to defer the creation of the table elements for
10494
		 * each row until they are needed for a draw - saving a significant amount of
10495
		 * time.
10496
		 *  @type boolean
10497
		 *  @default false
10498
		 *
10499
		 *  @dtopt Features
10500
		 *  @name DataTable.defaults.deferRender
10501
		 *
10502
		 *  @example
10503
		 *    $(document).ready( function() {
10504
		 *      $('#example').dataTable( {
10505
		 *        "ajax": "sources/arrays.txt",
10506
		 *        "deferRender": true
10507
		 *      } );
10508
		 *    } );
10509
		 */
10510
		"bDeferRender": false,
10511
	
10512
	
10513
		/**
10514
		 * Replace a DataTable which matches the given selector and replace it with
10515
		 * one which has the properties of the new initialisation object passed. If no
10516
		 * table matches the selector, then the new DataTable will be constructed as
10517
		 * per normal.
10518
		 *  @type boolean
10519
		 *  @default false
10520
		 *
10521
		 *  @dtopt Options
10522
		 *  @name DataTable.defaults.destroy
10523
		 *
10524
		 *  @example
10525
		 *    $(document).ready( function() {
10526
		 *      $('#example').dataTable( {
10527
		 *        "srollY": "200px",
10528
		 *        "paginate": false
10529
		 *      } );
10530
		 *
10531
		 *      // Some time later....
10532
		 *      $('#example').dataTable( {
10533
		 *        "filter": false,
10534
		 *        "destroy": true
10535
		 *      } );
10536
		 *    } );
10537
		 */
10538
		"bDestroy": false,
10539
	
10540
	
10541
		/**
10542
		 * Enable or disable filtering of data. Filtering in DataTables is "smart" in
10543
		 * that it allows the end user to input multiple words (space separated) and
10544
		 * will match a row containing those words, even if not in the order that was
10545
		 * specified (this allow matching across multiple columns). Note that if you
10546
		 * wish to use filtering in DataTables this must remain 'true' - to remove the
10547
		 * default filtering input box and retain filtering abilities, please use
10548
		 * {@link DataTable.defaults.dom}.
10549
		 *  @type boolean
10550
		 *  @default true
10551
		 *
10552
		 *  @dtopt Features
10553
		 *  @name DataTable.defaults.searching
10554
		 *
10555
		 *  @example
10556
		 *    $(document).ready( function () {
10557
		 *      $('#example').dataTable( {
10558
		 *        "searching": false
10559
		 *      } );
10560
		 *    } );
10561
		 */
10562
		"bFilter": true,
10563
	
10564
	
10565
		/**
10566
		 * Enable or disable the table information display. This shows information
10567
		 * about the data that is currently visible on the page, including information
10568
		 * about filtered data if that action is being performed.
10569
		 *  @type boolean
10570
		 *  @default true
10571
		 *
10572
		 *  @dtopt Features
10573
		 *  @name DataTable.defaults.info
10574
		 *
10575
		 *  @example
10576
		 *    $(document).ready( function () {
10577
		 *      $('#example').dataTable( {
10578
		 *        "info": false
10579
		 *      } );
10580
		 *    } );
10581
		 */
10582
		"bInfo": true,
10583
	
10584
	
10585
		/**
10586
		 * Allows the end user to select the size of a formatted page from a select
10587
		 * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`).
10588
		 *  @type boolean
10589
		 *  @default true
10590
		 *
10591
		 *  @dtopt Features
10592
		 *  @name DataTable.defaults.lengthChange
10593
		 *
10594
		 *  @example
10595
		 *    $(document).ready( function () {
10596
		 *      $('#example').dataTable( {
10597
		 *        "lengthChange": false
10598
		 *      } );
10599
		 *    } );
10600
		 */
10601
		"bLengthChange": true,
10602
	
10603
	
10604
		/**
10605
		 * Enable or disable pagination.
10606
		 *  @type boolean
10607
		 *  @default true
10608
		 *
10609
		 *  @dtopt Features
10610
		 *  @name DataTable.defaults.paging
10611
		 *
10612
		 *  @example
10613
		 *    $(document).ready( function () {
10614
		 *      $('#example').dataTable( {
10615
		 *        "paging": false
10616
		 *      } );
10617
		 *    } );
10618
		 */
10619
		"bPaginate": true,
10620
	
10621
	
10622
		/**
10623
		 * Enable or disable the display of a 'processing' indicator when the table is
10624
		 * being processed (e.g. a sort). This is particularly useful for tables with
10625
		 * large amounts of data where it can take a noticeable amount of time to sort
10626
		 * the entries.
10627
		 *  @type boolean
10628
		 *  @default false
10629
		 *
10630
		 *  @dtopt Features
10631
		 *  @name DataTable.defaults.processing
10632
		 *
10633
		 *  @example
10634
		 *    $(document).ready( function () {
10635
		 *      $('#example').dataTable( {
10636
		 *        "processing": true
10637
		 *      } );
10638
		 *    } );
10639
		 */
10640
		"bProcessing": false,
10641
	
10642
	
10643
		/**
10644
		 * Retrieve the DataTables object for the given selector. Note that if the
10645
		 * table has already been initialised, this parameter will cause DataTables
10646
		 * to simply return the object that has already been set up - it will not take
10647
		 * account of any changes you might have made to the initialisation object
10648
		 * passed to DataTables (setting this parameter to true is an acknowledgement
10649
		 * that you understand this). `destroy` can be used to reinitialise a table if
10650
		 * you need.
10651
		 *  @type boolean
10652
		 *  @default false
10653
		 *
10654
		 *  @dtopt Options
10655
		 *  @name DataTable.defaults.retrieve
10656
		 *
10657
		 *  @example
10658
		 *    $(document).ready( function() {
10659
		 *      initTable();
10660
		 *      tableActions();
10661
		 *    } );
10662
		 *
10663
		 *    function initTable ()
10664
		 *    {
10665
		 *      return $('#example').dataTable( {
10666
		 *        "scrollY": "200px",
10667
		 *        "paginate": false,
10668
		 *        "retrieve": true
10669
		 *      } );
10670
		 *    }
10671
		 *
10672
		 *    function tableActions ()
10673
		 *    {
10674
		 *      var table = initTable();
10675
		 *      // perform API operations with oTable
10676
		 *    }
10677
		 */
10678
		"bRetrieve": false,
10679
	
10680
	
10681
		/**
10682
		 * When vertical (y) scrolling is enabled, DataTables will force the height of
10683
		 * the table's viewport to the given height at all times (useful for layout).
10684
		 * However, this can look odd when filtering data down to a small data set,
10685
		 * and the footer is left "floating" further down. This parameter (when
10686
		 * enabled) will cause DataTables to collapse the table's viewport down when
10687
		 * the result set will fit within the given Y height.
10688
		 *  @type boolean
10689
		 *  @default false
10690
		 *
10691
		 *  @dtopt Options
10692
		 *  @name DataTable.defaults.scrollCollapse
10693
		 *
10694
		 *  @example
10695
		 *    $(document).ready( function() {
10696
		 *      $('#example').dataTable( {
10697
		 *        "scrollY": "200",
10698
		 *        "scrollCollapse": true
10699
		 *      } );
10700
		 *    } );
10701
		 */
10702
		"bScrollCollapse": false,
10703
	
10704
	
10705
		/**
10706
		 * Configure DataTables to use server-side processing. Note that the
10707
		 * `ajax` parameter must also be given in order to give DataTables a
10708
		 * source to obtain the required data for each draw.
10709
		 *  @type boolean
10710
		 *  @default false
10711
		 *
10712
		 *  @dtopt Features
10713
		 *  @dtopt Server-side
10714
		 *  @name DataTable.defaults.serverSide
10715
		 *
10716
		 *  @example
10717
		 *    $(document).ready( function () {
10718
		 *      $('#example').dataTable( {
10719
		 *        "serverSide": true,
10720
		 *        "ajax": "xhr.php"
10721
		 *      } );
10722
		 *    } );
10723
		 */
10724
		"bServerSide": false,
10725
	
10726
	
10727
		/**
10728
		 * Enable or disable sorting of columns. Sorting of individual columns can be
10729
		 * disabled by the `sortable` option for each column.
10730
		 *  @type boolean
10731
		 *  @default true
10732
		 *
10733
		 *  @dtopt Features
10734
		 *  @name DataTable.defaults.ordering
10735
		 *
10736
		 *  @example
10737
		 *    $(document).ready( function () {
10738
		 *      $('#example').dataTable( {
10739
		 *        "ordering": false
10740
		 *      } );
10741
		 *    } );
10742
		 */
10743
		"bSort": true,
10744
	
10745
	
10746
		/**
10747
		 * Enable or display DataTables' ability to sort multiple columns at the
10748
		 * same time (activated by shift-click by the user).
10749
		 *  @type boolean
10750
		 *  @default true
10751
		 *
10752
		 *  @dtopt Options
10753
		 *  @name DataTable.defaults.orderMulti
10754
		 *
10755
		 *  @example
10756
		 *    // Disable multiple column sorting ability
10757
		 *    $(document).ready( function () {
10758
		 *      $('#example').dataTable( {
10759
		 *        "orderMulti": false
10760
		 *      } );
10761
		 *    } );
10762
		 */
10763
		"bSortMulti": true,
10764
	
10765
	
10766
		/**
10767
		 * Allows control over whether DataTables should use the top (true) unique
10768
		 * cell that is found for a single column, or the bottom (false - default).
10769
		 * This is useful when using complex headers.
10770
		 *  @type boolean
10771
		 *  @default false
10772
		 *
10773
		 *  @dtopt Options
10774
		 *  @name DataTable.defaults.orderCellsTop
10775
		 *
10776
		 *  @example
10777
		 *    $(document).ready( function() {
10778
		 *      $('#example').dataTable( {
10779
		 *        "orderCellsTop": true
10780
		 *      } );
10781
		 *    } );
10782
		 */
10783
		"bSortCellsTop": false,
10784
	
10785
	
10786
		/**
10787
		 * Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and
10788
		 * `sorting\_3` to the columns which are currently being sorted on. This is
10789
		 * presented as a feature switch as it can increase processing time (while
10790
		 * classes are removed and added) so for large data sets you might want to
10791
		 * turn this off.
10792
		 *  @type boolean
10793
		 *  @default true
10794
		 *
10795
		 *  @dtopt Features
10796
		 *  @name DataTable.defaults.orderClasses
10797
		 *
10798
		 *  @example
10799
		 *    $(document).ready( function () {
10800
		 *      $('#example').dataTable( {
10801
		 *        "orderClasses": false
10802
		 *      } );
10803
		 *    } );
10804
		 */
10805
		"bSortClasses": true,
10806
	
10807
	
10808
		/**
10809
		 * Enable or disable state saving. When enabled HTML5 `localStorage` will be
10810
		 * used to save table display information such as pagination information,
10811
		 * display length, filtering and sorting. As such when the end user reloads
10812
		 * the page the display display will match what thy had previously set up.
10813
		 *
10814
		 * Due to the use of `localStorage` the default state saving is not supported
10815
		 * in IE6 or 7. If state saving is required in those browsers, use
10816
		 * `stateSaveCallback` to provide a storage solution such as cookies.
10817
		 *  @type boolean
10818
		 *  @default false
10819
		 *
10820
		 *  @dtopt Features
10821
		 *  @name DataTable.defaults.stateSave
10822
		 *
10823
		 *  @example
10824
		 *    $(document).ready( function () {
10825
		 *      $('#example').dataTable( {
10826
		 *        "stateSave": true
10827
		 *      } );
10828
		 *    } );
10829
		 */
10830
		"bStateSave": false,
10831
	
10832
	
10833
		/**
10834
		 * This function is called when a TR element is created (and all TD child
10835
		 * elements have been inserted), or registered if using a DOM source, allowing
10836
		 * manipulation of the TR element (adding classes etc).
10837
		 *  @type function
10838
		 *  @param {node} row "TR" element for the current row
10839
		 *  @param {array} data Raw data array for this row
10840
		 *  @param {int} dataIndex The index of this row in the internal aoData array
10841
		 *
10842
		 *  @dtopt Callbacks
10843
		 *  @name DataTable.defaults.createdRow
10844
		 *
10845
		 *  @example
10846
		 *    $(document).ready( function() {
10847
		 *      $('#example').dataTable( {
10848
		 *        "createdRow": function( row, data, dataIndex ) {
10849
		 *          // Bold the grade for all 'A' grade browsers
10850
		 *          if ( data[4] == "A" )
10851
		 *          {
10852
		 *            $('td:eq(4)', row).html( '<b>A</b>' );
10853
		 *          }
10854
		 *        }
10855
		 *      } );
10856
		 *    } );
10857
		 */
10858
		"fnCreatedRow": null,
10859
	
10860
	
10861
		/**
10862
		 * This function is called on every 'draw' event, and allows you to
10863
		 * dynamically modify any aspect you want about the created DOM.
10864
		 *  @type function
10865
		 *  @param {object} settings DataTables settings object
10866
		 *
10867
		 *  @dtopt Callbacks
10868
		 *  @name DataTable.defaults.drawCallback
10869
		 *
10870
		 *  @example
10871
		 *    $(document).ready( function() {
10872
		 *      $('#example').dataTable( {
10873
		 *        "drawCallback": function( settings ) {
10874
		 *          alert( 'DataTables has redrawn the table' );
10875
		 *        }
10876
		 *      } );
10877
		 *    } );
10878
		 */
10879
		"fnDrawCallback": null,
10880
	
10881
	
10882
		/**
10883
		 * Identical to fnHeaderCallback() but for the table footer this function
10884
		 * allows you to modify the table footer on every 'draw' event.
10885
		 *  @type function
10886
		 *  @param {node} foot "TR" element for the footer
10887
		 *  @param {array} data Full table data (as derived from the original HTML)
10888
		 *  @param {int} start Index for the current display starting point in the
10889
		 *    display array
10890
		 *  @param {int} end Index for the current display ending point in the
10891
		 *    display array
10892
		 *  @param {array int} display Index array to translate the visual position
10893
		 *    to the full data array
10894
		 *
10895
		 *  @dtopt Callbacks
10896
		 *  @name DataTable.defaults.footerCallback
10897
		 *
10898
		 *  @example
10899
		 *    $(document).ready( function() {
10900
		 *      $('#example').dataTable( {
10901
		 *        "footerCallback": function( tfoot, data, start, end, display ) {
10902
		 *          tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start;
10903
		 *        }
10904
		 *      } );
10905
		 *    } )
10906
		 */
10907
		"fnFooterCallback": null,
10908
	
10909
	
10910
		/**
10911
		 * When rendering large numbers in the information element for the table
10912
		 * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
10913
		 * to have a comma separator for the 'thousands' units (e.g. 1 million is
10914
		 * rendered as "1,000,000") to help readability for the end user. This
10915
		 * function will override the default method DataTables uses.
10916
		 *  @type function
10917
		 *  @member
10918
		 *  @param {int} toFormat number to be formatted
10919
		 *  @returns {string} formatted string for DataTables to show the number
10920
		 *
10921
		 *  @dtopt Callbacks
10922
		 *  @name DataTable.defaults.formatNumber
10923
		 *
10924
		 *  @example
10925
		 *    // Format a number using a single quote for the separator (note that
10926
		 *    // this can also be done with the language.thousands option)
10927
		 *    $(document).ready( function() {
10928
		 *      $('#example').dataTable( {
10929
		 *        "formatNumber": function ( toFormat ) {
10930
		 *          return toFormat.toString().replace(
10931
		 *            /\B(?=(\d{3})+(?!\d))/g, "'"
10932
		 *          );
10933
		 *        };
10934
		 *      } );
10935
		 *    } );
10936
		 */
10937
		"fnFormatNumber": function ( toFormat ) {
10938
			return toFormat.toString().replace(
10939
				/\B(?=(\d{3})+(?!\d))/g,
10940
				this.oLanguage.sThousands
10941
			);
10942
		},
10943
	
10944
	
10945
		/**
10946
		 * This function is called on every 'draw' event, and allows you to
10947
		 * dynamically modify the header row. This can be used to calculate and
10948
		 * display useful information about the table.
10949
		 *  @type function
10950
		 *  @param {node} head "TR" element for the header
10951
		 *  @param {array} data Full table data (as derived from the original HTML)
10952
		 *  @param {int} start Index for the current display starting point in the
10953
		 *    display array
10954
		 *  @param {int} end Index for the current display ending point in the
10955
		 *    display array
10956
		 *  @param {array int} display Index array to translate the visual position
10957
		 *    to the full data array
10958
		 *
10959
		 *  @dtopt Callbacks
10960
		 *  @name DataTable.defaults.headerCallback
10961
		 *
10962
		 *  @example
10963
		 *    $(document).ready( function() {
10964
		 *      $('#example').dataTable( {
10965
		 *        "fheaderCallback": function( head, data, start, end, display ) {
10966
		 *          head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records";
10967
		 *        }
10968
		 *      } );
10969
		 *    } )
10970
		 */
10971
		"fnHeaderCallback": null,
10972
	
10973
	
10974
		/**
10975
		 * The information element can be used to convey information about the current
10976
		 * state of the table. Although the internationalisation options presented by
10977
		 * DataTables are quite capable of dealing with most customisations, there may
10978
		 * be times where you wish to customise the string further. This callback
10979
		 * allows you to do exactly that.
10980
		 *  @type function
10981
		 *  @param {object} oSettings DataTables settings object
10982
		 *  @param {int} start Starting position in data for the draw
10983
		 *  @param {int} end End position in data for the draw
10984
		 *  @param {int} max Total number of rows in the table (regardless of
10985
		 *    filtering)
10986
		 *  @param {int} total Total number of rows in the data set, after filtering
10987
		 *  @param {string} pre The string that DataTables has formatted using it's
10988
		 *    own rules
10989
		 *  @returns {string} The string to be displayed in the information element.
10990
		 *
10991
		 *  @dtopt Callbacks
10992
		 *  @name DataTable.defaults.infoCallback
10993
		 *
10994
		 *  @example
10995
		 *    $('#example').dataTable( {
10996
		 *      "infoCallback": function( settings, start, end, max, total, pre ) {
10997
		 *        return start +" to "+ end;
10998
		 *      }
10999
		 *    } );
11000
		 */
11001
		"fnInfoCallback": null,
11002
	
11003
	
11004
		/**
11005
		 * Called when the table has been initialised. Normally DataTables will
11006
		 * initialise sequentially and there will be no need for this function,
11007
		 * however, this does not hold true when using external language information
11008
		 * since that is obtained using an async XHR call.
11009
		 *  @type function
11010
		 *  @param {object} settings DataTables settings object
11011
		 *  @param {object} json The JSON object request from the server - only
11012
		 *    present if client-side Ajax sourced data is used
11013
		 *
11014
		 *  @dtopt Callbacks
11015
		 *  @name DataTable.defaults.initComplete
11016
		 *
11017
		 *  @example
11018
		 *    $(document).ready( function() {
11019
		 *      $('#example').dataTable( {
11020
		 *        "initComplete": function(settings, json) {
11021
		 *          alert( 'DataTables has finished its initialisation.' );
11022
		 *        }
11023
		 *      } );
11024
		 *    } )
11025
		 */
11026
		"fnInitComplete": null,
11027
	
11028
	
11029
		/**
11030
		 * Called at the very start of each table draw and can be used to cancel the
11031
		 * draw by returning false, any other return (including undefined) results in
11032
		 * the full draw occurring).
11033
		 *  @type function
11034
		 *  @param {object} settings DataTables settings object
11035
		 *  @returns {boolean} False will cancel the draw, anything else (including no
11036
		 *    return) will allow it to complete.
11037
		 *
11038
		 *  @dtopt Callbacks
11039
		 *  @name DataTable.defaults.preDrawCallback
11040
		 *
11041
		 *  @example
11042
		 *    $(document).ready( function() {
11043
		 *      $('#example').dataTable( {
11044
		 *        "preDrawCallback": function( settings ) {
11045
		 *          if ( $('#test').val() == 1 ) {
11046
		 *            return false;
11047
		 *          }
11048
		 *        }
11049
		 *      } );
11050
		 *    } );
11051
		 */
11052
		"fnPreDrawCallback": null,
11053
	
11054
	
11055
		/**
11056
		 * This function allows you to 'post process' each row after it have been
11057
		 * generated for each table draw, but before it is rendered on screen. This
11058
		 * function might be used for setting the row class name etc.
11059
		 *  @type function
11060
		 *  @param {node} row "TR" element for the current row
11061
		 *  @param {array} data Raw data array for this row
11062
		 *  @param {int} displayIndex The display index for the current table draw
11063
		 *  @param {int} displayIndexFull The index of the data in the full list of
11064
		 *    rows (after filtering)
11065
		 *
11066
		 *  @dtopt Callbacks
11067
		 *  @name DataTable.defaults.rowCallback
11068
		 *
11069
		 *  @example
11070
		 *    $(document).ready( function() {
11071
		 *      $('#example').dataTable( {
11072
		 *        "rowCallback": function( row, data, displayIndex, displayIndexFull ) {
11073
		 *          // Bold the grade for all 'A' grade browsers
11074
		 *          if ( data[4] == "A" ) {
11075
		 *            $('td:eq(4)', row).html( '<b>A</b>' );
11076
		 *          }
11077
		 *        }
11078
		 *      } );
11079
		 *    } );
11080
		 */
11081
		"fnRowCallback": null,
11082
	
11083
	
11084
		/**
11085
		 * __Deprecated__ The functionality provided by this parameter has now been
11086
		 * superseded by that provided through `ajax`, which should be used instead.
11087
		 *
11088
		 * This parameter allows you to override the default function which obtains
11089
		 * the data from the server so something more suitable for your application.
11090
		 * For example you could use POST data, or pull information from a Gears or
11091
		 * AIR database.
11092
		 *  @type function
11093
		 *  @member
11094
		 *  @param {string} source HTTP source to obtain the data from (`ajax`)
11095
		 *  @param {array} data A key/value pair object containing the data to send
11096
		 *    to the server
11097
		 *  @param {function} callback to be called on completion of the data get
11098
		 *    process that will draw the data on the page.
11099
		 *  @param {object} settings DataTables settings object
11100
		 *
11101
		 *  @dtopt Callbacks
11102
		 *  @dtopt Server-side
11103
		 *  @name DataTable.defaults.serverData
11104
		 *
11105
		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11106
		 */
11107
		"fnServerData": null,
11108
	
11109
	
11110
		/**
11111
		 * __Deprecated__ The functionality provided by this parameter has now been
11112
		 * superseded by that provided through `ajax`, which should be used instead.
11113
		 *
11114
		 *  It is often useful to send extra data to the server when making an Ajax
11115
		 * request - for example custom filtering information, and this callback
11116
		 * function makes it trivial to send extra information to the server. The
11117
		 * passed in parameter is the data set that has been constructed by
11118
		 * DataTables, and you can add to this or modify it as you require.
11119
		 *  @type function
11120
		 *  @param {array} data Data array (array of objects which are name/value
11121
		 *    pairs) that has been constructed by DataTables and will be sent to the
11122
		 *    server. In the case of Ajax sourced data with server-side processing
11123
		 *    this will be an empty array, for server-side processing there will be a
11124
		 *    significant number of parameters!
11125
		 *  @returns {undefined} Ensure that you modify the data array passed in,
11126
		 *    as this is passed by reference.
11127
		 *
11128
		 *  @dtopt Callbacks
11129
		 *  @dtopt Server-side
11130
		 *  @name DataTable.defaults.serverParams
11131
		 *
11132
		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11133
		 */
11134
		"fnServerParams": null,
11135
	
11136
	
11137
		/**
11138
		 * Load the table state. With this function you can define from where, and how, the
11139
		 * state of a table is loaded. By default DataTables will load from `localStorage`
11140
		 * but you might wish to use a server-side database or cookies.
11141
		 *  @type function
11142
		 *  @member
11143
		 *  @param {object} settings DataTables settings object
11144
		 *  @param {object} callback Callback that can be executed when done. It
11145
		 *    should be passed the loaded state object.
11146
		 *  @return {object} The DataTables state object to be loaded
11147
		 *
11148
		 *  @dtopt Callbacks
11149
		 *  @name DataTable.defaults.stateLoadCallback
11150
		 *
11151
		 *  @example
11152
		 *    $(document).ready( function() {
11153
		 *      $('#example').dataTable( {
11154
		 *        "stateSave": true,
11155
		 *        "stateLoadCallback": function (settings, callback) {
11156
		 *          $.ajax( {
11157
		 *            "url": "/state_load",
11158
		 *            "dataType": "json",
11159
		 *            "success": function (json) {
11160
		 *              callback( json );
11161
		 *            }
11162
		 *          } );
11163
		 *        }
11164
		 *      } );
11165
		 *    } );
11166
		 */
11167
		"fnStateLoadCallback": function ( settings ) {
11168
			try {
11169
				return JSON.parse(
11170
					(settings.iStateDuration === -1 ? sessionStorage : localStorage).getItem(
11171
						'DataTables_'+settings.sInstance+'_'+location.pathname
11172
					)
11173
				);
11174
			} catch (e) {
11175
				return {};
11176
			}
11177
		},
11178
	
11179
	
11180
		/**
11181
		 * Callback which allows modification of the saved state prior to loading that state.
11182
		 * This callback is called when the table is loading state from the stored data, but
11183
		 * prior to the settings object being modified by the saved state. Note that for
11184
		 * plug-in authors, you should use the `stateLoadParams` event to load parameters for
11185
		 * a plug-in.
11186
		 *  @type function
11187
		 *  @param {object} settings DataTables settings object
11188
		 *  @param {object} data The state object that is to be loaded
11189
		 *
11190
		 *  @dtopt Callbacks
11191
		 *  @name DataTable.defaults.stateLoadParams
11192
		 *
11193
		 *  @example
11194
		 *    // Remove a saved filter, so filtering is never loaded
11195
		 *    $(document).ready( function() {
11196
		 *      $('#example').dataTable( {
11197
		 *        "stateSave": true,
11198
		 *        "stateLoadParams": function (settings, data) {
11199
		 *          data.oSearch.sSearch = "";
11200
		 *        }
11201
		 *      } );
11202
		 *    } );
11203
		 *
11204
		 *  @example
11205
		 *    // Disallow state loading by returning false
11206
		 *    $(document).ready( function() {
11207
		 *      $('#example').dataTable( {
11208
		 *        "stateSave": true,
11209
		 *        "stateLoadParams": function (settings, data) {
11210
		 *          return false;
11211
		 *        }
11212
		 *      } );
11213
		 *    } );
11214
		 */
11215
		"fnStateLoadParams": null,
11216
	
11217
	
11218
		/**
11219
		 * Callback that is called when the state has been loaded from the state saving method
11220
		 * and the DataTables settings object has been modified as a result of the loaded state.
11221
		 *  @type function
11222
		 *  @param {object} settings DataTables settings object
11223
		 *  @param {object} data The state object that was loaded
11224
		 *
11225
		 *  @dtopt Callbacks
11226
		 *  @name DataTable.defaults.stateLoaded
11227
		 *
11228
		 *  @example
11229
		 *    // Show an alert with the filtering value that was saved
11230
		 *    $(document).ready( function() {
11231
		 *      $('#example').dataTable( {
11232
		 *        "stateSave": true,
11233
		 *        "stateLoaded": function (settings, data) {
11234
		 *          alert( 'Saved filter was: '+data.oSearch.sSearch );
11235
		 *        }
11236
		 *      } );
11237
		 *    } );
11238
		 */
11239
		"fnStateLoaded": null,
11240
	
11241
	
11242
		/**
11243
		 * Save the table state. This function allows you to define where and how the state
11244
		 * information for the table is stored By default DataTables will use `localStorage`
11245
		 * but you might wish to use a server-side database or cookies.
11246
		 *  @type function
11247
		 *  @member
11248
		 *  @param {object} settings DataTables settings object
11249
		 *  @param {object} data The state object to be saved
11250
		 *
11251
		 *  @dtopt Callbacks
11252
		 *  @name DataTable.defaults.stateSaveCallback
11253
		 *
11254
		 *  @example
11255
		 *    $(document).ready( function() {
11256
		 *      $('#example').dataTable( {
11257
		 *        "stateSave": true,
11258
		 *        "stateSaveCallback": function (settings, data) {
11259
		 *          // Send an Ajax request to the server with the state object
11260
		 *          $.ajax( {
11261
		 *            "url": "/state_save",
11262
		 *            "data": data,
11263
		 *            "dataType": "json",
11264
		 *            "method": "POST"
11265
		 *            "success": function () {}
11266
		 *          } );
11267
		 *        }
11268
		 *      } );
11269
		 *    } );
11270
		 */
11271
		"fnStateSaveCallback": function ( settings, data ) {
11272
			try {
11273
				(settings.iStateDuration === -1 ? sessionStorage : localStorage).setItem(
11274
					'DataTables_'+settings.sInstance+'_'+location.pathname,
11275
					JSON.stringify( data )
11276
				);
11277
			} catch (e) {}
11278
		},
11279
	
11280
	
11281
		/**
11282
		 * Callback which allows modification of the state to be saved. Called when the table
11283
		 * has changed state a new state save is required. This method allows modification of
11284
		 * the state saving object prior to actually doing the save, including addition or
11285
		 * other state properties or modification. Note that for plug-in authors, you should
11286
		 * use the `stateSaveParams` event to save parameters for a plug-in.
11287
		 *  @type function
11288
		 *  @param {object} settings DataTables settings object
11289
		 *  @param {object} data The state object to be saved
11290
		 *
11291
		 *  @dtopt Callbacks
11292
		 *  @name DataTable.defaults.stateSaveParams
11293
		 *
11294
		 *  @example
11295
		 *    // Remove a saved filter, so filtering is never saved
11296
		 *    $(document).ready( function() {
11297
		 *      $('#example').dataTable( {
11298
		 *        "stateSave": true,
11299
		 *        "stateSaveParams": function (settings, data) {
11300
		 *          data.oSearch.sSearch = "";
11301
		 *        }
11302
		 *      } );
11303
		 *    } );
11304
		 */
11305
		"fnStateSaveParams": null,
11306
	
11307
	
11308
		/**
11309
		 * Duration for which the saved state information is considered valid. After this period
11310
		 * has elapsed the state will be returned to the default.
11311
		 * Value is given in seconds.
11312
		 *  @type int
11313
		 *  @default 7200 <i>(2 hours)</i>
11314
		 *
11315
		 *  @dtopt Options
11316
		 *  @name DataTable.defaults.stateDuration
11317
		 *
11318
		 *  @example
11319
		 *    $(document).ready( function() {
11320
		 *      $('#example').dataTable( {
11321
		 *        "stateDuration": 60*60*24; // 1 day
11322
		 *      } );
11323
		 *    } )
11324
		 */
11325
		"iStateDuration": 7200,
11326
	
11327
	
11328
		/**
11329
		 * When enabled DataTables will not make a request to the server for the first
11330
		 * page draw - rather it will use the data already on the page (no sorting etc
11331
		 * will be applied to it), thus saving on an XHR at load time. `deferLoading`
11332
		 * is used to indicate that deferred loading is required, but it is also used
11333
		 * to tell DataTables how many records there are in the full table (allowing
11334
		 * the information element and pagination to be displayed correctly). In the case
11335
		 * where a filtering is applied to the table on initial load, this can be
11336
		 * indicated by giving the parameter as an array, where the first element is
11337
		 * the number of records available after filtering and the second element is the
11338
		 * number of records without filtering (allowing the table information element
11339
		 * to be shown correctly).
11340
		 *  @type int | array
11341
		 *  @default null
11342
		 *
11343
		 *  @dtopt Options
11344
		 *  @name DataTable.defaults.deferLoading
11345
		 *
11346
		 *  @example
11347
		 *    // 57 records available in the table, no filtering applied
11348
		 *    $(document).ready( function() {
11349
		 *      $('#example').dataTable( {
11350
		 *        "serverSide": true,
11351
		 *        "ajax": "scripts/server_processing.php",
11352
		 *        "deferLoading": 57
11353
		 *      } );
11354
		 *    } );
11355
		 *
11356
		 *  @example
11357
		 *    // 57 records after filtering, 100 without filtering (an initial filter applied)
11358
		 *    $(document).ready( function() {
11359
		 *      $('#example').dataTable( {
11360
		 *        "serverSide": true,
11361
		 *        "ajax": "scripts/server_processing.php",
11362
		 *        "deferLoading": [ 57, 100 ],
11363
		 *        "search": {
11364
		 *          "search": "my_filter"
11365
		 *        }
11366
		 *      } );
11367
		 *    } );
11368
		 */
11369
		"iDeferLoading": null,
11370
	
11371
	
11372
		/**
11373
		 * Number of rows to display on a single page when using pagination. If
11374
		 * feature enabled (`lengthChange`) then the end user will be able to override
11375
		 * this to a custom setting using a pop-up menu.
11376
		 *  @type int
11377
		 *  @default 10
11378
		 *
11379
		 *  @dtopt Options
11380
		 *  @name DataTable.defaults.pageLength
11381
		 *
11382
		 *  @example
11383
		 *    $(document).ready( function() {
11384
		 *      $('#example').dataTable( {
11385
		 *        "pageLength": 50
11386
		 *      } );
11387
		 *    } )
11388
		 */
11389
		"iDisplayLength": 10,
11390
	
11391
	
11392
		/**
11393
		 * Define the starting point for data display when using DataTables with
11394
		 * pagination. Note that this parameter is the number of records, rather than
11395
		 * the page number, so if you have 10 records per page and want to start on
11396
		 * the third page, it should be "20".
11397
		 *  @type int
11398
		 *  @default 0
11399
		 *
11400
		 *  @dtopt Options
11401
		 *  @name DataTable.defaults.displayStart
11402
		 *
11403
		 *  @example
11404
		 *    $(document).ready( function() {
11405
		 *      $('#example').dataTable( {
11406
		 *        "displayStart": 20
11407
		 *      } );
11408
		 *    } )
11409
		 */
11410
		"iDisplayStart": 0,
11411
	
11412
	
11413
		/**
11414
		 * By default DataTables allows keyboard navigation of the table (sorting, paging,
11415
		 * and filtering) by adding a `tabindex` attribute to the required elements. This
11416
		 * allows you to tab through the controls and press the enter key to activate them.
11417
		 * The tabindex is default 0, meaning that the tab follows the flow of the document.
11418
		 * You can overrule this using this parameter if you wish. Use a value of -1 to
11419
		 * disable built-in keyboard navigation.
11420
		 *  @type int
11421
		 *  @default 0
11422
		 *
11423
		 *  @dtopt Options
11424
		 *  @name DataTable.defaults.tabIndex
11425
		 *
11426
		 *  @example
11427
		 *    $(document).ready( function() {
11428
		 *      $('#example').dataTable( {
11429
		 *        "tabIndex": 1
11430
		 *      } );
11431
		 *    } );
11432
		 */
11433
		"iTabIndex": 0,
11434
	
11435
	
11436
		/**
11437
		 * Classes that DataTables assigns to the various components and features
11438
		 * that it adds to the HTML table. This allows classes to be configured
11439
		 * during initialisation in addition to through the static
11440
		 * {@link DataTable.ext.oStdClasses} object).
11441
		 *  @namespace
11442
		 *  @name DataTable.defaults.classes
11443
		 */
11444
		"oClasses": {},
11445
	
11446
	
11447
		/**
11448
		 * All strings that DataTables uses in the user interface that it creates
11449
		 * are defined in this object, allowing you to modified them individually or
11450
		 * completely replace them all as required.
11451
		 *  @namespace
11452
		 *  @name DataTable.defaults.language
11453
		 */
11454
		"oLanguage": {
11455
			/**
11456
			 * Strings that are used for WAI-ARIA labels and controls only (these are not
11457
			 * actually visible on the page, but will be read by screenreaders, and thus
11458
			 * must be internationalised as well).
11459
			 *  @namespace
11460
			 *  @name DataTable.defaults.language.aria
11461
			 */
11462
			"oAria": {
11463
				/**
11464
				 * ARIA label that is added to the table headers when the column may be
11465
				 * sorted ascending by activing the column (click or return when focused).
11466
				 * Note that the column header is prefixed to this string.
11467
				 *  @type string
11468
				 *  @default : activate to sort column ascending
11469
				 *
11470
				 *  @dtopt Language
11471
				 *  @name DataTable.defaults.language.aria.sortAscending
11472
				 *
11473
				 *  @example
11474
				 *    $(document).ready( function() {
11475
				 *      $('#example').dataTable( {
11476
				 *        "language": {
11477
				 *          "aria": {
11478
				 *            "sortAscending": " - click/return to sort ascending"
11479
				 *          }
11480
				 *        }
11481
				 *      } );
11482
				 *    } );
11483
				 */
11484
				"sSortAscending": ": activate to sort column ascending",
11485
	
11486
				/**
11487
				 * ARIA label that is added to the table headers when the column may be
11488
				 * sorted descending by activing the column (click or return when focused).
11489
				 * Note that the column header is prefixed to this string.
11490
				 *  @type string
11491
				 *  @default : activate to sort column ascending
11492
				 *
11493
				 *  @dtopt Language
11494
				 *  @name DataTable.defaults.language.aria.sortDescending
11495
				 *
11496
				 *  @example
11497
				 *    $(document).ready( function() {
11498
				 *      $('#example').dataTable( {
11499
				 *        "language": {
11500
				 *          "aria": {
11501
				 *            "sortDescending": " - click/return to sort descending"
11502
				 *          }
11503
				 *        }
11504
				 *      } );
11505
				 *    } );
11506
				 */
11507
				"sSortDescending": ": activate to sort column descending"
11508
			},
11509
	
11510
			/**
11511
			 * Pagination string used by DataTables for the built-in pagination
11512
			 * control types.
11513
			 *  @namespace
11514
			 *  @name DataTable.defaults.language.paginate
11515
			 */
11516
			"oPaginate": {
11517
				/**
11518
				 * Text to use when using the 'full_numbers' type of pagination for the
11519
				 * button to take the user to the first page.
11520
				 *  @type string
11521
				 *  @default First
11522
				 *
11523
				 *  @dtopt Language
11524
				 *  @name DataTable.defaults.language.paginate.first
11525
				 *
11526
				 *  @example
11527
				 *    $(document).ready( function() {
11528
				 *      $('#example').dataTable( {
11529
				 *        "language": {
11530
				 *          "paginate": {
11531
				 *            "first": "First page"
11532
				 *          }
11533
				 *        }
11534
				 *      } );
11535
				 *    } );
11536
				 */
11537
				"sFirst": "First",
11538
	
11539
	
11540
				/**
11541
				 * Text to use when using the 'full_numbers' type of pagination for the
11542
				 * button to take the user to the last page.
11543
				 *  @type string
11544
				 *  @default Last
11545
				 *
11546
				 *  @dtopt Language
11547
				 *  @name DataTable.defaults.language.paginate.last
11548
				 *
11549
				 *  @example
11550
				 *    $(document).ready( function() {
11551
				 *      $('#example').dataTable( {
11552
				 *        "language": {
11553
				 *          "paginate": {
11554
				 *            "last": "Last page"
11555
				 *          }
11556
				 *        }
11557
				 *      } );
11558
				 *    } );
11559
				 */
11560
				"sLast": "Last",
11561
	
11562
	
11563
				/**
11564
				 * Text to use for the 'next' pagination button (to take the user to the
11565
				 * next page).
11566
				 *  @type string
11567
				 *  @default Next
11568
				 *
11569
				 *  @dtopt Language
11570
				 *  @name DataTable.defaults.language.paginate.next
11571
				 *
11572
				 *  @example
11573
				 *    $(document).ready( function() {
11574
				 *      $('#example').dataTable( {
11575
				 *        "language": {
11576
				 *          "paginate": {
11577
				 *            "next": "Next page"
11578
				 *          }
11579
				 *        }
11580
				 *      } );
11581
				 *    } );
11582
				 */
11583
				"sNext": "Next",
11584
	
11585
	
11586
				/**
11587
				 * Text to use for the 'previous' pagination button (to take the user to
11588
				 * the previous page).
11589
				 *  @type string
11590
				 *  @default Previous
11591
				 *
11592
				 *  @dtopt Language
11593
				 *  @name DataTable.defaults.language.paginate.previous
11594
				 *
11595
				 *  @example
11596
				 *    $(document).ready( function() {
11597
				 *      $('#example').dataTable( {
11598
				 *        "language": {
11599
				 *          "paginate": {
11600
				 *            "previous": "Previous page"
11601
				 *          }
11602
				 *        }
11603
				 *      } );
11604
				 *    } );
11605
				 */
11606
				"sPrevious": "Previous"
11607
			},
11608
	
11609
			/**
11610
			 * This string is shown in preference to `zeroRecords` when the table is
11611
			 * empty of data (regardless of filtering). Note that this is an optional
11612
			 * parameter - if it is not given, the value of `zeroRecords` will be used
11613
			 * instead (either the default or given value).
11614
			 *  @type string
11615
			 *  @default No data available in table
11616
			 *
11617
			 *  @dtopt Language
11618
			 *  @name DataTable.defaults.language.emptyTable
11619
			 *
11620
			 *  @example
11621
			 *    $(document).ready( function() {
11622
			 *      $('#example').dataTable( {
11623
			 *        "language": {
11624
			 *          "emptyTable": "No data available in table"
11625
			 *        }
11626
			 *      } );
11627
			 *    } );
11628
			 */
11629
			"sEmptyTable": "No data available in table",
11630
	
11631
	
11632
			/**
11633
			 * This string gives information to the end user about the information
11634
			 * that is current on display on the page. The following tokens can be
11635
			 * used in the string and will be dynamically replaced as the table
11636
			 * display updates. This tokens can be placed anywhere in the string, or
11637
			 * removed as needed by the language requires:
11638
			 *
11639
			 * * `\_START\_` - Display index of the first record on the current page
11640
			 * * `\_END\_` - Display index of the last record on the current page
11641
			 * * `\_TOTAL\_` - Number of records in the table after filtering
11642
			 * * `\_MAX\_` - Number of records in the table without filtering
11643
			 * * `\_PAGE\_` - Current page number
11644
			 * * `\_PAGES\_` - Total number of pages of data in the table
11645
			 *
11646
			 *  @type string
11647
			 *  @default Showing _START_ to _END_ of _TOTAL_ entries
11648
			 *
11649
			 *  @dtopt Language
11650
			 *  @name DataTable.defaults.language.info
11651
			 *
11652
			 *  @example
11653
			 *    $(document).ready( function() {
11654
			 *      $('#example').dataTable( {
11655
			 *        "language": {
11656
			 *          "info": "Showing page _PAGE_ of _PAGES_"
11657
			 *        }
11658
			 *      } );
11659
			 *    } );
11660
			 */
11661
			"sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
11662
	
11663
	
11664
			/**
11665
			 * Display information string for when the table is empty. Typically the
11666
			 * format of this string should match `info`.
11667
			 *  @type string
11668
			 *  @default Showing 0 to 0 of 0 entries
11669
			 *
11670
			 *  @dtopt Language
11671
			 *  @name DataTable.defaults.language.infoEmpty
11672
			 *
11673
			 *  @example
11674
			 *    $(document).ready( function() {
11675
			 *      $('#example').dataTable( {
11676
			 *        "language": {
11677
			 *          "infoEmpty": "No entries to show"
11678
			 *        }
11679
			 *      } );
11680
			 *    } );
11681
			 */
11682
			"sInfoEmpty": "Showing 0 to 0 of 0 entries",
11683
	
11684
	
11685
			/**
11686
			 * When a user filters the information in a table, this string is appended
11687
			 * to the information (`info`) to give an idea of how strong the filtering
11688
			 * is. The variable _MAX_ is dynamically updated.
11689
			 *  @type string
11690
			 *  @default (filtered from _MAX_ total entries)
11691
			 *
11692
			 *  @dtopt Language
11693
			 *  @name DataTable.defaults.language.infoFiltered
11694
			 *
11695
			 *  @example
11696
			 *    $(document).ready( function() {
11697
			 *      $('#example').dataTable( {
11698
			 *        "language": {
11699
			 *          "infoFiltered": " - filtering from _MAX_ records"
11700
			 *        }
11701
			 *      } );
11702
			 *    } );
11703
			 */
11704
			"sInfoFiltered": "(filtered from _MAX_ total entries)",
11705
	
11706
	
11707
			/**
11708
			 * If can be useful to append extra information to the info string at times,
11709
			 * and this variable does exactly that. This information will be appended to
11710
			 * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are
11711
			 * being used) at all times.
11712
			 *  @type string
11713
			 *  @default <i>Empty string</i>
11714
			 *
11715
			 *  @dtopt Language
11716
			 *  @name DataTable.defaults.language.infoPostFix
11717
			 *
11718
			 *  @example
11719
			 *    $(document).ready( function() {
11720
			 *      $('#example').dataTable( {
11721
			 *        "language": {
11722
			 *          "infoPostFix": "All records shown are derived from real information."
11723
			 *        }
11724
			 *      } );
11725
			 *    } );
11726
			 */
11727
			"sInfoPostFix": "",
11728
	
11729
	
11730
			/**
11731
			 * This decimal place operator is a little different from the other
11732
			 * language options since DataTables doesn't output floating point
11733
			 * numbers, so it won't ever use this for display of a number. Rather,
11734
			 * what this parameter does is modify the sort methods of the table so
11735
			 * that numbers which are in a format which has a character other than
11736
			 * a period (`.`) as a decimal place will be sorted numerically.
11737
			 *
11738
			 * Note that numbers with different decimal places cannot be shown in
11739
			 * the same table and still be sortable, the table must be consistent.
11740
			 * However, multiple different tables on the page can use different
11741
			 * decimal place characters.
11742
			 *  @type string
11743
			 *  @default 
11744
			 *
11745
			 *  @dtopt Language
11746
			 *  @name DataTable.defaults.language.decimal
11747
			 *
11748
			 *  @example
11749
			 *    $(document).ready( function() {
11750
			 *      $('#example').dataTable( {
11751
			 *        "language": {
11752
			 *          "decimal": ","
11753
			 *          "thousands": "."
11754
			 *        }
11755
			 *      } );
11756
			 *    } );
11757
			 */
11758
			"sDecimal": "",
11759
	
11760
	
11761
			/**
11762
			 * DataTables has a build in number formatter (`formatNumber`) which is
11763
			 * used to format large numbers that are used in the table information.
11764
			 * By default a comma is used, but this can be trivially changed to any
11765
			 * character you wish with this parameter.
11766
			 *  @type string
11767
			 *  @default ,
11768
			 *
11769
			 *  @dtopt Language
11770
			 *  @name DataTable.defaults.language.thousands
11771
			 *
11772
			 *  @example
11773
			 *    $(document).ready( function() {
11774
			 *      $('#example').dataTable( {
11775
			 *        "language": {
11776
			 *          "thousands": "'"
11777
			 *        }
11778
			 *      } );
11779
			 *    } );
11780
			 */
11781
			"sThousands": ",",
11782
	
11783
	
11784
			/**
11785
			 * Detail the action that will be taken when the drop down menu for the
11786
			 * pagination length option is changed. The '_MENU_' variable is replaced
11787
			 * with a default select list of 10, 25, 50 and 100, and can be replaced
11788
			 * with a custom select box if required.
11789
			 *  @type string
11790
			 *  @default Show _MENU_ entries
11791
			 *
11792
			 *  @dtopt Language
11793
			 *  @name DataTable.defaults.language.lengthMenu
11794
			 *
11795
			 *  @example
11796
			 *    // Language change only
11797
			 *    $(document).ready( function() {
11798
			 *      $('#example').dataTable( {
11799
			 *        "language": {
11800
			 *          "lengthMenu": "Display _MENU_ records"
11801
			 *        }
11802
			 *      } );
11803
			 *    } );
11804
			 *
11805
			 *  @example
11806
			 *    // Language and options change
11807
			 *    $(document).ready( function() {
11808
			 *      $('#example').dataTable( {
11809
			 *        "language": {
11810
			 *          "lengthMenu": 'Display <select>'+
11811
			 *            '<option value="10">10</option>'+
11812
			 *            '<option value="20">20</option>'+
11813
			 *            '<option value="30">30</option>'+
11814
			 *            '<option value="40">40</option>'+
11815
			 *            '<option value="50">50</option>'+
11816
			 *            '<option value="-1">All</option>'+
11817
			 *            '</select> records'
11818
			 *        }
11819
			 *      } );
11820
			 *    } );
11821
			 */
11822
			"sLengthMenu": "Show _MENU_ entries",
11823
	
11824
	
11825
			/**
11826
			 * When using Ajax sourced data and during the first draw when DataTables is
11827
			 * gathering the data, this message is shown in an empty row in the table to
11828
			 * indicate to the end user the the data is being loaded. Note that this
11829
			 * parameter is not used when loading data by server-side processing, just
11830
			 * Ajax sourced data with client-side processing.
11831
			 *  @type string
11832
			 *  @default Loading...
11833
			 *
11834
			 *  @dtopt Language
11835
			 *  @name DataTable.defaults.language.loadingRecords
11836
			 *
11837
			 *  @example
11838
			 *    $(document).ready( function() {
11839
			 *      $('#example').dataTable( {
11840
			 *        "language": {
11841
			 *          "loadingRecords": "Please wait - loading..."
11842
			 *        }
11843
			 *      } );
11844
			 *    } );
11845
			 */
11846
			"sLoadingRecords": "Loading...",
11847
	
11848
	
11849
			/**
11850
			 * Text which is displayed when the table is processing a user action
11851
			 * (usually a sort command or similar).
11852
			 *  @type string
11853
			 *  @default Processing...
11854
			 *
11855
			 *  @dtopt Language
11856
			 *  @name DataTable.defaults.language.processing
11857
			 *
11858
			 *  @example
11859
			 *    $(document).ready( function() {
11860
			 *      $('#example').dataTable( {
11861
			 *        "language": {
11862
			 *          "processing": "DataTables is currently busy"
11863
			 *        }
11864
			 *      } );
11865
			 *    } );
11866
			 */
11867
			"sProcessing": "Processing...",
11868
	
11869
	
11870
			/**
11871
			 * Details the actions that will be taken when the user types into the
11872
			 * filtering input text box. The variable "_INPUT_", if used in the string,
11873
			 * is replaced with the HTML text box for the filtering input allowing
11874
			 * control over where it appears in the string. If "_INPUT_" is not given
11875
			 * then the input box is appended to the string automatically.
11876
			 *  @type string
11877
			 *  @default Search:
11878
			 *
11879
			 *  @dtopt Language
11880
			 *  @name DataTable.defaults.language.search
11881
			 *
11882
			 *  @example
11883
			 *    // Input text box will be appended at the end automatically
11884
			 *    $(document).ready( function() {
11885
			 *      $('#example').dataTable( {
11886
			 *        "language": {
11887
			 *          "search": "Filter records:"
11888
			 *        }
11889
			 *      } );
11890
			 *    } );
11891
			 *
11892
			 *  @example
11893
			 *    // Specify where the filter should appear
11894
			 *    $(document).ready( function() {
11895
			 *      $('#example').dataTable( {
11896
			 *        "language": {
11897
			 *          "search": "Apply filter _INPUT_ to table"
11898
			 *        }
11899
			 *      } );
11900
			 *    } );
11901
			 */
11902
			"sSearch": "Search:",
11903
	
11904
	
11905
			/**
11906
			 * Assign a `placeholder` attribute to the search `input` element
11907
			 *  @type string
11908
			 *  @default 
11909
			 *
11910
			 *  @dtopt Language
11911
			 *  @name DataTable.defaults.language.searchPlaceholder
11912
			 */
11913
			"sSearchPlaceholder": "",
11914
	
11915
	
11916
			/**
11917
			 * All of the language information can be stored in a file on the
11918
			 * server-side, which DataTables will look up if this parameter is passed.
11919
			 * It must store the URL of the language file, which is in a JSON format,
11920
			 * and the object has the same properties as the oLanguage object in the
11921
			 * initialiser object (i.e. the above parameters). Please refer to one of
11922
			 * the example language files to see how this works in action.
11923
			 *  @type string
11924
			 *  @default <i>Empty string - i.e. disabled</i>
11925
			 *
11926
			 *  @dtopt Language
11927
			 *  @name DataTable.defaults.language.url
11928
			 *
11929
			 *  @example
11930
			 *    $(document).ready( function() {
11931
			 *      $('#example').dataTable( {
11932
			 *        "language": {
11933
			 *          "url": "http://www.sprymedia.co.uk/dataTables/lang.txt"
11934
			 *        }
11935
			 *      } );
11936
			 *    } );
11937
			 */
11938
			"sUrl": "",
11939
	
11940
	
11941
			/**
11942
			 * Text shown inside the table records when the is no information to be
11943
			 * displayed after filtering. `emptyTable` is shown when there is simply no
11944
			 * information in the table at all (regardless of filtering).
11945
			 *  @type string
11946
			 *  @default No matching records found
11947
			 *
11948
			 *  @dtopt Language
11949
			 *  @name DataTable.defaults.language.zeroRecords
11950
			 *
11951
			 *  @example
11952
			 *    $(document).ready( function() {
11953
			 *      $('#example').dataTable( {
11954
			 *        "language": {
11955
			 *          "zeroRecords": "No records to display"
11956
			 *        }
11957
			 *      } );
11958
			 *    } );
11959
			 */
11960
			"sZeroRecords": "No matching records found"
11961
		},
11962
	
11963
	
11964
		/**
11965
		 * This parameter allows you to have define the global filtering state at
11966
		 * initialisation time. As an object the `search` parameter must be
11967
		 * defined, but all other parameters are optional. When `regex` is true,
11968
		 * the search string will be treated as a regular expression, when false
11969
		 * (default) it will be treated as a straight string. When `smart`
11970
		 * DataTables will use it's smart filtering methods (to word match at
11971
		 * any point in the data), when false this will not be done.
11972
		 *  @namespace
11973
		 *  @extends DataTable.models.oSearch
11974
		 *
11975
		 *  @dtopt Options
11976
		 *  @name DataTable.defaults.search
11977
		 *
11978
		 *  @example
11979
		 *    $(document).ready( function() {
11980
		 *      $('#example').dataTable( {
11981
		 *        "search": {"search": "Initial search"}
11982
		 *      } );
11983
		 *    } )
11984
		 */
11985
		"oSearch": $.extend( {}, DataTable.models.oSearch ),
11986
	
11987
	
11988
		/**
11989
		 * __Deprecated__ The functionality provided by this parameter has now been
11990
		 * superseded by that provided through `ajax`, which should be used instead.
11991
		 *
11992
		 * By default DataTables will look for the property `data` (or `aaData` for
11993
		 * compatibility with DataTables 1.9-) when obtaining data from an Ajax
11994
		 * source or for server-side processing - this parameter allows that
11995
		 * property to be changed. You can use Javascript dotted object notation to
11996
		 * get a data source for multiple levels of nesting.
11997
		 *  @type string
11998
		 *  @default data
11999
		 *
12000
		 *  @dtopt Options
12001
		 *  @dtopt Server-side
12002
		 *  @name DataTable.defaults.ajaxDataProp
12003
		 *
12004
		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
12005
		 */
12006
		"sAjaxDataProp": "data",
12007
	
12008
	
12009
		/**
12010
		 * __Deprecated__ The functionality provided by this parameter has now been
12011
		 * superseded by that provided through `ajax`, which should be used instead.
12012
		 *
12013
		 * You can instruct DataTables to load data from an external
12014
		 * source using this parameter (use aData if you want to pass data in you
12015
		 * already have). Simply provide a url a JSON object can be obtained from.
12016
		 *  @type string
12017
		 *  @default null
12018
		 *
12019
		 *  @dtopt Options
12020
		 *  @dtopt Server-side
12021
		 *  @name DataTable.defaults.ajaxSource
12022
		 *
12023
		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
12024
		 */
12025
		"sAjaxSource": null,
12026
	
12027
	
12028
		/**
12029
		 * This initialisation variable allows you to specify exactly where in the
12030
		 * DOM you want DataTables to inject the various controls it adds to the page
12031
		 * (for example you might want the pagination controls at the top of the
12032
		 * table). DIV elements (with or without a custom class) can also be added to
12033
		 * aid styling. The follow syntax is used:
12034
		 *   <ul>
12035
		 *     <li>The following options are allowed:
12036
		 *       <ul>
12037
		 *         <li>'l' - Length changing</li>
12038
		 *         <li>'f' - Filtering input</li>
12039
		 *         <li>'t' - The table!</li>
12040
		 *         <li>'i' - Information</li>
12041
		 *         <li>'p' - Pagination</li>
12042
		 *         <li>'r' - pRocessing</li>
12043
		 *       </ul>
12044
		 *     </li>
12045
		 *     <li>The following constants are allowed:
12046
		 *       <ul>
12047
		 *         <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>
12048
		 *         <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>
12049
		 *       </ul>
12050
		 *     </li>
12051
		 *     <li>The following syntax is expected:
12052
		 *       <ul>
12053
		 *         <li>'&lt;' and '&gt;' - div elements</li>
12054
		 *         <li>'&lt;"class" and '&gt;' - div with a class</li>
12055
		 *         <li>'&lt;"#id" and '&gt;' - div with an ID</li>
12056
		 *       </ul>
12057
		 *     </li>
12058
		 *     <li>Examples:
12059
		 *       <ul>
12060
		 *         <li>'&lt;"wrapper"flipt&gt;'</li>
12061
		 *         <li>'&lt;lf&lt;t&gt;ip&gt;'</li>
12062
		 *       </ul>
12063
		 *     </li>
12064
		 *   </ul>
12065
		 *  @type string
12066
		 *  @default lfrtip <i>(when `jQueryUI` is false)</i> <b>or</b>
12067
		 *    <"H"lfr>t<"F"ip> <i>(when `jQueryUI` is true)</i>
12068
		 *
12069
		 *  @dtopt Options
12070
		 *  @name DataTable.defaults.dom
12071
		 *
12072
		 *  @example
12073
		 *    $(document).ready( function() {
12074
		 *      $('#example').dataTable( {
12075
		 *        "dom": '&lt;"top"i&gt;rt&lt;"bottom"flp&gt;&lt;"clear"&gt;'
12076
		 *      } );
12077
		 *    } );
12078
		 */
12079
		"sDom": "lfrtip",
12080
	
12081
	
12082
		/**
12083
		 * Search delay option. This will throttle full table searches that use the
12084
		 * DataTables provided search input element (it does not effect calls to
12085
		 * `dt-api search()`, providing a delay before the search is made.
12086
		 *  @type integer
12087
		 *  @default 0
12088
		 *
12089
		 *  @dtopt Options
12090
		 *  @name DataTable.defaults.searchDelay
12091
		 *
12092
		 *  @example
12093
		 *    $(document).ready( function() {
12094
		 *      $('#example').dataTable( {
12095
		 *        "searchDelay": 200
12096
		 *      } );
12097
		 *    } )
12098
		 */
12099
		"searchDelay": null,
12100
	
12101
	
12102
		/**
12103
		 * DataTables features six different built-in options for the buttons to
12104
		 * display for pagination control:
12105
		 *
12106
		 * * `numbers` - Page number buttons only
12107
		 * * `simple` - 'Previous' and 'Next' buttons only
12108
		 * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers
12109
		 * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons
12110
		 * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus page numbers
12111
		 * * `first_last_numbers` - 'First' and 'Last' buttons, plus page numbers
12112
		 *  
12113
		 * Further methods can be added using {@link DataTable.ext.oPagination}.
12114
		 *  @type string
12115
		 *  @default simple_numbers
12116
		 *
12117
		 *  @dtopt Options
12118
		 *  @name DataTable.defaults.pagingType
12119
		 *
12120
		 *  @example
12121
		 *    $(document).ready( function() {
12122
		 *      $('#example').dataTable( {
12123
		 *        "pagingType": "full_numbers"
12124
		 *      } );
12125
		 *    } )
12126
		 */
12127
		"sPaginationType": "simple_numbers",
12128
	
12129
	
12130
		/**
12131
		 * Enable horizontal scrolling. When a table is too wide to fit into a
12132
		 * certain layout, or you have a large number of columns in the table, you
12133
		 * can enable x-scrolling to show the table in a viewport, which can be
12134
		 * scrolled. This property can be `true` which will allow the table to
12135
		 * scroll horizontally when needed, or any CSS unit, or a number (in which
12136
		 * case it will be treated as a pixel measurement). Setting as simply `true`
12137
		 * is recommended.
12138
		 *  @type boolean|string
12139
		 *  @default <i>blank string - i.e. disabled</i>
12140
		 *
12141
		 *  @dtopt Features
12142
		 *  @name DataTable.defaults.scrollX
12143
		 *
12144
		 *  @example
12145
		 *    $(document).ready( function() {
12146
		 *      $('#example').dataTable( {
12147
		 *        "scrollX": true,
12148
		 *        "scrollCollapse": true
12149
		 *      } );
12150
		 *    } );
12151
		 */
12152
		"sScrollX": "",
12153
	
12154
	
12155
		/**
12156
		 * This property can be used to force a DataTable to use more width than it
12157
		 * might otherwise do when x-scrolling is enabled. For example if you have a
12158
		 * table which requires to be well spaced, this parameter is useful for
12159
		 * "over-sizing" the table, and thus forcing scrolling. This property can by
12160
		 * any CSS unit, or a number (in which case it will be treated as a pixel
12161
		 * measurement).
12162
		 *  @type string
12163
		 *  @default <i>blank string - i.e. disabled</i>
12164
		 *
12165
		 *  @dtopt Options
12166
		 *  @name DataTable.defaults.scrollXInner
12167
		 *
12168
		 *  @example
12169
		 *    $(document).ready( function() {
12170
		 *      $('#example').dataTable( {
12171
		 *        "scrollX": "100%",
12172
		 *        "scrollXInner": "110%"
12173
		 *      } );
12174
		 *    } );
12175
		 */
12176
		"sScrollXInner": "",
12177
	
12178
	
12179
		/**
12180
		 * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
12181
		 * to the given height, and enable scrolling for any data which overflows the
12182
		 * current viewport. This can be used as an alternative to paging to display
12183
		 * a lot of data in a small area (although paging and scrolling can both be
12184
		 * enabled at the same time). This property can be any CSS unit, or a number
12185
		 * (in which case it will be treated as a pixel measurement).
12186
		 *  @type string
12187
		 *  @default <i>blank string - i.e. disabled</i>
12188
		 *
12189
		 *  @dtopt Features
12190
		 *  @name DataTable.defaults.scrollY
12191
		 *
12192
		 *  @example
12193
		 *    $(document).ready( function() {
12194
		 *      $('#example').dataTable( {
12195
		 *        "scrollY": "200px",
12196
		 *        "paginate": false
12197
		 *      } );
12198
		 *    } );
12199
		 */
12200
		"sScrollY": "",
12201
	
12202
	
12203
		/**
12204
		 * __Deprecated__ The functionality provided by this parameter has now been
12205
		 * superseded by that provided through `ajax`, which should be used instead.
12206
		 *
12207
		 * Set the HTTP method that is used to make the Ajax call for server-side
12208
		 * processing or Ajax sourced data.
12209
		 *  @type string
12210
		 *  @default GET
12211
		 *
12212
		 *  @dtopt Options
12213
		 *  @dtopt Server-side
12214
		 *  @name DataTable.defaults.serverMethod
12215
		 *
12216
		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
12217
		 */
12218
		"sServerMethod": "GET",
12219
	
12220
	
12221
		/**
12222
		 * DataTables makes use of renderers when displaying HTML elements for
12223
		 * a table. These renderers can be added or modified by plug-ins to
12224
		 * generate suitable mark-up for a site. For example the Bootstrap
12225
		 * integration plug-in for DataTables uses a paging button renderer to
12226
		 * display pagination buttons in the mark-up required by Bootstrap.
12227
		 *
12228
		 * For further information about the renderers available see
12229
		 * DataTable.ext.renderer
12230
		 *  @type string|object
12231
		 *  @default null
12232
		 *
12233
		 *  @name DataTable.defaults.renderer
12234
		 *
12235
		 */
12236
		"renderer": null,
12237
	
12238
	
12239
		/**
12240
		 * Set the data property name that DataTables should use to get a row's id
12241
		 * to set as the `id` property in the node.
12242
		 *  @type string
12243
		 *  @default DT_RowId
12244
		 *
12245
		 *  @name DataTable.defaults.rowId
12246
		 */
12247
		"rowId": "DT_RowId"
12248
	};
12249
	
12250
	_fnHungarianMap( DataTable.defaults );
12251
	
12252
	
12253
	
12254
	/*
12255
	 * Developer note - See note in model.defaults.js about the use of Hungarian
12256
	 * notation and camel case.
12257
	 */
12258
	
12259
	/**
12260
	 * Column options that can be given to DataTables at initialisation time.
12261
	 *  @namespace
12262
	 */
12263
	DataTable.defaults.column = {
12264
		/**
12265
		 * Define which column(s) an order will occur on for this column. This
12266
		 * allows a column's ordering to take multiple columns into account when
12267
		 * doing a sort or use the data from a different column. For example first
12268
		 * name / last name columns make sense to do a multi-column sort over the
12269
		 * two columns.
12270
		 *  @type array|int
12271
		 *  @default null <i>Takes the value of the column index automatically</i>
12272
		 *
12273
		 *  @name DataTable.defaults.column.orderData
12274
		 *  @dtopt Columns
12275
		 *
12276
		 *  @example
12277
		 *    // Using `columnDefs`
12278
		 *    $(document).ready( function() {
12279
		 *      $('#example').dataTable( {
12280
		 *        "columnDefs": [
12281
		 *          { "orderData": [ 0, 1 ], "targets": [ 0 ] },
12282
		 *          { "orderData": [ 1, 0 ], "targets": [ 1 ] },
12283
		 *          { "orderData": 2, "targets": [ 2 ] }
12284
		 *        ]
12285
		 *      } );
12286
		 *    } );
12287
		 *
12288
		 *  @example
12289
		 *    // Using `columns`
12290
		 *    $(document).ready( function() {
12291
		 *      $('#example').dataTable( {
12292
		 *        "columns": [
12293
		 *          { "orderData": [ 0, 1 ] },
12294
		 *          { "orderData": [ 1, 0 ] },
12295
		 *          { "orderData": 2 },
12296
		 *          null,
12297
		 *          null
12298
		 *        ]
12299
		 *      } );
12300
		 *    } );
12301
		 */
12302
		"aDataSort": null,
12303
		"iDataSort": -1,
12304
	
12305
	
12306
		/**
12307
		 * You can control the default ordering direction, and even alter the
12308
		 * behaviour of the sort handler (i.e. only allow ascending ordering etc)
12309
		 * using this parameter.
12310
		 *  @type array
12311
		 *  @default [ 'asc', 'desc' ]
12312
		 *
12313
		 *  @name DataTable.defaults.column.orderSequence
12314
		 *  @dtopt Columns
12315
		 *
12316
		 *  @example
12317
		 *    // Using `columnDefs`
12318
		 *    $(document).ready( function() {
12319
		 *      $('#example').dataTable( {
12320
		 *        "columnDefs": [
12321
		 *          { "orderSequence": [ "asc" ], "targets": [ 1 ] },
12322
		 *          { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] },
12323
		 *          { "orderSequence": [ "desc" ], "targets": [ 3 ] }
12324
		 *        ]
12325
		 *      } );
12326
		 *    } );
12327
		 *
12328
		 *  @example
12329
		 *    // Using `columns`
12330
		 *    $(document).ready( function() {
12331
		 *      $('#example').dataTable( {
12332
		 *        "columns": [
12333
		 *          null,
12334
		 *          { "orderSequence": [ "asc" ] },
12335
		 *          { "orderSequence": [ "desc", "asc", "asc" ] },
12336
		 *          { "orderSequence": [ "desc" ] },
12337
		 *          null
12338
		 *        ]
12339
		 *      } );
12340
		 *    } );
12341
		 */
12342
		"asSorting": [ 'asc', 'desc' ],
12343
	
12344
	
12345
		/**
12346
		 * Enable or disable filtering on the data in this column.
12347
		 *  @type boolean
12348
		 *  @default true
12349
		 *
12350
		 *  @name DataTable.defaults.column.searchable
12351
		 *  @dtopt Columns
12352
		 *
12353
		 *  @example
12354
		 *    // Using `columnDefs`
12355
		 *    $(document).ready( function() {
12356
		 *      $('#example').dataTable( {
12357
		 *        "columnDefs": [
12358
		 *          { "searchable": false, "targets": [ 0 ] }
12359
		 *        ] } );
12360
		 *    } );
12361
		 *
12362
		 *  @example
12363
		 *    // Using `columns`
12364
		 *    $(document).ready( function() {
12365
		 *      $('#example').dataTable( {
12366
		 *        "columns": [
12367
		 *          { "searchable": false },
12368
		 *          null,
12369
		 *          null,
12370
		 *          null,
12371
		 *          null
12372
		 *        ] } );
12373
		 *    } );
12374
		 */
12375
		"bSearchable": true,
12376
	
12377
	
12378
		/**
12379
		 * Enable or disable ordering on this column.
12380
		 *  @type boolean
12381
		 *  @default true
12382
		 *
12383
		 *  @name DataTable.defaults.column.orderable
12384
		 *  @dtopt Columns
12385
		 *
12386
		 *  @example
12387
		 *    // Using `columnDefs`
12388
		 *    $(document).ready( function() {
12389
		 *      $('#example').dataTable( {
12390
		 *        "columnDefs": [
12391
		 *          { "orderable": false, "targets": [ 0 ] }
12392
		 *        ] } );
12393
		 *    } );
12394
		 *
12395
		 *  @example
12396
		 *    // Using `columns`
12397
		 *    $(document).ready( function() {
12398
		 *      $('#example').dataTable( {
12399
		 *        "columns": [
12400
		 *          { "orderable": false },
12401
		 *          null,
12402
		 *          null,
12403
		 *          null,
12404
		 *          null
12405
		 *        ] } );
12406
		 *    } );
12407
		 */
12408
		"bSortable": true,
12409
	
12410
	
12411
		/**
12412
		 * Enable or disable the display of this column.
12413
		 *  @type boolean
12414
		 *  @default true
12415
		 *
12416
		 *  @name DataTable.defaults.column.visible
12417
		 *  @dtopt Columns
12418
		 *
12419
		 *  @example
12420
		 *    // Using `columnDefs`
12421
		 *    $(document).ready( function() {
12422
		 *      $('#example').dataTable( {
12423
		 *        "columnDefs": [
12424
		 *          { "visible": false, "targets": [ 0 ] }
12425
		 *        ] } );
12426
		 *    } );
12427
		 *
12428
		 *  @example
12429
		 *    // Using `columns`
12430
		 *    $(document).ready( function() {
12431
		 *      $('#example').dataTable( {
12432
		 *        "columns": [
12433
		 *          { "visible": false },
12434
		 *          null,
12435
		 *          null,
12436
		 *          null,
12437
		 *          null
12438
		 *        ] } );
12439
		 *    } );
12440
		 */
12441
		"bVisible": true,
12442
	
12443
	
12444
		/**
12445
		 * Developer definable function that is called whenever a cell is created (Ajax source,
12446
		 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
12447
		 * allowing you to modify the DOM element (add background colour for example) when the
12448
		 * element is available.
12449
		 *  @type function
12450
		 *  @param {element} td The TD node that has been created
12451
		 *  @param {*} cellData The Data for the cell
12452
		 *  @param {array|object} rowData The data for the whole row
12453
		 *  @param {int} row The row index for the aoData data store
12454
		 *  @param {int} col The column index for aoColumns
12455
		 *
12456
		 *  @name DataTable.defaults.column.createdCell
12457
		 *  @dtopt Columns
12458
		 *
12459
		 *  @example
12460
		 *    $(document).ready( function() {
12461
		 *      $('#example').dataTable( {
12462
		 *        "columnDefs": [ {
12463
		 *          "targets": [3],
12464
		 *          "createdCell": function (td, cellData, rowData, row, col) {
12465
		 *            if ( cellData == "1.7" ) {
12466
		 *              $(td).css('color', 'blue')
12467
		 *            }
12468
		 *          }
12469
		 *        } ]
12470
		 *      });
12471
		 *    } );
12472
		 */
12473
		"fnCreatedCell": null,
12474
	
12475
	
12476
		/**
12477
		 * This parameter has been replaced by `data` in DataTables to ensure naming
12478
		 * consistency. `dataProp` can still be used, as there is backwards
12479
		 * compatibility in DataTables for this option, but it is strongly
12480
		 * recommended that you use `data` in preference to `dataProp`.
12481
		 *  @name DataTable.defaults.column.dataProp
12482
		 */
12483
	
12484
	
12485
		/**
12486
		 * This property can be used to read data from any data source property,
12487
		 * including deeply nested objects / properties. `data` can be given in a
12488
		 * number of different ways which effect its behaviour:
12489
		 *
12490
		 * * `integer` - treated as an array index for the data source. This is the
12491
		 *   default that DataTables uses (incrementally increased for each column).
12492
		 * * `string` - read an object property from the data source. There are
12493
		 *   three 'special' options that can be used in the string to alter how
12494
		 *   DataTables reads the data from the source object:
12495
		 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
12496
		 *      Javascript to read from nested objects, so to can the options
12497
		 *      specified in `data`. For example: `browser.version` or
12498
		 *      `browser.name`. If your object parameter name contains a period, use
12499
		 *      `\\` to escape it - i.e. `first\\.name`.
12500
		 *    * `[]` - Array notation. DataTables can automatically combine data
12501
		 *      from and array source, joining the data with the characters provided
12502
		 *      between the two brackets. For example: `name[, ]` would provide a
12503
		 *      comma-space separated list from the source array. If no characters
12504
		 *      are provided between the brackets, the original array source is
12505
		 *      returned.
12506
		 *    * `()` - Function notation. Adding `()` to the end of a parameter will
12507
		 *      execute a function of the name given. For example: `browser()` for a
12508
		 *      simple function on the data source, `browser.version()` for a
12509
		 *      function in a nested property or even `browser().version` to get an
12510
		 *      object property if the function called returns an object. Note that
12511
		 *      function notation is recommended for use in `render` rather than
12512
		 *      `data` as it is much simpler to use as a renderer.
12513
		 * * `null` - use the original data source for the row rather than plucking
12514
		 *   data directly from it. This action has effects on two other
12515
		 *   initialisation options:
12516
		 *    * `defaultContent` - When null is given as the `data` option and
12517
		 *      `defaultContent` is specified for the column, the value defined by
12518
		 *      `defaultContent` will be used for the cell.
12519
		 *    * `render` - When null is used for the `data` option and the `render`
12520
		 *      option is specified for the column, the whole data source for the
12521
		 *      row is used for the renderer.
12522
		 * * `function` - the function given will be executed whenever DataTables
12523
		 *   needs to set or get the data for a cell in the column. The function
12524
		 *   takes three parameters:
12525
		 *    * Parameters:
12526
		 *      * `{array|object}` The data source for the row
12527
		 *      * `{string}` The type call data requested - this will be 'set' when
12528
		 *        setting data or 'filter', 'display', 'type', 'sort' or undefined
12529
		 *        when gathering data. Note that when `undefined` is given for the
12530
		 *        type DataTables expects to get the raw data for the object back<
12531
		 *      * `{*}` Data to set when the second parameter is 'set'.
12532
		 *    * Return:
12533
		 *      * The return value from the function is not required when 'set' is
12534
		 *        the type of call, but otherwise the return is what will be used
12535
		 *        for the data requested.
12536
		 *
12537
		 * Note that `data` is a getter and setter option. If you just require
12538
		 * formatting of data for output, you will likely want to use `render` which
12539
		 * is simply a getter and thus simpler to use.
12540
		 *
12541
		 * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The
12542
		 * name change reflects the flexibility of this property and is consistent
12543
		 * with the naming of mRender. If 'mDataProp' is given, then it will still
12544
		 * be used by DataTables, as it automatically maps the old name to the new
12545
		 * if required.
12546
		 *
12547
		 *  @type string|int|function|null
12548
		 *  @default null <i>Use automatically calculated column index</i>
12549
		 *
12550
		 *  @name DataTable.defaults.column.data
12551
		 *  @dtopt Columns
12552
		 *
12553
		 *  @example
12554
		 *    // Read table data from objects
12555
		 *    // JSON structure for each row:
12556
		 *    //   {
12557
		 *    //      "engine": {value},
12558
		 *    //      "browser": {value},
12559
		 *    //      "platform": {value},
12560
		 *    //      "version": {value},
12561
		 *    //      "grade": {value}
12562
		 *    //   }
12563
		 *    $(document).ready( function() {
12564
		 *      $('#example').dataTable( {
12565
		 *        "ajaxSource": "sources/objects.txt",
12566
		 *        "columns": [
12567
		 *          { "data": "engine" },
12568
		 *          { "data": "browser" },
12569
		 *          { "data": "platform" },
12570
		 *          { "data": "version" },
12571
		 *          { "data": "grade" }
12572
		 *        ]
12573
		 *      } );
12574
		 *    } );
12575
		 *
12576
		 *  @example
12577
		 *    // Read information from deeply nested objects
12578
		 *    // JSON structure for each row:
12579
		 *    //   {
12580
		 *    //      "engine": {value},
12581
		 *    //      "browser": {value},
12582
		 *    //      "platform": {
12583
		 *    //         "inner": {value}
12584
		 *    //      },
12585
		 *    //      "details": [
12586
		 *    //         {value}, {value}
12587
		 *    //      ]
12588
		 *    //   }
12589
		 *    $(document).ready( function() {
12590
		 *      $('#example').dataTable( {
12591
		 *        "ajaxSource": "sources/deep.txt",
12592
		 *        "columns": [
12593
		 *          { "data": "engine" },
12594
		 *          { "data": "browser" },
12595
		 *          { "data": "platform.inner" },
12596
		 *          { "data": "details.0" },
12597
		 *          { "data": "details.1" }
12598
		 *        ]
12599
		 *      } );
12600
		 *    } );
12601
		 *
12602
		 *  @example
12603
		 *    // Using `data` as a function to provide different information for
12604
		 *    // sorting, filtering and display. In this case, currency (price)
12605
		 *    $(document).ready( function() {
12606
		 *      $('#example').dataTable( {
12607
		 *        "columnDefs": [ {
12608
		 *          "targets": [ 0 ],
12609
		 *          "data": function ( source, type, val ) {
12610
		 *            if (type === 'set') {
12611
		 *              source.price = val;
12612
		 *              // Store the computed display and filter values for efficiency
12613
		 *              source.price_display = val=="" ? "" : "$"+numberFormat(val);
12614
		 *              source.price_filter  = val=="" ? "" : "$"+numberFormat(val)+" "+val;
12615
		 *              return;
12616
		 *            }
12617
		 *            else if (type === 'display') {
12618
		 *              return source.price_display;
12619
		 *            }
12620
		 *            else if (type === 'filter') {
12621
		 *              return source.price_filter;
12622
		 *            }
12623
		 *            // 'sort', 'type' and undefined all just use the integer
12624
		 *            return source.price;
12625
		 *          }
12626
		 *        } ]
12627
		 *      } );
12628
		 *    } );
12629
		 *
12630
		 *  @example
12631
		 *    // Using default content
12632
		 *    $(document).ready( function() {
12633
		 *      $('#example').dataTable( {
12634
		 *        "columnDefs": [ {
12635
		 *          "targets": [ 0 ],
12636
		 *          "data": null,
12637
		 *          "defaultContent": "Click to edit"
12638
		 *        } ]
12639
		 *      } );
12640
		 *    } );
12641
		 *
12642
		 *  @example
12643
		 *    // Using array notation - outputting a list from an array
12644
		 *    $(document).ready( function() {
12645
		 *      $('#example').dataTable( {
12646
		 *        "columnDefs": [ {
12647
		 *          "targets": [ 0 ],
12648
		 *          "data": "name[, ]"
12649
		 *        } ]
12650
		 *      } );
12651
		 *    } );
12652
		 *
12653
		 */
12654
		"mData": null,
12655
	
12656
	
12657
		/**
12658
		 * This property is the rendering partner to `data` and it is suggested that
12659
		 * when you want to manipulate data for display (including filtering,
12660
		 * sorting etc) without altering the underlying data for the table, use this
12661
		 * property. `render` can be considered to be the the read only companion to
12662
		 * `data` which is read / write (then as such more complex). Like `data`
12663
		 * this option can be given in a number of different ways to effect its
12664
		 * behaviour:
12665
		 *
12666
		 * * `integer` - treated as an array index for the data source. This is the
12667
		 *   default that DataTables uses (incrementally increased for each column).
12668
		 * * `string` - read an object property from the data source. There are
12669
		 *   three 'special' options that can be used in the string to alter how
12670
		 *   DataTables reads the data from the source object:
12671
		 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
12672
		 *      Javascript to read from nested objects, so to can the options
12673
		 *      specified in `data`. For example: `browser.version` or
12674
		 *      `browser.name`. If your object parameter name contains a period, use
12675
		 *      `\\` to escape it - i.e. `first\\.name`.
12676
		 *    * `[]` - Array notation. DataTables can automatically combine data
12677
		 *      from and array source, joining the data with the characters provided
12678
		 *      between the two brackets. For example: `name[, ]` would provide a
12679
		 *      comma-space separated list from the source array. If no characters
12680
		 *      are provided between the brackets, the original array source is
12681
		 *      returned.
12682
		 *    * `()` - Function notation. Adding `()` to the end of a parameter will
12683
		 *      execute a function of the name given. For example: `browser()` for a
12684
		 *      simple function on the data source, `browser.version()` for a
12685
		 *      function in a nested property or even `browser().version` to get an
12686
		 *      object property if the function called returns an object.
12687
		 * * `object` - use different data for the different data types requested by
12688
		 *   DataTables ('filter', 'display', 'type' or 'sort'). The property names
12689
		 *   of the object is the data type the property refers to and the value can
12690
		 *   defined using an integer, string or function using the same rules as
12691
		 *   `render` normally does. Note that an `_` option _must_ be specified.
12692
		 *   This is the default value to use if you haven't specified a value for
12693
		 *   the data type requested by DataTables.
12694
		 * * `function` - the function given will be executed whenever DataTables
12695
		 *   needs to set or get the data for a cell in the column. The function
12696
		 *   takes three parameters:
12697
		 *    * Parameters:
12698
		 *      * {array|object} The data source for the row (based on `data`)
12699
		 *      * {string} The type call data requested - this will be 'filter',
12700
		 *        'display', 'type' or 'sort'.
12701
		 *      * {array|object} The full data source for the row (not based on
12702
		 *        `data`)
12703
		 *    * Return:
12704
		 *      * The return value from the function is what will be used for the
12705
		 *        data requested.
12706
		 *
12707
		 *  @type string|int|function|object|null
12708
		 *  @default null Use the data source value.
12709
		 *
12710
		 *  @name DataTable.defaults.column.render
12711
		 *  @dtopt Columns
12712
		 *
12713
		 *  @example
12714
		 *    // Create a comma separated list from an array of objects
12715
		 *    $(document).ready( function() {
12716
		 *      $('#example').dataTable( {
12717
		 *        "ajaxSource": "sources/deep.txt",
12718
		 *        "columns": [
12719
		 *          { "data": "engine" },
12720
		 *          { "data": "browser" },
12721
		 *          {
12722
		 *            "data": "platform",
12723
		 *            "render": "[, ].name"
12724
		 *          }
12725
		 *        ]
12726
		 *      } );
12727
		 *    } );
12728
		 *
12729
		 *  @example
12730
		 *    // Execute a function to obtain data
12731
		 *    $(document).ready( function() {
12732
		 *      $('#example').dataTable( {
12733
		 *        "columnDefs": [ {
12734
		 *          "targets": [ 0 ],
12735
		 *          "data": null, // Use the full data source object for the renderer's source
12736
		 *          "render": "browserName()"
12737
		 *        } ]
12738
		 *      } );
12739
		 *    } );
12740
		 *
12741
		 *  @example
12742
		 *    // As an object, extracting different data for the different types
12743
		 *    // This would be used with a data source such as:
12744
		 *    //   { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" }
12745
		 *    // Here the `phone` integer is used for sorting and type detection, while `phone_filter`
12746
		 *    // (which has both forms) is used for filtering for if a user inputs either format, while
12747
		 *    // the formatted phone number is the one that is shown in the table.
12748
		 *    $(document).ready( function() {
12749
		 *      $('#example').dataTable( {
12750
		 *        "columnDefs": [ {
12751
		 *          "targets": [ 0 ],
12752
		 *          "data": null, // Use the full data source object for the renderer's source
12753
		 *          "render": {
12754
		 *            "_": "phone",
12755
		 *            "filter": "phone_filter",
12756
		 *            "display": "phone_display"
12757
		 *          }
12758
		 *        } ]
12759
		 *      } );
12760
		 *    } );
12761
		 *
12762
		 *  @example
12763
		 *    // Use as a function to create a link from the data source
12764
		 *    $(document).ready( function() {
12765
		 *      $('#example').dataTable( {
12766
		 *        "columnDefs": [ {
12767
		 *          "targets": [ 0 ],
12768
		 *          "data": "download_link",
12769
		 *          "render": function ( data, type, full ) {
12770
		 *            return '<a href="'+data+'">Download</a>';
12771
		 *          }
12772
		 *        } ]
12773
		 *      } );
12774
		 *    } );
12775
		 */
12776
		"mRender": null,
12777
	
12778
	
12779
		/**
12780
		 * Change the cell type created for the column - either TD cells or TH cells. This
12781
		 * can be useful as TH cells have semantic meaning in the table body, allowing them
12782
		 * to act as a header for a row (you may wish to add scope='row' to the TH elements).
12783
		 *  @type string
12784
		 *  @default td
12785
		 *
12786
		 *  @name DataTable.defaults.column.cellType
12787
		 *  @dtopt Columns
12788
		 *
12789
		 *  @example
12790
		 *    // Make the first column use TH cells
12791
		 *    $(document).ready( function() {
12792
		 *      $('#example').dataTable( {
12793
		 *        "columnDefs": [ {
12794
		 *          "targets": [ 0 ],
12795
		 *          "cellType": "th"
12796
		 *        } ]
12797
		 *      } );
12798
		 *    } );
12799
		 */
12800
		"sCellType": "td",
12801
	
12802
	
12803
		/**
12804
		 * Class to give to each cell in this column.
12805
		 *  @type string
12806
		 *  @default <i>Empty string</i>
12807
		 *
12808
		 *  @name DataTable.defaults.column.class
12809
		 *  @dtopt Columns
12810
		 *
12811
		 *  @example
12812
		 *    // Using `columnDefs`
12813
		 *    $(document).ready( function() {
12814
		 *      $('#example').dataTable( {
12815
		 *        "columnDefs": [
12816
		 *          { "class": "my_class", "targets": [ 0 ] }
12817
		 *        ]
12818
		 *      } );
12819
		 *    } );
12820
		 *
12821
		 *  @example
12822
		 *    // Using `columns`
12823
		 *    $(document).ready( function() {
12824
		 *      $('#example').dataTable( {
12825
		 *        "columns": [
12826
		 *          { "class": "my_class" },
12827
		 *          null,
12828
		 *          null,
12829
		 *          null,
12830
		 *          null
12831
		 *        ]
12832
		 *      } );
12833
		 *    } );
12834
		 */
12835
		"sClass": "",
12836
	
12837
		/**
12838
		 * When DataTables calculates the column widths to assign to each column,
12839
		 * it finds the longest string in each column and then constructs a
12840
		 * temporary table and reads the widths from that. The problem with this
12841
		 * is that "mmm" is much wider then "iiii", but the latter is a longer
12842
		 * string - thus the calculation can go wrong (doing it properly and putting
12843
		 * it into an DOM object and measuring that is horribly(!) slow). Thus as
12844
		 * a "work around" we provide this option. It will append its value to the
12845
		 * text that is found to be the longest string for the column - i.e. padding.
12846
		 * Generally you shouldn't need this!
12847
		 *  @type string
12848
		 *  @default <i>Empty string<i>
12849
		 *
12850
		 *  @name DataTable.defaults.column.contentPadding
12851
		 *  @dtopt Columns
12852
		 *
12853
		 *  @example
12854
		 *    // Using `columns`
12855
		 *    $(document).ready( function() {
12856
		 *      $('#example').dataTable( {
12857
		 *        "columns": [
12858
		 *          null,
12859
		 *          null,
12860
		 *          null,
12861
		 *          {
12862
		 *            "contentPadding": "mmm"
12863
		 *          }
12864
		 *        ]
12865
		 *      } );
12866
		 *    } );
12867
		 */
12868
		"sContentPadding": "",
12869
	
12870
	
12871
		/**
12872
		 * Allows a default value to be given for a column's data, and will be used
12873
		 * whenever a null data source is encountered (this can be because `data`
12874
		 * is set to null, or because the data source itself is null).
12875
		 *  @type string
12876
		 *  @default null
12877
		 *
12878
		 *  @name DataTable.defaults.column.defaultContent
12879
		 *  @dtopt Columns
12880
		 *
12881
		 *  @example
12882
		 *    // Using `columnDefs`
12883
		 *    $(document).ready( function() {
12884
		 *      $('#example').dataTable( {
12885
		 *        "columnDefs": [
12886
		 *          {
12887
		 *            "data": null,
12888
		 *            "defaultContent": "Edit",
12889
		 *            "targets": [ -1 ]
12890
		 *          }
12891
		 *        ]
12892
		 *      } );
12893
		 *    } );
12894
		 *
12895
		 *  @example
12896
		 *    // Using `columns`
12897
		 *    $(document).ready( function() {
12898
		 *      $('#example').dataTable( {
12899
		 *        "columns": [
12900
		 *          null,
12901
		 *          null,
12902
		 *          null,
12903
		 *          {
12904
		 *            "data": null,
12905
		 *            "defaultContent": "Edit"
12906
		 *          }
12907
		 *        ]
12908
		 *      } );
12909
		 *    } );
12910
		 */
12911
		"sDefaultContent": null,
12912
	
12913
	
12914
		/**
12915
		 * This parameter is only used in DataTables' server-side processing. It can
12916
		 * be exceptionally useful to know what columns are being displayed on the
12917
		 * client side, and to map these to database fields. When defined, the names
12918
		 * also allow DataTables to reorder information from the server if it comes
12919
		 * back in an unexpected order (i.e. if you switch your columns around on the
12920
		 * client-side, your server-side code does not also need updating).
12921
		 *  @type string
12922
		 *  @default <i>Empty string</i>
12923
		 *
12924
		 *  @name DataTable.defaults.column.name
12925
		 *  @dtopt Columns
12926
		 *
12927
		 *  @example
12928
		 *    // Using `columnDefs`
12929
		 *    $(document).ready( function() {
12930
		 *      $('#example').dataTable( {
12931
		 *        "columnDefs": [
12932
		 *          { "name": "engine", "targets": [ 0 ] },
12933
		 *          { "name": "browser", "targets": [ 1 ] },
12934
		 *          { "name": "platform", "targets": [ 2 ] },
12935
		 *          { "name": "version", "targets": [ 3 ] },
12936
		 *          { "name": "grade", "targets": [ 4 ] }
12937
		 *        ]
12938
		 *      } );
12939
		 *    } );
12940
		 *
12941
		 *  @example
12942
		 *    // Using `columns`
12943
		 *    $(document).ready( function() {
12944
		 *      $('#example').dataTable( {
12945
		 *        "columns": [
12946
		 *          { "name": "engine" },
12947
		 *          { "name": "browser" },
12948
		 *          { "name": "platform" },
12949
		 *          { "name": "version" },
12950
		 *          { "name": "grade" }
12951
		 *        ]
12952
		 *      } );
12953
		 *    } );
12954
		 */
12955
		"sName": "",
12956
	
12957
	
12958
		/**
12959
		 * Defines a data source type for the ordering which can be used to read
12960
		 * real-time information from the table (updating the internally cached
12961
		 * version) prior to ordering. This allows ordering to occur on user
12962
		 * editable elements such as form inputs.
12963
		 *  @type string
12964
		 *  @default std
12965
		 *
12966
		 *  @name DataTable.defaults.column.orderDataType
12967
		 *  @dtopt Columns
12968
		 *
12969
		 *  @example
12970
		 *    // Using `columnDefs`
12971
		 *    $(document).ready( function() {
12972
		 *      $('#example').dataTable( {
12973
		 *        "columnDefs": [
12974
		 *          { "orderDataType": "dom-text", "targets": [ 2, 3 ] },
12975
		 *          { "type": "numeric", "targets": [ 3 ] },
12976
		 *          { "orderDataType": "dom-select", "targets": [ 4 ] },
12977
		 *          { "orderDataType": "dom-checkbox", "targets": [ 5 ] }
12978
		 *        ]
12979
		 *      } );
12980
		 *    } );
12981
		 *
12982
		 *  @example
12983
		 *    // Using `columns`
12984
		 *    $(document).ready( function() {
12985
		 *      $('#example').dataTable( {
12986
		 *        "columns": [
12987
		 *          null,
12988
		 *          null,
12989
		 *          { "orderDataType": "dom-text" },
12990
		 *          { "orderDataType": "dom-text", "type": "numeric" },
12991
		 *          { "orderDataType": "dom-select" },
12992
		 *          { "orderDataType": "dom-checkbox" }
12993
		 *        ]
12994
		 *      } );
12995
		 *    } );
12996
		 */
12997
		"sSortDataType": "std",
12998
	
12999
	
13000
		/**
13001
		 * The title of this column.
13002
		 *  @type string
13003
		 *  @default null <i>Derived from the 'TH' value for this column in the
13004
		 *    original HTML table.</i>
13005
		 *
13006
		 *  @name DataTable.defaults.column.title
13007
		 *  @dtopt Columns
13008
		 *
13009
		 *  @example
13010
		 *    // Using `columnDefs`
13011
		 *    $(document).ready( function() {
13012
		 *      $('#example').dataTable( {
13013
		 *        "columnDefs": [
13014
		 *          { "title": "My column title", "targets": [ 0 ] }
13015
		 *        ]
13016
		 *      } );
13017
		 *    } );
13018
		 *
13019
		 *  @example
13020
		 *    // Using `columns`
13021
		 *    $(document).ready( function() {
13022
		 *      $('#example').dataTable( {
13023
		 *        "columns": [
13024
		 *          { "title": "My column title" },
13025
		 *          null,
13026
		 *          null,
13027
		 *          null,
13028
		 *          null
13029
		 *        ]
13030
		 *      } );
13031
		 *    } );
13032
		 */
13033
		"sTitle": null,
13034
	
13035
	
13036
		/**
13037
		 * The type allows you to specify how the data for this column will be
13038
		 * ordered. Four types (string, numeric, date and html (which will strip
13039
		 * HTML tags before ordering)) are currently available. Note that only date
13040
		 * formats understood by Javascript's Date() object will be accepted as type
13041
		 * date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string',
13042
		 * 'numeric', 'date' or 'html' (by default). Further types can be adding
13043
		 * through plug-ins.
13044
		 *  @type string
13045
		 *  @default null <i>Auto-detected from raw data</i>
13046
		 *
13047
		 *  @name DataTable.defaults.column.type
13048
		 *  @dtopt Columns
13049
		 *
13050
		 *  @example
13051
		 *    // Using `columnDefs`
13052
		 *    $(document).ready( function() {
13053
		 *      $('#example').dataTable( {
13054
		 *        "columnDefs": [
13055
		 *          { "type": "html", "targets": [ 0 ] }
13056
		 *        ]
13057
		 *      } );
13058
		 *    } );
13059
		 *
13060
		 *  @example
13061
		 *    // Using `columns`
13062
		 *    $(document).ready( function() {
13063
		 *      $('#example').dataTable( {
13064
		 *        "columns": [
13065
		 *          { "type": "html" },
13066
		 *          null,
13067
		 *          null,
13068
		 *          null,
13069
		 *          null
13070
		 *        ]
13071
		 *      } );
13072
		 *    } );
13073
		 */
13074
		"sType": null,
13075
	
13076
	
13077
		/**
13078
		 * Defining the width of the column, this parameter may take any CSS value
13079
		 * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not
13080
		 * been given a specific width through this interface ensuring that the table
13081
		 * remains readable.
13082
		 *  @type string
13083
		 *  @default null <i>Automatic</i>
13084
		 *
13085
		 *  @name DataTable.defaults.column.width
13086
		 *  @dtopt Columns
13087
		 *
13088
		 *  @example
13089
		 *    // Using `columnDefs`
13090
		 *    $(document).ready( function() {
13091
		 *      $('#example').dataTable( {
13092
		 *        "columnDefs": [
13093
		 *          { "width": "20%", "targets": [ 0 ] }
13094
		 *        ]
13095
		 *      } );
13096
		 *    } );
13097
		 *
13098
		 *  @example
13099
		 *    // Using `columns`
13100
		 *    $(document).ready( function() {
13101
		 *      $('#example').dataTable( {
13102
		 *        "columns": [
13103
		 *          { "width": "20%" },
13104
		 *          null,
13105
		 *          null,
13106
		 *          null,
13107
		 *          null
13108
		 *        ]
13109
		 *      } );
13110
		 *    } );
13111
		 */
13112
		"sWidth": null
13113
	};
13114
	
13115
	_fnHungarianMap( DataTable.defaults.column );
13116
	
13117
	
13118
	
13119
	/**
13120
	 * DataTables settings object - this holds all the information needed for a
13121
	 * given table, including configuration, data and current application of the
13122
	 * table options. DataTables does not have a single instance for each DataTable
13123
	 * with the settings attached to that instance, but rather instances of the
13124
	 * DataTable "class" are created on-the-fly as needed (typically by a
13125
	 * $().dataTable() call) and the settings object is then applied to that
13126
	 * instance.
13127
	 *
13128
	 * Note that this object is related to {@link DataTable.defaults} but this
13129
	 * one is the internal data store for DataTables's cache of columns. It should
13130
	 * NOT be manipulated outside of DataTables. Any configuration should be done
13131
	 * through the initialisation options.
13132
	 *  @namespace
13133
	 *  @todo Really should attach the settings object to individual instances so we
13134
	 *    don't need to create new instances on each $().dataTable() call (if the
13135
	 *    table already exists). It would also save passing oSettings around and
13136
	 *    into every single function. However, this is a very significant
13137
	 *    architecture change for DataTables and will almost certainly break
13138
	 *    backwards compatibility with older installations. This is something that
13139
	 *    will be done in 2.0.
13140
	 */
13141
	DataTable.models.oSettings = {
13142
		/**
13143
		 * Primary features of DataTables and their enablement state.
13144
		 *  @namespace
13145
		 */
13146
		"oFeatures": {
13147
	
13148
			/**
13149
			 * Flag to say if DataTables should automatically try to calculate the
13150
			 * optimum table and columns widths (true) or not (false).
13151
			 * Note that this parameter will be set by the initialisation routine. To
13152
			 * set a default use {@link DataTable.defaults}.
13153
			 *  @type boolean
13154
			 */
13155
			"bAutoWidth": null,
13156
	
13157
			/**
13158
			 * Delay the creation of TR and TD elements until they are actually
13159
			 * needed by a driven page draw. This can give a significant speed
13160
			 * increase for Ajax source and Javascript source data, but makes no
13161
			 * difference at all for DOM and server-side processing tables.
13162
			 * Note that this parameter will be set by the initialisation routine. To
13163
			 * set a default use {@link DataTable.defaults}.
13164
			 *  @type boolean
13165
			 */
13166
			"bDeferRender": null,
13167
	
13168
			/**
13169
			 * Enable filtering on the table or not. Note that if this is disabled
13170
			 * then there is no filtering at all on the table, including fnFilter.
13171
			 * To just remove the filtering input use sDom and remove the 'f' option.
13172
			 * Note that this parameter will be set by the initialisation routine. To
13173
			 * set a default use {@link DataTable.defaults}.
13174
			 *  @type boolean
13175
			 */
13176
			"bFilter": null,
13177
	
13178
			/**
13179
			 * Table information element (the 'Showing x of y records' div) enable
13180
			 * flag.
13181
			 * Note that this parameter will be set by the initialisation routine. To
13182
			 * set a default use {@link DataTable.defaults}.
13183
			 *  @type boolean
13184
			 */
13185
			"bInfo": null,
13186
	
13187
			/**
13188
			 * Present a user control allowing the end user to change the page size
13189
			 * when pagination is enabled.
13190
			 * Note that this parameter will be set by the initialisation routine. To
13191
			 * set a default use {@link DataTable.defaults}.
13192
			 *  @type boolean
13193
			 */
13194
			"bLengthChange": null,
13195
	
13196
			/**
13197
			 * Pagination enabled or not. Note that if this is disabled then length
13198
			 * changing must also be disabled.
13199
			 * Note that this parameter will be set by the initialisation routine. To
13200
			 * set a default use {@link DataTable.defaults}.
13201
			 *  @type boolean
13202
			 */
13203
			"bPaginate": null,
13204
	
13205
			/**
13206
			 * Processing indicator enable flag whenever DataTables is enacting a
13207
			 * user request - typically an Ajax request for server-side processing.
13208
			 * Note that this parameter will be set by the initialisation routine. To
13209
			 * set a default use {@link DataTable.defaults}.
13210
			 *  @type boolean
13211
			 */
13212
			"bProcessing": null,
13213
	
13214
			/**
13215
			 * Server-side processing enabled flag - when enabled DataTables will
13216
			 * get all data from the server for every draw - there is no filtering,
13217
			 * sorting or paging done on the client-side.
13218
			 * Note that this parameter will be set by the initialisation routine. To
13219
			 * set a default use {@link DataTable.defaults}.
13220
			 *  @type boolean
13221
			 */
13222
			"bServerSide": null,
13223
	
13224
			/**
13225
			 * Sorting enablement flag.
13226
			 * Note that this parameter will be set by the initialisation routine. To
13227
			 * set a default use {@link DataTable.defaults}.
13228
			 *  @type boolean
13229
			 */
13230
			"bSort": null,
13231
	
13232
			/**
13233
			 * Multi-column sorting
13234
			 * Note that this parameter will be set by the initialisation routine. To
13235
			 * set a default use {@link DataTable.defaults}.
13236
			 *  @type boolean
13237
			 */
13238
			"bSortMulti": null,
13239
	
13240
			/**
13241
			 * Apply a class to the columns which are being sorted to provide a
13242
			 * visual highlight or not. This can slow things down when enabled since
13243
			 * there is a lot of DOM interaction.
13244
			 * Note that this parameter will be set by the initialisation routine. To
13245
			 * set a default use {@link DataTable.defaults}.
13246
			 *  @type boolean
13247
			 */
13248
			"bSortClasses": null,
13249
	
13250
			/**
13251
			 * State saving enablement flag.
13252
			 * Note that this parameter will be set by the initialisation routine. To
13253
			 * set a default use {@link DataTable.defaults}.
13254
			 *  @type boolean
13255
			 */
13256
			"bStateSave": null
13257
		},
13258
	
13259
	
13260
		/**
13261
		 * Scrolling settings for a table.
13262
		 *  @namespace
13263
		 */
13264
		"oScroll": {
13265
			/**
13266
			 * When the table is shorter in height than sScrollY, collapse the
13267
			 * table container down to the height of the table (when true).
13268
			 * Note that this parameter will be set by the initialisation routine. To
13269
			 * set a default use {@link DataTable.defaults}.
13270
			 *  @type boolean
13271
			 */
13272
			"bCollapse": null,
13273
	
13274
			/**
13275
			 * Width of the scrollbar for the web-browser's platform. Calculated
13276
			 * during table initialisation.
13277
			 *  @type int
13278
			 *  @default 0
13279
			 */
13280
			"iBarWidth": 0,
13281
	
13282
			/**
13283
			 * Viewport width for horizontal scrolling. Horizontal scrolling is
13284
			 * disabled if an empty string.
13285
			 * Note that this parameter will be set by the initialisation routine. To
13286
			 * set a default use {@link DataTable.defaults}.
13287
			 *  @type string
13288
			 */
13289
			"sX": null,
13290
	
13291
			/**
13292
			 * Width to expand the table to when using x-scrolling. Typically you
13293
			 * should not need to use this.
13294
			 * Note that this parameter will be set by the initialisation routine. To
13295
			 * set a default use {@link DataTable.defaults}.
13296
			 *  @type string
13297
			 *  @deprecated
13298
			 */
13299
			"sXInner": null,
13300
	
13301
			/**
13302
			 * Viewport height for vertical scrolling. Vertical scrolling is disabled
13303
			 * if an empty string.
13304
			 * Note that this parameter will be set by the initialisation routine. To
13305
			 * set a default use {@link DataTable.defaults}.
13306
			 *  @type string
13307
			 */
13308
			"sY": null
13309
		},
13310
	
13311
		/**
13312
		 * Language information for the table.
13313
		 *  @namespace
13314
		 *  @extends DataTable.defaults.oLanguage
13315
		 */
13316
		"oLanguage": {
13317
			/**
13318
			 * Information callback function. See
13319
			 * {@link DataTable.defaults.fnInfoCallback}
13320
			 *  @type function
13321
			 *  @default null
13322
			 */
13323
			"fnInfoCallback": null
13324
		},
13325
	
13326
		/**
13327
		 * Browser support parameters
13328
		 *  @namespace
13329
		 */
13330
		"oBrowser": {
13331
			/**
13332
			 * Indicate if the browser incorrectly calculates width:100% inside a
13333
			 * scrolling element (IE6/7)
13334
			 *  @type boolean
13335
			 *  @default false
13336
			 */
13337
			"bScrollOversize": false,
13338
	
13339
			/**
13340
			 * Determine if the vertical scrollbar is on the right or left of the
13341
			 * scrolling container - needed for rtl language layout, although not
13342
			 * all browsers move the scrollbar (Safari).
13343
			 *  @type boolean
13344
			 *  @default false
13345
			 */
13346
			"bScrollbarLeft": false,
13347
	
13348
			/**
13349
			 * Flag for if `getBoundingClientRect` is fully supported or not
13350
			 *  @type boolean
13351
			 *  @default false
13352
			 */
13353
			"bBounding": false,
13354
	
13355
			/**
13356
			 * Browser scrollbar width
13357
			 *  @type integer
13358
			 *  @default 0
13359
			 */
13360
			"barWidth": 0
13361
		},
13362
	
13363
	
13364
		"ajax": null,
13365
	
13366
	
13367
		/**
13368
		 * Array referencing the nodes which are used for the features. The
13369
		 * parameters of this object match what is allowed by sDom - i.e.
13370
		 *   <ul>
13371
		 *     <li>'l' - Length changing</li>
13372
		 *     <li>'f' - Filtering input</li>
13373
		 *     <li>'t' - The table!</li>
13374
		 *     <li>'i' - Information</li>
13375
		 *     <li>'p' - Pagination</li>
13376
		 *     <li>'r' - pRocessing</li>
13377
		 *   </ul>
13378
		 *  @type array
13379
		 *  @default []
13380
		 */
13381
		"aanFeatures": [],
13382
	
13383
		/**
13384
		 * Store data information - see {@link DataTable.models.oRow} for detailed
13385
		 * information.
13386
		 *  @type array
13387
		 *  @default []
13388
		 */
13389
		"aoData": [],
13390
	
13391
		/**
13392
		 * Array of indexes which are in the current display (after filtering etc)
13393
		 *  @type array
13394
		 *  @default []
13395
		 */
13396
		"aiDisplay": [],
13397
	
13398
		/**
13399
		 * Array of indexes for display - no filtering
13400
		 *  @type array
13401
		 *  @default []
13402
		 */
13403
		"aiDisplayMaster": [],
13404
	
13405
		/**
13406
		 * Map of row ids to data indexes
13407
		 *  @type object
13408
		 *  @default {}
13409
		 */
13410
		"aIds": {},
13411
	
13412
		/**
13413
		 * Store information about each column that is in use
13414
		 *  @type array
13415
		 *  @default []
13416
		 */
13417
		"aoColumns": [],
13418
	
13419
		/**
13420
		 * Store information about the table's header
13421
		 *  @type array
13422
		 *  @default []
13423
		 */
13424
		"aoHeader": [],
13425
	
13426
		/**
13427
		 * Store information about the table's footer
13428
		 *  @type array
13429
		 *  @default []
13430
		 */
13431
		"aoFooter": [],
13432
	
13433
		/**
13434
		 * Store the applied global search information in case we want to force a
13435
		 * research or compare the old search to a new one.
13436
		 * Note that this parameter will be set by the initialisation routine. To
13437
		 * set a default use {@link DataTable.defaults}.
13438
		 *  @namespace
13439
		 *  @extends DataTable.models.oSearch
13440
		 */
13441
		"oPreviousSearch": {},
13442
	
13443
		/**
13444
		 * Store the applied search for each column - see
13445
		 * {@link DataTable.models.oSearch} for the format that is used for the
13446
		 * filtering information for each column.
13447
		 *  @type array
13448
		 *  @default []
13449
		 */
13450
		"aoPreSearchCols": [],
13451
	
13452
		/**
13453
		 * Sorting that is applied to the table. Note that the inner arrays are
13454
		 * used in the following manner:
13455
		 * <ul>
13456
		 *   <li>Index 0 - column number</li>
13457
		 *   <li>Index 1 - current sorting direction</li>
13458
		 * </ul>
13459
		 * Note that this parameter will be set by the initialisation routine. To
13460
		 * set a default use {@link DataTable.defaults}.
13461
		 *  @type array
13462
		 *  @todo These inner arrays should really be objects
13463
		 */
13464
		"aaSorting": null,
13465
	
13466
		/**
13467
		 * Sorting that is always applied to the table (i.e. prefixed in front of
13468
		 * aaSorting).
13469
		 * Note that this parameter will be set by the initialisation routine. To
13470
		 * set a default use {@link DataTable.defaults}.
13471
		 *  @type array
13472
		 *  @default []
13473
		 */
13474
		"aaSortingFixed": [],
13475
	
13476
		/**
13477
		 * Classes to use for the striping of a table.
13478
		 * Note that this parameter will be set by the initialisation routine. To
13479
		 * set a default use {@link DataTable.defaults}.
13480
		 *  @type array
13481
		 *  @default []
13482
		 */
13483
		"asStripeClasses": null,
13484
	
13485
		/**
13486
		 * If restoring a table - we should restore its striping classes as well
13487
		 *  @type array
13488
		 *  @default []
13489
		 */
13490
		"asDestroyStripes": [],
13491
	
13492
		/**
13493
		 * If restoring a table - we should restore its width
13494
		 *  @type int
13495
		 *  @default 0
13496
		 */
13497
		"sDestroyWidth": 0,
13498
	
13499
		/**
13500
		 * Callback functions array for every time a row is inserted (i.e. on a draw).
13501
		 *  @type array
13502
		 *  @default []
13503
		 */
13504
		"aoRowCallback": [],
13505
	
13506
		/**
13507
		 * Callback functions for the header on each draw.
13508
		 *  @type array
13509
		 *  @default []
13510
		 */
13511
		"aoHeaderCallback": [],
13512
	
13513
		/**
13514
		 * Callback function for the footer on each draw.
13515
		 *  @type array
13516
		 *  @default []
13517
		 */
13518
		"aoFooterCallback": [],
13519
	
13520
		/**
13521
		 * Array of callback functions for draw callback functions
13522
		 *  @type array
13523
		 *  @default []
13524
		 */
13525
		"aoDrawCallback": [],
13526
	
13527
		/**
13528
		 * Array of callback functions for row created function
13529
		 *  @type array
13530
		 *  @default []
13531
		 */
13532
		"aoRowCreatedCallback": [],
13533
	
13534
		/**
13535
		 * Callback functions for just before the table is redrawn. A return of
13536
		 * false will be used to cancel the draw.
13537
		 *  @type array
13538
		 *  @default []
13539
		 */
13540
		"aoPreDrawCallback": [],
13541
	
13542
		/**
13543
		 * Callback functions for when the table has been initialised.
13544
		 *  @type array
13545
		 *  @default []
13546
		 */
13547
		"aoInitComplete": [],
13548
	
13549
	
13550
		/**
13551
		 * Callbacks for modifying the settings to be stored for state saving, prior to
13552
		 * saving state.
13553
		 *  @type array
13554
		 *  @default []
13555
		 */
13556
		"aoStateSaveParams": [],
13557
	
13558
		/**
13559
		 * Callbacks for modifying the settings that have been stored for state saving
13560
		 * prior to using the stored values to restore the state.
13561
		 *  @type array
13562
		 *  @default []
13563
		 */
13564
		"aoStateLoadParams": [],
13565
	
13566
		/**
13567
		 * Callbacks for operating on the settings object once the saved state has been
13568
		 * loaded
13569
		 *  @type array
13570
		 *  @default []
13571
		 */
13572
		"aoStateLoaded": [],
13573
	
13574
		/**
13575
		 * Cache the table ID for quick access
13576
		 *  @type string
13577
		 *  @default <i>Empty string</i>
13578
		 */
13579
		"sTableId": "",
13580
	
13581
		/**
13582
		 * The TABLE node for the main table
13583
		 *  @type node
13584
		 *  @default null
13585
		 */
13586
		"nTable": null,
13587
	
13588
		/**
13589
		 * Permanent ref to the thead element
13590
		 *  @type node
13591
		 *  @default null
13592
		 */
13593
		"nTHead": null,
13594
	
13595
		/**
13596
		 * Permanent ref to the tfoot element - if it exists
13597
		 *  @type node
13598
		 *  @default null
13599
		 */
13600
		"nTFoot": null,
13601
	
13602
		/**
13603
		 * Permanent ref to the tbody element
13604
		 *  @type node
13605
		 *  @default null
13606
		 */
13607
		"nTBody": null,
13608
	
13609
		/**
13610
		 * Cache the wrapper node (contains all DataTables controlled elements)
13611
		 *  @type node
13612
		 *  @default null
13613
		 */
13614
		"nTableWrapper": null,
13615
	
13616
		/**
13617
		 * Indicate if when using server-side processing the loading of data
13618
		 * should be deferred until the second draw.
13619
		 * Note that this parameter will be set by the initialisation routine. To
13620
		 * set a default use {@link DataTable.defaults}.
13621
		 *  @type boolean
13622
		 *  @default false
13623
		 */
13624
		"bDeferLoading": false,
13625
	
13626
		/**
13627
		 * Indicate if all required information has been read in
13628
		 *  @type boolean
13629
		 *  @default false
13630
		 */
13631
		"bInitialised": false,
13632
	
13633
		/**
13634
		 * Information about open rows. Each object in the array has the parameters
13635
		 * 'nTr' and 'nParent'
13636
		 *  @type array
13637
		 *  @default []
13638
		 */
13639
		"aoOpenRows": [],
13640
	
13641
		/**
13642
		 * Dictate the positioning of DataTables' control elements - see
13643
		 * {@link DataTable.model.oInit.sDom}.
13644
		 * Note that this parameter will be set by the initialisation routine. To
13645
		 * set a default use {@link DataTable.defaults}.
13646
		 *  @type string
13647
		 *  @default null
13648
		 */
13649
		"sDom": null,
13650
	
13651
		/**
13652
		 * Search delay (in mS)
13653
		 *  @type integer
13654
		 *  @default null
13655
		 */
13656
		"searchDelay": null,
13657
	
13658
		/**
13659
		 * Which type of pagination should be used.
13660
		 * Note that this parameter will be set by the initialisation routine. To
13661
		 * set a default use {@link DataTable.defaults}.
13662
		 *  @type string
13663
		 *  @default two_button
13664
		 */
13665
		"sPaginationType": "two_button",
13666
	
13667
		/**
13668
		 * The state duration (for `stateSave`) in seconds.
13669
		 * Note that this parameter will be set by the initialisation routine. To
13670
		 * set a default use {@link DataTable.defaults}.
13671
		 *  @type int
13672
		 *  @default 0
13673
		 */
13674
		"iStateDuration": 0,
13675
	
13676
		/**
13677
		 * Array of callback functions for state saving. Each array element is an
13678
		 * object with the following parameters:
13679
		 *   <ul>
13680
		 *     <li>function:fn - function to call. Takes two parameters, oSettings
13681
		 *       and the JSON string to save that has been thus far created. Returns
13682
		 *       a JSON string to be inserted into a json object
13683
		 *       (i.e. '"param": [ 0, 1, 2]')</li>
13684
		 *     <li>string:sName - name of callback</li>
13685
		 *   </ul>
13686
		 *  @type array
13687
		 *  @default []
13688
		 */
13689
		"aoStateSave": [],
13690
	
13691
		/**
13692
		 * Array of callback functions for state loading. Each array element is an
13693
		 * object with the following parameters:
13694
		 *   <ul>
13695
		 *     <li>function:fn - function to call. Takes two parameters, oSettings
13696
		 *       and the object stored. May return false to cancel state loading</li>
13697
		 *     <li>string:sName - name of callback</li>
13698
		 *   </ul>
13699
		 *  @type array
13700
		 *  @default []
13701
		 */
13702
		"aoStateLoad": [],
13703
	
13704
		/**
13705
		 * State that was saved. Useful for back reference
13706
		 *  @type object
13707
		 *  @default null
13708
		 */
13709
		"oSavedState": null,
13710
	
13711
		/**
13712
		 * State that was loaded. Useful for back reference
13713
		 *  @type object
13714
		 *  @default null
13715
		 */
13716
		"oLoadedState": null,
13717
	
13718
		/**
13719
		 * Source url for AJAX data for the table.
13720
		 * Note that this parameter will be set by the initialisation routine. To
13721
		 * set a default use {@link DataTable.defaults}.
13722
		 *  @type string
13723
		 *  @default null
13724
		 */
13725
		"sAjaxSource": null,
13726
	
13727
		/**
13728
		 * Property from a given object from which to read the table data from. This
13729
		 * can be an empty string (when not server-side processing), in which case
13730
		 * it is  assumed an an array is given directly.
13731
		 * Note that this parameter will be set by the initialisation routine. To
13732
		 * set a default use {@link DataTable.defaults}.
13733
		 *  @type string
13734
		 */
13735
		"sAjaxDataProp": null,
13736
	
13737
		/**
13738
		 * The last jQuery XHR object that was used for server-side data gathering.
13739
		 * This can be used for working with the XHR information in one of the
13740
		 * callbacks
13741
		 *  @type object
13742
		 *  @default null
13743
		 */
13744
		"jqXHR": null,
13745
	
13746
		/**
13747
		 * JSON returned from the server in the last Ajax request
13748
		 *  @type object
13749
		 *  @default undefined
13750
		 */
13751
		"json": undefined,
13752
	
13753
		/**
13754
		 * Data submitted as part of the last Ajax request
13755
		 *  @type object
13756
		 *  @default undefined
13757
		 */
13758
		"oAjaxData": undefined,
13759
	
13760
		/**
13761
		 * Function to get the server-side data.
13762
		 * Note that this parameter will be set by the initialisation routine. To
13763
		 * set a default use {@link DataTable.defaults}.
13764
		 *  @type function
13765
		 */
13766
		"fnServerData": null,
13767
	
13768
		/**
13769
		 * Functions which are called prior to sending an Ajax request so extra
13770
		 * parameters can easily be sent to the server
13771
		 *  @type array
13772
		 *  @default []
13773
		 */
13774
		"aoServerParams": [],
13775
	
13776
		/**
13777
		 * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
13778
		 * required).
13779
		 * Note that this parameter will be set by the initialisation routine. To
13780
		 * set a default use {@link DataTable.defaults}.
13781
		 *  @type string
13782
		 */
13783
		"sServerMethod": null,
13784
	
13785
		/**
13786
		 * Format numbers for display.
13787
		 * Note that this parameter will be set by the initialisation routine. To
13788
		 * set a default use {@link DataTable.defaults}.
13789
		 *  @type function
13790
		 */
13791
		"fnFormatNumber": null,
13792
	
13793
		/**
13794
		 * List of options that can be used for the user selectable length menu.
13795
		 * Note that this parameter will be set by the initialisation routine. To
13796
		 * set a default use {@link DataTable.defaults}.
13797
		 *  @type array
13798
		 *  @default []
13799
		 */
13800
		"aLengthMenu": null,
13801
	
13802
		/**
13803
		 * Counter for the draws that the table does. Also used as a tracker for
13804
		 * server-side processing
13805
		 *  @type int
13806
		 *  @default 0
13807
		 */
13808
		"iDraw": 0,
13809
	
13810
		/**
13811
		 * Indicate if a redraw is being done - useful for Ajax
13812
		 *  @type boolean
13813
		 *  @default false
13814
		 */
13815
		"bDrawing": false,
13816
	
13817
		/**
13818
		 * Draw index (iDraw) of the last error when parsing the returned data
13819
		 *  @type int
13820
		 *  @default -1
13821
		 */
13822
		"iDrawError": -1,
13823
	
13824
		/**
13825
		 * Paging display length
13826
		 *  @type int
13827
		 *  @default 10
13828
		 */
13829
		"_iDisplayLength": 10,
13830
	
13831
		/**
13832
		 * Paging start point - aiDisplay index
13833
		 *  @type int
13834
		 *  @default 0
13835
		 */
13836
		"_iDisplayStart": 0,
13837
	
13838
		/**
13839
		 * Server-side processing - number of records in the result set
13840
		 * (i.e. before filtering), Use fnRecordsTotal rather than
13841
		 * this property to get the value of the number of records, regardless of
13842
		 * the server-side processing setting.
13843
		 *  @type int
13844
		 *  @default 0
13845
		 *  @private
13846
		 */
13847
		"_iRecordsTotal": 0,
13848
	
13849
		/**
13850
		 * Server-side processing - number of records in the current display set
13851
		 * (i.e. after filtering). Use fnRecordsDisplay rather than
13852
		 * this property to get the value of the number of records, regardless of
13853
		 * the server-side processing setting.
13854
		 *  @type boolean
13855
		 *  @default 0
13856
		 *  @private
13857
		 */
13858
		"_iRecordsDisplay": 0,
13859
	
13860
		/**
13861
		 * The classes to use for the table
13862
		 *  @type object
13863
		 *  @default {}
13864
		 */
13865
		"oClasses": {},
13866
	
13867
		/**
13868
		 * Flag attached to the settings object so you can check in the draw
13869
		 * callback if filtering has been done in the draw. Deprecated in favour of
13870
		 * events.
13871
		 *  @type boolean
13872
		 *  @default false
13873
		 *  @deprecated
13874
		 */
13875
		"bFiltered": false,
13876
	
13877
		/**
13878
		 * Flag attached to the settings object so you can check in the draw
13879
		 * callback if sorting has been done in the draw. Deprecated in favour of
13880
		 * events.
13881
		 *  @type boolean
13882
		 *  @default false
13883
		 *  @deprecated
13884
		 */
13885
		"bSorted": false,
13886
	
13887
		/**
13888
		 * Indicate that if multiple rows are in the header and there is more than
13889
		 * one unique cell per column, if the top one (true) or bottom one (false)
13890
		 * should be used for sorting / title by DataTables.
13891
		 * Note that this parameter will be set by the initialisation routine. To
13892
		 * set a default use {@link DataTable.defaults}.
13893
		 *  @type boolean
13894
		 */
13895
		"bSortCellsTop": null,
13896
	
13897
		/**
13898
		 * Initialisation object that is used for the table
13899
		 *  @type object
13900
		 *  @default null
13901
		 */
13902
		"oInit": null,
13903
	
13904
		/**
13905
		 * Destroy callback functions - for plug-ins to attach themselves to the
13906
		 * destroy so they can clean up markup and events.
13907
		 *  @type array
13908
		 *  @default []
13909
		 */
13910
		"aoDestroyCallback": [],
13911
	
13912
	
13913
		/**
13914
		 * Get the number of records in the current record set, before filtering
13915
		 *  @type function
13916
		 */
13917
		"fnRecordsTotal": function ()
13918
		{
13919
			return _fnDataSource( this ) == 'ssp' ?
13920
				this._iRecordsTotal * 1 :
13921
				this.aiDisplayMaster.length;
13922
		},
13923
	
13924
		/**
13925
		 * Get the number of records in the current record set, after filtering
13926
		 *  @type function
13927
		 */
13928
		"fnRecordsDisplay": function ()
13929
		{
13930
			return _fnDataSource( this ) == 'ssp' ?
13931
				this._iRecordsDisplay * 1 :
13932
				this.aiDisplay.length;
13933
		},
13934
	
13935
		/**
13936
		 * Get the display end point - aiDisplay index
13937
		 *  @type function
13938
		 */
13939
		"fnDisplayEnd": function ()
13940
		{
13941
			var
13942
				len      = this._iDisplayLength,
13943
				start    = this._iDisplayStart,
13944
				calc     = start + len,
13945
				records  = this.aiDisplay.length,
13946
				features = this.oFeatures,
13947
				paginate = features.bPaginate;
13948
	
13949
			if ( features.bServerSide ) {
13950
				return paginate === false || len === -1 ?
13951
					start + records :
13952
					Math.min( start+len, this._iRecordsDisplay );
13953
			}
13954
			else {
13955
				return ! paginate || calc>records || len===-1 ?
13956
					records :
13957
					calc;
13958
			}
13959
		},
13960
	
13961
		/**
13962
		 * The DataTables object for this table
13963
		 *  @type object
13964
		 *  @default null
13965
		 */
13966
		"oInstance": null,
13967
	
13968
		/**
13969
		 * Unique identifier for each instance of the DataTables object. If there
13970
		 * is an ID on the table node, then it takes that value, otherwise an
13971
		 * incrementing internal counter is used.
13972
		 *  @type string
13973
		 *  @default null
13974
		 */
13975
		"sInstance": null,
13976
	
13977
		/**
13978
		 * tabindex attribute value that is added to DataTables control elements, allowing
13979
		 * keyboard navigation of the table and its controls.
13980
		 */
13981
		"iTabIndex": 0,
13982
	
13983
		/**
13984
		 * DIV container for the footer scrolling table if scrolling
13985
		 */
13986
		"nScrollHead": null,
13987
	
13988
		/**
13989
		 * DIV container for the footer scrolling table if scrolling
13990
		 */
13991
		"nScrollFoot": null,
13992
	
13993
		/**
13994
		 * Last applied sort
13995
		 *  @type array
13996
		 *  @default []
13997
		 */
13998
		"aLastSort": [],
13999
	
14000
		/**
14001
		 * Stored plug-in instances
14002
		 *  @type object
14003
		 *  @default {}
14004
		 */
14005
		"oPlugins": {},
14006
	
14007
		/**
14008
		 * Function used to get a row's id from the row's data
14009
		 *  @type function
14010
		 *  @default null
14011
		 */
14012
		"rowIdFn": null,
14013
	
14014
		/**
14015
		 * Data location where to store a row's id
14016
		 *  @type string
14017
		 *  @default null
14018
		 */
14019
		"rowId": null
14020
	};
14021

14022
	/**
14023
	 * Extension object for DataTables that is used to provide all extension
14024
	 * options.
14025
	 *
14026
	 * Note that the `DataTable.ext` object is available through
14027
	 * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is
14028
	 * also aliased to `jQuery.fn.dataTableExt` for historic reasons.
14029
	 *  @namespace
14030
	 *  @extends DataTable.models.ext
14031
	 */
14032
	
14033
	
14034
	/**
14035
	 * DataTables extensions
14036
	 * 
14037
	 * This namespace acts as a collection area for plug-ins that can be used to
14038
	 * extend DataTables capabilities. Indeed many of the build in methods
14039
	 * use this method to provide their own capabilities (sorting methods for
14040
	 * example).
14041
	 *
14042
	 * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy
14043
	 * reasons
14044
	 *
14045
	 *  @namespace
14046
	 */
14047
	DataTable.ext = _ext = {
14048
		/**
14049
		 * Buttons. For use with the Buttons extension for DataTables. This is
14050
		 * defined here so other extensions can define buttons regardless of load
14051
		 * order. It is _not_ used by DataTables core.
14052
		 *
14053
		 *  @type object
14054
		 *  @default {}
14055
		 */
14056
		buttons: {},
14057
	
14058
	
14059
		/**
14060
		 * Element class names
14061
		 *
14062
		 *  @type object
14063
		 *  @default {}
14064
		 */
14065
		classes: {},
14066
	
14067
	
14068
		/**
14069
		 * DataTables build type (expanded by the download builder)
14070
		 *
14071
		 *  @type string
14072
		 */
14073
		builder: "-source-",
14074
	
14075
	
14076
		/**
14077
		 * Error reporting.
14078
		 * 
14079
		 * How should DataTables report an error. Can take the value 'alert',
14080
		 * 'throw', 'none' or a function.
14081
		 *
14082
		 *  @type string|function
14083
		 *  @default alert
14084
		 */
14085
		errMode: "alert",
14086
	
14087
	
14088
		/**
14089
		 * Feature plug-ins.
14090
		 * 
14091
		 * This is an array of objects which describe the feature plug-ins that are
14092
		 * available to DataTables. These feature plug-ins are then available for
14093
		 * use through the `dom` initialisation option.
14094
		 * 
14095
		 * Each feature plug-in is described by an object which must have the
14096
		 * following properties:
14097
		 * 
14098
		 * * `fnInit` - function that is used to initialise the plug-in,
14099
		 * * `cFeature` - a character so the feature can be enabled by the `dom`
14100
		 *   instillation option. This is case sensitive.
14101
		 *
14102
		 * The `fnInit` function has the following input parameters:
14103
		 *
14104
		 * 1. `{object}` DataTables settings object: see
14105
		 *    {@link DataTable.models.oSettings}
14106
		 *
14107
		 * And the following return is expected:
14108
		 * 
14109
		 * * {node|null} The element which contains your feature. Note that the
14110
		 *   return may also be void if your plug-in does not require to inject any
14111
		 *   DOM elements into DataTables control (`dom`) - for example this might
14112
		 *   be useful when developing a plug-in which allows table control via
14113
		 *   keyboard entry
14114
		 *
14115
		 *  @type array
14116
		 *
14117
		 *  @example
14118
		 *    $.fn.dataTable.ext.features.push( {
14119
		 *      "fnInit": function( oSettings ) {
14120
		 *        return new TableTools( { "oDTSettings": oSettings } );
14121
		 *      },
14122
		 *      "cFeature": "T"
14123
		 *    } );
14124
		 */
14125
		feature: [],
14126
	
14127
	
14128
		/**
14129
		 * Row searching.
14130
		 * 
14131
		 * This method of searching is complimentary to the default type based
14132
		 * searching, and a lot more comprehensive as it allows you complete control
14133
		 * over the searching logic. Each element in this array is a function
14134
		 * (parameters described below) that is called for every row in the table,
14135
		 * and your logic decides if it should be included in the searching data set
14136
		 * or not.
14137
		 *
14138
		 * Searching functions have the following input parameters:
14139
		 *
14140
		 * 1. `{object}` DataTables settings object: see
14141
		 *    {@link DataTable.models.oSettings}
14142
		 * 2. `{array|object}` Data for the row to be processed (same as the
14143
		 *    original format that was passed in as the data source, or an array
14144
		 *    from a DOM data source
14145
		 * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which
14146
		 *    can be useful to retrieve the `TR` element if you need DOM interaction.
14147
		 *
14148
		 * And the following return is expected:
14149
		 *
14150
		 * * {boolean} Include the row in the searched result set (true) or not
14151
		 *   (false)
14152
		 *
14153
		 * Note that as with the main search ability in DataTables, technically this
14154
		 * is "filtering", since it is subtractive. However, for consistency in
14155
		 * naming we call it searching here.
14156
		 *
14157
		 *  @type array
14158
		 *  @default []
14159
		 *
14160
		 *  @example
14161
		 *    // The following example shows custom search being applied to the
14162
		 *    // fourth column (i.e. the data[3] index) based on two input values
14163
		 *    // from the end-user, matching the data in a certain range.
14164
		 *    $.fn.dataTable.ext.search.push(
14165
		 *      function( settings, data, dataIndex ) {
14166
		 *        var min = document.getElementById('min').value * 1;
14167
		 *        var max = document.getElementById('max').value * 1;
14168
		 *        var version = data[3] == "-" ? 0 : data[3]*1;
14169
		 *
14170
		 *        if ( min == "" && max == "" ) {
14171
		 *          return true;
14172
		 *        }
14173
		 *        else if ( min == "" && version < max ) {
14174
		 *          return true;
14175
		 *        }
14176
		 *        else if ( min < version && "" == max ) {
14177
		 *          return true;
14178
		 *        }
14179
		 *        else if ( min < version && version < max ) {
14180
		 *          return true;
14181
		 *        }
14182
		 *        return false;
14183
		 *      }
14184
		 *    );
14185
		 */
14186
		search: [],
14187
	
14188
	
14189
		/**
14190
		 * Selector extensions
14191
		 *
14192
		 * The `selector` option can be used to extend the options available for the
14193
		 * selector modifier options (`selector-modifier` object data type) that
14194
		 * each of the three built in selector types offer (row, column and cell +
14195
		 * their plural counterparts). For example the Select extension uses this
14196
		 * mechanism to provide an option to select only rows, columns and cells
14197
		 * that have been marked as selected by the end user (`{selected: true}`),
14198
		 * which can be used in conjunction with the existing built in selector
14199
		 * options.
14200
		 *
14201
		 * Each property is an array to which functions can be pushed. The functions
14202
		 * take three attributes:
14203
		 *
14204
		 * * Settings object for the host table
14205
		 * * Options object (`selector-modifier` object type)
14206
		 * * Array of selected item indexes
14207
		 *
14208
		 * The return is an array of the resulting item indexes after the custom
14209
		 * selector has been applied.
14210
		 *
14211
		 *  @type object
14212
		 */
14213
		selector: {
14214
			cell: [],
14215
			column: [],
14216
			row: []
14217
		},
14218
	
14219
	
14220
		/**
14221
		 * Internal functions, exposed for used in plug-ins.
14222
		 * 
14223
		 * Please note that you should not need to use the internal methods for
14224
		 * anything other than a plug-in (and even then, try to avoid if possible).
14225
		 * The internal function may change between releases.
14226
		 *
14227
		 *  @type object
14228
		 *  @default {}
14229
		 */
14230
		internal: {},
14231
	
14232
	
14233
		/**
14234
		 * Legacy configuration options. Enable and disable legacy options that
14235
		 * are available in DataTables.
14236
		 *
14237
		 *  @type object
14238
		 */
14239
		legacy: {
14240
			/**
14241
			 * Enable / disable DataTables 1.9 compatible server-side processing
14242
			 * requests
14243
			 *
14244
			 *  @type boolean
14245
			 *  @default null
14246
			 */
14247
			ajax: null
14248
		},
14249
	
14250
	
14251
		/**
14252
		 * Pagination plug-in methods.
14253
		 * 
14254
		 * Each entry in this object is a function and defines which buttons should
14255
		 * be shown by the pagination rendering method that is used for the table:
14256
		 * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the
14257
		 * buttons are displayed in the document, while the functions here tell it
14258
		 * what buttons to display. This is done by returning an array of button
14259
		 * descriptions (what each button will do).
14260
		 *
14261
		 * Pagination types (the four built in options and any additional plug-in
14262
		 * options defined here) can be used through the `paginationType`
14263
		 * initialisation parameter.
14264
		 *
14265
		 * The functions defined take two parameters:
14266
		 *
14267
		 * 1. `{int} page` The current page index
14268
		 * 2. `{int} pages` The number of pages in the table
14269
		 *
14270
		 * Each function is expected to return an array where each element of the
14271
		 * array can be one of:
14272
		 *
14273
		 * * `first` - Jump to first page when activated
14274
		 * * `last` - Jump to last page when activated
14275
		 * * `previous` - Show previous page when activated
14276
		 * * `next` - Show next page when activated
14277
		 * * `{int}` - Show page of the index given
14278
		 * * `{array}` - A nested array containing the above elements to add a
14279
		 *   containing 'DIV' element (might be useful for styling).
14280
		 *
14281
		 * Note that DataTables v1.9- used this object slightly differently whereby
14282
		 * an object with two functions would be defined for each plug-in. That
14283
		 * ability is still supported by DataTables 1.10+ to provide backwards
14284
		 * compatibility, but this option of use is now decremented and no longer
14285
		 * documented in DataTables 1.10+.
14286
		 *
14287
		 *  @type object
14288
		 *  @default {}
14289
		 *
14290
		 *  @example
14291
		 *    // Show previous, next and current page buttons only
14292
		 *    $.fn.dataTableExt.oPagination.current = function ( page, pages ) {
14293
		 *      return [ 'previous', page, 'next' ];
14294
		 *    };
14295
		 */
14296
		pager: {},
14297
	
14298
	
14299
		renderer: {
14300
			pageButton: {},
14301
			header: {}
14302
		},
14303
	
14304
	
14305
		/**
14306
		 * Ordering plug-ins - custom data source
14307
		 * 
14308
		 * The extension options for ordering of data available here is complimentary
14309
		 * to the default type based ordering that DataTables typically uses. It
14310
		 * allows much greater control over the the data that is being used to
14311
		 * order a column, but is necessarily therefore more complex.
14312
		 * 
14313
		 * This type of ordering is useful if you want to do ordering based on data
14314
		 * live from the DOM (for example the contents of an 'input' element) rather
14315
		 * than just the static string that DataTables knows of.
14316
		 * 
14317
		 * The way these plug-ins work is that you create an array of the values you
14318
		 * wish to be ordering for the column in question and then return that
14319
		 * array. The data in the array much be in the index order of the rows in
14320
		 * the table (not the currently ordering order!). Which order data gathering
14321
		 * function is run here depends on the `dt-init columns.orderDataType`
14322
		 * parameter that is used for the column (if any).
14323
		 *
14324
		 * The functions defined take two parameters:
14325
		 *
14326
		 * 1. `{object}` DataTables settings object: see
14327
		 *    {@link DataTable.models.oSettings}
14328
		 * 2. `{int}` Target column index
14329
		 *
14330
		 * Each function is expected to return an array:
14331
		 *
14332
		 * * `{array}` Data for the column to be ordering upon
14333
		 *
14334
		 *  @type array
14335
		 *
14336
		 *  @example
14337
		 *    // Ordering using `input` node values
14338
		 *    $.fn.dataTable.ext.order['dom-text'] = function  ( settings, col )
14339
		 *    {
14340
		 *      return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
14341
		 *        return $('input', td).val();
14342
		 *      } );
14343
		 *    }
14344
		 */
14345
		order: {},
14346
	
14347
	
14348
		/**
14349
		 * Type based plug-ins.
14350
		 *
14351
		 * Each column in DataTables has a type assigned to it, either by automatic
14352
		 * detection or by direct assignment using the `type` option for the column.
14353
		 * The type of a column will effect how it is ordering and search (plug-ins
14354
		 * can also make use of the column type if required).
14355
		 *
14356
		 * @namespace
14357
		 */
14358
		type: {
14359
			/**
14360
			 * Type detection functions.
14361
			 *
14362
			 * The functions defined in this object are used to automatically detect
14363
			 * a column's type, making initialisation of DataTables super easy, even
14364
			 * when complex data is in the table.
14365
			 *
14366
			 * The functions defined take two parameters:
14367
			 *
14368
		     *  1. `{*}` Data from the column cell to be analysed
14369
		     *  2. `{settings}` DataTables settings object. This can be used to
14370
		     *     perform context specific type detection - for example detection
14371
		     *     based on language settings such as using a comma for a decimal
14372
		     *     place. Generally speaking the options from the settings will not
14373
		     *     be required
14374
			 *
14375
			 * Each function is expected to return:
14376
			 *
14377
			 * * `{string|null}` Data type detected, or null if unknown (and thus
14378
			 *   pass it on to the other type detection functions.
14379
			 *
14380
			 *  @type array
14381
			 *
14382
			 *  @example
14383
			 *    // Currency type detection plug-in:
14384
			 *    $.fn.dataTable.ext.type.detect.push(
14385
			 *      function ( data, settings ) {
14386
			 *        // Check the numeric part
14387
			 *        if ( ! data.substring(1).match(/[0-9]/) ) {
14388
			 *          return null;
14389
			 *        }
14390
			 *
14391
			 *        // Check prefixed by currency
14392
			 *        if ( data.charAt(0) == '$' || data.charAt(0) == '&pound;' ) {
14393
			 *          return 'currency';
14394
			 *        }
14395
			 *        return null;
14396
			 *      }
14397
			 *    );
14398
			 */
14399
			detect: [],
14400
	
14401
	
14402
			/**
14403
			 * Type based search formatting.
14404
			 *
14405
			 * The type based searching functions can be used to pre-format the
14406
			 * data to be search on. For example, it can be used to strip HTML
14407
			 * tags or to de-format telephone numbers for numeric only searching.
14408
			 *
14409
			 * Note that is a search is not defined for a column of a given type,
14410
			 * no search formatting will be performed.
14411
			 * 
14412
			 * Pre-processing of searching data plug-ins - When you assign the sType
14413
			 * for a column (or have it automatically detected for you by DataTables
14414
			 * or a type detection plug-in), you will typically be using this for
14415
			 * custom sorting, but it can also be used to provide custom searching
14416
			 * by allowing you to pre-processing the data and returning the data in
14417
			 * the format that should be searched upon. This is done by adding
14418
			 * functions this object with a parameter name which matches the sType
14419
			 * for that target column. This is the corollary of <i>afnSortData</i>
14420
			 * for searching data.
14421
			 *
14422
			 * The functions defined take a single parameter:
14423
			 *
14424
		     *  1. `{*}` Data from the column cell to be prepared for searching
14425
			 *
14426
			 * Each function is expected to return:
14427
			 *
14428
			 * * `{string|null}` Formatted string that will be used for the searching.
14429
			 *
14430
			 *  @type object
14431
			 *  @default {}
14432
			 *
14433
			 *  @example
14434
			 *    $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) {
14435
			 *      return d.replace(/\n/g," ").replace( /<.*?>/g, "" );
14436
			 *    }
14437
			 */
14438
			search: {},
14439
	
14440
	
14441
			/**
14442
			 * Type based ordering.
14443
			 *
14444
			 * The column type tells DataTables what ordering to apply to the table
14445
			 * when a column is sorted upon. The order for each type that is defined,
14446
			 * is defined by the functions available in this object.
14447
			 *
14448
			 * Each ordering option can be described by three properties added to
14449
			 * this object:
14450
			 *
14451
			 * * `{type}-pre` - Pre-formatting function
14452
			 * * `{type}-asc` - Ascending order function
14453
			 * * `{type}-desc` - Descending order function
14454
			 *
14455
			 * All three can be used together, only `{type}-pre` or only
14456
			 * `{type}-asc` and `{type}-desc` together. It is generally recommended
14457
			 * that only `{type}-pre` is used, as this provides the optimal
14458
			 * implementation in terms of speed, although the others are provided
14459
			 * for compatibility with existing Javascript sort functions.
14460
			 *
14461
			 * `{type}-pre`: Functions defined take a single parameter:
14462
			 *
14463
		     *  1. `{*}` Data from the column cell to be prepared for ordering
14464
			 *
14465
			 * And return:
14466
			 *
14467
			 * * `{*}` Data to be sorted upon
14468
			 *
14469
			 * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort
14470
			 * functions, taking two parameters:
14471
			 *
14472
		     *  1. `{*}` Data to compare to the second parameter
14473
		     *  2. `{*}` Data to compare to the first parameter
14474
			 *
14475
			 * And returning:
14476
			 *
14477
			 * * `{*}` Ordering match: <0 if first parameter should be sorted lower
14478
			 *   than the second parameter, ===0 if the two parameters are equal and
14479
			 *   >0 if the first parameter should be sorted height than the second
14480
			 *   parameter.
14481
			 * 
14482
			 *  @type object
14483
			 *  @default {}
14484
			 *
14485
			 *  @example
14486
			 *    // Numeric ordering of formatted numbers with a pre-formatter
14487
			 *    $.extend( $.fn.dataTable.ext.type.order, {
14488
			 *      "string-pre": function(x) {
14489
			 *        a = (a === "-" || a === "") ? 0 : a.replace( /[^\d\-\.]/g, "" );
14490
			 *        return parseFloat( a );
14491
			 *      }
14492
			 *    } );
14493
			 *
14494
			 *  @example
14495
			 *    // Case-sensitive string ordering, with no pre-formatting method
14496
			 *    $.extend( $.fn.dataTable.ext.order, {
14497
			 *      "string-case-asc": function(x,y) {
14498
			 *        return ((x < y) ? -1 : ((x > y) ? 1 : 0));
14499
			 *      },
14500
			 *      "string-case-desc": function(x,y) {
14501
			 *        return ((x < y) ? 1 : ((x > y) ? -1 : 0));
14502
			 *      }
14503
			 *    } );
14504
			 */
14505
			order: {}
14506
		},
14507
	
14508
		/**
14509
		 * Unique DataTables instance counter
14510
		 *
14511
		 * @type int
14512
		 * @private
14513
		 */
14514
		_unique: 0,
14515
	
14516
	
14517
		//
14518
		// Depreciated
14519
		// The following properties are retained for backwards compatibility only.
14520
		// The should not be used in new projects and will be removed in a future
14521
		// version
14522
		//
14523
	
14524
		/**
14525
		 * Version check function.
14526
		 *  @type function
14527
		 *  @depreciated Since 1.10
14528
		 */
14529
		fnVersionCheck: DataTable.fnVersionCheck,
14530
	
14531
	
14532
		/**
14533
		 * Index for what 'this' index API functions should use
14534
		 *  @type int
14535
		 *  @deprecated Since v1.10
14536
		 */
14537
		iApiIndex: 0,
14538
	
14539
	
14540
		/**
14541
		 * jQuery UI class container
14542
		 *  @type object
14543
		 *  @deprecated Since v1.10
14544
		 */
14545
		oJUIClasses: {},
14546
	
14547
	
14548
		/**
14549
		 * Software version
14550
		 *  @type string
14551
		 *  @deprecated Since v1.10
14552
		 */
14553
		sVersion: DataTable.version
14554
	};
14555
	
14556
	
14557
	//
14558
	// Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts
14559
	//
14560
	$.extend( _ext, {
14561
		afnFiltering: _ext.search,
14562
		aTypes:       _ext.type.detect,
14563
		ofnSearch:    _ext.type.search,
14564
		oSort:        _ext.type.order,
14565
		afnSortData:  _ext.order,
14566
		aoFeatures:   _ext.feature,
14567
		oApi:         _ext.internal,
14568
		oStdClasses:  _ext.classes,
14569
		oPagination:  _ext.pager
14570
	} );
14571
	
14572
	
14573
	$.extend( DataTable.ext.classes, {
14574
		"sTable": "dataTable",
14575
		"sNoFooter": "no-footer",
14576
	
14577
		/* Paging buttons */
14578
		"sPageButton": "paginate_button",
14579
		"sPageButtonActive": "current",
14580
		"sPageButtonDisabled": "disabled",
14581
	
14582
		/* Striping classes */
14583
		"sStripeOdd": "odd",
14584
		"sStripeEven": "even",
14585
	
14586
		/* Empty row */
14587
		"sRowEmpty": "dataTables_empty",
14588
	
14589
		/* Features */
14590
		"sWrapper": "dataTables_wrapper",
14591
		"sFilter": "dataTables_filter",
14592
		"sInfo": "dataTables_info",
14593
		"sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
14594
		"sLength": "dataTables_length",
14595
		"sProcessing": "dataTables_processing",
14596
	
14597
		/* Sorting */
14598
		"sSortAsc": "sorting_asc",
14599
		"sSortDesc": "sorting_desc",
14600
		"sSortable": "sorting", /* Sortable in both directions */
14601
		"sSortableAsc": "sorting_desc_disabled",
14602
		"sSortableDesc": "sorting_asc_disabled",
14603
		"sSortableNone": "sorting_disabled",
14604
		"sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
14605
	
14606
		/* Filtering */
14607
		"sFilterInput": "",
14608
	
14609
		/* Page length */
14610
		"sLengthSelect": "",
14611
	
14612
		/* Scrolling */
14613
		"sScrollWrapper": "dataTables_scroll",
14614
		"sScrollHead": "dataTables_scrollHead",
14615
		"sScrollHeadInner": "dataTables_scrollHeadInner",
14616
		"sScrollBody": "dataTables_scrollBody",
14617
		"sScrollFoot": "dataTables_scrollFoot",
14618
		"sScrollFootInner": "dataTables_scrollFootInner",
14619
	
14620
		/* Misc */
14621
		"sHeaderTH": "",
14622
		"sFooterTH": "",
14623
	
14624
		// Deprecated
14625
		"sSortJUIAsc": "",
14626
		"sSortJUIDesc": "",
14627
		"sSortJUI": "",
14628
		"sSortJUIAscAllowed": "",
14629
		"sSortJUIDescAllowed": "",
14630
		"sSortJUIWrapper": "",
14631
		"sSortIcon": "",
14632
		"sJUIHeader": "",
14633
		"sJUIFooter": ""
14634
	} );
14635
	
14636
	
14637
	var extPagination = DataTable.ext.pager;
14638
	
14639
	function _numbers ( page, pages ) {
14640
		var
14641
			numbers = [],
14642
			buttons = extPagination.numbers_length,
14643
			half = Math.floor( buttons / 2 ),
14644
			i = 1;
14645
	
14646
		if ( pages <= buttons ) {
14647
			numbers = _range( 0, pages );
14648
		}
14649
		else if ( page <= half ) {
14650
			numbers = _range( 0, buttons-2 );
14651
			numbers.push( 'ellipsis' );
14652
			numbers.push( pages-1 );
14653
		}
14654
		else if ( page >= pages - 1 - half ) {
14655
			numbers = _range( pages-(buttons-2), pages );
14656
			numbers.splice( 0, 0, 'ellipsis' ); // no unshift in ie6
14657
			numbers.splice( 0, 0, 0 );
14658
		}
14659
		else {
14660
			numbers = _range( page-half+2, page+half-1 );
14661
			numbers.push( 'ellipsis' );
14662
			numbers.push( pages-1 );
14663
			numbers.splice( 0, 0, 'ellipsis' );
14664
			numbers.splice( 0, 0, 0 );
14665
		}
14666
	
14667
		numbers.DT_el = 'span';
14668
		return numbers;
14669
	}
14670
	
14671
	
14672
	$.extend( extPagination, {
14673
		simple: function ( page, pages ) {
14674
			return [ 'previous', 'next' ];
14675
		},
14676
	
14677
		full: function ( page, pages ) {
14678
			return [  'first', 'previous', 'next', 'last' ];
14679
		},
14680
	
14681
		numbers: function ( page, pages ) {
14682
			return [ _numbers(page, pages) ];
14683
		},
14684
	
14685
		simple_numbers: function ( page, pages ) {
14686
			return [ 'previous', _numbers(page, pages), 'next' ];
14687
		},
14688
	
14689
		full_numbers: function ( page, pages ) {
14690
			return [ 'first', 'previous', _numbers(page, pages), 'next', 'last' ];
14691
		},
14692
		
14693
		first_last_numbers: function (page, pages) {
14694
	 		return ['first', _numbers(page, pages), 'last'];
14695
	 	},
14696
	
14697
		// For testing and plug-ins to use
14698
		_numbers: _numbers,
14699
	
14700
		// Number of number buttons (including ellipsis) to show. _Must be odd!_
14701
		numbers_length: 7
14702
	} );
14703
	
14704
	
14705
	$.extend( true, DataTable.ext.renderer, {
14706
		pageButton: {
14707
			_: function ( settings, host, idx, buttons, page, pages ) {
14708
				var classes = settings.oClasses;
14709
				var lang = settings.oLanguage.oPaginate;
14710
				var aria = settings.oLanguage.oAria.paginate || {};
14711
				var btnDisplay, btnClass, counter=0;
14712
	
14713
				var attach = function( container, buttons ) {
14714
					var i, ien, node, button, tabIndex;
14715
					var disabledClass = classes.sPageButtonDisabled;
14716
					var clickHandler = function ( e ) {
14717
						_fnPageChange( settings, e.data.action, true );
14718
					};
14719
	
14720
					for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
14721
						button = buttons[i];
14722
	
14723
						if ( Array.isArray( button ) ) {
14724
							var inner = $( '<'+(button.DT_el || 'div')+'/>' )
14725
								.appendTo( container );
14726
							attach( inner, button );
14727
						}
14728
						else {
14729
							btnDisplay = null;
14730
							btnClass = button;
14731
							tabIndex = settings.iTabIndex;
14732
	
14733
							switch ( button ) {
14734
								case 'ellipsis':
14735
									container.append('<span class="ellipsis">&#x2026;</span>');
14736
									break;
14737
	
14738
								case 'first':
14739
									btnDisplay = lang.sFirst;
14740
	
14741
									if ( page === 0 ) {
14742
										tabIndex = -1;
14743
										btnClass += ' ' + disabledClass;
14744
									}
14745
									break;
14746
	
14747
								case 'previous':
14748
									btnDisplay = lang.sPrevious;
14749
	
14750
									if ( page === 0 ) {
14751
										tabIndex = -1;
14752
										btnClass += ' ' + disabledClass;
14753
									}
14754
									break;
14755
	
14756
								case 'next':
14757
									btnDisplay = lang.sNext;
14758
	
14759
									if ( pages === 0 || page === pages-1 ) {
14760
										tabIndex = -1;
14761
										btnClass += ' ' + disabledClass;
14762
									}
14763
									break;
14764
	
14765
								case 'last':
14766
									btnDisplay = lang.sLast;
14767
	
14768
									if ( pages === 0 || page === pages-1 ) {
14769
										tabIndex = -1;
14770
										btnClass += ' ' + disabledClass;
14771
									}
14772
									break;
14773
	
14774
								default:
14775
									btnDisplay = settings.fnFormatNumber( button + 1 );
14776
									btnClass = page === button ?
14777
										classes.sPageButtonActive : '';
14778
									break;
14779
							}
14780
	
14781
							if ( btnDisplay !== null ) {
14782
								node = $('<a>', {
14783
										'class': classes.sPageButton+' '+btnClass,
14784
										'aria-controls': settings.sTableId,
14785
										'aria-label': aria[ button ],
14786
										'data-dt-idx': counter,
14787
										'tabindex': tabIndex,
14788
										'id': idx === 0 && typeof button === 'string' ?
14789
											settings.sTableId +'_'+ button :
14790
											null
14791
									} )
14792
									.html( btnDisplay )
14793
									.appendTo( container );
14794
	
14795
								_fnBindAction(
14796
									node, {action: button}, clickHandler
14797
								);
14798
	
14799
								counter++;
14800
							}
14801
						}
14802
					}
14803
				};
14804
	
14805
				// IE9 throws an 'unknown error' if document.activeElement is used
14806
				// inside an iframe or frame. Try / catch the error. Not good for
14807
				// accessibility, but neither are frames.
14808
				var activeEl;
14809
	
14810
				try {
14811
					// Because this approach is destroying and recreating the paging
14812
					// elements, focus is lost on the select button which is bad for
14813
					// accessibility. So we want to restore focus once the draw has
14814
					// completed
14815
					activeEl = $(host).find(document.activeElement).data('dt-idx');
14816
				}
14817
				catch (e) {}
14818
	
14819
				attach( $(host).empty(), buttons );
14820
	
14821
				if ( activeEl !== undefined ) {
14822
					$(host).find( '[data-dt-idx='+activeEl+']' ).trigger('focus');
14823
				}
14824
			}
14825
		}
14826
	} );
14827
	
14828
	
14829
	
14830
	// Built in type detection. See model.ext.aTypes for information about
14831
	// what is required from this methods.
14832
	$.extend( DataTable.ext.type.detect, [
14833
		// Plain numbers - first since V8 detects some plain numbers as dates
14834
		// e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...).
14835
		function ( d, settings )
14836
		{
14837
			var decimal = settings.oLanguage.sDecimal;
14838
			return _isNumber( d, decimal ) ? 'num'+decimal : null;
14839
		},
14840
	
14841
		// Dates (only those recognised by the browser's Date.parse)
14842
		function ( d, settings )
14843
		{
14844
			// V8 tries _very_ hard to make a string passed into `Date.parse()`
14845
			// valid, so we need to use a regex to restrict date formats. Use a
14846
			// plug-in for anything other than ISO8601 style strings
14847
			if ( d && !(d instanceof Date) && ! _re_date.test(d) ) {
14848
				return null;
14849
			}
14850
			var parsed = Date.parse(d);
14851
			return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null;
14852
		},
14853
	
14854
		// Formatted numbers
14855
		function ( d, settings )
14856
		{
14857
			var decimal = settings.oLanguage.sDecimal;
14858
			return _isNumber( d, decimal, true ) ? 'num-fmt'+decimal : null;
14859
		},
14860
	
14861
		// HTML numeric
14862
		function ( d, settings )
14863
		{
14864
			var decimal = settings.oLanguage.sDecimal;
14865
			return _htmlNumeric( d, decimal ) ? 'html-num'+decimal : null;
14866
		},
14867
	
14868
		// HTML numeric, formatted
14869
		function ( d, settings )
14870
		{
14871
			var decimal = settings.oLanguage.sDecimal;
14872
			return _htmlNumeric( d, decimal, true ) ? 'html-num-fmt'+decimal : null;
14873
		},
14874
	
14875
		// HTML (this is strict checking - there must be html)
14876
		function ( d, settings )
14877
		{
14878
			return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ?
14879
				'html' : null;
14880
		}
14881
	] );
14882
	
14883
	
14884
	
14885
	// Filter formatting functions. See model.ext.ofnSearch for information about
14886
	// what is required from these methods.
14887
	// 
14888
	// Note that additional search methods are added for the html numbers and
14889
	// html formatted numbers by `_addNumericSort()` when we know what the decimal
14890
	// place is
14891
	
14892
	
14893
	$.extend( DataTable.ext.type.search, {
14894
		html: function ( data ) {
14895
			return _empty(data) ?
14896
				data :
14897
				typeof data === 'string' ?
14898
					data
14899
						.replace( _re_new_lines, " " )
14900
						.replace( _re_html, "" ) :
14901
					'';
14902
		},
14903
	
14904
		string: function ( data ) {
14905
			return _empty(data) ?
14906
				data :
14907
				typeof data === 'string' ?
14908
					data.replace( _re_new_lines, " " ) :
14909
					data;
14910
		}
14911
	} );
14912
	
14913
	
14914
	
14915
	var __numericReplace = function ( d, decimalPlace, re1, re2 ) {
14916
		if ( d !== 0 && (!d || d === '-') ) {
14917
			return -Infinity;
14918
		}
14919
	
14920
		// If a decimal place other than `.` is used, it needs to be given to the
14921
		// function so we can detect it and replace with a `.` which is the only
14922
		// decimal place Javascript recognises - it is not locale aware.
14923
		if ( decimalPlace ) {
14924
			d = _numToDecimal( d, decimalPlace );
14925
		}
14926
	
14927
		if ( d.replace ) {
14928
			if ( re1 ) {
14929
				d = d.replace( re1, '' );
14930
			}
14931
	
14932
			if ( re2 ) {
14933
				d = d.replace( re2, '' );
14934
			}
14935
		}
14936
	
14937
		return d * 1;
14938
	};
14939
	
14940
	
14941
	// Add the numeric 'deformatting' functions for sorting and search. This is done
14942
	// in a function to provide an easy ability for the language options to add
14943
	// additional methods if a non-period decimal place is used.
14944
	function _addNumericSort ( decimalPlace ) {
14945
		$.each(
14946
			{
14947
				// Plain numbers
14948
				"num": function ( d ) {
14949
					return __numericReplace( d, decimalPlace );
14950
				},
14951
	
14952
				// Formatted numbers
14953
				"num-fmt": function ( d ) {
14954
					return __numericReplace( d, decimalPlace, _re_formatted_numeric );
14955
				},
14956
	
14957
				// HTML numeric
14958
				"html-num": function ( d ) {
14959
					return __numericReplace( d, decimalPlace, _re_html );
14960
				},
14961
	
14962
				// HTML numeric, formatted
14963
				"html-num-fmt": function ( d ) {
14964
					return __numericReplace( d, decimalPlace, _re_html, _re_formatted_numeric );
14965
				}
14966
			},
14967
			function ( key, fn ) {
14968
				// Add the ordering method
14969
				_ext.type.order[ key+decimalPlace+'-pre' ] = fn;
14970
	
14971
				// For HTML types add a search formatter that will strip the HTML
14972
				if ( key.match(/^html\-/) ) {
14973
					_ext.type.search[ key+decimalPlace ] = _ext.type.search.html;
14974
				}
14975
			}
14976
		);
14977
	}
14978
	
14979
	
14980
	// Default sort methods
14981
	$.extend( _ext.type.order, {
14982
		// Dates
14983
		"date-pre": function ( d ) {
14984
			var ts = Date.parse( d );
14985
			return isNaN(ts) ? -Infinity : ts;
14986
		},
14987
	
14988
		// html
14989
		"html-pre": function ( a ) {
14990
			return _empty(a) ?
14991
				'' :
14992
				a.replace ?
14993
					a.replace( /<.*?>/g, "" ).toLowerCase() :
14994
					a+'';
14995
		},
14996
	
14997
		// string
14998
		"string-pre": function ( a ) {
14999
			// This is a little complex, but faster than always calling toString,
15000
			// http://jsperf.com/tostring-v-check
15001
			return _empty(a) ?
15002
				'' :
15003
				typeof a === 'string' ?
15004
					a.toLowerCase() :
15005
					! a.toString ?
15006
						'' :
15007
						a.toString();
15008
		},
15009
	
15010
		// string-asc and -desc are retained only for compatibility with the old
15011
		// sort methods
15012
		"string-asc": function ( x, y ) {
15013
			return ((x < y) ? -1 : ((x > y) ? 1 : 0));
15014
		},
15015
	
15016
		"string-desc": function ( x, y ) {
15017
			return ((x < y) ? 1 : ((x > y) ? -1 : 0));
15018
		}
15019
	} );
15020
	
15021
	
15022
	// Numeric sorting types - order doesn't matter here
15023
	_addNumericSort( '' );
15024
	
15025
	
15026
	$.extend( true, DataTable.ext.renderer, {
15027
		header: {
15028
			_: function ( settings, cell, column, classes ) {
15029
				// No additional mark-up required
15030
				// Attach a sort listener to update on sort - note that using the
15031
				// `DT` namespace will allow the event to be removed automatically
15032
				// on destroy, while the `dt` namespaced event is the one we are
15033
				// listening for
15034
				$(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
15035
					if ( settings !== ctx ) { // need to check this this is the host
15036
						return;               // table, not a nested one
15037
					}
15038
	
15039
					var colIdx = column.idx;
15040
	
15041
					cell
15042
						.removeClass(
15043
							classes.sSortAsc +' '+
15044
							classes.sSortDesc
15045
						)
15046
						.addClass( columns[ colIdx ] == 'asc' ?
15047
							classes.sSortAsc : columns[ colIdx ] == 'desc' ?
15048
								classes.sSortDesc :
15049
								column.sSortingClass
15050
						);
15051
				} );
15052
			},
15053
	
15054
			jqueryui: function ( settings, cell, column, classes ) {
15055
				$('<div/>')
15056
					.addClass( classes.sSortJUIWrapper )
15057
					.append( cell.contents() )
15058
					.append( $('<span/>')
15059
						.addClass( classes.sSortIcon+' '+column.sSortingClassJUI )
15060
					)
15061
					.appendTo( cell );
15062
	
15063
				// Attach a sort listener to update on sort
15064
				$(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
15065
					if ( settings !== ctx ) {
15066
						return;
15067
					}
15068
	
15069
					var colIdx = column.idx;
15070
	
15071
					cell
15072
						.removeClass( classes.sSortAsc +" "+classes.sSortDesc )
15073
						.addClass( columns[ colIdx ] == 'asc' ?
15074
							classes.sSortAsc : columns[ colIdx ] == 'desc' ?
15075
								classes.sSortDesc :
15076
								column.sSortingClass
15077
						);
15078
	
15079
					cell
15080
						.find( 'span.'+classes.sSortIcon )
15081
						.removeClass(
15082
							classes.sSortJUIAsc +" "+
15083
							classes.sSortJUIDesc +" "+
15084
							classes.sSortJUI +" "+
15085
							classes.sSortJUIAscAllowed +" "+
15086
							classes.sSortJUIDescAllowed
15087
						)
15088
						.addClass( columns[ colIdx ] == 'asc' ?
15089
							classes.sSortJUIAsc : columns[ colIdx ] == 'desc' ?
15090
								classes.sSortJUIDesc :
15091
								column.sSortingClassJUI
15092
						);
15093
				} );
15094
			}
15095
		}
15096
	} );
15097
	
15098
	/*
15099
	 * Public helper functions. These aren't used internally by DataTables, or
15100
	 * called by any of the options passed into DataTables, but they can be used
15101
	 * externally by developers working with DataTables. They are helper functions
15102
	 * to make working with DataTables a little bit easier.
15103
	 */
15104
	
15105
	var __htmlEscapeEntities = function ( d ) {
15106
		if (Array.isArray(d)) {
15107
			d = d.join(',');
15108
		}
15109
	
15110
		return typeof d === 'string' ?
15111
			d
15112
				.replace(/&/g, '&amp;')
15113
				.replace(/</g, '&lt;')
15114
				.replace(/>/g, '&gt;')
15115
				.replace(/"/g, '&quot;') :
15116
			d;
15117
	};
15118
	
15119
	/**
15120
	 * Helpers for `columns.render`.
15121
	 *
15122
	 * The options defined here can be used with the `columns.render` initialisation
15123
	 * option to provide a display renderer. The following functions are defined:
15124
	 *
15125
	 * * `number` - Will format numeric data (defined by `columns.data`) for
15126
	 *   display, retaining the original unformatted data for sorting and filtering.
15127
	 *   It takes 5 parameters:
15128
	 *   * `string` - Thousands grouping separator
15129
	 *   * `string` - Decimal point indicator
15130
	 *   * `integer` - Number of decimal points to show
15131
	 *   * `string` (optional) - Prefix.
15132
	 *   * `string` (optional) - Postfix (/suffix).
15133
	 * * `text` - Escape HTML to help prevent XSS attacks. It has no optional
15134
	 *   parameters.
15135
	 *
15136
	 * @example
15137
	 *   // Column definition using the number renderer
15138
	 *   {
15139
	 *     data: "salary",
15140
	 *     render: $.fn.dataTable.render.number( '\'', '.', 0, '$' )
15141
	 *   }
15142
	 *
15143
	 * @namespace
15144
	 */
15145
	DataTable.render = {
15146
		number: function ( thousands, decimal, precision, prefix, postfix ) {
15147
			return {
15148
				display: function ( d ) {
15149
					if ( typeof d !== 'number' && typeof d !== 'string' ) {
15150
						return d;
15151
					}
15152
	
15153
					var negative = d < 0 ? '-' : '';
15154
					var flo = parseFloat( d );
15155
	
15156
					// If NaN then there isn't much formatting that we can do - just
15157
					// return immediately, escaping any HTML (this was supposed to
15158
					// be a number after all)
15159
					if ( isNaN( flo ) ) {
15160
						return __htmlEscapeEntities( d );
15161
					}
15162
	
15163
					flo = flo.toFixed( precision );
15164
					d = Math.abs( flo );
15165
	
15166
					var intPart = parseInt( d, 10 );
15167
					var floatPart = precision ?
15168
						decimal+(d - intPart).toFixed( precision ).substring( 2 ):
15169
						'';
15170
	
15171
					// If zero, then can't have a negative prefix
15172
					if (intPart === 0 && parseFloat(floatPart) === 0) {
15173
						negative = '';
15174
					}
15175
	
15176
					return negative + (prefix||'') +
15177
						intPart.toString().replace(
15178
							/\B(?=(\d{3})+(?!\d))/g, thousands
15179
						) +
15180
						floatPart +
15181
						(postfix||'');
15182
				}
15183
			};
15184
		},
15185
	
15186
		text: function () {
15187
			return {
15188
				display: __htmlEscapeEntities,
15189
				filter: __htmlEscapeEntities
15190
			};
15191
		}
15192
	};
15193
	
15194
	
15195
	/*
15196
	 * This is really a good bit rubbish this method of exposing the internal methods
15197
	 * publicly... - To be fixed in 2.0 using methods on the prototype
15198
	 */
15199
	
15200
	
15201
	/**
15202
	 * Create a wrapper function for exporting an internal functions to an external API.
15203
	 *  @param {string} fn API function name
15204
	 *  @returns {function} wrapped function
15205
	 *  @memberof DataTable#internal
15206
	 */
15207
	function _fnExternApiFunc (fn)
15208
	{
15209
		return function() {
15210
			var args = [_fnSettingsFromNode( this[DataTable.ext.iApiIndex] )].concat(
15211
				Array.prototype.slice.call(arguments)
15212
			);
15213
			return DataTable.ext.internal[fn].apply( this, args );
15214
		};
15215
	}
15216
	
15217
	
15218
	/**
15219
	 * Reference to internal functions for use by plug-in developers. Note that
15220
	 * these methods are references to internal functions and are considered to be
15221
	 * private. If you use these methods, be aware that they are liable to change
15222
	 * between versions.
15223
	 *  @namespace
15224
	 */
15225
	$.extend( DataTable.ext.internal, {
15226
		_fnExternApiFunc: _fnExternApiFunc,
15227
		_fnBuildAjax: _fnBuildAjax,
15228
		_fnAjaxUpdate: _fnAjaxUpdate,
15229
		_fnAjaxParameters: _fnAjaxParameters,
15230
		_fnAjaxUpdateDraw: _fnAjaxUpdateDraw,
15231
		_fnAjaxDataSrc: _fnAjaxDataSrc,
15232
		_fnAddColumn: _fnAddColumn,
15233
		_fnColumnOptions: _fnColumnOptions,
15234
		_fnAdjustColumnSizing: _fnAdjustColumnSizing,
15235
		_fnVisibleToColumnIndex: _fnVisibleToColumnIndex,
15236
		_fnColumnIndexToVisible: _fnColumnIndexToVisible,
15237
		_fnVisbleColumns: _fnVisbleColumns,
15238
		_fnGetColumns: _fnGetColumns,
15239
		_fnColumnTypes: _fnColumnTypes,
15240
		_fnApplyColumnDefs: _fnApplyColumnDefs,
15241
		_fnHungarianMap: _fnHungarianMap,
15242
		_fnCamelToHungarian: _fnCamelToHungarian,
15243
		_fnLanguageCompat: _fnLanguageCompat,
15244
		_fnBrowserDetect: _fnBrowserDetect,
15245
		_fnAddData: _fnAddData,
15246
		_fnAddTr: _fnAddTr,
15247
		_fnNodeToDataIndex: _fnNodeToDataIndex,
15248
		_fnNodeToColumnIndex: _fnNodeToColumnIndex,
15249
		_fnGetCellData: _fnGetCellData,
15250
		_fnSetCellData: _fnSetCellData,
15251
		_fnSplitObjNotation: _fnSplitObjNotation,
15252
		_fnGetObjectDataFn: _fnGetObjectDataFn,
15253
		_fnSetObjectDataFn: _fnSetObjectDataFn,
15254
		_fnGetDataMaster: _fnGetDataMaster,
15255
		_fnClearTable: _fnClearTable,
15256
		_fnDeleteIndex: _fnDeleteIndex,
15257
		_fnInvalidate: _fnInvalidate,
15258
		_fnGetRowElements: _fnGetRowElements,
15259
		_fnCreateTr: _fnCreateTr,
15260
		_fnBuildHead: _fnBuildHead,
15261
		_fnDrawHead: _fnDrawHead,
15262
		_fnDraw: _fnDraw,
15263
		_fnReDraw: _fnReDraw,
15264
		_fnAddOptionsHtml: _fnAddOptionsHtml,
15265
		_fnDetectHeader: _fnDetectHeader,
15266
		_fnGetUniqueThs: _fnGetUniqueThs,
15267
		_fnFeatureHtmlFilter: _fnFeatureHtmlFilter,
15268
		_fnFilterComplete: _fnFilterComplete,
15269
		_fnFilterCustom: _fnFilterCustom,
15270
		_fnFilterColumn: _fnFilterColumn,
15271
		_fnFilter: _fnFilter,
15272
		_fnFilterCreateSearch: _fnFilterCreateSearch,
15273
		_fnEscapeRegex: _fnEscapeRegex,
15274
		_fnFilterData: _fnFilterData,
15275
		_fnFeatureHtmlInfo: _fnFeatureHtmlInfo,
15276
		_fnUpdateInfo: _fnUpdateInfo,
15277
		_fnInfoMacros: _fnInfoMacros,
15278
		_fnInitialise: _fnInitialise,
15279
		_fnInitComplete: _fnInitComplete,
15280
		_fnLengthChange: _fnLengthChange,
15281
		_fnFeatureHtmlLength: _fnFeatureHtmlLength,
15282
		_fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate,
15283
		_fnPageChange: _fnPageChange,
15284
		_fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing,
15285
		_fnProcessingDisplay: _fnProcessingDisplay,
15286
		_fnFeatureHtmlTable: _fnFeatureHtmlTable,
15287
		_fnScrollDraw: _fnScrollDraw,
15288
		_fnApplyToChildren: _fnApplyToChildren,
15289
		_fnCalculateColumnWidths: _fnCalculateColumnWidths,
15290
		_fnThrottle: _fnThrottle,
15291
		_fnConvertToWidth: _fnConvertToWidth,
15292
		_fnGetWidestNode: _fnGetWidestNode,
15293
		_fnGetMaxLenString: _fnGetMaxLenString,
15294
		_fnStringToCss: _fnStringToCss,
15295
		_fnSortFlatten: _fnSortFlatten,
15296
		_fnSort: _fnSort,
15297
		_fnSortAria: _fnSortAria,
15298
		_fnSortListener: _fnSortListener,
15299
		_fnSortAttachListener: _fnSortAttachListener,
15300
		_fnSortingClasses: _fnSortingClasses,
15301
		_fnSortData: _fnSortData,
15302
		_fnSaveState: _fnSaveState,
15303
		_fnLoadState: _fnLoadState,
15304
		_fnImplementState: _fnImplementState,
15305
		_fnSettingsFromNode: _fnSettingsFromNode,
15306
		_fnLog: _fnLog,
15307
		_fnMap: _fnMap,
15308
		_fnBindAction: _fnBindAction,
15309
		_fnCallbackReg: _fnCallbackReg,
15310
		_fnCallbackFire: _fnCallbackFire,
15311
		_fnLengthOverflow: _fnLengthOverflow,
15312
		_fnRenderer: _fnRenderer,
15313
		_fnDataSource: _fnDataSource,
15314
		_fnRowAttributes: _fnRowAttributes,
15315
		_fnExtend: _fnExtend,
15316
		_fnCalculateEnd: function () {} // Used by a lot of plug-ins, but redundant
15317
		                                // in 1.10, so this dead-end function is
15318
		                                // added to prevent errors
15319
	} );
15320
	
15321

15322
	// jQuery access
15323
	$.fn.dataTable = DataTable;
15324

15325
	// Provide access to the host jQuery object (circular reference)
15326
	DataTable.$ = $;
15327

15328
	// Legacy aliases
15329
	$.fn.dataTableSettings = DataTable.settings;
15330
	$.fn.dataTableExt = DataTable.ext;
15331

15332
	// With a capital `D` we return a DataTables API instance rather than a
15333
	// jQuery object
15334
	$.fn.DataTable = function ( opts ) {
15335
		return $(this).dataTable( opts ).api();
15336
	};
15337

15338
	// All properties that are available to $.fn.dataTable should also be
15339
	// available on $.fn.DataTable
15340
	$.each( DataTable, function ( prop, val ) {
15341
		$.fn.DataTable[ prop ] = val;
15342
	} );
15343

15344
	return DataTable;
15345
}));
15346

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.