lavkach3

Форк
0
15648 строк · 428.1 Кб
1
/*! DataTables 1.13.5
2
 * ©2008-2023 SpryMedia Ltd - datatables.net/license
3
 */
4

5
import jQuery from 'jquery';
6

7
// DataTables code uses $ internally, but we want to be able to
8
// reassign $ with the `use` method, so it is a regular var.
9
var $ = jQuery;
10

11

12
var DataTable = function ( selector, options )
13
{
14
	// Check if called with a window or jQuery object for DOM less applications
15
	// This is for backwards compatibility
16
	if (DataTable.factory(selector, options)) {
17
		return DataTable;
18
	}
19

20
	// When creating with `new`, create a new DataTable, returning the API instance
21
	if (this instanceof DataTable) {
22
		return $(selector).DataTable(options);
23
	}
24
	else {
25
		// Argument switching
26
		options = selector;
27
	}
28

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

785
	var _that = this;
786
	var emptyInit = options === undefined;
787
	var len = this.length;
788

789
	if ( emptyInit ) {
790
		options = {};
791
	}
792

793
	this.oApi = this.internal = _ext.internal;
794

795
	// Extend with old style plug-in API methods
796
	for ( var fn in DataTable.ext.internal ) {
797
		if ( fn ) {
798
			this[fn] = _fnExternApiFunc(fn);
799
		}
800
	}
801

802
	this.each(function() {
803
		// For each initialisation we want to give it a clean initialisation
804
		// object that can be bashed around
805
		var o = {};
806
		var oInit = len > 1 ? // optimisation for single table case
807
			_fnExtend( o, options, true ) :
808
			options;
809

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

1258

1259
/*
1260
 * It is useful to have variables which are scoped locally so only the
1261
 * DataTables functions can access them and they don't leak into global space.
1262
 * At the same time these functions are often useful over multiple files in the
1263
 * core and API, so we list, or at least document, all variables which are used
1264
 * by DataTables as private variables here. This also ensures that there is no
1265
 * clashing of variable names and that they can easily referenced for reuse.
1266
 */
1267

1268

1269
// Defined else where
1270
//  _selector_run
1271
//  _selector_opts
1272
//  _selector_first
1273
//  _selector_row_indexes
1274

1275
var _ext; // DataTable.ext
1276
var _Api; // DataTable.Api
1277
var _api_register; // DataTable.Api.register
1278
var _api_registerPlural; // DataTable.Api.registerPlural
1279

1280
var _re_dic = {};
1281
var _re_new_lines = /[\r\n\u2028]/g;
1282
var _re_html = /<.*?>/g;
1283

1284
// This is not strict ISO8601 - Date.parse() is quite lax, although
1285
// implementations differ between browsers.
1286
var _re_date = /^\d{2,4}[\.\/\-]\d{1,2}[\.\/\-]\d{1,2}([T ]{1}\d{1,2}[:\.]\d{2}([\.:]\d{2})?)?$/;
1287

1288
// Escape regular expression special characters
1289
var _re_escape_regex = new RegExp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' );
1290

1291
// http://en.wikipedia.org/wiki/Foreign_exchange_market
1292
// - \u20BD - Russian ruble.
1293
// - \u20a9 - South Korean Won
1294
// - \u20BA - Turkish Lira
1295
// - \u20B9 - Indian Rupee
1296
// - R - Brazil (R$) and South Africa
1297
// - fr - Swiss Franc
1298
// - kr - Swedish krona, Norwegian krone and Danish krone
1299
// - \u2009 is thin space and \u202F is narrow no-break space, both used in many
1300
// - Ƀ - Bitcoin
1301
// - Ξ - Ethereum
1302
//   standards as thousands separators.
1303
var _re_formatted_numeric = /['\u00A0,$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfkɃΞ]/gi;
1304

1305

1306
var _empty = function ( d ) {
1307
	return !d || d === true || d === '-' ? true : false;
1308
};
1309

1310

1311
var _intVal = function ( s ) {
1312
	var integer = parseInt( s, 10 );
1313
	return !isNaN(integer) && isFinite(s) ? integer : null;
1314
};
1315

1316
// Convert from a formatted number with characters other than `.` as the
1317
// decimal place, to a Javascript number
1318
var _numToDecimal = function ( num, decimalPoint ) {
1319
	// Cache created regular expressions for speed as this function is called often
1320
	if ( ! _re_dic[ decimalPoint ] ) {
1321
		_re_dic[ decimalPoint ] = new RegExp( _fnEscapeRegex( decimalPoint ), 'g' );
1322
	}
1323
	return typeof num === 'string' && decimalPoint !== '.' ?
1324
		num.replace( /\./g, '' ).replace( _re_dic[ decimalPoint ], '.' ) :
1325
		num;
1326
};
1327

1328

1329
var _isNumber = function ( d, decimalPoint, formatted ) {
1330
	var type = typeof d;
1331
	var strType = type === 'string';
1332

1333
	if ( type === 'number' || type === 'bigint') {
1334
		return true;
1335
	}
1336

1337
	// If empty return immediately so there must be a number if it is a
1338
	// formatted string (this stops the string "k", or "kr", etc being detected
1339
	// as a formatted number for currency
1340
	if ( _empty( d ) ) {
1341
		return true;
1342
	}
1343

1344
	if ( decimalPoint && strType ) {
1345
		d = _numToDecimal( d, decimalPoint );
1346
	}
1347

1348
	if ( formatted && strType ) {
1349
		d = d.replace( _re_formatted_numeric, '' );
1350
	}
1351

1352
	return !isNaN( parseFloat(d) ) && isFinite( d );
1353
};
1354

1355

1356
// A string without HTML in it can be considered to be HTML still
1357
var _isHtml = function ( d ) {
1358
	return _empty( d ) || typeof d === 'string';
1359
};
1360

1361

1362
var _htmlNumeric = function ( d, decimalPoint, formatted ) {
1363
	if ( _empty( d ) ) {
1364
		return true;
1365
	}
1366

1367
	var html = _isHtml( d );
1368
	return ! html ?
1369
		null :
1370
		_isNumber( _stripHtml( d ), decimalPoint, formatted ) ?
1371
			true :
1372
			null;
1373
};
1374

1375

1376
var _pluck = function ( a, prop, prop2 ) {
1377
	var out = [];
1378
	var i=0, ien=a.length;
1379

1380
	// Could have the test in the loop for slightly smaller code, but speed
1381
	// is essential here
1382
	if ( prop2 !== undefined ) {
1383
		for ( ; i<ien ; i++ ) {
1384
			if ( a[i] && a[i][ prop ] ) {
1385
				out.push( a[i][ prop ][ prop2 ] );
1386
			}
1387
		}
1388
	}
1389
	else {
1390
		for ( ; i<ien ; i++ ) {
1391
			if ( a[i] ) {
1392
				out.push( a[i][ prop ] );
1393
			}
1394
		}
1395
	}
1396

1397
	return out;
1398
};
1399

1400

1401
// Basically the same as _pluck, but rather than looping over `a` we use `order`
1402
// as the indexes to pick from `a`
1403
var _pluck_order = function ( a, order, prop, prop2 )
1404
{
1405
	var out = [];
1406
	var i=0, ien=order.length;
1407

1408
	// Could have the test in the loop for slightly smaller code, but speed
1409
	// is essential here
1410
	if ( prop2 !== undefined ) {
1411
		for ( ; i<ien ; i++ ) {
1412
			if ( a[ order[i] ][ prop ] ) {
1413
				out.push( a[ order[i] ][ prop ][ prop2 ] );
1414
			}
1415
		}
1416
	}
1417
	else {
1418
		for ( ; i<ien ; i++ ) {
1419
			out.push( a[ order[i] ][ prop ] );
1420
		}
1421
	}
1422

1423
	return out;
1424
};
1425

1426

1427
var _range = function ( len, start )
1428
{
1429
	var out = [];
1430
	var end;
1431

1432
	if ( start === undefined ) {
1433
		start = 0;
1434
		end = len;
1435
	}
1436
	else {
1437
		end = start;
1438
		start = len;
1439
	}
1440

1441
	for ( var i=start ; i<end ; i++ ) {
1442
		out.push( i );
1443
	}
1444

1445
	return out;
1446
};
1447

1448

1449
var _removeEmpty = function ( a )
1450
{
1451
	var out = [];
1452

1453
	for ( var i=0, ien=a.length ; i<ien ; i++ ) {
1454
		if ( a[i] ) { // careful - will remove all falsy values!
1455
			out.push( a[i] );
1456
		}
1457
	}
1458

1459
	return out;
1460
};
1461

1462

1463
var _stripHtml = function ( d ) {
1464
	return d
1465
		.replace( _re_html, '' ) // Complete tags
1466
		.replace(/<script/i, ''); // Safety for incomplete script tag
1467
};
1468

1469

1470
/**
1471
 * Determine if all values in the array are unique. This means we can short
1472
 * cut the _unique method at the cost of a single loop. A sorted array is used
1473
 * to easily check the values.
1474
 *
1475
 * @param  {array} src Source array
1476
 * @return {boolean} true if all unique, false otherwise
1477
 * @ignore
1478
 */
1479
var _areAllUnique = function ( src ) {
1480
	if ( src.length < 2 ) {
1481
		return true;
1482
	}
1483

1484
	var sorted = src.slice().sort();
1485
	var last = sorted[0];
1486

1487
	for ( var i=1, ien=sorted.length ; i<ien ; i++ ) {
1488
		if ( sorted[i] === last ) {
1489
			return false;
1490
		}
1491

1492
		last = sorted[i];
1493
	}
1494

1495
	return true;
1496
};
1497

1498

1499
/**
1500
 * Find the unique elements in a source array.
1501
 *
1502
 * @param  {array} src Source array
1503
 * @return {array} Array of unique items
1504
 * @ignore
1505
 */
1506
var _unique = function ( src )
1507
{
1508
	if ( _areAllUnique( src ) ) {
1509
		return src.slice();
1510
	}
1511

1512
	// A faster unique method is to use object keys to identify used values,
1513
	// but this doesn't work with arrays or objects, which we must also
1514
	// consider. See jsperf.com/compare-array-unique-versions/4 for more
1515
	// information.
1516
	var
1517
		out = [],
1518
		val,
1519
		i, ien=src.length,
1520
		j, k=0;
1521

1522
	again: for ( i=0 ; i<ien ; i++ ) {
1523
		val = src[i];
1524

1525
		for ( j=0 ; j<k ; j++ ) {
1526
			if ( out[j] === val ) {
1527
				continue again;
1528
			}
1529
		}
1530

1531
		out.push( val );
1532
		k++;
1533
	}
1534

1535
	return out;
1536
};
1537

1538
// Surprisingly this is faster than [].concat.apply
1539
// https://jsperf.com/flatten-an-array-loop-vs-reduce/2
1540
var _flatten = function (out, val) {
1541
	if (Array.isArray(val)) {
1542
		for (var i=0 ; i<val.length ; i++) {
1543
			_flatten(out, val[i]);
1544
		}
1545
	}
1546
	else {
1547
		out.push(val);
1548
	}
1549
  
1550
	return out;
1551
}
1552

1553
var _includes = function (search, start) {
1554
	if (start === undefined) {
1555
		start = 0;
1556
	}
1557

1558
	return this.indexOf(search, start) !== -1;	
1559
};
1560

1561
// Array.isArray polyfill.
1562
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
1563
if (! Array.isArray) {
1564
    Array.isArray = function(arg) {
1565
        return Object.prototype.toString.call(arg) === '[object Array]';
1566
    };
1567
}
1568

1569
if (! Array.prototype.includes) {
1570
	Array.prototype.includes = _includes;
1571
}
1572

1573
// .trim() polyfill
1574
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trim
1575
if (!String.prototype.trim) {
1576
  String.prototype.trim = function () {
1577
    return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
1578
  };
1579
}
1580

1581
if (! String.prototype.includes) {
1582
	String.prototype.includes = _includes;
1583
}
1584

1585
/**
1586
 * DataTables utility methods
1587
 * 
1588
 * This namespace provides helper methods that DataTables uses internally to
1589
 * create a DataTable, but which are not exclusively used only for DataTables.
1590
 * These methods can be used by extension authors to save the duplication of
1591
 * code.
1592
 *
1593
 *  @namespace
1594
 */
1595
DataTable.util = {
1596
	/**
1597
	 * Throttle the calls to a function. Arguments and context are maintained
1598
	 * for the throttled function.
1599
	 *
1600
	 * @param {function} fn Function to be called
1601
	 * @param {integer} freq Call frequency in mS
1602
	 * @return {function} Wrapped function
1603
	 */
1604
	throttle: function ( fn, freq ) {
1605
		var
1606
			frequency = freq !== undefined ? freq : 200,
1607
			last,
1608
			timer;
1609

1610
		return function () {
1611
			var
1612
				that = this,
1613
				now  = +new Date(),
1614
				args = arguments;
1615

1616
			if ( last && now < last + frequency ) {
1617
				clearTimeout( timer );
1618

1619
				timer = setTimeout( function () {
1620
					last = undefined;
1621
					fn.apply( that, args );
1622
				}, frequency );
1623
			}
1624
			else {
1625
				last = now;
1626
				fn.apply( that, args );
1627
			}
1628
		};
1629
	},
1630

1631

1632
	/**
1633
	 * Escape a string such that it can be used in a regular expression
1634
	 *
1635
	 *  @param {string} val string to escape
1636
	 *  @returns {string} escaped string
1637
	 */
1638
	escapeRegex: function ( val ) {
1639
		return val.replace( _re_escape_regex, '\\$1' );
1640
	},
1641

1642
	/**
1643
	 * Create a function that will write to a nested object or array
1644
	 * @param {*} source JSON notation string
1645
	 * @returns Write function
1646
	 */
1647
	set: function ( source ) {
1648
		if ( $.isPlainObject( source ) ) {
1649
			/* Unlike get, only the underscore (global) option is used for for
1650
			 * setting data since we don't know the type here. This is why an object
1651
			 * option is not documented for `mData` (which is read/write), but it is
1652
			 * for `mRender` which is read only.
1653
			 */
1654
			return DataTable.util.set( source._ );
1655
		}
1656
		else if ( source === null ) {
1657
			// Nothing to do when the data source is null
1658
			return function () {};
1659
		}
1660
		else if ( typeof source === 'function' ) {
1661
			return function (data, val, meta) {
1662
				source( data, 'set', val, meta );
1663
			};
1664
		}
1665
		else if ( typeof source === 'string' && (source.indexOf('.') !== -1 ||
1666
				  source.indexOf('[') !== -1 || source.indexOf('(') !== -1) )
1667
		{
1668
			// Like the get, we need to get data from a nested object
1669
			var setData = function (data, val, src) {
1670
				var a = _fnSplitObjNotation( src ), b;
1671
				var aLast = a[a.length-1];
1672
				var arrayNotation, funcNotation, o, innerSrc;
1673
	
1674
				for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ ) {
1675
					// Protect against prototype pollution
1676
					if (a[i] === '__proto__' || a[i] === 'constructor') {
1677
						throw new Error('Cannot set prototype values');
1678
					}
1679
	
1680
					// Check if we are dealing with an array notation request
1681
					arrayNotation = a[i].match(__reArray);
1682
					funcNotation = a[i].match(__reFn);
1683
	
1684
					if ( arrayNotation ) {
1685
						a[i] = a[i].replace(__reArray, '');
1686
						data[ a[i] ] = [];
1687
	
1688
						// Get the remainder of the nested object to set so we can recurse
1689
						b = a.slice();
1690
						b.splice( 0, i+1 );
1691
						innerSrc = b.join('.');
1692
	
1693
						// Traverse each entry in the array setting the properties requested
1694
						if ( Array.isArray( val ) ) {
1695
							for ( var j=0, jLen=val.length ; j<jLen ; j++ ) {
1696
								o = {};
1697
								setData( o, val[j], innerSrc );
1698
								data[ a[i] ].push( o );
1699
							}
1700
						}
1701
						else {
1702
							// We've been asked to save data to an array, but it
1703
							// isn't array data to be saved. Best that can be done
1704
							// is to just save the value.
1705
							data[ a[i] ] = val;
1706
						}
1707
	
1708
						// The inner call to setData has already traversed through the remainder
1709
						// of the source and has set the data, thus we can exit here
1710
						return;
1711
					}
1712
					else if ( funcNotation ) {
1713
						// Function call
1714
						a[i] = a[i].replace(__reFn, '');
1715
						data = data[ a[i] ]( val );
1716
					}
1717
	
1718
					// If the nested object doesn't currently exist - since we are
1719
					// trying to set the value - create it
1720
					if ( data[ a[i] ] === null || data[ a[i] ] === undefined ) {
1721
						data[ a[i] ] = {};
1722
					}
1723
					data = data[ a[i] ];
1724
				}
1725
	
1726
				// Last item in the input - i.e, the actual set
1727
				if ( aLast.match(__reFn ) ) {
1728
					// Function call
1729
					data = data[ aLast.replace(__reFn, '') ]( val );
1730
				}
1731
				else {
1732
					// If array notation is used, we just want to strip it and use the property name
1733
					// and assign the value. If it isn't used, then we get the result we want anyway
1734
					data[ aLast.replace(__reArray, '') ] = val;
1735
				}
1736
			};
1737
	
1738
			return function (data, val) { // meta is also passed in, but not used
1739
				return setData( data, val, source );
1740
			};
1741
		}
1742
		else {
1743
			// Array or flat object mapping
1744
			return function (data, val) { // meta is also passed in, but not used
1745
				data[source] = val;
1746
			};
1747
		}
1748
	},
1749

1750
	/**
1751
	 * Create a function that will read nested objects from arrays, based on JSON notation
1752
	 * @param {*} source JSON notation string
1753
	 * @returns Value read
1754
	 */
1755
	get: function ( source ) {
1756
		if ( $.isPlainObject( source ) ) {
1757
			// Build an object of get functions, and wrap them in a single call
1758
			var o = {};
1759
			$.each( source, function (key, val) {
1760
				if ( val ) {
1761
					o[key] = DataTable.util.get( val );
1762
				}
1763
			} );
1764
	
1765
			return function (data, type, row, meta) {
1766
				var t = o[type] || o._;
1767
				return t !== undefined ?
1768
					t(data, type, row, meta) :
1769
					data;
1770
			};
1771
		}
1772
		else if ( source === null ) {
1773
			// Give an empty string for rendering / sorting etc
1774
			return function (data) { // type, row and meta also passed, but not used
1775
				return data;
1776
			};
1777
		}
1778
		else if ( typeof source === 'function' ) {
1779
			return function (data, type, row, meta) {
1780
				return source( data, type, row, meta );
1781
			};
1782
		}
1783
		else if ( typeof source === 'string' && (source.indexOf('.') !== -1 ||
1784
				  source.indexOf('[') !== -1 || source.indexOf('(') !== -1) )
1785
		{
1786
			/* If there is a . in the source string then the data source is in a
1787
			 * nested object so we loop over the data for each level to get the next
1788
			 * level down. On each loop we test for undefined, and if found immediately
1789
			 * return. This allows entire objects to be missing and sDefaultContent to
1790
			 * be used if defined, rather than throwing an error
1791
			 */
1792
			var fetchData = function (data, type, src) {
1793
				var arrayNotation, funcNotation, out, innerSrc;
1794
	
1795
				if ( src !== "" ) {
1796
					var a = _fnSplitObjNotation( src );
1797
	
1798
					for ( var i=0, iLen=a.length ; i<iLen ; i++ ) {
1799
						// Check if we are dealing with special notation
1800
						arrayNotation = a[i].match(__reArray);
1801
						funcNotation = a[i].match(__reFn);
1802
	
1803
						if ( arrayNotation ) {
1804
							// Array notation
1805
							a[i] = a[i].replace(__reArray, '');
1806
	
1807
							// Condition allows simply [] to be passed in
1808
							if ( a[i] !== "" ) {
1809
								data = data[ a[i] ];
1810
							}
1811
							out = [];
1812
	
1813
							// Get the remainder of the nested object to get
1814
							a.splice( 0, i+1 );
1815
							innerSrc = a.join('.');
1816
	
1817
							// Traverse each entry in the array getting the properties requested
1818
							if ( Array.isArray( data ) ) {
1819
								for ( var j=0, jLen=data.length ; j<jLen ; j++ ) {
1820
									out.push( fetchData( data[j], type, innerSrc ) );
1821
								}
1822
							}
1823
	
1824
							// If a string is given in between the array notation indicators, that
1825
							// is used to join the strings together, otherwise an array is returned
1826
							var join = arrayNotation[0].substring(1, arrayNotation[0].length-1);
1827
							data = (join==="") ? out : out.join(join);
1828
	
1829
							// The inner call to fetchData has already traversed through the remainder
1830
							// of the source requested, so we exit from the loop
1831
							break;
1832
						}
1833
						else if ( funcNotation ) {
1834
							// Function call
1835
							a[i] = a[i].replace(__reFn, '');
1836
							data = data[ a[i] ]();
1837
							continue;
1838
						}
1839
	
1840
						if (data === null || data[ a[i] ] === null) {
1841
							return null;
1842
						}
1843
						else if ( data === undefined || data[ a[i] ] === undefined ) {
1844
							return undefined;
1845
						}
1846

1847
						data = data[ a[i] ];
1848
					}
1849
				}
1850
	
1851
				return data;
1852
			};
1853
	
1854
			return function (data, type) { // row and meta also passed, but not used
1855
				return fetchData( data, type, source );
1856
			};
1857
		}
1858
		else {
1859
			// Array or flat object mapping
1860
			return function (data, type) { // row and meta also passed, but not used
1861
				return data[source];
1862
			};
1863
		}
1864
	}
1865
};
1866

1867

1868

1869
/**
1870
 * Create a mapping object that allows camel case parameters to be looked up
1871
 * for their Hungarian counterparts. The mapping is stored in a private
1872
 * parameter called `_hungarianMap` which can be accessed on the source object.
1873
 *  @param {object} o
1874
 *  @memberof DataTable#oApi
1875
 */
1876
function _fnHungarianMap ( o )
1877
{
1878
	var
1879
		hungarian = 'a aa ai ao as b fn i m o s ',
1880
		match,
1881
		newKey,
1882
		map = {};
1883

1884
	$.each( o, function (key, val) {
1885
		match = key.match(/^([^A-Z]+?)([A-Z])/);
1886

1887
		if ( match && hungarian.indexOf(match[1]+' ') !== -1 )
1888
		{
1889
			newKey = key.replace( match[0], match[2].toLowerCase() );
1890
			map[ newKey ] = key;
1891

1892
			if ( match[1] === 'o' )
1893
			{
1894
				_fnHungarianMap( o[key] );
1895
			}
1896
		}
1897
	} );
1898

1899
	o._hungarianMap = map;
1900
}
1901

1902

1903
/**
1904
 * Convert from camel case parameters to Hungarian, based on a Hungarian map
1905
 * created by _fnHungarianMap.
1906
 *  @param {object} src The model object which holds all parameters that can be
1907
 *    mapped.
1908
 *  @param {object} user The object to convert from camel case to Hungarian.
1909
 *  @param {boolean} force When set to `true`, properties which already have a
1910
 *    Hungarian value in the `user` object will be overwritten. Otherwise they
1911
 *    won't be.
1912
 *  @memberof DataTable#oApi
1913
 */
1914
function _fnCamelToHungarian ( src, user, force )
1915
{
1916
	if ( ! src._hungarianMap ) {
1917
		_fnHungarianMap( src );
1918
	}
1919

1920
	var hungarianKey;
1921

1922
	$.each( user, function (key, val) {
1923
		hungarianKey = src._hungarianMap[ key ];
1924

1925
		if ( hungarianKey !== undefined && (force || user[hungarianKey] === undefined) )
1926
		{
1927
			// For objects, we need to buzz down into the object to copy parameters
1928
			if ( hungarianKey.charAt(0) === 'o' )
1929
			{
1930
				// Copy the camelCase options over to the hungarian
1931
				if ( ! user[ hungarianKey ] ) {
1932
					user[ hungarianKey ] = {};
1933
				}
1934
				$.extend( true, user[hungarianKey], user[key] );
1935

1936
				_fnCamelToHungarian( src[hungarianKey], user[hungarianKey], force );
1937
			}
1938
			else {
1939
				user[hungarianKey] = user[ key ];
1940
			}
1941
		}
1942
	} );
1943
}
1944

1945

1946
/**
1947
 * Language compatibility - when certain options are given, and others aren't, we
1948
 * need to duplicate the values over, in order to provide backwards compatibility
1949
 * with older language files.
1950
 *  @param {object} oSettings dataTables settings object
1951
 *  @memberof DataTable#oApi
1952
 */
1953
function _fnLanguageCompat( lang )
1954
{
1955
	// Note the use of the Hungarian notation for the parameters in this method as
1956
	// this is called after the mapping of camelCase to Hungarian
1957
	var defaults = DataTable.defaults.oLanguage;
1958

1959
	// Default mapping
1960
	var defaultDecimal = defaults.sDecimal;
1961
	if ( defaultDecimal ) {
1962
		_addNumericSort( defaultDecimal );
1963
	}
1964

1965
	if ( lang ) {
1966
		var zeroRecords = lang.sZeroRecords;
1967

1968
		// Backwards compatibility - if there is no sEmptyTable given, then use the same as
1969
		// sZeroRecords - assuming that is given.
1970
		if ( ! lang.sEmptyTable && zeroRecords &&
1971
			defaults.sEmptyTable === "No data available in table" )
1972
		{
1973
			_fnMap( lang, lang, 'sZeroRecords', 'sEmptyTable' );
1974
		}
1975

1976
		// Likewise with loading records
1977
		if ( ! lang.sLoadingRecords && zeroRecords &&
1978
			defaults.sLoadingRecords === "Loading..." )
1979
		{
1980
			_fnMap( lang, lang, 'sZeroRecords', 'sLoadingRecords' );
1981
		}
1982

1983
		// Old parameter name of the thousands separator mapped onto the new
1984
		if ( lang.sInfoThousands ) {
1985
			lang.sThousands = lang.sInfoThousands;
1986
		}
1987

1988
		var decimal = lang.sDecimal;
1989
		if ( decimal && defaultDecimal !== decimal ) {
1990
			_addNumericSort( decimal );
1991
		}
1992
	}
1993
}
1994

1995

1996
/**
1997
 * Map one parameter onto another
1998
 *  @param {object} o Object to map
1999
 *  @param {*} knew The new parameter name
2000
 *  @param {*} old The old parameter name
2001
 */
2002
var _fnCompatMap = function ( o, knew, old ) {
2003
	if ( o[ knew ] !== undefined ) {
2004
		o[ old ] = o[ knew ];
2005
	}
2006
};
2007

2008

2009
/**
2010
 * Provide backwards compatibility for the main DT options. Note that the new
2011
 * options are mapped onto the old parameters, so this is an external interface
2012
 * change only.
2013
 *  @param {object} init Object to map
2014
 */
2015
function _fnCompatOpts ( init )
2016
{
2017
	_fnCompatMap( init, 'ordering',      'bSort' );
2018
	_fnCompatMap( init, 'orderMulti',    'bSortMulti' );
2019
	_fnCompatMap( init, 'orderClasses',  'bSortClasses' );
2020
	_fnCompatMap( init, 'orderCellsTop', 'bSortCellsTop' );
2021
	_fnCompatMap( init, 'order',         'aaSorting' );
2022
	_fnCompatMap( init, 'orderFixed',    'aaSortingFixed' );
2023
	_fnCompatMap( init, 'paging',        'bPaginate' );
2024
	_fnCompatMap( init, 'pagingType',    'sPaginationType' );
2025
	_fnCompatMap( init, 'pageLength',    'iDisplayLength' );
2026
	_fnCompatMap( init, 'searching',     'bFilter' );
2027

2028
	// Boolean initialisation of x-scrolling
2029
	if ( typeof init.sScrollX === 'boolean' ) {
2030
		init.sScrollX = init.sScrollX ? '100%' : '';
2031
	}
2032
	if ( typeof init.scrollX === 'boolean' ) {
2033
		init.scrollX = init.scrollX ? '100%' : '';
2034
	}
2035

2036
	// Column search objects are in an array, so it needs to be converted
2037
	// element by element
2038
	var searchCols = init.aoSearchCols;
2039

2040
	if ( searchCols ) {
2041
		for ( var i=0, ien=searchCols.length ; i<ien ; i++ ) {
2042
			if ( searchCols[i] ) {
2043
				_fnCamelToHungarian( DataTable.models.oSearch, searchCols[i] );
2044
			}
2045
		}
2046
	}
2047
}
2048

2049

2050
/**
2051
 * Provide backwards compatibility for column options. Note that the new options
2052
 * are mapped onto the old parameters, so this is an external interface change
2053
 * only.
2054
 *  @param {object} init Object to map
2055
 */
2056
function _fnCompatCols ( init )
2057
{
2058
	_fnCompatMap( init, 'orderable',     'bSortable' );
2059
	_fnCompatMap( init, 'orderData',     'aDataSort' );
2060
	_fnCompatMap( init, 'orderSequence', 'asSorting' );
2061
	_fnCompatMap( init, 'orderDataType', 'sortDataType' );
2062

2063
	// orderData can be given as an integer
2064
	var dataSort = init.aDataSort;
2065
	if ( typeof dataSort === 'number' && ! Array.isArray( dataSort ) ) {
2066
		init.aDataSort = [ dataSort ];
2067
	}
2068
}
2069

2070

2071
/**
2072
 * Browser feature detection for capabilities, quirks
2073
 *  @param {object} settings dataTables settings object
2074
 *  @memberof DataTable#oApi
2075
 */
2076
function _fnBrowserDetect( settings )
2077
{
2078
	// We don't need to do this every time DataTables is constructed, the values
2079
	// calculated are specific to the browser and OS configuration which we
2080
	// don't expect to change between initialisations
2081
	if ( ! DataTable.__browser ) {
2082
		var browser = {};
2083
		DataTable.__browser = browser;
2084

2085
		// Scrolling feature / quirks detection
2086
		var n = $('<div/>')
2087
			.css( {
2088
				position: 'fixed',
2089
				top: 0,
2090
				left: $(window).scrollLeft()*-1, // allow for scrolling
2091
				height: 1,
2092
				width: 1,
2093
				overflow: 'hidden'
2094
			} )
2095
			.append(
2096
				$('<div/>')
2097
					.css( {
2098
						position: 'absolute',
2099
						top: 1,
2100
						left: 1,
2101
						width: 100,
2102
						overflow: 'scroll'
2103
					} )
2104
					.append(
2105
						$('<div/>')
2106
							.css( {
2107
								width: '100%',
2108
								height: 10
2109
							} )
2110
					)
2111
			)
2112
			.appendTo( 'body' );
2113

2114
		var outer = n.children();
2115
		var inner = outer.children();
2116

2117
		// Numbers below, in order, are:
2118
		// inner.offsetWidth, inner.clientWidth, outer.offsetWidth, outer.clientWidth
2119
		//
2120
		// IE6 XP:                           100 100 100  83
2121
		// IE7 Vista:                        100 100 100  83
2122
		// IE 8+ Windows:                     83  83 100  83
2123
		// Evergreen Windows:                 83  83 100  83
2124
		// Evergreen Mac with scrollbars:     85  85 100  85
2125
		// Evergreen Mac without scrollbars: 100 100 100 100
2126

2127
		// Get scrollbar width
2128
		browser.barWidth = outer[0].offsetWidth - outer[0].clientWidth;
2129

2130
		// IE6/7 will oversize a width 100% element inside a scrolling element, to
2131
		// include the width of the scrollbar, while other browsers ensure the inner
2132
		// element is contained without forcing scrolling
2133
		browser.bScrollOversize = inner[0].offsetWidth === 100 && outer[0].clientWidth !== 100;
2134

2135
		// In rtl text layout, some browsers (most, but not all) will place the
2136
		// scrollbar on the left, rather than the right.
2137
		browser.bScrollbarLeft = Math.round( inner.offset().left ) !== 1;
2138

2139
		// IE8- don't provide height and width for getBoundingClientRect
2140
		browser.bBounding = n[0].getBoundingClientRect().width ? true : false;
2141

2142
		n.remove();
2143
	}
2144

2145
	$.extend( settings.oBrowser, DataTable.__browser );
2146
	settings.oScroll.iBarWidth = DataTable.__browser.barWidth;
2147
}
2148

2149

2150
/**
2151
 * Array.prototype reduce[Right] method, used for browsers which don't support
2152
 * JS 1.6. Done this way to reduce code size, since we iterate either way
2153
 *  @param {object} settings dataTables settings object
2154
 *  @memberof DataTable#oApi
2155
 */
2156
function _fnReduce ( that, fn, init, start, end, inc )
2157
{
2158
	var
2159
		i = start,
2160
		value,
2161
		isSet = false;
2162

2163
	if ( init !== undefined ) {
2164
		value = init;
2165
		isSet = true;
2166
	}
2167

2168
	while ( i !== end ) {
2169
		if ( ! that.hasOwnProperty(i) ) {
2170
			continue;
2171
		}
2172

2173
		value = isSet ?
2174
			fn( value, that[i], i, that ) :
2175
			that[i];
2176

2177
		isSet = true;
2178
		i += inc;
2179
	}
2180

2181
	return value;
2182
}
2183

2184
/**
2185
 * Add a column to the list used for the table with default values
2186
 *  @param {object} oSettings dataTables settings object
2187
 *  @param {node} nTh The th element for this column
2188
 *  @memberof DataTable#oApi
2189
 */
2190
function _fnAddColumn( oSettings, nTh )
2191
{
2192
	// Add column to aoColumns array
2193
	var oDefaults = DataTable.defaults.column;
2194
	var iCol = oSettings.aoColumns.length;
2195
	var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {
2196
		"nTh": nTh ? nTh : document.createElement('th'),
2197
		"sTitle":    oDefaults.sTitle    ? oDefaults.sTitle    : nTh ? nTh.innerHTML : '',
2198
		"aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],
2199
		"mData": oDefaults.mData ? oDefaults.mData : iCol,
2200
		idx: iCol
2201
	} );
2202
	oSettings.aoColumns.push( oCol );
2203

2204
	// Add search object for column specific search. Note that the `searchCols[ iCol ]`
2205
	// passed into extend can be undefined. This allows the user to give a default
2206
	// with only some of the parameters defined, and also not give a default
2207
	var searchCols = oSettings.aoPreSearchCols;
2208
	searchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] );
2209

2210
	// Use the default column options function to initialise classes etc
2211
	_fnColumnOptions( oSettings, iCol, $(nTh).data() );
2212
}
2213

2214

2215
/**
2216
 * Apply options for a column
2217
 *  @param {object} oSettings dataTables settings object
2218
 *  @param {int} iCol column index to consider
2219
 *  @param {object} oOptions object with sType, bVisible and bSearchable etc
2220
 *  @memberof DataTable#oApi
2221
 */
2222
function _fnColumnOptions( oSettings, iCol, oOptions )
2223
{
2224
	var oCol = oSettings.aoColumns[ iCol ];
2225
	var oClasses = oSettings.oClasses;
2226
	var th = $(oCol.nTh);
2227

2228
	// Try to get width information from the DOM. We can't get it from CSS
2229
	// as we'd need to parse the CSS stylesheet. `width` option can override
2230
	if ( ! oCol.sWidthOrig ) {
2231
		// Width attribute
2232
		oCol.sWidthOrig = th.attr('width') || null;
2233

2234
		// Style attribute
2235
		var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/);
2236
		if ( t ) {
2237
			oCol.sWidthOrig = t[1];
2238
		}
2239
	}
2240

2241
	/* User specified column options */
2242
	if ( oOptions !== undefined && oOptions !== null )
2243
	{
2244
		// Backwards compatibility
2245
		_fnCompatCols( oOptions );
2246

2247
		// Map camel case parameters to their Hungarian counterparts
2248
		_fnCamelToHungarian( DataTable.defaults.column, oOptions, true );
2249

2250
		/* Backwards compatibility for mDataProp */
2251
		if ( oOptions.mDataProp !== undefined && !oOptions.mData )
2252
		{
2253
			oOptions.mData = oOptions.mDataProp;
2254
		}
2255

2256
		if ( oOptions.sType )
2257
		{
2258
			oCol._sManualType = oOptions.sType;
2259
		}
2260

2261
		// `class` is a reserved word in Javascript, so we need to provide
2262
		// the ability to use a valid name for the camel case input
2263
		if ( oOptions.className && ! oOptions.sClass )
2264
		{
2265
			oOptions.sClass = oOptions.className;
2266
		}
2267
		if ( oOptions.sClass ) {
2268
			th.addClass( oOptions.sClass );
2269
		}
2270

2271
		var origClass = oCol.sClass;
2272

2273
		$.extend( oCol, oOptions );
2274
		_fnMap( oCol, oOptions, "sWidth", "sWidthOrig" );
2275

2276
		// Merge class from previously defined classes with this one, rather than just
2277
		// overwriting it in the extend above
2278
		if (origClass !== oCol.sClass) {
2279
			oCol.sClass = origClass + ' ' + oCol.sClass;
2280
		}
2281

2282
		/* iDataSort to be applied (backwards compatibility), but aDataSort will take
2283
		 * priority if defined
2284
		 */
2285
		if ( oOptions.iDataSort !== undefined )
2286
		{
2287
			oCol.aDataSort = [ oOptions.iDataSort ];
2288
		}
2289
		_fnMap( oCol, oOptions, "aDataSort" );
2290
	}
2291

2292
	/* Cache the data get and set functions for speed */
2293
	var mDataSrc = oCol.mData;
2294
	var mData = _fnGetObjectDataFn( mDataSrc );
2295
	var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null;
2296

2297
	var attrTest = function( src ) {
2298
		return typeof src === 'string' && src.indexOf('@') !== -1;
2299
	};
2300
	oCol._bAttrSrc = $.isPlainObject( mDataSrc ) && (
2301
		attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter)
2302
	);
2303
	oCol._setter = null;
2304

2305
	oCol.fnGetData = function (rowData, type, meta) {
2306
		var innerData = mData( rowData, type, undefined, meta );
2307

2308
		return mRender && type ?
2309
			mRender( innerData, type, rowData, meta ) :
2310
			innerData;
2311
	};
2312
	oCol.fnSetData = function ( rowData, val, meta ) {
2313
		return _fnSetObjectDataFn( mDataSrc )( rowData, val, meta );
2314
	};
2315

2316
	// Indicate if DataTables should read DOM data as an object or array
2317
	// Used in _fnGetRowElements
2318
	if ( typeof mDataSrc !== 'number' && ! oCol._isArrayHost ) {
2319
		oSettings._rowReadObject = true;
2320
	}
2321

2322
	/* Feature sorting overrides column specific when off */
2323
	if ( !oSettings.oFeatures.bSort )
2324
	{
2325
		oCol.bSortable = false;
2326
		th.addClass( oClasses.sSortableNone ); // Have to add class here as order event isn't called
2327
	}
2328

2329
	/* Check that the class assignment is correct for sorting */
2330
	var bAsc = $.inArray('asc', oCol.asSorting) !== -1;
2331
	var bDesc = $.inArray('desc', oCol.asSorting) !== -1;
2332
	if ( !oCol.bSortable || (!bAsc && !bDesc) )
2333
	{
2334
		oCol.sSortingClass = oClasses.sSortableNone;
2335
		oCol.sSortingClassJUI = "";
2336
	}
2337
	else if ( bAsc && !bDesc )
2338
	{
2339
		oCol.sSortingClass = oClasses.sSortableAsc;
2340
		oCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed;
2341
	}
2342
	else if ( !bAsc && bDesc )
2343
	{
2344
		oCol.sSortingClass = oClasses.sSortableDesc;
2345
		oCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed;
2346
	}
2347
	else
2348
	{
2349
		oCol.sSortingClass = oClasses.sSortable;
2350
		oCol.sSortingClassJUI = oClasses.sSortJUI;
2351
	}
2352
}
2353

2354

2355
/**
2356
 * Adjust the table column widths for new data. Note: you would probably want to
2357
 * do a redraw after calling this function!
2358
 *  @param {object} settings dataTables settings object
2359
 *  @memberof DataTable#oApi
2360
 */
2361
function _fnAdjustColumnSizing ( settings )
2362
{
2363
	/* Not interested in doing column width calculation if auto-width is disabled */
2364
	if ( settings.oFeatures.bAutoWidth !== false )
2365
	{
2366
		var columns = settings.aoColumns;
2367

2368
		_fnCalculateColumnWidths( settings );
2369
		for ( var i=0 , iLen=columns.length ; i<iLen ; i++ )
2370
		{
2371
			columns[i].nTh.style.width = columns[i].sWidth;
2372
		}
2373
	}
2374

2375
	var scroll = settings.oScroll;
2376
	if ( scroll.sY !== '' || scroll.sX !== '')
2377
	{
2378
		_fnScrollDraw( settings );
2379
	}
2380

2381
	_fnCallbackFire( settings, null, 'column-sizing', [settings] );
2382
}
2383

2384

2385
/**
2386
 * Convert the index of a visible column to the index in the data array (take account
2387
 * of hidden columns)
2388
 *  @param {object} oSettings dataTables settings object
2389
 *  @param {int} iMatch Visible column index to lookup
2390
 *  @returns {int} i the data index
2391
 *  @memberof DataTable#oApi
2392
 */
2393
function _fnVisibleToColumnIndex( oSettings, iMatch )
2394
{
2395
	var aiVis = _fnGetColumns( oSettings, 'bVisible' );
2396

2397
	return typeof aiVis[iMatch] === 'number' ?
2398
		aiVis[iMatch] :
2399
		null;
2400
}
2401

2402

2403
/**
2404
 * Convert the index of an index in the data array and convert it to the visible
2405
 *   column index (take account of hidden columns)
2406
 *  @param {int} iMatch Column index to lookup
2407
 *  @param {object} oSettings dataTables settings object
2408
 *  @returns {int} i the data index
2409
 *  @memberof DataTable#oApi
2410
 */
2411
function _fnColumnIndexToVisible( oSettings, iMatch )
2412
{
2413
	var aiVis = _fnGetColumns( oSettings, 'bVisible' );
2414
	var iPos = $.inArray( iMatch, aiVis );
2415

2416
	return iPos !== -1 ? iPos : null;
2417
}
2418

2419

2420
/**
2421
 * Get the number of visible columns
2422
 *  @param {object} oSettings dataTables settings object
2423
 *  @returns {int} i the number of visible columns
2424
 *  @memberof DataTable#oApi
2425
 */
2426
function _fnVisbleColumns( oSettings )
2427
{
2428
	var vis = 0;
2429

2430
	// No reduce in IE8, use a loop for now
2431
	$.each( oSettings.aoColumns, function ( i, col ) {
2432
		if ( col.bVisible && $(col.nTh).css('display') !== 'none' ) {
2433
			vis++;
2434
		}
2435
	} );
2436

2437
	return vis;
2438
}
2439

2440

2441
/**
2442
 * Get an array of column indexes that match a given property
2443
 *  @param {object} oSettings dataTables settings object
2444
 *  @param {string} sParam Parameter in aoColumns to look for - typically
2445
 *    bVisible or bSearchable
2446
 *  @returns {array} Array of indexes with matched properties
2447
 *  @memberof DataTable#oApi
2448
 */
2449
function _fnGetColumns( oSettings, sParam )
2450
{
2451
	var a = [];
2452

2453
	$.map( oSettings.aoColumns, function(val, i) {
2454
		if ( val[sParam] ) {
2455
			a.push( i );
2456
		}
2457
	} );
2458

2459
	return a;
2460
}
2461

2462

2463
/**
2464
 * Calculate the 'type' of a column
2465
 *  @param {object} settings dataTables settings object
2466
 *  @memberof DataTable#oApi
2467
 */
2468
function _fnColumnTypes ( settings )
2469
{
2470
	var columns = settings.aoColumns;
2471
	var data = settings.aoData;
2472
	var types = DataTable.ext.type.detect;
2473
	var i, ien, j, jen, k, ken;
2474
	var col, cell, detectedType, cache;
2475

2476
	// For each column, spin over the 
2477
	for ( i=0, ien=columns.length ; i<ien ; i++ ) {
2478
		col = columns[i];
2479
		cache = [];
2480

2481
		if ( ! col.sType && col._sManualType ) {
2482
			col.sType = col._sManualType;
2483
		}
2484
		else if ( ! col.sType ) {
2485
			for ( j=0, jen=types.length ; j<jen ; j++ ) {
2486
				for ( k=0, ken=data.length ; k<ken ; k++ ) {
2487
					// Use a cache array so we only need to get the type data
2488
					// from the formatter once (when using multiple detectors)
2489
					if ( cache[k] === undefined ) {
2490
						cache[k] = _fnGetCellData( settings, k, i, 'type' );
2491
					}
2492

2493
					detectedType = types[j]( cache[k], settings );
2494

2495
					// If null, then this type can't apply to this column, so
2496
					// rather than testing all cells, break out. There is an
2497
					// exception for the last type which is `html`. We need to
2498
					// scan all rows since it is possible to mix string and HTML
2499
					// types
2500
					if ( ! detectedType && j !== types.length-1 ) {
2501
						break;
2502
					}
2503

2504
					// Only a single match is needed for html type since it is
2505
					// bottom of the pile and very similar to string - but it
2506
					// must not be empty
2507
					if ( detectedType === 'html' && ! _empty(cache[k]) ) {
2508
						break;
2509
					}
2510
				}
2511

2512
				// Type is valid for all data points in the column - use this
2513
				// type
2514
				if ( detectedType ) {
2515
					col.sType = detectedType;
2516
					break;
2517
				}
2518
			}
2519

2520
			// Fall back - if no type was detected, always use string
2521
			if ( ! col.sType ) {
2522
				col.sType = 'string';
2523
			}
2524
		}
2525
	}
2526
}
2527

2528

2529
/**
2530
 * Take the column definitions and static columns arrays and calculate how
2531
 * they relate to column indexes. The callback function will then apply the
2532
 * definition found for a column to a suitable configuration object.
2533
 *  @param {object} oSettings dataTables settings object
2534
 *  @param {array} aoColDefs The aoColumnDefs array that is to be applied
2535
 *  @param {array} aoCols The aoColumns array that defines columns individually
2536
 *  @param {function} fn Callback function - takes two parameters, the calculated
2537
 *    column index and the definition for that column.
2538
 *  @memberof DataTable#oApi
2539
 */
2540
function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )
2541
{
2542
	var i, iLen, j, jLen, k, kLen, def;
2543
	var columns = oSettings.aoColumns;
2544

2545
	// Column definitions with aTargets
2546
	if ( aoColDefs )
2547
	{
2548
		/* Loop over the definitions array - loop in reverse so first instance has priority */
2549
		for ( i=aoColDefs.length-1 ; i>=0 ; i-- )
2550
		{
2551
			def = aoColDefs[i];
2552

2553
			/* Each definition can target multiple columns, as it is an array */
2554
			var aTargets = def.target !== undefined
2555
				? def.target
2556
				: def.targets !== undefined
2557
					? def.targets
2558
					: def.aTargets;
2559

2560
			if ( ! Array.isArray( aTargets ) )
2561
			{
2562
				aTargets = [ aTargets ];
2563
			}
2564

2565
			for ( j=0, jLen=aTargets.length ; j<jLen ; j++ )
2566
			{
2567
				if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 )
2568
				{
2569
					/* Add columns that we don't yet know about */
2570
					while( columns.length <= aTargets[j] )
2571
					{
2572
						_fnAddColumn( oSettings );
2573
					}
2574

2575
					/* Integer, basic index */
2576
					fn( aTargets[j], def );
2577
				}
2578
				else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 )
2579
				{
2580
					/* Negative integer, right to left column counting */
2581
					fn( columns.length+aTargets[j], def );
2582
				}
2583
				else if ( typeof aTargets[j] === 'string' )
2584
				{
2585
					/* Class name matching on TH element */
2586
					for ( k=0, kLen=columns.length ; k<kLen ; k++ )
2587
					{
2588
						if ( aTargets[j] == "_all" ||
2589
						     $(columns[k].nTh).hasClass( aTargets[j] ) )
2590
						{
2591
							fn( k, def );
2592
						}
2593
					}
2594
				}
2595
			}
2596
		}
2597
	}
2598

2599
	// Statically defined columns array
2600
	if ( aoCols )
2601
	{
2602
		for ( i=0, iLen=aoCols.length ; i<iLen ; i++ )
2603
		{
2604
			fn( i, aoCols[i] );
2605
		}
2606
	}
2607
}
2608

2609
/**
2610
 * Add a data array to the table, creating DOM node etc. This is the parallel to
2611
 * _fnGatherData, but for adding rows from a Javascript source, rather than a
2612
 * DOM source.
2613
 *  @param {object} oSettings dataTables settings object
2614
 *  @param {array} aData data array to be added
2615
 *  @param {node} [nTr] TR element to add to the table - optional. If not given,
2616
 *    DataTables will create a row automatically
2617
 *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
2618
 *    if nTr is.
2619
 *  @returns {int} >=0 if successful (index of new aoData entry), -1 if failed
2620
 *  @memberof DataTable#oApi
2621
 */
2622
function _fnAddData ( oSettings, aDataIn, nTr, anTds )
2623
{
2624
	/* Create the object for storing information about this new row */
2625
	var iRow = oSettings.aoData.length;
2626
	var oData = $.extend( true, {}, DataTable.models.oRow, {
2627
		src: nTr ? 'dom' : 'data',
2628
		idx: iRow
2629
	} );
2630

2631
	oData._aData = aDataIn;
2632
	oSettings.aoData.push( oData );
2633

2634
	/* Create the cells */
2635
	var nTd, sThisType;
2636
	var columns = oSettings.aoColumns;
2637

2638
	// Invalidate the column types as the new data needs to be revalidated
2639
	for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
2640
	{
2641
		columns[i].sType = null;
2642
	}
2643

2644
	/* Add to the display array */
2645
	oSettings.aiDisplayMaster.push( iRow );
2646

2647
	var id = oSettings.rowIdFn( aDataIn );
2648
	if ( id !== undefined ) {
2649
		oSettings.aIds[ id ] = oData;
2650
	}
2651

2652
	/* Create the DOM information, or register it if already present */
2653
	if ( nTr || ! oSettings.oFeatures.bDeferRender )
2654
	{
2655
		_fnCreateTr( oSettings, iRow, nTr, anTds );
2656
	}
2657

2658
	return iRow;
2659
}
2660

2661

2662
/**
2663
 * Add one or more TR elements to the table. Generally we'd expect to
2664
 * use this for reading data from a DOM sourced table, but it could be
2665
 * used for an TR element. Note that if a TR is given, it is used (i.e.
2666
 * it is not cloned).
2667
 *  @param {object} settings dataTables settings object
2668
 *  @param {array|node|jQuery} trs The TR element(s) to add to the table
2669
 *  @returns {array} Array of indexes for the added rows
2670
 *  @memberof DataTable#oApi
2671
 */
2672
function _fnAddTr( settings, trs )
2673
{
2674
	var row;
2675

2676
	// Allow an individual node to be passed in
2677
	if ( ! (trs instanceof $) ) {
2678
		trs = $(trs);
2679
	}
2680

2681
	return trs.map( function (i, el) {
2682
		row = _fnGetRowElements( settings, el );
2683
		return _fnAddData( settings, row.data, el, row.cells );
2684
	} );
2685
}
2686

2687

2688
/**
2689
 * Take a TR element and convert it to an index in aoData
2690
 *  @param {object} oSettings dataTables settings object
2691
 *  @param {node} n the TR element to find
2692
 *  @returns {int} index if the node is found, null if not
2693
 *  @memberof DataTable#oApi
2694
 */
2695
function _fnNodeToDataIndex( oSettings, n )
2696
{
2697
	return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null;
2698
}
2699

2700

2701
/**
2702
 * Take a TD element and convert it into a column data index (not the visible index)
2703
 *  @param {object} oSettings dataTables settings object
2704
 *  @param {int} iRow The row number the TD/TH can be found in
2705
 *  @param {node} n The TD/TH element to find
2706
 *  @returns {int} index if the node is found, -1 if not
2707
 *  @memberof DataTable#oApi
2708
 */
2709
function _fnNodeToColumnIndex( oSettings, iRow, n )
2710
{
2711
	return $.inArray( n, oSettings.aoData[ iRow ].anCells );
2712
}
2713

2714

2715
/**
2716
 * Get the data for a given cell from the internal cache, taking into account data mapping
2717
 *  @param {object} settings dataTables settings object
2718
 *  @param {int} rowIdx aoData row id
2719
 *  @param {int} colIdx Column index
2720
 *  @param {string} type data get type ('display', 'type' 'filter|search' 'sort|order')
2721
 *  @returns {*} Cell data
2722
 *  @memberof DataTable#oApi
2723
 */
2724
function _fnGetCellData( settings, rowIdx, colIdx, type )
2725
{
2726
	if (type === 'search') {
2727
		type = 'filter';
2728
	}
2729
	else if (type === 'order') {
2730
		type = 'sort';
2731
	}
2732

2733
	var draw           = settings.iDraw;
2734
	var col            = settings.aoColumns[colIdx];
2735
	var rowData        = settings.aoData[rowIdx]._aData;
2736
	var defaultContent = col.sDefaultContent;
2737
	var cellData       = col.fnGetData( rowData, type, {
2738
		settings: settings,
2739
		row:      rowIdx,
2740
		col:      colIdx
2741
	} );
2742

2743
	if ( cellData === undefined ) {
2744
		if ( settings.iDrawError != draw && defaultContent === null ) {
2745
			_fnLog( settings, 0, "Requested unknown parameter "+
2746
				(typeof col.mData=='function' ? '{function}' : "'"+col.mData+"'")+
2747
				" for row "+rowIdx+", column "+colIdx, 4 );
2748
			settings.iDrawError = draw;
2749
		}
2750
		return defaultContent;
2751
	}
2752

2753
	// When the data source is null and a specific data type is requested (i.e.
2754
	// not the original data), we can use default column data
2755
	if ( (cellData === rowData || cellData === null) && defaultContent !== null && type !== undefined ) {
2756
		cellData = defaultContent;
2757
	}
2758
	else if ( typeof cellData === 'function' ) {
2759
		// If the data source is a function, then we run it and use the return,
2760
		// executing in the scope of the data object (for instances)
2761
		return cellData.call( rowData );
2762
	}
2763

2764
	if ( cellData === null && type === 'display' ) {
2765
		return '';
2766
	}
2767

2768
	if ( type === 'filter' ) {
2769
		var fomatters = DataTable.ext.type.search;
2770

2771
		if ( fomatters[ col.sType ] ) {
2772
			cellData = fomatters[ col.sType ]( cellData );
2773
		}
2774
	}
2775

2776
	return cellData;
2777
}
2778

2779

2780
/**
2781
 * Set the value for a specific cell, into the internal data cache
2782
 *  @param {object} settings dataTables settings object
2783
 *  @param {int} rowIdx aoData row id
2784
 *  @param {int} colIdx Column index
2785
 *  @param {*} val Value to set
2786
 *  @memberof DataTable#oApi
2787
 */
2788
function _fnSetCellData( settings, rowIdx, colIdx, val )
2789
{
2790
	var col     = settings.aoColumns[colIdx];
2791
	var rowData = settings.aoData[rowIdx]._aData;
2792

2793
	col.fnSetData( rowData, val, {
2794
		settings: settings,
2795
		row:      rowIdx,
2796
		col:      colIdx
2797
	}  );
2798
}
2799

2800

2801
// Private variable that is used to match action syntax in the data property object
2802
var __reArray = /\[.*?\]$/;
2803
var __reFn = /\(\)$/;
2804

2805
/**
2806
 * Split string on periods, taking into account escaped periods
2807
 * @param  {string} str String to split
2808
 * @return {array} Split string
2809
 */
2810
function _fnSplitObjNotation( str )
2811
{
2812
	return $.map( str.match(/(\\.|[^\.])+/g) || [''], function ( s ) {
2813
		return s.replace(/\\\./g, '.');
2814
	} );
2815
}
2816

2817

2818
/**
2819
 * Return a function that can be used to get data from a source object, taking
2820
 * into account the ability to use nested objects as a source
2821
 *  @param {string|int|function} mSource The data source for the object
2822
 *  @returns {function} Data get function
2823
 *  @memberof DataTable#oApi
2824
 */
2825
var _fnGetObjectDataFn = DataTable.util.get;
2826

2827

2828
/**
2829
 * Return a function that can be used to set data from a source object, taking
2830
 * into account the ability to use nested objects as a source
2831
 *  @param {string|int|function} mSource The data source for the object
2832
 *  @returns {function} Data set function
2833
 *  @memberof DataTable#oApi
2834
 */
2835
var _fnSetObjectDataFn = DataTable.util.set;
2836

2837

2838
/**
2839
 * Return an array with the full table data
2840
 *  @param {object} oSettings dataTables settings object
2841
 *  @returns array {array} aData Master data array
2842
 *  @memberof DataTable#oApi
2843
 */
2844
function _fnGetDataMaster ( settings )
2845
{
2846
	return _pluck( settings.aoData, '_aData' );
2847
}
2848

2849

2850
/**
2851
 * Nuke the table
2852
 *  @param {object} oSettings dataTables settings object
2853
 *  @memberof DataTable#oApi
2854
 */
2855
function _fnClearTable( settings )
2856
{
2857
	settings.aoData.length = 0;
2858
	settings.aiDisplayMaster.length = 0;
2859
	settings.aiDisplay.length = 0;
2860
	settings.aIds = {};
2861
}
2862

2863

2864
 /**
2865
 * Take an array of integers (index array) and remove a target integer (value - not
2866
 * the key!)
2867
 *  @param {array} a Index array to target
2868
 *  @param {int} iTarget value to find
2869
 *  @memberof DataTable#oApi
2870
 */
2871
function _fnDeleteIndex( a, iTarget, splice )
2872
{
2873
	var iTargetIndex = -1;
2874

2875
	for ( var i=0, iLen=a.length ; i<iLen ; i++ )
2876
	{
2877
		if ( a[i] == iTarget )
2878
		{
2879
			iTargetIndex = i;
2880
		}
2881
		else if ( a[i] > iTarget )
2882
		{
2883
			a[i]--;
2884
		}
2885
	}
2886

2887
	if ( iTargetIndex != -1 && splice === undefined )
2888
	{
2889
		a.splice( iTargetIndex, 1 );
2890
	}
2891
}
2892

2893

2894
/**
2895
 * Mark cached data as invalid such that a re-read of the data will occur when
2896
 * the cached data is next requested. Also update from the data source object.
2897
 *
2898
 * @param {object} settings DataTables settings object
2899
 * @param {int}    rowIdx   Row index to invalidate
2900
 * @param {string} [src]    Source to invalidate from: undefined, 'auto', 'dom'
2901
 *     or 'data'
2902
 * @param {int}    [colIdx] Column index to invalidate. If undefined the whole
2903
 *     row will be invalidated
2904
 * @memberof DataTable#oApi
2905
 *
2906
 * @todo For the modularisation of v1.11 this will need to become a callback, so
2907
 *   the sort and filter methods can subscribe to it. That will required
2908
 *   initialisation options for sorting, which is why it is not already baked in
2909
 */
2910
function _fnInvalidate( settings, rowIdx, src, colIdx )
2911
{
2912
	var row = settings.aoData[ rowIdx ];
2913
	var i, ien;
2914
	var cellWrite = function ( cell, col ) {
2915
		// This is very frustrating, but in IE if you just write directly
2916
		// to innerHTML, and elements that are overwritten are GC'ed,
2917
		// even if there is a reference to them elsewhere
2918
		while ( cell.childNodes.length ) {
2919
			cell.removeChild( cell.firstChild );
2920
		}
2921

2922
		cell.innerHTML = _fnGetCellData( settings, rowIdx, col, 'display' );
2923
	};
2924

2925
	// Are we reading last data from DOM or the data object?
2926
	if ( src === 'dom' || ((! src || src === 'auto') && row.src === 'dom') ) {
2927
		// Read the data from the DOM
2928
		row._aData = _fnGetRowElements(
2929
				settings, row, colIdx, colIdx === undefined ? undefined : row._aData
2930
			)
2931
			.data;
2932
	}
2933
	else {
2934
		// Reading from data object, update the DOM
2935
		var cells = row.anCells;
2936

2937
		if ( cells ) {
2938
			if ( colIdx !== undefined ) {
2939
				cellWrite( cells[colIdx], colIdx );
2940
			}
2941
			else {
2942
				for ( i=0, ien=cells.length ; i<ien ; i++ ) {
2943
					cellWrite( cells[i], i );
2944
				}
2945
			}
2946
		}
2947
	}
2948

2949
	// For both row and cell invalidation, the cached data for sorting and
2950
	// filtering is nulled out
2951
	row._aSortData = null;
2952
	row._aFilterData = null;
2953

2954
	// Invalidate the type for a specific column (if given) or all columns since
2955
	// the data might have changed
2956
	var cols = settings.aoColumns;
2957
	if ( colIdx !== undefined ) {
2958
		cols[ colIdx ].sType = null;
2959
	}
2960
	else {
2961
		for ( i=0, ien=cols.length ; i<ien ; i++ ) {
2962
			cols[i].sType = null;
2963
		}
2964

2965
		// Update DataTables special `DT_*` attributes for the row
2966
		_fnRowAttributes( settings, row );
2967
	}
2968
}
2969

2970

2971
/**
2972
 * Build a data source object from an HTML row, reading the contents of the
2973
 * cells that are in the row.
2974
 *
2975
 * @param {object} settings DataTables settings object
2976
 * @param {node|object} TR element from which to read data or existing row
2977
 *   object from which to re-read the data from the cells
2978
 * @param {int} [colIdx] Optional column index
2979
 * @param {array|object} [d] Data source object. If `colIdx` is given then this
2980
 *   parameter should also be given and will be used to write the data into.
2981
 *   Only the column in question will be written
2982
 * @returns {object} Object with two parameters: `data` the data read, in
2983
 *   document order, and `cells` and array of nodes (they can be useful to the
2984
 *   caller, so rather than needing a second traversal to get them, just return
2985
 *   them from here).
2986
 * @memberof DataTable#oApi
2987
 */
2988
function _fnGetRowElements( settings, row, colIdx, d )
2989
{
2990
	var
2991
		tds = [],
2992
		td = row.firstChild,
2993
		name, col, o, i=0, contents,
2994
		columns = settings.aoColumns,
2995
		objectRead = settings._rowReadObject;
2996

2997
	// Allow the data object to be passed in, or construct
2998
	d = d !== undefined ?
2999
		d :
3000
		objectRead ?
3001
			{} :
3002
			[];
3003

3004
	var attr = function ( str, td  ) {
3005
		if ( typeof str === 'string' ) {
3006
			var idx = str.indexOf('@');
3007

3008
			if ( idx !== -1 ) {
3009
				var attr = str.substring( idx+1 );
3010
				var setter = _fnSetObjectDataFn( str );
3011
				setter( d, td.getAttribute( attr ) );
3012
			}
3013
		}
3014
	};
3015

3016
	// Read data from a cell and store into the data object
3017
	var cellProcess = function ( cell ) {
3018
		if ( colIdx === undefined || colIdx === i ) {
3019
			col = columns[i];
3020
			contents = (cell.innerHTML).trim();
3021

3022
			if ( col && col._bAttrSrc ) {
3023
				var setter = _fnSetObjectDataFn( col.mData._ );
3024
				setter( d, contents );
3025

3026
				attr( col.mData.sort, cell );
3027
				attr( col.mData.type, cell );
3028
				attr( col.mData.filter, cell );
3029
			}
3030
			else {
3031
				// Depending on the `data` option for the columns the data can
3032
				// be read to either an object or an array.
3033
				if ( objectRead ) {
3034
					if ( ! col._setter ) {
3035
						// Cache the setter function
3036
						col._setter = _fnSetObjectDataFn( col.mData );
3037
					}
3038
					col._setter( d, contents );
3039
				}
3040
				else {
3041
					d[i] = contents;
3042
				}
3043
			}
3044
		}
3045

3046
		i++;
3047
	};
3048

3049
	if ( td ) {
3050
		// `tr` element was passed in
3051
		while ( td ) {
3052
			name = td.nodeName.toUpperCase();
3053

3054
			if ( name == "TD" || name == "TH" ) {
3055
				cellProcess( td );
3056
				tds.push( td );
3057
			}
3058

3059
			td = td.nextSibling;
3060
		}
3061
	}
3062
	else {
3063
		// Existing row object passed in
3064
		tds = row.anCells;
3065

3066
		for ( var j=0, jen=tds.length ; j<jen ; j++ ) {
3067
			cellProcess( tds[j] );
3068
		}
3069
	}
3070

3071
	// Read the ID from the DOM if present
3072
	var rowNode = row.firstChild ? row : row.nTr;
3073

3074
	if ( rowNode ) {
3075
		var id = rowNode.getAttribute( 'id' );
3076

3077
		if ( id ) {
3078
			_fnSetObjectDataFn( settings.rowId )( d, id );
3079
		}
3080
	}
3081

3082
	return {
3083
		data: d,
3084
		cells: tds
3085
	};
3086
}
3087
/**
3088
 * Create a new TR element (and it's TD children) for a row
3089
 *  @param {object} oSettings dataTables settings object
3090
 *  @param {int} iRow Row to consider
3091
 *  @param {node} [nTrIn] TR element to add to the table - optional. If not given,
3092
 *    DataTables will create a row automatically
3093
 *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
3094
 *    if nTr is.
3095
 *  @memberof DataTable#oApi
3096
 */
3097
function _fnCreateTr ( oSettings, iRow, nTrIn, anTds )
3098
{
3099
	var
3100
		row = oSettings.aoData[iRow],
3101
		rowData = row._aData,
3102
		cells = [],
3103
		nTr, nTd, oCol,
3104
		i, iLen, create;
3105

3106
	if ( row.nTr === null )
3107
	{
3108
		nTr = nTrIn || document.createElement('tr');
3109

3110
		row.nTr = nTr;
3111
		row.anCells = cells;
3112

3113
		/* Use a private property on the node to allow reserve mapping from the node
3114
		 * to the aoData array for fast look up
3115
		 */
3116
		nTr._DT_RowIndex = iRow;
3117

3118
		/* Special parameters can be given by the data source to be used on the row */
3119
		_fnRowAttributes( oSettings, row );
3120

3121
		/* Process each column */
3122
		for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
3123
		{
3124
			oCol = oSettings.aoColumns[i];
3125
			create = nTrIn ? false : true;
3126

3127
			nTd = create ? document.createElement( oCol.sCellType ) : anTds[i];
3128

3129
			if (! nTd) {
3130
				_fnLog( oSettings, 0, 'Incorrect column count', 18 );
3131
			}
3132

3133
			nTd._DT_CellIndex = {
3134
				row: iRow,
3135
				column: i
3136
			};
3137
			
3138
			cells.push( nTd );
3139

3140
			// Need to create the HTML if new, or if a rendering function is defined
3141
			if ( create || ((oCol.mRender || oCol.mData !== i) &&
3142
				 (!$.isPlainObject(oCol.mData) || oCol.mData._ !== i+'.display')
3143
			)) {
3144
				nTd.innerHTML = _fnGetCellData( oSettings, iRow, i, 'display' );
3145
			}
3146

3147
			/* Add user defined class */
3148
			if ( oCol.sClass )
3149
			{
3150
				nTd.className += ' '+oCol.sClass;
3151
			}
3152

3153
			// Visibility - add or remove as required
3154
			if ( oCol.bVisible && ! nTrIn )
3155
			{
3156
				nTr.appendChild( nTd );
3157
			}
3158
			else if ( ! oCol.bVisible && nTrIn )
3159
			{
3160
				nTd.parentNode.removeChild( nTd );
3161
			}
3162

3163
			if ( oCol.fnCreatedCell )
3164
			{
3165
				oCol.fnCreatedCell.call( oSettings.oInstance,
3166
					nTd, _fnGetCellData( oSettings, iRow, i ), rowData, iRow, i
3167
				);
3168
			}
3169
		}
3170

3171
		_fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow, cells] );
3172
	}
3173
}
3174

3175

3176
/**
3177
 * Add attributes to a row based on the special `DT_*` parameters in a data
3178
 * source object.
3179
 *  @param {object} settings DataTables settings object
3180
 *  @param {object} DataTables row object for the row to be modified
3181
 *  @memberof DataTable#oApi
3182
 */
3183
function _fnRowAttributes( settings, row )
3184
{
3185
	var tr = row.nTr;
3186
	var data = row._aData;
3187

3188
	if ( tr ) {
3189
		var id = settings.rowIdFn( data );
3190

3191
		if ( id ) {
3192
			tr.id = id;
3193
		}
3194

3195
		if ( data.DT_RowClass ) {
3196
			// Remove any classes added by DT_RowClass before
3197
			var a = data.DT_RowClass.split(' ');
3198
			row.__rowc = row.__rowc ?
3199
				_unique( row.__rowc.concat( a ) ) :
3200
				a;
3201

3202
			$(tr)
3203
				.removeClass( row.__rowc.join(' ') )
3204
				.addClass( data.DT_RowClass );
3205
		}
3206

3207
		if ( data.DT_RowAttr ) {
3208
			$(tr).attr( data.DT_RowAttr );
3209
		}
3210

3211
		if ( data.DT_RowData ) {
3212
			$(tr).data( data.DT_RowData );
3213
		}
3214
	}
3215
}
3216

3217

3218
/**
3219
 * Create the HTML header for the table
3220
 *  @param {object} oSettings dataTables settings object
3221
 *  @memberof DataTable#oApi
3222
 */
3223
function _fnBuildHead( oSettings )
3224
{
3225
	var i, ien, cell, row, column;
3226
	var thead = oSettings.nTHead;
3227
	var tfoot = oSettings.nTFoot;
3228
	var createHeader = $('th, td', thead).length === 0;
3229
	var classes = oSettings.oClasses;
3230
	var columns = oSettings.aoColumns;
3231

3232
	if ( createHeader ) {
3233
		row = $('<tr/>').appendTo( thead );
3234
	}
3235

3236
	for ( i=0, ien=columns.length ; i<ien ; i++ ) {
3237
		column = columns[i];
3238
		cell = $( column.nTh ).addClass( column.sClass );
3239

3240
		if ( createHeader ) {
3241
			cell.appendTo( row );
3242
		}
3243

3244
		// 1.11 move into sorting
3245
		if ( oSettings.oFeatures.bSort ) {
3246
			cell.addClass( column.sSortingClass );
3247

3248
			if ( column.bSortable !== false ) {
3249
				cell
3250
					.attr( 'tabindex', oSettings.iTabIndex )
3251
					.attr( 'aria-controls', oSettings.sTableId );
3252

3253
				_fnSortAttachListener( oSettings, column.nTh, i );
3254
			}
3255
		}
3256

3257
		if ( column.sTitle != cell[0].innerHTML ) {
3258
			cell.html( column.sTitle );
3259
		}
3260

3261
		_fnRenderer( oSettings, 'header' )(
3262
			oSettings, cell, column, classes
3263
		);
3264
	}
3265

3266
	if ( createHeader ) {
3267
		_fnDetectHeader( oSettings.aoHeader, thead );
3268
	}
3269

3270
	/* Deal with the footer - add classes if required */
3271
	$(thead).children('tr').children('th, td').addClass( classes.sHeaderTH );
3272
	$(tfoot).children('tr').children('th, td').addClass( classes.sFooterTH );
3273

3274
	// Cache the footer cells. Note that we only take the cells from the first
3275
	// row in the footer. If there is more than one row the user wants to
3276
	// interact with, they need to use the table().foot() method. Note also this
3277
	// allows cells to be used for multiple columns using colspan
3278
	if ( tfoot !== null ) {
3279
		var cells = oSettings.aoFooter[0];
3280

3281
		for ( i=0, ien=cells.length ; i<ien ; i++ ) {
3282
			column = columns[i];
3283

3284
			if (column) {
3285
				column.nTf = cells[i].cell;
3286
	
3287
				if ( column.sClass ) {
3288
					$(column.nTf).addClass( column.sClass );
3289
				}
3290
			}
3291
			else {
3292
				_fnLog( oSettings, 0, 'Incorrect column count', 18 );
3293
			}
3294
		}
3295
	}
3296
}
3297

3298

3299
/**
3300
 * Draw the header (or footer) element based on the column visibility states. The
3301
 * methodology here is to use the layout array from _fnDetectHeader, modified for
3302
 * the instantaneous column visibility, to construct the new layout. The grid is
3303
 * traversed over cell at a time in a rows x columns grid fashion, although each
3304
 * cell insert can cover multiple elements in the grid - which is tracks using the
3305
 * aApplied array. Cell inserts in the grid will only occur where there isn't
3306
 * already a cell in that position.
3307
 *  @param {object} oSettings dataTables settings object
3308
 *  @param array {objects} aoSource Layout array from _fnDetectHeader
3309
 *  @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,
3310
 *  @memberof DataTable#oApi
3311
 */
3312
function _fnDrawHead( oSettings, aoSource, bIncludeHidden )
3313
{
3314
	var i, iLen, j, jLen, k, kLen, n, nLocalTr;
3315
	var aoLocal = [];
3316
	var aApplied = [];
3317
	var iColumns = oSettings.aoColumns.length;
3318
	var iRowspan, iColspan;
3319

3320
	if ( ! aoSource )
3321
	{
3322
		return;
3323
	}
3324

3325
	if (  bIncludeHidden === undefined )
3326
	{
3327
		bIncludeHidden = false;
3328
	}
3329

3330
	/* Make a copy of the master layout array, but without the visible columns in it */
3331
	for ( i=0, iLen=aoSource.length ; i<iLen ; i++ )
3332
	{
3333
		aoLocal[i] = aoSource[i].slice();
3334
		aoLocal[i].nTr = aoSource[i].nTr;
3335

3336
		/* Remove any columns which are currently hidden */
3337
		for ( j=iColumns-1 ; j>=0 ; j-- )
3338
		{
3339
			if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden )
3340
			{
3341
				aoLocal[i].splice( j, 1 );
3342
			}
3343
		}
3344

3345
		/* Prep the applied array - it needs an element for each row */
3346
		aApplied.push( [] );
3347
	}
3348

3349
	for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ )
3350
	{
3351
		nLocalTr = aoLocal[i].nTr;
3352

3353
		/* All cells are going to be replaced, so empty out the row */
3354
		if ( nLocalTr )
3355
		{
3356
			while( (n = nLocalTr.firstChild) )
3357
			{
3358
				nLocalTr.removeChild( n );
3359
			}
3360
		}
3361

3362
		for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ )
3363
		{
3364
			iRowspan = 1;
3365
			iColspan = 1;
3366

3367
			/* Check to see if there is already a cell (row/colspan) covering our target
3368
			 * insert point. If there is, then there is nothing to do.
3369
			 */
3370
			if ( aApplied[i][j] === undefined )
3371
			{
3372
				nLocalTr.appendChild( aoLocal[i][j].cell );
3373
				aApplied[i][j] = 1;
3374

3375
				/* Expand the cell to cover as many rows as needed */
3376
				while ( aoLocal[i+iRowspan] !== undefined &&
3377
				        aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell )
3378
				{
3379
					aApplied[i+iRowspan][j] = 1;
3380
					iRowspan++;
3381
				}
3382

3383
				/* Expand the cell to cover as many columns as needed */
3384
				while ( aoLocal[i][j+iColspan] !== undefined &&
3385
				        aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell )
3386
				{
3387
					/* Must update the applied array over the rows for the columns */
3388
					for ( k=0 ; k<iRowspan ; k++ )
3389
					{
3390
						aApplied[i+k][j+iColspan] = 1;
3391
					}
3392
					iColspan++;
3393
				}
3394

3395
				/* Do the actual expansion in the DOM */
3396
				$(aoLocal[i][j].cell)
3397
					.attr('rowspan', iRowspan)
3398
					.attr('colspan', iColspan);
3399
			}
3400
		}
3401
	}
3402
}
3403

3404

3405
/**
3406
 * Insert the required TR nodes into the table for display
3407
 *  @param {object} oSettings dataTables settings object
3408
 *  @param ajaxComplete true after ajax call to complete rendering
3409
 *  @memberof DataTable#oApi
3410
 */
3411
function _fnDraw( oSettings, ajaxComplete )
3412
{
3413
	// Allow for state saving and a custom start position
3414
	_fnStart( oSettings );
3415

3416
	/* Provide a pre-callback function which can be used to cancel the draw is false is returned */
3417
	var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] );
3418
	if ( $.inArray( false, aPreDraw ) !== -1 )
3419
	{
3420
		_fnProcessingDisplay( oSettings, false );
3421
		return;
3422
	}
3423

3424
	var anRows = [];
3425
	var iRowCount = 0;
3426
	var asStripeClasses = oSettings.asStripeClasses;
3427
	var iStripes = asStripeClasses.length;
3428
	var oLang = oSettings.oLanguage;
3429
	var bServerSide = _fnDataSource( oSettings ) == 'ssp';
3430
	var aiDisplay = oSettings.aiDisplay;
3431
	var iDisplayStart = oSettings._iDisplayStart;
3432
	var iDisplayEnd = oSettings.fnDisplayEnd();
3433

3434
	oSettings.bDrawing = true;
3435

3436
	/* Server-side processing draw intercept */
3437
	if ( oSettings.bDeferLoading )
3438
	{
3439
		oSettings.bDeferLoading = false;
3440
		oSettings.iDraw++;
3441
		_fnProcessingDisplay( oSettings, false );
3442
	}
3443
	else if ( !bServerSide )
3444
	{
3445
		oSettings.iDraw++;
3446
	}
3447
	else if ( !oSettings.bDestroying && !ajaxComplete)
3448
	{
3449
		_fnAjaxUpdate( oSettings );
3450
		return;
3451
	}
3452

3453
	if ( aiDisplay.length !== 0 )
3454
	{
3455
		var iStart = bServerSide ? 0 : iDisplayStart;
3456
		var iEnd = bServerSide ? oSettings.aoData.length : iDisplayEnd;
3457

3458
		for ( var j=iStart ; j<iEnd ; j++ )
3459
		{
3460
			var iDataIndex = aiDisplay[j];
3461
			var aoData = oSettings.aoData[ iDataIndex ];
3462
			if ( aoData.nTr === null )
3463
			{
3464
				_fnCreateTr( oSettings, iDataIndex );
3465
			}
3466

3467
			var nRow = aoData.nTr;
3468

3469
			/* Remove the old striping classes and then add the new one */
3470
			if ( iStripes !== 0 )
3471
			{
3472
				var sStripe = asStripeClasses[ iRowCount % iStripes ];
3473
				if ( aoData._sRowStripe != sStripe )
3474
				{
3475
					$(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe );
3476
					aoData._sRowStripe = sStripe;
3477
				}
3478
			}
3479

3480
			// Row callback functions - might want to manipulate the row
3481
			// iRowCount and j are not currently documented. Are they at all
3482
			// useful?
3483
			_fnCallbackFire( oSettings, 'aoRowCallback', null,
3484
				[nRow, aoData._aData, iRowCount, j, iDataIndex] );
3485

3486
			anRows.push( nRow );
3487
			iRowCount++;
3488
		}
3489
	}
3490
	else
3491
	{
3492
		/* Table is empty - create a row with an empty message in it */
3493
		var sZero = oLang.sZeroRecords;
3494
		if ( oSettings.iDraw == 1 &&  _fnDataSource( oSettings ) == 'ajax' )
3495
		{
3496
			sZero = oLang.sLoadingRecords;
3497
		}
3498
		else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 )
3499
		{
3500
			sZero = oLang.sEmptyTable;
3501
		}
3502

3503
		anRows[ 0 ] = $( '<tr/>', { 'class': iStripes ? asStripeClasses[0] : '' } )
3504
			.append( $('<td />', {
3505
				'valign':  'top',
3506
				'colSpan': _fnVisbleColumns( oSettings ),
3507
				'class':   oSettings.oClasses.sRowEmpty
3508
			} ).html( sZero ) )[0];
3509
	}
3510

3511
	/* Header and footer callbacks */
3512
	_fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0],
3513
		_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
3514

3515
	_fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0],
3516
		_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
3517

3518
	var body = $(oSettings.nTBody);
3519

3520
	body.children().detach();
3521
	body.append( $(anRows) );
3522

3523
	/* Call all required callback functions for the end of a draw */
3524
	_fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] );
3525

3526
	/* Draw is complete, sorting and filtering must be as well */
3527
	oSettings.bSorted = false;
3528
	oSettings.bFiltered = false;
3529
	oSettings.bDrawing = false;
3530
}
3531

3532

3533
/**
3534
 * Redraw the table - taking account of the various features which are enabled
3535
 *  @param {object} oSettings dataTables settings object
3536
 *  @param {boolean} [holdPosition] Keep the current paging position. By default
3537
 *    the paging is reset to the first page
3538
 *  @memberof DataTable#oApi
3539
 */
3540
function _fnReDraw( settings, holdPosition )
3541
{
3542
	var
3543
		features = settings.oFeatures,
3544
		sort     = features.bSort,
3545
		filter   = features.bFilter;
3546

3547
	if ( sort ) {
3548
		_fnSort( settings );
3549
	}
3550

3551
	if ( filter ) {
3552
		_fnFilterComplete( settings, settings.oPreviousSearch );
3553
	}
3554
	else {
3555
		// No filtering, so we want to just use the display master
3556
		settings.aiDisplay = settings.aiDisplayMaster.slice();
3557
	}
3558

3559
	if ( holdPosition !== true ) {
3560
		settings._iDisplayStart = 0;
3561
	}
3562

3563
	// Let any modules know about the draw hold position state (used by
3564
	// scrolling internally)
3565
	settings._drawHold = holdPosition;
3566

3567
	_fnDraw( settings );
3568

3569
	settings._drawHold = false;
3570
}
3571

3572

3573
/**
3574
 * Add the options to the page HTML for the table
3575
 *  @param {object} oSettings dataTables settings object
3576
 *  @memberof DataTable#oApi
3577
 */
3578
function _fnAddOptionsHtml ( oSettings )
3579
{
3580
	var classes = oSettings.oClasses;
3581
	var table = $(oSettings.nTable);
3582
	var holding = $('<div/>').insertBefore( table ); // Holding element for speed
3583
	var features = oSettings.oFeatures;
3584

3585
	// All DataTables are wrapped in a div
3586
	var insert = $('<div/>', {
3587
		id:      oSettings.sTableId+'_wrapper',
3588
		'class': classes.sWrapper + (oSettings.nTFoot ? '' : ' '+classes.sNoFooter)
3589
	} );
3590

3591
	oSettings.nHolding = holding[0];
3592
	oSettings.nTableWrapper = insert[0];
3593
	oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;
3594

3595
	/* Loop over the user set positioning and place the elements as needed */
3596
	var aDom = oSettings.sDom.split('');
3597
	var featureNode, cOption, nNewNode, cNext, sAttr, j;
3598
	for ( var i=0 ; i<aDom.length ; i++ )
3599
	{
3600
		featureNode = null;
3601
		cOption = aDom[i];
3602

3603
		if ( cOption == '<' )
3604
		{
3605
			/* New container div */
3606
			nNewNode = $('<div/>')[0];
3607

3608
			/* Check to see if we should append an id and/or a class name to the container */
3609
			cNext = aDom[i+1];
3610
			if ( cNext == "'" || cNext == '"' )
3611
			{
3612
				sAttr = "";
3613
				j = 2;
3614
				while ( aDom[i+j] != cNext )
3615
				{
3616
					sAttr += aDom[i+j];
3617
					j++;
3618
				}
3619

3620
				/* Replace jQuery UI constants @todo depreciated */
3621
				if ( sAttr == "H" )
3622
				{
3623
					sAttr = classes.sJUIHeader;
3624
				}
3625
				else if ( sAttr == "F" )
3626
				{
3627
					sAttr = classes.sJUIFooter;
3628
				}
3629

3630
				/* The attribute can be in the format of "#id.class", "#id" or "class" This logic
3631
				 * breaks the string into parts and applies them as needed
3632
				 */
3633
				if ( sAttr.indexOf('.') != -1 )
3634
				{
3635
					var aSplit = sAttr.split('.');
3636
					nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);
3637
					nNewNode.className = aSplit[1];
3638
				}
3639
				else if ( sAttr.charAt(0) == "#" )
3640
				{
3641
					nNewNode.id = sAttr.substr(1, sAttr.length-1);
3642
				}
3643
				else
3644
				{
3645
					nNewNode.className = sAttr;
3646
				}
3647

3648
				i += j; /* Move along the position array */
3649
			}
3650

3651
			insert.append( nNewNode );
3652
			insert = $(nNewNode);
3653
		}
3654
		else if ( cOption == '>' )
3655
		{
3656
			/* End container div */
3657
			insert = insert.parent();
3658
		}
3659
		// @todo Move options into their own plugins?
3660
		else if ( cOption == 'l' && features.bPaginate && features.bLengthChange )
3661
		{
3662
			/* Length */
3663
			featureNode = _fnFeatureHtmlLength( oSettings );
3664
		}
3665
		else if ( cOption == 'f' && features.bFilter )
3666
		{
3667
			/* Filter */
3668
			featureNode = _fnFeatureHtmlFilter( oSettings );
3669
		}
3670
		else if ( cOption == 'r' && features.bProcessing )
3671
		{
3672
			/* pRocessing */
3673
			featureNode = _fnFeatureHtmlProcessing( oSettings );
3674
		}
3675
		else if ( cOption == 't' )
3676
		{
3677
			/* Table */
3678
			featureNode = _fnFeatureHtmlTable( oSettings );
3679
		}
3680
		else if ( cOption ==  'i' && features.bInfo )
3681
		{
3682
			/* Info */
3683
			featureNode = _fnFeatureHtmlInfo( oSettings );
3684
		}
3685
		else if ( cOption == 'p' && features.bPaginate )
3686
		{
3687
			/* Pagination */
3688
			featureNode = _fnFeatureHtmlPaginate( oSettings );
3689
		}
3690
		else if ( DataTable.ext.feature.length !== 0 )
3691
		{
3692
			/* Plug-in features */
3693
			var aoFeatures = DataTable.ext.feature;
3694
			for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )
3695
			{
3696
				if ( cOption == aoFeatures[k].cFeature )
3697
				{
3698
					featureNode = aoFeatures[k].fnInit( oSettings );
3699
					break;
3700
				}
3701
			}
3702
		}
3703

3704
		/* Add to the 2D features array */
3705
		if ( featureNode )
3706
		{
3707
			var aanFeatures = oSettings.aanFeatures;
3708

3709
			if ( ! aanFeatures[cOption] )
3710
			{
3711
				aanFeatures[cOption] = [];
3712
			}
3713

3714
			aanFeatures[cOption].push( featureNode );
3715
			insert.append( featureNode );
3716
		}
3717
	}
3718

3719
	/* Built our DOM structure - replace the holding div with what we want */
3720
	holding.replaceWith( insert );
3721
	oSettings.nHolding = null;
3722
}
3723

3724

3725
/**
3726
 * Use the DOM source to create up an array of header cells. The idea here is to
3727
 * create a layout grid (array) of rows x columns, which contains a reference
3728
 * to the cell that that point in the grid (regardless of col/rowspan), such that
3729
 * any column / row could be removed and the new grid constructed
3730
 *  @param array {object} aLayout Array to store the calculated layout in
3731
 *  @param {node} nThead The header/footer element for the table
3732
 *  @memberof DataTable#oApi
3733
 */
3734
function _fnDetectHeader ( aLayout, nThead )
3735
{
3736
	var nTrs = $(nThead).children('tr');
3737
	var nTr, nCell;
3738
	var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan;
3739
	var bUnique;
3740
	var fnShiftCol = function ( a, i, j ) {
3741
		var k = a[i];
3742
                while ( k[j] ) {
3743
			j++;
3744
		}
3745
		return j;
3746
	};
3747

3748
	aLayout.splice( 0, aLayout.length );
3749

3750
	/* We know how many rows there are in the layout - so prep it */
3751
	for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
3752
	{
3753
		aLayout.push( [] );
3754
	}
3755

3756
	/* Calculate a layout array */
3757
	for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
3758
	{
3759
		nTr = nTrs[i];
3760
		iColumn = 0;
3761

3762
		/* For every cell in the row... */
3763
		nCell = nTr.firstChild;
3764
		while ( nCell ) {
3765
			if ( nCell.nodeName.toUpperCase() == "TD" ||
3766
			     nCell.nodeName.toUpperCase() == "TH" )
3767
			{
3768
				/* Get the col and rowspan attributes from the DOM and sanitise them */
3769
				iColspan = nCell.getAttribute('colspan') * 1;
3770
				iRowspan = nCell.getAttribute('rowspan') * 1;
3771
				iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan;
3772
				iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan;
3773

3774
				/* There might be colspan cells already in this row, so shift our target
3775
				 * accordingly
3776
				 */
3777
				iColShifted = fnShiftCol( aLayout, i, iColumn );
3778

3779
				/* Cache calculation for unique columns */
3780
				bUnique = iColspan === 1 ? true : false;
3781

3782
				/* If there is col / rowspan, copy the information into the layout grid */
3783
				for ( l=0 ; l<iColspan ; l++ )
3784
				{
3785
					for ( k=0 ; k<iRowspan ; k++ )
3786
					{
3787
						aLayout[i+k][iColShifted+l] = {
3788
							"cell": nCell,
3789
							"unique": bUnique
3790
						};
3791
						aLayout[i+k].nTr = nTr;
3792
					}
3793
				}
3794
			}
3795
			nCell = nCell.nextSibling;
3796
		}
3797
	}
3798
}
3799

3800

3801
/**
3802
 * Get an array of unique th elements, one for each column
3803
 *  @param {object} oSettings dataTables settings object
3804
 *  @param {node} nHeader automatically detect the layout from this node - optional
3805
 *  @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional
3806
 *  @returns array {node} aReturn list of unique th's
3807
 *  @memberof DataTable#oApi
3808
 */
3809
function _fnGetUniqueThs ( oSettings, nHeader, aLayout )
3810
{
3811
	var aReturn = [];
3812
	if ( !aLayout )
3813
	{
3814
		aLayout = oSettings.aoHeader;
3815
		if ( nHeader )
3816
		{
3817
			aLayout = [];
3818
			_fnDetectHeader( aLayout, nHeader );
3819
		}
3820
	}
3821

3822
	for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ )
3823
	{
3824
		for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ )
3825
		{
3826
			if ( aLayout[i][j].unique &&
3827
				 (!aReturn[j] || !oSettings.bSortCellsTop) )
3828
			{
3829
				aReturn[j] = aLayout[i][j].cell;
3830
			}
3831
		}
3832
	}
3833

3834
	return aReturn;
3835
}
3836

3837
/**
3838
 * Set the start position for draw
3839
 *  @param {object} oSettings dataTables settings object
3840
 */
3841
function _fnStart( oSettings )
3842
{
3843
	var bServerSide = _fnDataSource( oSettings ) == 'ssp';
3844
	var iInitDisplayStart = oSettings.iInitDisplayStart;
3845

3846
	// Check and see if we have an initial draw position from state saving
3847
	if ( iInitDisplayStart !== undefined && iInitDisplayStart !== -1 )
3848
	{
3849
		oSettings._iDisplayStart = bServerSide ?
3850
			iInitDisplayStart :
3851
			iInitDisplayStart >= oSettings.fnRecordsDisplay() ?
3852
				0 :
3853
				iInitDisplayStart;
3854

3855
		oSettings.iInitDisplayStart = -1;
3856
	}
3857
}
3858

3859
/**
3860
 * Create an Ajax call based on the table's settings, taking into account that
3861
 * parameters can have multiple forms, and backwards compatibility.
3862
 *
3863
 * @param {object} oSettings dataTables settings object
3864
 * @param {array} data Data to send to the server, required by
3865
 *     DataTables - may be augmented by developer callbacks
3866
 * @param {function} fn Callback function to run when data is obtained
3867
 */
3868
function _fnBuildAjax( oSettings, data, fn )
3869
{
3870
	// Compatibility with 1.9-, allow fnServerData and event to manipulate
3871
	_fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [data] );
3872

3873
	// Convert to object based for 1.10+ if using the old array scheme which can
3874
	// come from server-side processing or serverParams
3875
	if ( data && Array.isArray(data) ) {
3876
		var tmp = {};
3877
		var rbracket = /(.*?)\[\]$/;
3878

3879
		$.each( data, function (key, val) {
3880
			var match = val.name.match(rbracket);
3881

3882
			if ( match ) {
3883
				// Support for arrays
3884
				var name = match[0];
3885

3886
				if ( ! tmp[ name ] ) {
3887
					tmp[ name ] = [];
3888
				}
3889
				tmp[ name ].push( val.value );
3890
			}
3891
			else {
3892
				tmp[val.name] = val.value;
3893
			}
3894
		} );
3895
		data = tmp;
3896
	}
3897

3898
	var ajaxData;
3899
	var ajax = oSettings.ajax;
3900
	var instance = oSettings.oInstance;
3901
	var callback = function ( json ) {
3902
		var status = oSettings.jqXHR
3903
			? oSettings.jqXHR.status
3904
			: null;
3905

3906
		if ( json === null || (typeof status === 'number' && status == 204 ) ) {
3907
			json = {};
3908
			_fnAjaxDataSrc( oSettings, json, [] );
3909
		}
3910

3911
		var error = json.error || json.sError;
3912
		if ( error ) {
3913
			_fnLog( oSettings, 0, error );
3914
		}
3915

3916
		oSettings.json = json;
3917

3918
		_fnCallbackFire( oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR] );
3919
		fn( json );
3920
	};
3921

3922
	if ( $.isPlainObject( ajax ) && ajax.data )
3923
	{
3924
		ajaxData = ajax.data;
3925

3926
		var newData = typeof ajaxData === 'function' ?
3927
			ajaxData( data, oSettings ) :  // fn can manipulate data or return
3928
			ajaxData;                      // an object object or array to merge
3929

3930
		// If the function returned something, use that alone
3931
		data = typeof ajaxData === 'function' && newData ?
3932
			newData :
3933
			$.extend( true, data, newData );
3934

3935
		// Remove the data property as we've resolved it already and don't want
3936
		// jQuery to do it again (it is restored at the end of the function)
3937
		delete ajax.data;
3938
	}
3939

3940
	var baseAjax = {
3941
		"data": data,
3942
		"success": callback,
3943
		"dataType": "json",
3944
		"cache": false,
3945
		"type": oSettings.sServerMethod,
3946
		"error": function (xhr, error, thrown) {
3947
			var ret = _fnCallbackFire( oSettings, null, 'xhr', [oSettings, null, oSettings.jqXHR] );
3948

3949
			if ( $.inArray( true, ret ) === -1 ) {
3950
				if ( error == "parsererror" ) {
3951
					_fnLog( oSettings, 0, 'Invalid JSON response', 1 );
3952
				}
3953
				else if ( xhr.readyState === 4 ) {
3954
					_fnLog( oSettings, 0, 'Ajax error', 7 );
3955
				}
3956
			}
3957

3958
			_fnProcessingDisplay( oSettings, false );
3959
		}
3960
	};
3961

3962
	// Store the data submitted for the API
3963
	oSettings.oAjaxData = data;
3964

3965
	// Allow plug-ins and external processes to modify the data
3966
	_fnCallbackFire( oSettings, null, 'preXhr', [oSettings, data] );
3967

3968
	if ( oSettings.fnServerData )
3969
	{
3970
		// DataTables 1.9- compatibility
3971
		oSettings.fnServerData.call( instance,
3972
			oSettings.sAjaxSource,
3973
			$.map( data, function (val, key) { // Need to convert back to 1.9 trad format
3974
				return { name: key, value: val };
3975
			} ),
3976
			callback,
3977
			oSettings
3978
		);
3979
	}
3980
	else if ( oSettings.sAjaxSource || typeof ajax === 'string' )
3981
	{
3982
		// DataTables 1.9- compatibility
3983
		oSettings.jqXHR = $.ajax( $.extend( baseAjax, {
3984
			url: ajax || oSettings.sAjaxSource
3985
		} ) );
3986
	}
3987
	else if ( typeof ajax === 'function' )
3988
	{
3989
		// Is a function - let the caller define what needs to be done
3990
		oSettings.jqXHR = ajax.call( instance, data, callback, oSettings );
3991
	}
3992
	else
3993
	{
3994
		// Object to extend the base settings
3995
		oSettings.jqXHR = $.ajax( $.extend( baseAjax, ajax ) );
3996

3997
		// Restore for next time around
3998
		ajax.data = ajaxData;
3999
	}
4000
}
4001

4002

4003
/**
4004
 * Update the table using an Ajax call
4005
 *  @param {object} settings dataTables settings object
4006
 *  @returns {boolean} Block the table drawing or not
4007
 *  @memberof DataTable#oApi
4008
 */
4009
function _fnAjaxUpdate( settings )
4010
{
4011
	settings.iDraw++;
4012
	_fnProcessingDisplay( settings, true );
4013

4014
	// Keep track of drawHold state to handle scrolling after the Ajax call
4015
	var drawHold = settings._drawHold;
4016

4017
	_fnBuildAjax(
4018
		settings,
4019
		_fnAjaxParameters( settings ),
4020
		function(json) {
4021
			settings._drawHold = drawHold;
4022
			_fnAjaxUpdateDraw( settings, json );
4023
			settings._drawHold = false;
4024
		}
4025
	);
4026
}
4027

4028

4029
/**
4030
 * Build up the parameters in an object needed for a server-side processing
4031
 * request. Note that this is basically done twice, is different ways - a modern
4032
 * method which is used by default in DataTables 1.10 which uses objects and
4033
 * arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if
4034
 * the sAjaxSource option is used in the initialisation, or the legacyAjax
4035
 * option is set.
4036
 *  @param {object} oSettings dataTables settings object
4037
 *  @returns {bool} block the table drawing or not
4038
 *  @memberof DataTable#oApi
4039
 */
4040
function _fnAjaxParameters( settings )
4041
{
4042
	var
4043
		columns = settings.aoColumns,
4044
		columnCount = columns.length,
4045
		features = settings.oFeatures,
4046
		preSearch = settings.oPreviousSearch,
4047
		preColSearch = settings.aoPreSearchCols,
4048
		i, data = [], dataProp, column, columnSearch,
4049
		sort = _fnSortFlatten( settings ),
4050
		displayStart = settings._iDisplayStart,
4051
		displayLength = features.bPaginate !== false ?
4052
			settings._iDisplayLength :
4053
			-1;
4054

4055
	var param = function ( name, value ) {
4056
		data.push( { 'name': name, 'value': value } );
4057
	};
4058

4059
	// DataTables 1.9- compatible method
4060
	param( 'sEcho',          settings.iDraw );
4061
	param( 'iColumns',       columnCount );
4062
	param( 'sColumns',       _pluck( columns, 'sName' ).join(',') );
4063
	param( 'iDisplayStart',  displayStart );
4064
	param( 'iDisplayLength', displayLength );
4065

4066
	// DataTables 1.10+ method
4067
	var d = {
4068
		draw:    settings.iDraw,
4069
		columns: [],
4070
		order:   [],
4071
		start:   displayStart,
4072
		length:  displayLength,
4073
		search:  {
4074
			value: preSearch.sSearch,
4075
			regex: preSearch.bRegex
4076
		}
4077
	};
4078

4079
	for ( i=0 ; i<columnCount ; i++ ) {
4080
		column = columns[i];
4081
		columnSearch = preColSearch[i];
4082
		dataProp = typeof column.mData=="function" ? 'function' : column.mData ;
4083

4084
		d.columns.push( {
4085
			data:       dataProp,
4086
			name:       column.sName,
4087
			searchable: column.bSearchable,
4088
			orderable:  column.bSortable,
4089
			search:     {
4090
				value: columnSearch.sSearch,
4091
				regex: columnSearch.bRegex
4092
			}
4093
		} );
4094

4095
		param( "mDataProp_"+i, dataProp );
4096

4097
		if ( features.bFilter ) {
4098
			param( 'sSearch_'+i,     columnSearch.sSearch );
4099
			param( 'bRegex_'+i,      columnSearch.bRegex );
4100
			param( 'bSearchable_'+i, column.bSearchable );
4101
		}
4102

4103
		if ( features.bSort ) {
4104
			param( 'bSortable_'+i, column.bSortable );
4105
		}
4106
	}
4107

4108
	if ( features.bFilter ) {
4109
		param( 'sSearch', preSearch.sSearch );
4110
		param( 'bRegex', preSearch.bRegex );
4111
	}
4112

4113
	if ( features.bSort ) {
4114
		$.each( sort, function ( i, val ) {
4115
			d.order.push( { column: val.col, dir: val.dir } );
4116

4117
			param( 'iSortCol_'+i, val.col );
4118
			param( 'sSortDir_'+i, val.dir );
4119
		} );
4120

4121
		param( 'iSortingCols', sort.length );
4122
	}
4123

4124
	// If the legacy.ajax parameter is null, then we automatically decide which
4125
	// form to use, based on sAjaxSource
4126
	var legacy = DataTable.ext.legacy.ajax;
4127
	if ( legacy === null ) {
4128
		return settings.sAjaxSource ? data : d;
4129
	}
4130

4131
	// Otherwise, if legacy has been specified then we use that to decide on the
4132
	// form
4133
	return legacy ? data : d;
4134
}
4135

4136

4137
/**
4138
 * Data the data from the server (nuking the old) and redraw the table
4139
 *  @param {object} oSettings dataTables settings object
4140
 *  @param {object} json json data return from the server.
4141
 *  @param {string} json.sEcho Tracking flag for DataTables to match requests
4142
 *  @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering
4143
 *  @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering
4144
 *  @param {array} json.aaData The data to display on this page
4145
 *  @param {string} [json.sColumns] Column ordering (sName, comma separated)
4146
 *  @memberof DataTable#oApi
4147
 */
4148
function _fnAjaxUpdateDraw ( settings, json )
4149
{
4150
	// v1.10 uses camelCase variables, while 1.9 uses Hungarian notation.
4151
	// Support both
4152
	var compat = function ( old, modern ) {
4153
		return json[old] !== undefined ? json[old] : json[modern];
4154
	};
4155

4156
	var data = _fnAjaxDataSrc( settings, json );
4157
	var draw            = compat( 'sEcho',                'draw' );
4158
	var recordsTotal    = compat( 'iTotalRecords',        'recordsTotal' );
4159
	var recordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' );
4160

4161
	if ( draw !== undefined ) {
4162
		// Protect against out of sequence returns
4163
		if ( draw*1 < settings.iDraw ) {
4164
			return;
4165
		}
4166
		settings.iDraw = draw * 1;
4167
	}
4168

4169
	// No data in returned object, so rather than an array, we show an empty table
4170
	if ( ! data ) {
4171
		data = [];
4172
	}
4173

4174
	_fnClearTable( settings );
4175
	settings._iRecordsTotal   = parseInt(recordsTotal, 10);
4176
	settings._iRecordsDisplay = parseInt(recordsFiltered, 10);
4177

4178
	for ( var i=0, ien=data.length ; i<ien ; i++ ) {
4179
		_fnAddData( settings, data[i] );
4180
	}
4181
	settings.aiDisplay = settings.aiDisplayMaster.slice();
4182

4183
	_fnDraw( settings, true );
4184

4185
	if ( ! settings._bInitComplete ) {
4186
		_fnInitComplete( settings, json );
4187
	}
4188

4189
	_fnProcessingDisplay( settings, false );
4190
}
4191

4192

4193
/**
4194
 * Get the data from the JSON data source to use for drawing a table. Using
4195
 * `_fnGetObjectDataFn` allows the data to be sourced from a property of the
4196
 * source object, or from a processing function.
4197
 *  @param {object} oSettings dataTables settings object
4198
 *  @param  {object} json Data source object / array from the server
4199
 *  @return {array} Array of data to use
4200
 */
4201
 function _fnAjaxDataSrc ( oSettings, json, write )
4202
 {
4203
	var dataSrc = $.isPlainObject( oSettings.ajax ) && oSettings.ajax.dataSrc !== undefined ?
4204
		oSettings.ajax.dataSrc :
4205
		oSettings.sAjaxDataProp; // Compatibility with 1.9-.
4206

4207
	if ( ! write ) {
4208
		if ( dataSrc === 'data' ) {
4209
			// If the default, then we still want to support the old style, and safely ignore
4210
			// it if possible
4211
			return json.aaData || json[dataSrc];
4212
		}
4213

4214
		return dataSrc !== "" ?
4215
			_fnGetObjectDataFn( dataSrc )( json ) :
4216
			json;
4217
	}
4218

4219
	// set
4220
	_fnSetObjectDataFn( dataSrc )( json, write );
4221
}
4222

4223
/**
4224
 * Generate the node required for filtering text
4225
 *  @returns {node} Filter control element
4226
 *  @param {object} oSettings dataTables settings object
4227
 *  @memberof DataTable#oApi
4228
 */
4229
function _fnFeatureHtmlFilter ( settings )
4230
{
4231
	var classes = settings.oClasses;
4232
	var tableId = settings.sTableId;
4233
	var language = settings.oLanguage;
4234
	var previousSearch = settings.oPreviousSearch;
4235
	var features = settings.aanFeatures;
4236
	var input = '<input type="search" class="'+classes.sFilterInput+'"/>';
4237

4238
	var str = language.sSearch;
4239
	str = str.match(/_INPUT_/) ?
4240
		str.replace('_INPUT_', input) :
4241
		str+input;
4242

4243
	var filter = $('<div/>', {
4244
			'id': ! features.f ? tableId+'_filter' : null,
4245
			'class': classes.sFilter
4246
		} )
4247
		.append( $('<label/>' ).append( str ) );
4248

4249
	var searchFn = function(event) {
4250
		/* Update all other filter input elements for the new display */
4251
		var n = features.f;
4252
		var val = !this.value ? "" : this.value; // mental IE8 fix :-(
4253
		if(previousSearch.return && event.key !== "Enter") {
4254
			return;
4255
		}
4256
		/* Now do the filter */
4257
		if ( val != previousSearch.sSearch ) {
4258
			_fnFilterComplete( settings, {
4259
				"sSearch": val,
4260
				"bRegex": previousSearch.bRegex,
4261
				"bSmart": previousSearch.bSmart ,
4262
				"bCaseInsensitive": previousSearch.bCaseInsensitive,
4263
				"return": previousSearch.return
4264
			} );
4265

4266
			// Need to redraw, without resorting
4267
			settings._iDisplayStart = 0;
4268
			_fnDraw( settings );
4269
		}
4270
	};
4271

4272
	var searchDelay = settings.searchDelay !== null ?
4273
		settings.searchDelay :
4274
		_fnDataSource( settings ) === 'ssp' ?
4275
			400 :
4276
			0;
4277

4278
	var jqFilter = $('input', filter)
4279
		.val( previousSearch.sSearch )
4280
		.attr( 'placeholder', language.sSearchPlaceholder )
4281
		.on(
4282
			'keyup.DT search.DT input.DT paste.DT cut.DT',
4283
			searchDelay ?
4284
				_fnThrottle( searchFn, searchDelay ) :
4285
				searchFn
4286
		)
4287
		.on( 'mouseup.DT', function(e) {
4288
			// Edge fix! Edge 17 does not trigger anything other than mouse events when clicking
4289
			// on the clear icon (Edge bug 17584515). This is safe in other browsers as `searchFn`
4290
			// checks the value to see if it has changed. In other browsers it won't have.
4291
			setTimeout( function () {
4292
				searchFn.call(jqFilter[0], e);
4293
			}, 10);
4294
		} )
4295
		.on( 'keypress.DT', function(e) {
4296
			/* Prevent form submission */
4297
			if ( e.keyCode == 13 ) {
4298
				return false;
4299
			}
4300
		} )
4301
		.attr('aria-controls', tableId);
4302

4303
	// Update the input elements whenever the table is filtered
4304
	$(settings.nTable).on( 'search.dt.DT', function ( ev, s ) {
4305
		if ( settings === s ) {
4306
			// IE9 throws an 'unknown error' if document.activeElement is used
4307
			// inside an iframe or frame...
4308
			try {
4309
				if ( jqFilter[0] !== document.activeElement ) {
4310
					jqFilter.val( previousSearch.sSearch );
4311
				}
4312
			}
4313
			catch ( e ) {}
4314
		}
4315
	} );
4316

4317
	return filter[0];
4318
}
4319

4320

4321
/**
4322
 * Filter the table using both the global filter and column based filtering
4323
 *  @param {object} oSettings dataTables settings object
4324
 *  @param {object} oSearch search information
4325
 *  @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)
4326
 *  @memberof DataTable#oApi
4327
 */
4328
function _fnFilterComplete ( oSettings, oInput, iForce )
4329
{
4330
	var oPrevSearch = oSettings.oPreviousSearch;
4331
	var aoPrevSearch = oSettings.aoPreSearchCols;
4332
	var fnSaveFilter = function ( oFilter ) {
4333
		/* Save the filtering values */
4334
		oPrevSearch.sSearch = oFilter.sSearch;
4335
		oPrevSearch.bRegex = oFilter.bRegex;
4336
		oPrevSearch.bSmart = oFilter.bSmart;
4337
		oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive;
4338
		oPrevSearch.return = oFilter.return;
4339
	};
4340
	var fnRegex = function ( o ) {
4341
		// Backwards compatibility with the bEscapeRegex option
4342
		return o.bEscapeRegex !== undefined ? !o.bEscapeRegex : o.bRegex;
4343
	};
4344

4345
	// Resolve any column types that are unknown due to addition or invalidation
4346
	// @todo As per sort - can this be moved into an event handler?
4347
	_fnColumnTypes( oSettings );
4348

4349
	/* In server-side processing all filtering is done by the server, so no point hanging around here */
4350
	if ( _fnDataSource( oSettings ) != 'ssp' )
4351
	{
4352
		/* Global filter */
4353
		_fnFilter( oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive );
4354
		fnSaveFilter( oInput );
4355

4356
		/* Now do the individual column filter */
4357
		for ( var i=0 ; i<aoPrevSearch.length ; i++ )
4358
		{
4359
			_fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, fnRegex(aoPrevSearch[i]),
4360
				aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive );
4361
		}
4362

4363
		/* Custom filtering */
4364
		_fnFilterCustom( oSettings );
4365
	}
4366
	else
4367
	{
4368
		fnSaveFilter( oInput );
4369
	}
4370

4371
	/* Tell the draw function we have been filtering */
4372
	oSettings.bFiltered = true;
4373
	_fnCallbackFire( oSettings, null, 'search', [oSettings] );
4374
}
4375

4376

4377
/**
4378
 * Apply custom filtering functions
4379
 *  @param {object} oSettings dataTables settings object
4380
 *  @memberof DataTable#oApi
4381
 */
4382
function _fnFilterCustom( settings )
4383
{
4384
	var filters = DataTable.ext.search;
4385
	var displayRows = settings.aiDisplay;
4386
	var row, rowIdx;
4387

4388
	for ( var i=0, ien=filters.length ; i<ien ; i++ ) {
4389
		var rows = [];
4390

4391
		// Loop over each row and see if it should be included
4392
		for ( var j=0, jen=displayRows.length ; j<jen ; j++ ) {
4393
			rowIdx = displayRows[ j ];
4394
			row = settings.aoData[ rowIdx ];
4395

4396
			if ( filters[i]( settings, row._aFilterData, rowIdx, row._aData, j ) ) {
4397
				rows.push( rowIdx );
4398
			}
4399
		}
4400

4401
		// So the array reference doesn't break set the results into the
4402
		// existing array
4403
		displayRows.length = 0;
4404
		$.merge( displayRows, rows );
4405
	}
4406
}
4407

4408

4409
/**
4410
 * Filter the table on a per-column basis
4411
 *  @param {object} oSettings dataTables settings object
4412
 *  @param {string} sInput string to filter on
4413
 *  @param {int} iColumn column to filter
4414
 *  @param {bool} bRegex treat search string as a regular expression or not
4415
 *  @param {bool} bSmart use smart filtering or not
4416
 *  @param {bool} bCaseInsensitive Do case insensitive matching or not
4417
 *  @memberof DataTable#oApi
4418
 */
4419
function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, caseInsensitive )
4420
{
4421
	if ( searchStr === '' ) {
4422
		return;
4423
	}
4424

4425
	var data;
4426
	var out = [];
4427
	var display = settings.aiDisplay;
4428
	var rpSearch = _fnFilterCreateSearch( searchStr, regex, smart, caseInsensitive );
4429

4430
	for ( var i=0 ; i<display.length ; i++ ) {
4431
		data = settings.aoData[ display[i] ]._aFilterData[ colIdx ];
4432

4433
		if ( rpSearch.test( data ) ) {
4434
			out.push( display[i] );
4435
		}
4436
	}
4437

4438
	settings.aiDisplay = out;
4439
}
4440

4441

4442
/**
4443
 * Filter the data table based on user input and draw the table
4444
 *  @param {object} settings dataTables settings object
4445
 *  @param {string} input string to filter on
4446
 *  @param {int} force optional - force a research of the master array (1) or not (undefined or 0)
4447
 *  @param {bool} regex treat as a regular expression or not
4448
 *  @param {bool} smart perform smart filtering or not
4449
 *  @param {bool} caseInsensitive Do case insensitive matching or not
4450
 *  @memberof DataTable#oApi
4451
 */
4452
function _fnFilter( settings, input, force, regex, smart, caseInsensitive )
4453
{
4454
	var rpSearch = _fnFilterCreateSearch( input, regex, smart, caseInsensitive );
4455
	var prevSearch = settings.oPreviousSearch.sSearch;
4456
	var displayMaster = settings.aiDisplayMaster;
4457
	var display, invalidated, i;
4458
	var filtered = [];
4459

4460
	// Need to take account of custom filtering functions - always filter
4461
	if ( DataTable.ext.search.length !== 0 ) {
4462
		force = true;
4463
	}
4464

4465
	// Check if any of the rows were invalidated
4466
	invalidated = _fnFilterData( settings );
4467

4468
	// If the input is blank - we just want the full data set
4469
	if ( input.length <= 0 ) {
4470
		settings.aiDisplay = displayMaster.slice();
4471
	}
4472
	else {
4473
		// New search - start from the master array
4474
		if ( invalidated ||
4475
			 force ||
4476
			 regex ||
4477
			 prevSearch.length > input.length ||
4478
			 input.indexOf(prevSearch) !== 0 ||
4479
			 settings.bSorted // On resort, the display master needs to be
4480
			                  // re-filtered since indexes will have changed
4481
		) {
4482
			settings.aiDisplay = displayMaster.slice();
4483
		}
4484

4485
		// Search the display array
4486
		display = settings.aiDisplay;
4487

4488
		for ( i=0 ; i<display.length ; i++ ) {
4489
			if ( rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) {
4490
				filtered.push( display[i] );
4491
			}
4492
		}
4493

4494
		settings.aiDisplay = filtered;
4495
	}
4496
}
4497

4498

4499
/**
4500
 * Build a regular expression object suitable for searching a table
4501
 *  @param {string} sSearch string to search for
4502
 *  @param {bool} bRegex treat as a regular expression or not
4503
 *  @param {bool} bSmart perform smart filtering or not
4504
 *  @param {bool} bCaseInsensitive Do case insensitive matching or not
4505
 *  @returns {RegExp} constructed object
4506
 *  @memberof DataTable#oApi
4507
 */
4508
function _fnFilterCreateSearch( search, regex, smart, caseInsensitive )
4509
{
4510
	search = regex ?
4511
		search :
4512
		_fnEscapeRegex( search );
4513
	
4514
	if ( smart ) {
4515
		/* For smart filtering we want to allow the search to work regardless of
4516
		 * word order. We also want double quoted text to be preserved, so word
4517
		 * order is important - a la google. So this is what we want to
4518
		 * generate:
4519
		 * 
4520
		 * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$
4521
		 */
4522
		var a = $.map( search.match( /["\u201C][^"\u201D]+["\u201D]|[^ ]+/g ) || [''], function ( word ) {
4523
			if ( word.charAt(0) === '"' ) {
4524
				var m = word.match( /^"(.*)"$/ );
4525
				word = m ? m[1] : word;
4526
			}
4527
			else if ( word.charAt(0) === '\u201C' ) {
4528
				var m = word.match( /^\u201C(.*)\u201D$/ );
4529
				word = m ? m[1] : word;
4530
			}
4531

4532
			return word.replace('"', '');
4533
		} );
4534

4535
		search = '^(?=.*?'+a.join( ')(?=.*?' )+').*$';
4536
	}
4537

4538
	return new RegExp( search, caseInsensitive ? 'i' : '' );
4539
}
4540

4541

4542
/**
4543
 * Escape a string such that it can be used in a regular expression
4544
 *  @param {string} sVal string to escape
4545
 *  @returns {string} escaped string
4546
 *  @memberof DataTable#oApi
4547
 */
4548
var _fnEscapeRegex = DataTable.util.escapeRegex;
4549

4550
var __filter_div = $('<div>')[0];
4551
var __filter_div_textContent = __filter_div.textContent !== undefined;
4552

4553
// Update the filtering data for each row if needed (by invalidation or first run)
4554
function _fnFilterData ( settings )
4555
{
4556
	var columns = settings.aoColumns;
4557
	var column;
4558
	var i, j, ien, jen, filterData, cellData, row;
4559
	var wasInvalidated = false;
4560

4561
	for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
4562
		row = settings.aoData[i];
4563

4564
		if ( ! row._aFilterData ) {
4565
			filterData = [];
4566

4567
			for ( j=0, jen=columns.length ; j<jen ; j++ ) {
4568
				column = columns[j];
4569

4570
				if ( column.bSearchable ) {
4571
					cellData = _fnGetCellData( settings, i, j, 'filter' );
4572

4573
					// Search in DataTables 1.10 is string based. In 1.11 this
4574
					// should be altered to also allow strict type checking.
4575
					if ( cellData === null ) {
4576
						cellData = '';
4577
					}
4578

4579
					if ( typeof cellData !== 'string' && cellData.toString ) {
4580
						cellData = cellData.toString();
4581
					}
4582
				}
4583
				else {
4584
					cellData = '';
4585
				}
4586

4587
				// If it looks like there is an HTML entity in the string,
4588
				// attempt to decode it so sorting works as expected. Note that
4589
				// we could use a single line of jQuery to do this, but the DOM
4590
				// method used here is much faster http://jsperf.com/html-decode
4591
				if ( cellData.indexOf && cellData.indexOf('&') !== -1 ) {
4592
					__filter_div.innerHTML = cellData;
4593
					cellData = __filter_div_textContent ?
4594
						__filter_div.textContent :
4595
						__filter_div.innerText;
4596
				}
4597

4598
				if ( cellData.replace ) {
4599
					cellData = cellData.replace(/[\r\n\u2028]/g, '');
4600
				}
4601

4602
				filterData.push( cellData );
4603
			}
4604

4605
			row._aFilterData = filterData;
4606
			row._sFilterRow = filterData.join('  ');
4607
			wasInvalidated = true;
4608
		}
4609
	}
4610

4611
	return wasInvalidated;
4612
}
4613

4614

4615
/**
4616
 * Convert from the internal Hungarian notation to camelCase for external
4617
 * interaction
4618
 *  @param {object} obj Object to convert
4619
 *  @returns {object} Inverted object
4620
 *  @memberof DataTable#oApi
4621
 */
4622
function _fnSearchToCamel ( obj )
4623
{
4624
	return {
4625
		search:          obj.sSearch,
4626
		smart:           obj.bSmart,
4627
		regex:           obj.bRegex,
4628
		caseInsensitive: obj.bCaseInsensitive
4629
	};
4630
}
4631

4632

4633

4634
/**
4635
 * Convert from camelCase notation to the internal Hungarian. We could use the
4636
 * Hungarian convert function here, but this is cleaner
4637
 *  @param {object} obj Object to convert
4638
 *  @returns {object} Inverted object
4639
 *  @memberof DataTable#oApi
4640
 */
4641
function _fnSearchToHung ( obj )
4642
{
4643
	return {
4644
		sSearch:          obj.search,
4645
		bSmart:           obj.smart,
4646
		bRegex:           obj.regex,
4647
		bCaseInsensitive: obj.caseInsensitive
4648
	};
4649
}
4650

4651
/**
4652
 * Generate the node required for the info display
4653
 *  @param {object} oSettings dataTables settings object
4654
 *  @returns {node} Information element
4655
 *  @memberof DataTable#oApi
4656
 */
4657
function _fnFeatureHtmlInfo ( settings )
4658
{
4659
	var
4660
		tid = settings.sTableId,
4661
		nodes = settings.aanFeatures.i,
4662
		n = $('<div/>', {
4663
			'class': settings.oClasses.sInfo,
4664
			'id': ! nodes ? tid+'_info' : null
4665
		} );
4666

4667
	if ( ! nodes ) {
4668
		// Update display on each draw
4669
		settings.aoDrawCallback.push( {
4670
			"fn": _fnUpdateInfo,
4671
			"sName": "information"
4672
		} );
4673

4674
		n
4675
			.attr( 'role', 'status' )
4676
			.attr( 'aria-live', 'polite' );
4677

4678
		// Table is described by our info div
4679
		$(settings.nTable).attr( 'aria-describedby', tid+'_info' );
4680
	}
4681

4682
	return n[0];
4683
}
4684

4685

4686
/**
4687
 * Update the information elements in the display
4688
 *  @param {object} settings dataTables settings object
4689
 *  @memberof DataTable#oApi
4690
 */
4691
function _fnUpdateInfo ( settings )
4692
{
4693
	/* Show information about the table */
4694
	var nodes = settings.aanFeatures.i;
4695
	if ( nodes.length === 0 ) {
4696
		return;
4697
	}
4698

4699
	var
4700
		lang  = settings.oLanguage,
4701
		start = settings._iDisplayStart+1,
4702
		end   = settings.fnDisplayEnd(),
4703
		max   = settings.fnRecordsTotal(),
4704
		total = settings.fnRecordsDisplay(),
4705
		out   = total ?
4706
			lang.sInfo :
4707
			lang.sInfoEmpty;
4708

4709
	if ( total !== max ) {
4710
		/* Record set after filtering */
4711
		out += ' ' + lang.sInfoFiltered;
4712
	}
4713

4714
	// Convert the macros
4715
	out += lang.sInfoPostFix;
4716
	out = _fnInfoMacros( settings, out );
4717

4718
	var callback = lang.fnInfoCallback;
4719
	if ( callback !== null ) {
4720
		out = callback.call( settings.oInstance,
4721
			settings, start, end, max, total, out
4722
		);
4723
	}
4724

4725
	$(nodes).html( out );
4726
}
4727

4728

4729
function _fnInfoMacros ( settings, str )
4730
{
4731
	// When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
4732
	// internally
4733
	var
4734
		formatter  = settings.fnFormatNumber,
4735
		start      = settings._iDisplayStart+1,
4736
		len        = settings._iDisplayLength,
4737
		vis        = settings.fnRecordsDisplay(),
4738
		all        = len === -1;
4739

4740
	return str.
4741
		replace(/_START_/g, formatter.call( settings, start ) ).
4742
		replace(/_END_/g,   formatter.call( settings, settings.fnDisplayEnd() ) ).
4743
		replace(/_MAX_/g,   formatter.call( settings, settings.fnRecordsTotal() ) ).
4744
		replace(/_TOTAL_/g, formatter.call( settings, vis ) ).
4745
		replace(/_PAGE_/g,  formatter.call( settings, all ? 1 : Math.ceil( start / len ) ) ).
4746
		replace(/_PAGES_/g, formatter.call( settings, all ? 1 : Math.ceil( vis / len ) ) );
4747
}
4748

4749

4750

4751
/**
4752
 * Draw the table for the first time, adding all required features
4753
 *  @param {object} settings dataTables settings object
4754
 *  @memberof DataTable#oApi
4755
 */
4756
function _fnInitialise ( settings )
4757
{
4758
	var i, iLen, iAjaxStart=settings.iInitDisplayStart;
4759
	var columns = settings.aoColumns, column;
4760
	var features = settings.oFeatures;
4761
	var deferLoading = settings.bDeferLoading; // value modified by the draw
4762

4763
	/* Ensure that the table data is fully initialised */
4764
	if ( ! settings.bInitialised ) {
4765
		setTimeout( function(){ _fnInitialise( settings ); }, 200 );
4766
		return;
4767
	}
4768

4769
	/* Show the display HTML options */
4770
	_fnAddOptionsHtml( settings );
4771

4772
	/* Build and draw the header / footer for the table */
4773
	_fnBuildHead( settings );
4774
	_fnDrawHead( settings, settings.aoHeader );
4775
	_fnDrawHead( settings, settings.aoFooter );
4776

4777
	/* Okay to show that something is going on now */
4778
	_fnProcessingDisplay( settings, true );
4779

4780
	/* Calculate sizes for columns */
4781
	if ( features.bAutoWidth ) {
4782
		_fnCalculateColumnWidths( settings );
4783
	}
4784

4785
	for ( i=0, iLen=columns.length ; i<iLen ; i++ ) {
4786
		column = columns[i];
4787

4788
		if ( column.sWidth ) {
4789
			column.nTh.style.width = _fnStringToCss( column.sWidth );
4790
		}
4791
	}
4792

4793
	_fnCallbackFire( settings, null, 'preInit', [settings] );
4794

4795
	// If there is default sorting required - let's do it. The sort function
4796
	// will do the drawing for us. Otherwise we draw the table regardless of the
4797
	// Ajax source - this allows the table to look initialised for Ajax sourcing
4798
	// data (show 'loading' message possibly)
4799
	_fnReDraw( settings );
4800

4801
	// Server-side processing init complete is done by _fnAjaxUpdateDraw
4802
	var dataSrc = _fnDataSource( settings );
4803
	if ( dataSrc != 'ssp' || deferLoading ) {
4804
		// if there is an ajax source load the data
4805
		if ( dataSrc == 'ajax' ) {
4806
			_fnBuildAjax( settings, [], function(json) {
4807
				var aData = _fnAjaxDataSrc( settings, json );
4808

4809
				// Got the data - add it to the table
4810
				for ( i=0 ; i<aData.length ; i++ ) {
4811
					_fnAddData( settings, aData[i] );
4812
				}
4813

4814
				// Reset the init display for cookie saving. We've already done
4815
				// a filter, and therefore cleared it before. So we need to make
4816
				// it appear 'fresh'
4817
				settings.iInitDisplayStart = iAjaxStart;
4818

4819
				_fnReDraw( settings );
4820

4821
				_fnProcessingDisplay( settings, false );
4822
				_fnInitComplete( settings, json );
4823
			}, settings );
4824
		}
4825
		else {
4826
			_fnProcessingDisplay( settings, false );
4827
			_fnInitComplete( settings );
4828
		}
4829
	}
4830
}
4831

4832

4833
/**
4834
 * Draw the table for the first time, adding all required features
4835
 *  @param {object} oSettings dataTables settings object
4836
 *  @param {object} [json] JSON from the server that completed the table, if using Ajax source
4837
 *    with client-side processing (optional)
4838
 *  @memberof DataTable#oApi
4839
 */
4840
function _fnInitComplete ( settings, json )
4841
{
4842
	settings._bInitComplete = true;
4843

4844
	// When data was added after the initialisation (data or Ajax) we need to
4845
	// calculate the column sizing
4846
	if ( json || settings.oInit.aaData ) {
4847
		_fnAdjustColumnSizing( settings );
4848
	}
4849

4850
	_fnCallbackFire( settings, null, 'plugin-init', [settings, json] );
4851
	_fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] );
4852
}
4853

4854

4855
function _fnLengthChange ( settings, val )
4856
{
4857
	var len = parseInt( val, 10 );
4858
	settings._iDisplayLength = len;
4859

4860
	_fnLengthOverflow( settings );
4861

4862
	// Fire length change event
4863
	_fnCallbackFire( settings, null, 'length', [settings, len] );
4864
}
4865

4866

4867
/**
4868
 * Generate the node required for user display length changing
4869
 *  @param {object} settings dataTables settings object
4870
 *  @returns {node} Display length feature node
4871
 *  @memberof DataTable#oApi
4872
 */
4873
function _fnFeatureHtmlLength ( settings )
4874
{
4875
	var
4876
		classes  = settings.oClasses,
4877
		tableId  = settings.sTableId,
4878
		menu     = settings.aLengthMenu,
4879
		d2       = Array.isArray( menu[0] ),
4880
		lengths  = d2 ? menu[0] : menu,
4881
		language = d2 ? menu[1] : menu;
4882

4883
	var select = $('<select/>', {
4884
		'name':          tableId+'_length',
4885
		'aria-controls': tableId,
4886
		'class':         classes.sLengthSelect
4887
	} );
4888

4889
	for ( var i=0, ien=lengths.length ; i<ien ; i++ ) {
4890
		select[0][ i ] = new Option(
4891
			typeof language[i] === 'number' ?
4892
				settings.fnFormatNumber( language[i] ) :
4893
				language[i],
4894
			lengths[i]
4895
		);
4896
	}
4897

4898
	var div = $('<div><label/></div>').addClass( classes.sLength );
4899
	if ( ! settings.aanFeatures.l ) {
4900
		div[0].id = tableId+'_length';
4901
	}
4902

4903
	div.children().append(
4904
		settings.oLanguage.sLengthMenu.replace( '_MENU_', select[0].outerHTML )
4905
	);
4906

4907
	// Can't use `select` variable as user might provide their own and the
4908
	// reference is broken by the use of outerHTML
4909
	$('select', div)
4910
		.val( settings._iDisplayLength )
4911
		.on( 'change.DT', function(e) {
4912
			_fnLengthChange( settings, $(this).val() );
4913
			_fnDraw( settings );
4914
		} );
4915

4916
	// Update node value whenever anything changes the table's length
4917
	$(settings.nTable).on( 'length.dt.DT', function (e, s, len) {
4918
		if ( settings === s ) {
4919
			$('select', div).val( len );
4920
		}
4921
	} );
4922

4923
	return div[0];
4924
}
4925

4926

4927

4928
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
4929
 * Note that most of the paging logic is done in
4930
 * DataTable.ext.pager
4931
 */
4932

4933
/**
4934
 * Generate the node required for default pagination
4935
 *  @param {object} oSettings dataTables settings object
4936
 *  @returns {node} Pagination feature node
4937
 *  @memberof DataTable#oApi
4938
 */
4939
function _fnFeatureHtmlPaginate ( settings )
4940
{
4941
	var
4942
		type   = settings.sPaginationType,
4943
		plugin = DataTable.ext.pager[ type ],
4944
		modern = typeof plugin === 'function',
4945
		redraw = function( settings ) {
4946
			_fnDraw( settings );
4947
		},
4948
		node = $('<div/>').addClass( settings.oClasses.sPaging + type )[0],
4949
		features = settings.aanFeatures;
4950

4951
	if ( ! modern ) {
4952
		plugin.fnInit( settings, node, redraw );
4953
	}
4954

4955
	/* Add a draw callback for the pagination on first instance, to update the paging display */
4956
	if ( ! features.p )
4957
	{
4958
		node.id = settings.sTableId+'_paginate';
4959

4960
		settings.aoDrawCallback.push( {
4961
			"fn": function( settings ) {
4962
				if ( modern ) {
4963
					var
4964
						start      = settings._iDisplayStart,
4965
						len        = settings._iDisplayLength,
4966
						visRecords = settings.fnRecordsDisplay(),
4967
						all        = len === -1,
4968
						page = all ? 0 : Math.ceil( start / len ),
4969
						pages = all ? 1 : Math.ceil( visRecords / len ),
4970
						buttons = plugin(page, pages),
4971
						i, ien;
4972

4973
					for ( i=0, ien=features.p.length ; i<ien ; i++ ) {
4974
						_fnRenderer( settings, 'pageButton' )(
4975
							settings, features.p[i], i, buttons, page, pages
4976
						);
4977
					}
4978
				}
4979
				else {
4980
					plugin.fnUpdate( settings, redraw );
4981
				}
4982
			},
4983
			"sName": "pagination"
4984
		} );
4985
	}
4986

4987
	return node;
4988
}
4989

4990

4991
/**
4992
 * Alter the display settings to change the page
4993
 *  @param {object} settings DataTables settings object
4994
 *  @param {string|int} action Paging action to take: "first", "previous",
4995
 *    "next" or "last" or page number to jump to (integer)
4996
 *  @param [bool] redraw Automatically draw the update or not
4997
 *  @returns {bool} true page has changed, false - no change
4998
 *  @memberof DataTable#oApi
4999
 */
5000
function _fnPageChange ( settings, action, redraw )
5001
{
5002
	var
5003
		start     = settings._iDisplayStart,
5004
		len       = settings._iDisplayLength,
5005
		records   = settings.fnRecordsDisplay();
5006

5007
	if ( records === 0 || len === -1 )
5008
	{
5009
		start = 0;
5010
	}
5011
	else if ( typeof action === "number" )
5012
	{
5013
		start = action * len;
5014

5015
		if ( start > records )
5016
		{
5017
			start = 0;
5018
		}
5019
	}
5020
	else if ( action == "first" )
5021
	{
5022
		start = 0;
5023
	}
5024
	else if ( action == "previous" )
5025
	{
5026
		start = len >= 0 ?
5027
			start - len :
5028
			0;
5029

5030
		if ( start < 0 )
5031
		{
5032
		  start = 0;
5033
		}
5034
	}
5035
	else if ( action == "next" )
5036
	{
5037
		if ( start + len < records )
5038
		{
5039
			start += len;
5040
		}
5041
	}
5042
	else if ( action == "last" )
5043
	{
5044
		start = Math.floor( (records-1) / len) * len;
5045
	}
5046
	else
5047
	{
5048
		_fnLog( settings, 0, "Unknown paging action: "+action, 5 );
5049
	}
5050

5051
	var changed = settings._iDisplayStart !== start;
5052
	settings._iDisplayStart = start;
5053

5054
	if ( changed ) {
5055
		_fnCallbackFire( settings, null, 'page', [settings] );
5056

5057
		if ( redraw ) {
5058
			_fnDraw( settings );
5059
		}
5060
	}
5061
	else {
5062
		// No change event - paging was called, but no change
5063
		_fnCallbackFire( settings, null, 'page-nc', [settings] );
5064
	}
5065

5066
	return changed;
5067
}
5068

5069

5070

5071
/**
5072
 * Generate the node required for the processing node
5073
 *  @param {object} settings dataTables settings object
5074
 *  @returns {node} Processing element
5075
 *  @memberof DataTable#oApi
5076
 */
5077
function _fnFeatureHtmlProcessing ( settings )
5078
{
5079
	return $('<div/>', {
5080
			'id': ! settings.aanFeatures.r ? settings.sTableId+'_processing' : null,
5081
			'class': settings.oClasses.sProcessing,
5082
			'role': 'status'
5083
		} )
5084
		.html( settings.oLanguage.sProcessing )
5085
		.append('<div><div></div><div></div><div></div><div></div></div>')
5086
		.insertBefore( settings.nTable )[0];
5087
}
5088

5089

5090
/**
5091
 * Display or hide the processing indicator
5092
 *  @param {object} settings dataTables settings object
5093
 *  @param {bool} show Show the processing indicator (true) or not (false)
5094
 *  @memberof DataTable#oApi
5095
 */
5096
function _fnProcessingDisplay ( settings, show )
5097
{
5098
	if ( settings.oFeatures.bProcessing ) {
5099
		$(settings.aanFeatures.r).css( 'display', show ? 'block' : 'none' );
5100
	}
5101

5102
	_fnCallbackFire( settings, null, 'processing', [settings, show] );
5103
}
5104

5105
/**
5106
 * Add any control elements for the table - specifically scrolling
5107
 *  @param {object} settings dataTables settings object
5108
 *  @returns {node} Node to add to the DOM
5109
 *  @memberof DataTable#oApi
5110
 */
5111
function _fnFeatureHtmlTable ( settings )
5112
{
5113
	var table = $(settings.nTable);
5114

5115
	// Scrolling from here on in
5116
	var scroll = settings.oScroll;
5117

5118
	if ( scroll.sX === '' && scroll.sY === '' ) {
5119
		return settings.nTable;
5120
	}
5121

5122
	var scrollX = scroll.sX;
5123
	var scrollY = scroll.sY;
5124
	var classes = settings.oClasses;
5125
	var caption = table.children('caption');
5126
	var captionSide = caption.length ? caption[0]._captionSide : null;
5127
	var headerClone = $( table[0].cloneNode(false) );
5128
	var footerClone = $( table[0].cloneNode(false) );
5129
	var footer = table.children('tfoot');
5130
	var _div = '<div/>';
5131
	var size = function ( s ) {
5132
		return !s ? null : _fnStringToCss( s );
5133
	};
5134

5135
	if ( ! footer.length ) {
5136
		footer = null;
5137
	}
5138

5139
	/*
5140
	 * The HTML structure that we want to generate in this function is:
5141
	 *  div - scroller
5142
	 *    div - scroll head
5143
	 *      div - scroll head inner
5144
	 *        table - scroll head table
5145
	 *          thead - thead
5146
	 *    div - scroll body
5147
	 *      table - table (master table)
5148
	 *        thead - thead clone for sizing
5149
	 *        tbody - tbody
5150
	 *    div - scroll foot
5151
	 *      div - scroll foot inner
5152
	 *        table - scroll foot table
5153
	 *          tfoot - tfoot
5154
	 */
5155
	var scroller = $( _div, { 'class': classes.sScrollWrapper } )
5156
		.append(
5157
			$(_div, { 'class': classes.sScrollHead } )
5158
				.css( {
5159
					overflow: 'hidden',
5160
					position: 'relative',
5161
					border: 0,
5162
					width: scrollX ? size(scrollX) : '100%'
5163
				} )
5164
				.append(
5165
					$(_div, { 'class': classes.sScrollHeadInner } )
5166
						.css( {
5167
							'box-sizing': 'content-box',
5168
							width: scroll.sXInner || '100%'
5169
						} )
5170
						.append(
5171
							headerClone
5172
								.removeAttr('id')
5173
								.css( 'margin-left', 0 )
5174
								.append( captionSide === 'top' ? caption : null )
5175
								.append(
5176
									table.children('thead')
5177
								)
5178
						)
5179
				)
5180
		)
5181
		.append(
5182
			$(_div, { 'class': classes.sScrollBody } )
5183
				.css( {
5184
					position: 'relative',
5185
					overflow: 'auto',
5186
					width: size( scrollX )
5187
				} )
5188
				.append( table )
5189
		);
5190

5191
	if ( footer ) {
5192
		scroller.append(
5193
			$(_div, { 'class': classes.sScrollFoot } )
5194
				.css( {
5195
					overflow: 'hidden',
5196
					border: 0,
5197
					width: scrollX ? size(scrollX) : '100%'
5198
				} )
5199
				.append(
5200
					$(_div, { 'class': classes.sScrollFootInner } )
5201
						.append(
5202
							footerClone
5203
								.removeAttr('id')
5204
								.css( 'margin-left', 0 )
5205
								.append( captionSide === 'bottom' ? caption : null )
5206
								.append(
5207
									table.children('tfoot')
5208
								)
5209
						)
5210
				)
5211
		);
5212
	}
5213

5214
	var children = scroller.children();
5215
	var scrollHead = children[0];
5216
	var scrollBody = children[1];
5217
	var scrollFoot = footer ? children[2] : null;
5218

5219
	// When the body is scrolled, then we also want to scroll the headers
5220
	if ( scrollX ) {
5221
		$(scrollBody).on( 'scroll.DT', function (e) {
5222
			var scrollLeft = this.scrollLeft;
5223

5224
			scrollHead.scrollLeft = scrollLeft;
5225

5226
			if ( footer ) {
5227
				scrollFoot.scrollLeft = scrollLeft;
5228
			}
5229
		} );
5230
	}
5231

5232
	$(scrollBody).css('max-height', scrollY);
5233
	if (! scroll.bCollapse) {
5234
		$(scrollBody).css('height', scrollY);
5235
	}
5236

5237
	settings.nScrollHead = scrollHead;
5238
	settings.nScrollBody = scrollBody;
5239
	settings.nScrollFoot = scrollFoot;
5240

5241
	// On redraw - align columns
5242
	settings.aoDrawCallback.push( {
5243
		"fn": _fnScrollDraw,
5244
		"sName": "scrolling"
5245
	} );
5246

5247
	return scroller[0];
5248
}
5249

5250

5251

5252
/**
5253
 * Update the header, footer and body tables for resizing - i.e. column
5254
 * alignment.
5255
 *
5256
 * Welcome to the most horrible function DataTables. The process that this
5257
 * function follows is basically:
5258
 *   1. Re-create the table inside the scrolling div
5259
 *   2. Take live measurements from the DOM
5260
 *   3. Apply the measurements to align the columns
5261
 *   4. Clean up
5262
 *
5263
 *  @param {object} settings dataTables settings object
5264
 *  @memberof DataTable#oApi
5265
 */
5266
function _fnScrollDraw ( settings )
5267
{
5268
	// Given that this is such a monster function, a lot of variables are use
5269
	// to try and keep the minimised size as small as possible
5270
	var
5271
		scroll         = settings.oScroll,
5272
		scrollX        = scroll.sX,
5273
		scrollXInner   = scroll.sXInner,
5274
		scrollY        = scroll.sY,
5275
		barWidth       = scroll.iBarWidth,
5276
		divHeader      = $(settings.nScrollHead),
5277
		divHeaderStyle = divHeader[0].style,
5278
		divHeaderInner = divHeader.children('div'),
5279
		divHeaderInnerStyle = divHeaderInner[0].style,
5280
		divHeaderTable = divHeaderInner.children('table'),
5281
		divBodyEl      = settings.nScrollBody,
5282
		divBody        = $(divBodyEl),
5283
		divBodyStyle   = divBodyEl.style,
5284
		divFooter      = $(settings.nScrollFoot),
5285
		divFooterInner = divFooter.children('div'),
5286
		divFooterTable = divFooterInner.children('table'),
5287
		header         = $(settings.nTHead),
5288
		table          = $(settings.nTable),
5289
		tableEl        = table[0],
5290
		tableStyle     = tableEl.style,
5291
		footer         = settings.nTFoot ? $(settings.nTFoot) : null,
5292
		browser        = settings.oBrowser,
5293
		ie67           = browser.bScrollOversize,
5294
		dtHeaderCells  = _pluck( settings.aoColumns, 'nTh' ),
5295
		headerTrgEls, footerTrgEls,
5296
		headerSrcEls, footerSrcEls,
5297
		headerCopy, footerCopy,
5298
		headerWidths=[], footerWidths=[],
5299
		headerContent=[], footerContent=[],
5300
		idx, correction, sanityWidth,
5301
		zeroOut = function(nSizer) {
5302
			var style = nSizer.style;
5303
			style.paddingTop = "0";
5304
			style.paddingBottom = "0";
5305
			style.borderTopWidth = "0";
5306
			style.borderBottomWidth = "0";
5307
			style.height = 0;
5308
		};
5309

5310
	// If the scrollbar visibility has changed from the last draw, we need to
5311
	// adjust the column sizes as the table width will have changed to account
5312
	// for the scrollbar
5313
	var scrollBarVis = divBodyEl.scrollHeight > divBodyEl.clientHeight;
5314
	
5315
	if ( settings.scrollBarVis !== scrollBarVis && settings.scrollBarVis !== undefined ) {
5316
		settings.scrollBarVis = scrollBarVis;
5317
		_fnAdjustColumnSizing( settings );
5318
		return; // adjust column sizing will call this function again
5319
	}
5320
	else {
5321
		settings.scrollBarVis = scrollBarVis;
5322
	}
5323

5324
	/*
5325
	 * 1. Re-create the table inside the scrolling div
5326
	 */
5327

5328
	// Remove the old minimised thead and tfoot elements in the inner table
5329
	table.children('thead, tfoot').remove();
5330

5331
	if ( footer ) {
5332
		footerCopy = footer.clone().prependTo( table );
5333
		footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized
5334
		footerSrcEls = footerCopy.find('tr');
5335
		footerCopy.find('[id]').removeAttr('id');
5336
	}
5337

5338
	// Clone the current header and footer elements and then place it into the inner table
5339
	headerCopy = header.clone().prependTo( table );
5340
	headerTrgEls = header.find('tr'); // original header is in its own table
5341
	headerSrcEls = headerCopy.find('tr');
5342
	headerCopy.find('th, td').removeAttr('tabindex');
5343
	headerCopy.find('[id]').removeAttr('id');
5344

5345

5346
	/*
5347
	 * 2. Take live measurements from the DOM - do not alter the DOM itself!
5348
	 */
5349

5350
	// Remove old sizing and apply the calculated column widths
5351
	// Get the unique column headers in the newly created (cloned) header. We want to apply the
5352
	// calculated sizes to this header
5353
	if ( ! scrollX )
5354
	{
5355
		divBodyStyle.width = '100%';
5356
		divHeader[0].style.width = '100%';
5357
	}
5358

5359
	$.each( _fnGetUniqueThs( settings, headerCopy ), function ( i, el ) {
5360
		idx = _fnVisibleToColumnIndex( settings, i );
5361
		el.style.width = settings.aoColumns[idx].sWidth;
5362
	} );
5363

5364
	if ( footer ) {
5365
		_fnApplyToChildren( function(n) {
5366
			n.style.width = "";
5367
		}, footerSrcEls );
5368
	}
5369

5370
	// Size the table as a whole
5371
	sanityWidth = table.outerWidth();
5372
	if ( scrollX === "" ) {
5373
		// No x scrolling
5374
		tableStyle.width = "100%";
5375

5376
		// IE7 will make the width of the table when 100% include the scrollbar
5377
		// - which is shouldn't. When there is a scrollbar we need to take this
5378
		// into account.
5379
		if ( ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight ||
5380
			divBody.css('overflow-y') == "scroll")
5381
		) {
5382
			tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth);
5383
		}
5384

5385
		// Recalculate the sanity width
5386
		sanityWidth = table.outerWidth();
5387
	}
5388
	else if ( scrollXInner !== "" ) {
5389
		// legacy x scroll inner has been given - use it
5390
		tableStyle.width = _fnStringToCss(scrollXInner);
5391

5392
		// Recalculate the sanity width
5393
		sanityWidth = table.outerWidth();
5394
	}
5395

5396
	// Hidden header should have zero height, so remove padding and borders. Then
5397
	// set the width based on the real headers
5398

5399
	// Apply all styles in one pass
5400
	_fnApplyToChildren( zeroOut, headerSrcEls );
5401

5402
	// Read all widths in next pass
5403
	_fnApplyToChildren( function(nSizer) {
5404
		var style = window.getComputedStyle ?
5405
			window.getComputedStyle(nSizer).width :
5406
			_fnStringToCss( $(nSizer).width() );
5407

5408
		headerContent.push( nSizer.innerHTML );
5409
		headerWidths.push( style );
5410
	}, headerSrcEls );
5411

5412
	// Apply all widths in final pass
5413
	_fnApplyToChildren( function(nToSize, i) {
5414
		nToSize.style.width = headerWidths[i];
5415
	}, headerTrgEls );
5416

5417
	$(headerSrcEls).css('height', 0);
5418

5419
	/* Same again with the footer if we have one */
5420
	if ( footer )
5421
	{
5422
		_fnApplyToChildren( zeroOut, footerSrcEls );
5423

5424
		_fnApplyToChildren( function(nSizer) {
5425
			footerContent.push( nSizer.innerHTML );
5426
			footerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
5427
		}, footerSrcEls );
5428

5429
		_fnApplyToChildren( function(nToSize, i) {
5430
			nToSize.style.width = footerWidths[i];
5431
		}, footerTrgEls );
5432

5433
		$(footerSrcEls).height(0);
5434
	}
5435

5436

5437
	/*
5438
	 * 3. Apply the measurements
5439
	 */
5440

5441
	// "Hide" the header and footer that we used for the sizing. We need to keep
5442
	// the content of the cell so that the width applied to the header and body
5443
	// both match, but we want to hide it completely. We want to also fix their
5444
	// width to what they currently are
5445
	_fnApplyToChildren( function(nSizer, i) {
5446
		nSizer.innerHTML = '<div class="dataTables_sizing">'+headerContent[i]+'</div>';
5447
		nSizer.childNodes[0].style.height = "0";
5448
		nSizer.childNodes[0].style.overflow = "hidden";
5449
		nSizer.style.width = headerWidths[i];
5450
	}, headerSrcEls );
5451

5452
	if ( footer )
5453
	{
5454
		_fnApplyToChildren( function(nSizer, i) {
5455
			nSizer.innerHTML = '<div class="dataTables_sizing">'+footerContent[i]+'</div>';
5456
			nSizer.childNodes[0].style.height = "0";
5457
			nSizer.childNodes[0].style.overflow = "hidden";
5458
			nSizer.style.width = footerWidths[i];
5459
		}, footerSrcEls );
5460
	}
5461

5462
	// Sanity check that the table is of a sensible width. If not then we are going to get
5463
	// misalignment - try to prevent this by not allowing the table to shrink below its min width
5464
	if ( Math.round(table.outerWidth()) < Math.round(sanityWidth) )
5465
	{
5466
		// The min width depends upon if we have a vertical scrollbar visible or not */
5467
		correction = ((divBodyEl.scrollHeight > divBodyEl.offsetHeight ||
5468
			divBody.css('overflow-y') == "scroll")) ?
5469
				sanityWidth+barWidth :
5470
				sanityWidth;
5471

5472
		// IE6/7 are a law unto themselves...
5473
		if ( ie67 && (divBodyEl.scrollHeight >
5474
			divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll")
5475
		) {
5476
			tableStyle.width = _fnStringToCss( correction-barWidth );
5477
		}
5478

5479
		// And give the user a warning that we've stopped the table getting too small
5480
		if ( scrollX === "" || scrollXInner !== "" ) {
5481
			_fnLog( settings, 1, 'Possible column misalignment', 6 );
5482
		}
5483
	}
5484
	else
5485
	{
5486
		correction = '100%';
5487
	}
5488

5489
	// Apply to the container elements
5490
	divBodyStyle.width = _fnStringToCss( correction );
5491
	divHeaderStyle.width = _fnStringToCss( correction );
5492

5493
	if ( footer ) {
5494
		settings.nScrollFoot.style.width = _fnStringToCss( correction );
5495
	}
5496

5497

5498
	/*
5499
	 * 4. Clean up
5500
	 */
5501
	if ( ! scrollY ) {
5502
		/* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
5503
		 * the scrollbar height from the visible display, rather than adding it on. We need to
5504
		 * set the height in order to sort this. Don't want to do it in any other browsers.
5505
		 */
5506
		if ( ie67 ) {
5507
			divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+barWidth );
5508
		}
5509
	}
5510

5511
	/* Finally set the width's of the header and footer tables */
5512
	var iOuterWidth = table.outerWidth();
5513
	divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth );
5514
	divHeaderInnerStyle.width = _fnStringToCss( iOuterWidth );
5515

5516
	// Figure out if there are scrollbar present - if so then we need a the header and footer to
5517
	// provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
5518
	var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll";
5519
	var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' );
5520
	divHeaderInnerStyle[ padding ] = bScrolling ? barWidth+"px" : "0px";
5521

5522
	if ( footer ) {
5523
		divFooterTable[0].style.width = _fnStringToCss( iOuterWidth );
5524
		divFooterInner[0].style.width = _fnStringToCss( iOuterWidth );
5525
		divFooterInner[0].style[padding] = bScrolling ? barWidth+"px" : "0px";
5526
	}
5527

5528
	// Correct DOM ordering for colgroup - comes before the thead
5529
	table.children('colgroup').insertBefore( table.children('thead') );
5530

5531
	/* Adjust the position of the header in case we loose the y-scrollbar */
5532
	divBody.trigger('scroll');
5533

5534
	// If sorting or filtering has occurred, jump the scrolling back to the top
5535
	// only if we aren't holding the position
5536
	if ( (settings.bSorted || settings.bFiltered) && ! settings._drawHold ) {
5537
		divBodyEl.scrollTop = 0;
5538
	}
5539
}
5540

5541

5542

5543
/**
5544
 * Apply a given function to the display child nodes of an element array (typically
5545
 * TD children of TR rows
5546
 *  @param {function} fn Method to apply to the objects
5547
 *  @param array {nodes} an1 List of elements to look through for display children
5548
 *  @param array {nodes} an2 Another list (identical structure to the first) - optional
5549
 *  @memberof DataTable#oApi
5550
 */
5551
function _fnApplyToChildren( fn, an1, an2 )
5552
{
5553
	var index=0, i=0, iLen=an1.length;
5554
	var nNode1, nNode2;
5555

5556
	while ( i < iLen ) {
5557
		nNode1 = an1[i].firstChild;
5558
		nNode2 = an2 ? an2[i].firstChild : null;
5559

5560
		while ( nNode1 ) {
5561
			if ( nNode1.nodeType === 1 ) {
5562
				if ( an2 ) {
5563
					fn( nNode1, nNode2, index );
5564
				}
5565
				else {
5566
					fn( nNode1, index );
5567
				}
5568

5569
				index++;
5570
			}
5571

5572
			nNode1 = nNode1.nextSibling;
5573
			nNode2 = an2 ? nNode2.nextSibling : null;
5574
		}
5575

5576
		i++;
5577
	}
5578
}
5579

5580

5581

5582
var __re_html_remove = /<.*?>/g;
5583

5584

5585
/**
5586
 * Calculate the width of columns for the table
5587
 *  @param {object} oSettings dataTables settings object
5588
 *  @memberof DataTable#oApi
5589
 */
5590
function _fnCalculateColumnWidths ( oSettings )
5591
{
5592
	var
5593
		table = oSettings.nTable,
5594
		columns = oSettings.aoColumns,
5595
		scroll = oSettings.oScroll,
5596
		scrollY = scroll.sY,
5597
		scrollX = scroll.sX,
5598
		scrollXInner = scroll.sXInner,
5599
		columnCount = columns.length,
5600
		visibleColumns = _fnGetColumns( oSettings, 'bVisible' ),
5601
		headerCells = $('th', oSettings.nTHead),
5602
		tableWidthAttr = table.getAttribute('width'), // from DOM element
5603
		tableContainer = table.parentNode,
5604
		userInputs = false,
5605
		i, column, columnIdx, width, outerWidth,
5606
		browser = oSettings.oBrowser,
5607
		ie67 = browser.bScrollOversize;
5608

5609
	var styleWidth = table.style.width;
5610
	if ( styleWidth && styleWidth.indexOf('%') !== -1 ) {
5611
		tableWidthAttr = styleWidth;
5612
	}
5613

5614
	/* Convert any user input sizes into pixel sizes */
5615
	for ( i=0 ; i<visibleColumns.length ; i++ ) {
5616
		column = columns[ visibleColumns[i] ];
5617

5618
		if ( column.sWidth !== null ) {
5619
			column.sWidth = _fnConvertToWidth( column.sWidthOrig, tableContainer );
5620

5621
			userInputs = true;
5622
		}
5623
	}
5624

5625
	/* If the number of columns in the DOM equals the number that we have to
5626
	 * process in DataTables, then we can use the offsets that are created by
5627
	 * the web- browser. No custom sizes can be set in order for this to happen,
5628
	 * nor scrolling used
5629
	 */
5630
	if ( ie67 || ! userInputs && ! scrollX && ! scrollY &&
5631
	     columnCount == _fnVisbleColumns( oSettings ) &&
5632
	     columnCount == headerCells.length
5633
	) {
5634
		for ( i=0 ; i<columnCount ; i++ ) {
5635
			var colIdx = _fnVisibleToColumnIndex( oSettings, i );
5636

5637
			if ( colIdx !== null ) {
5638
				columns[ colIdx ].sWidth = _fnStringToCss( headerCells.eq(i).width() );
5639
			}
5640
		}
5641
	}
5642
	else
5643
	{
5644
		// Otherwise construct a single row, worst case, table with the widest
5645
		// node in the data, assign any user defined widths, then insert it into
5646
		// the DOM and allow the browser to do all the hard work of calculating
5647
		// table widths
5648
		var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table
5649
			.css( 'visibility', 'hidden' )
5650
			.removeAttr( 'id' );
5651

5652
		// Clean up the table body
5653
		tmpTable.find('tbody tr').remove();
5654
		var tr = $('<tr/>').appendTo( tmpTable.find('tbody') );
5655

5656
		// Clone the table header and footer - we can't use the header / footer
5657
		// from the cloned table, since if scrolling is active, the table's
5658
		// real header and footer are contained in different table tags
5659
		tmpTable.find('thead, tfoot').remove();
5660
		tmpTable
5661
			.append( $(oSettings.nTHead).clone() )
5662
			.append( $(oSettings.nTFoot).clone() );
5663

5664
		// Remove any assigned widths from the footer (from scrolling)
5665
		tmpTable.find('tfoot th, tfoot td').css('width', '');
5666

5667
		// Apply custom sizing to the cloned header
5668
		headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] );
5669

5670
		for ( i=0 ; i<visibleColumns.length ; i++ ) {
5671
			column = columns[ visibleColumns[i] ];
5672

5673
			headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ?
5674
				_fnStringToCss( column.sWidthOrig ) :
5675
				'';
5676

5677
			// For scrollX we need to force the column width otherwise the
5678
			// browser will collapse it. If this width is smaller than the
5679
			// width the column requires, then it will have no effect
5680
			if ( column.sWidthOrig && scrollX ) {
5681
				$( headerCells[i] ).append( $('<div/>').css( {
5682
					width: column.sWidthOrig,
5683
					margin: 0,
5684
					padding: 0,
5685
					border: 0,
5686
					height: 1
5687
				} ) );
5688
			}
5689
		}
5690

5691
		// Find the widest cell for each column and put it into the table
5692
		if ( oSettings.aoData.length ) {
5693
			for ( i=0 ; i<visibleColumns.length ; i++ ) {
5694
				columnIdx = visibleColumns[i];
5695
				column = columns[ columnIdx ];
5696

5697
				$( _fnGetWidestNode( oSettings, columnIdx ) )
5698
					.clone( false )
5699
					.append( column.sContentPadding )
5700
					.appendTo( tr );
5701
			}
5702
		}
5703

5704
		// Tidy the temporary table - remove name attributes so there aren't
5705
		// duplicated in the dom (radio elements for example)
5706
		$('[name]', tmpTable).removeAttr('name');
5707

5708
		// Table has been built, attach to the document so we can work with it.
5709
		// A holding element is used, positioned at the top of the container
5710
		// with minimal height, so it has no effect on if the container scrolls
5711
		// or not. Otherwise it might trigger scrolling when it actually isn't
5712
		// needed
5713
		var holder = $('<div/>').css( scrollX || scrollY ?
5714
				{
5715
					position: 'absolute',
5716
					top: 0,
5717
					left: 0,
5718
					height: 1,
5719
					right: 0,
5720
					overflow: 'hidden'
5721
				} :
5722
				{}
5723
			)
5724
			.append( tmpTable )
5725
			.appendTo( tableContainer );
5726

5727
		// When scrolling (X or Y) we want to set the width of the table as 
5728
		// appropriate. However, when not scrolling leave the table width as it
5729
		// is. This results in slightly different, but I think correct behaviour
5730
		if ( scrollX && scrollXInner ) {
5731
			tmpTable.width( scrollXInner );
5732
		}
5733
		else if ( scrollX ) {
5734
			tmpTable.css( 'width', 'auto' );
5735
			tmpTable.removeAttr('width');
5736

5737
			// If there is no width attribute or style, then allow the table to
5738
			// collapse
5739
			if ( tmpTable.width() < tableContainer.clientWidth && tableWidthAttr ) {
5740
				tmpTable.width( tableContainer.clientWidth );
5741
			}
5742
		}
5743
		else if ( scrollY ) {
5744
			tmpTable.width( tableContainer.clientWidth );
5745
		}
5746
		else if ( tableWidthAttr ) {
5747
			tmpTable.width( tableWidthAttr );
5748
		}
5749

5750
		// Get the width of each column in the constructed table - we need to
5751
		// know the inner width (so it can be assigned to the other table's
5752
		// cells) and the outer width so we can calculate the full width of the
5753
		// table. This is safe since DataTables requires a unique cell for each
5754
		// column, but if ever a header can span multiple columns, this will
5755
		// need to be modified.
5756
		var total = 0;
5757
		for ( i=0 ; i<visibleColumns.length ; i++ ) {
5758
			var cell = $(headerCells[i]);
5759
			var border = cell.outerWidth() - cell.width();
5760

5761
			// Use getBounding... where possible (not IE8-) because it can give
5762
			// sub-pixel accuracy, which we then want to round up!
5763
			var bounding = browser.bBounding ?
5764
				Math.ceil( headerCells[i].getBoundingClientRect().width ) :
5765
				cell.outerWidth();
5766

5767
			// Total is tracked to remove any sub-pixel errors as the outerWidth
5768
			// of the table might not equal the total given here (IE!).
5769
			total += bounding;
5770

5771
			// Width for each column to use
5772
			columns[ visibleColumns[i] ].sWidth = _fnStringToCss( bounding - border );
5773
		}
5774

5775
		table.style.width = _fnStringToCss( total );
5776

5777
		// Finished with the table - ditch it
5778
		holder.remove();
5779
	}
5780

5781
	// If there is a width attr, we want to attach an event listener which
5782
	// allows the table sizing to automatically adjust when the window is
5783
	// resized. Use the width attr rather than CSS, since we can't know if the
5784
	// CSS is a relative value or absolute - DOM read is always px.
5785
	if ( tableWidthAttr ) {
5786
		table.style.width = _fnStringToCss( tableWidthAttr );
5787
	}
5788

5789
	if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) {
5790
		var bindResize = function () {
5791
			$(window).on('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {
5792
				_fnAdjustColumnSizing( oSettings );
5793
			} ) );
5794
		};
5795

5796
		// IE6/7 will crash if we bind a resize event handler on page load.
5797
		// To be removed in 1.11 which drops IE6/7 support
5798
		if ( ie67 ) {
5799
			setTimeout( bindResize, 1000 );
5800
		}
5801
		else {
5802
			bindResize();
5803
		}
5804

5805
		oSettings._reszEvt = true;
5806
	}
5807
}
5808

5809

5810
/**
5811
 * Throttle the calls to a function. Arguments and context are maintained for
5812
 * the throttled function
5813
 *  @param {function} fn Function to be called
5814
 *  @param {int} [freq=200] call frequency in mS
5815
 *  @returns {function} wrapped function
5816
 *  @memberof DataTable#oApi
5817
 */
5818
var _fnThrottle = DataTable.util.throttle;
5819

5820

5821
/**
5822
 * Convert a CSS unit width to pixels (e.g. 2em)
5823
 *  @param {string} width width to be converted
5824
 *  @param {node} parent parent to get the with for (required for relative widths) - optional
5825
 *  @returns {int} width in pixels
5826
 *  @memberof DataTable#oApi
5827
 */
5828
function _fnConvertToWidth ( width, parent )
5829
{
5830
	if ( ! width ) {
5831
		return 0;
5832
	}
5833

5834
	var n = $('<div/>')
5835
		.css( 'width', _fnStringToCss( width ) )
5836
		.appendTo( parent || document.body );
5837

5838
	var val = n[0].offsetWidth;
5839
	n.remove();
5840

5841
	return val;
5842
}
5843

5844

5845
/**
5846
 * Get the widest node
5847
 *  @param {object} settings dataTables settings object
5848
 *  @param {int} colIdx column of interest
5849
 *  @returns {node} widest table node
5850
 *  @memberof DataTable#oApi
5851
 */
5852
function _fnGetWidestNode( settings, colIdx )
5853
{
5854
	var idx = _fnGetMaxLenString( settings, colIdx );
5855
	if ( idx < 0 ) {
5856
		return null;
5857
	}
5858

5859
	var data = settings.aoData[ idx ];
5860
	return ! data.nTr ? // Might not have been created when deferred rendering
5861
		$('<td/>').html( _fnGetCellData( settings, idx, colIdx, 'display' ) )[0] :
5862
		data.anCells[ colIdx ];
5863
}
5864

5865

5866
/**
5867
 * Get the maximum strlen for each data column
5868
 *  @param {object} settings dataTables settings object
5869
 *  @param {int} colIdx column of interest
5870
 *  @returns {string} max string length for each column
5871
 *  @memberof DataTable#oApi
5872
 */
5873
function _fnGetMaxLenString( settings, colIdx )
5874
{
5875
	var s, max=-1, maxIdx = -1;
5876

5877
	for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
5878
		s = _fnGetCellData( settings, i, colIdx, 'display' )+'';
5879
		s = s.replace( __re_html_remove, '' );
5880
		s = s.replace( /&nbsp;/g, ' ' );
5881

5882
		if ( s.length > max ) {
5883
			max = s.length;
5884
			maxIdx = i;
5885
		}
5886
	}
5887

5888
	return maxIdx;
5889
}
5890

5891

5892
/**
5893
 * Append a CSS unit (only if required) to a string
5894
 *  @param {string} value to css-ify
5895
 *  @returns {string} value with css unit
5896
 *  @memberof DataTable#oApi
5897
 */
5898
function _fnStringToCss( s )
5899
{
5900
	if ( s === null ) {
5901
		return '0px';
5902
	}
5903

5904
	if ( typeof s == 'number' ) {
5905
		return s < 0 ?
5906
			'0px' :
5907
			s+'px';
5908
	}
5909

5910
	// Check it has a unit character already
5911
	return s.match(/\d$/) ?
5912
		s+'px' :
5913
		s;
5914
}
5915

5916

5917

5918
function _fnSortFlatten ( settings )
5919
{
5920
	var
5921
		i, iLen, k, kLen,
5922
		aSort = [],
5923
		aiOrig = [],
5924
		aoColumns = settings.aoColumns,
5925
		aDataSort, iCol, sType, srcCol,
5926
		fixed = settings.aaSortingFixed,
5927
		fixedObj = $.isPlainObject( fixed ),
5928
		nestedSort = [],
5929
		add = function ( a ) {
5930
			if ( a.length && ! Array.isArray( a[0] ) ) {
5931
				// 1D array
5932
				nestedSort.push( a );
5933
			}
5934
			else {
5935
				// 2D array
5936
				$.merge( nestedSort, a );
5937
			}
5938
		};
5939

5940
	// Build the sort array, with pre-fix and post-fix options if they have been
5941
	// specified
5942
	if ( Array.isArray( fixed ) ) {
5943
		add( fixed );
5944
	}
5945

5946
	if ( fixedObj && fixed.pre ) {
5947
		add( fixed.pre );
5948
	}
5949

5950
	add( settings.aaSorting );
5951

5952
	if (fixedObj && fixed.post ) {
5953
		add( fixed.post );
5954
	}
5955

5956
	for ( i=0 ; i<nestedSort.length ; i++ )
5957
	{
5958
		srcCol = nestedSort[i][0];
5959
		aDataSort = aoColumns[ srcCol ].aDataSort;
5960

5961
		for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ )
5962
		{
5963
			iCol = aDataSort[k];
5964
			sType = aoColumns[ iCol ].sType || 'string';
5965

5966
			if ( nestedSort[i]._idx === undefined ) {
5967
				nestedSort[i]._idx = $.inArray( nestedSort[i][1], aoColumns[iCol].asSorting );
5968
			}
5969

5970
			aSort.push( {
5971
				src:       srcCol,
5972
				col:       iCol,
5973
				dir:       nestedSort[i][1],
5974
				index:     nestedSort[i]._idx,
5975
				type:      sType,
5976
				formatter: DataTable.ext.type.order[ sType+"-pre" ]
5977
			} );
5978
		}
5979
	}
5980

5981
	return aSort;
5982
}
5983

5984
/**
5985
 * Change the order of the table
5986
 *  @param {object} oSettings dataTables settings object
5987
 *  @memberof DataTable#oApi
5988
 *  @todo This really needs split up!
5989
 */
5990
function _fnSort ( oSettings )
5991
{
5992
	var
5993
		i, ien, iLen, j, jLen, k, kLen,
5994
		sDataType, nTh,
5995
		aiOrig = [],
5996
		oExtSort = DataTable.ext.type.order,
5997
		aoData = oSettings.aoData,
5998
		aoColumns = oSettings.aoColumns,
5999
		aDataSort, data, iCol, sType, oSort,
6000
		formatters = 0,
6001
		sortCol,
6002
		displayMaster = oSettings.aiDisplayMaster,
6003
		aSort;
6004

6005
	// Resolve any column types that are unknown due to addition or invalidation
6006
	// @todo Can this be moved into a 'data-ready' handler which is called when
6007
	//   data is going to be used in the table?
6008
	_fnColumnTypes( oSettings );
6009

6010
	aSort = _fnSortFlatten( oSettings );
6011

6012
	for ( i=0, ien=aSort.length ; i<ien ; i++ ) {
6013
		sortCol = aSort[i];
6014

6015
		// Track if we can use the fast sort algorithm
6016
		if ( sortCol.formatter ) {
6017
			formatters++;
6018
		}
6019

6020
		// Load the data needed for the sort, for each cell
6021
		_fnSortData( oSettings, sortCol.col );
6022
	}
6023

6024
	/* No sorting required if server-side or no sorting array */
6025
	if ( _fnDataSource( oSettings ) != 'ssp' && aSort.length !== 0 )
6026
	{
6027
		// Create a value - key array of the current row positions such that we can use their
6028
		// current position during the sort, if values match, in order to perform stable sorting
6029
		for ( i=0, iLen=displayMaster.length ; i<iLen ; i++ ) {
6030
			aiOrig[ displayMaster[i] ] = i;
6031
		}
6032

6033
		/* Do the sort - here we want multi-column sorting based on a given data source (column)
6034
		 * and sorting function (from oSort) in a certain direction. It's reasonably complex to
6035
		 * follow on it's own, but this is what we want (example two column sorting):
6036
		 *  fnLocalSorting = function(a,b){
6037
		 *    var iTest;
6038
		 *    iTest = oSort['string-asc']('data11', 'data12');
6039
		 *      if (iTest !== 0)
6040
		 *        return iTest;
6041
		 *    iTest = oSort['numeric-desc']('data21', 'data22');
6042
		 *    if (iTest !== 0)
6043
		 *      return iTest;
6044
		 *    return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
6045
		 *  }
6046
		 * Basically we have a test for each sorting column, if the data in that column is equal,
6047
		 * test the next column. If all columns match, then we use a numeric sort on the row
6048
		 * positions in the original data array to provide a stable sort.
6049
		 *
6050
		 * Note - I know it seems excessive to have two sorting methods, but the first is around
6051
		 * 15% faster, so the second is only maintained for backwards compatibility with sorting
6052
		 * methods which do not have a pre-sort formatting function.
6053
		 */
6054
		if ( formatters === aSort.length ) {
6055
			// All sort types have formatting functions
6056
			displayMaster.sort( function ( a, b ) {
6057
				var
6058
					x, y, k, test, sort,
6059
					len=aSort.length,
6060
					dataA = aoData[a]._aSortData,
6061
					dataB = aoData[b]._aSortData;
6062

6063
				for ( k=0 ; k<len ; k++ ) {
6064
					sort = aSort[k];
6065

6066
					x = dataA[ sort.col ];
6067
					y = dataB[ sort.col ];
6068

6069
					test = x<y ? -1 : x>y ? 1 : 0;
6070
					if ( test !== 0 ) {
6071
						return sort.dir === 'asc' ? test : -test;
6072
					}
6073
				}
6074

6075
				x = aiOrig[a];
6076
				y = aiOrig[b];
6077
				return x<y ? -1 : x>y ? 1 : 0;
6078
			} );
6079
		}
6080
		else {
6081
			// Depreciated - remove in 1.11 (providing a plug-in option)
6082
			// Not all sort types have formatting methods, so we have to call their sorting
6083
			// methods.
6084
			displayMaster.sort( function ( a, b ) {
6085
				var
6086
					x, y, k, l, test, sort, fn,
6087
					len=aSort.length,
6088
					dataA = aoData[a]._aSortData,
6089
					dataB = aoData[b]._aSortData;
6090

6091
				for ( k=0 ; k<len ; k++ ) {
6092
					sort = aSort[k];
6093

6094
					x = dataA[ sort.col ];
6095
					y = dataB[ sort.col ];
6096

6097
					fn = oExtSort[ sort.type+"-"+sort.dir ] || oExtSort[ "string-"+sort.dir ];
6098
					test = fn( x, y );
6099
					if ( test !== 0 ) {
6100
						return test;
6101
					}
6102
				}
6103

6104
				x = aiOrig[a];
6105
				y = aiOrig[b];
6106
				return x<y ? -1 : x>y ? 1 : 0;
6107
			} );
6108
		}
6109
	}
6110

6111
	/* Tell the draw function that we have sorted the data */
6112
	oSettings.bSorted = true;
6113
}
6114

6115

6116
function _fnSortAria ( settings )
6117
{
6118
	var label;
6119
	var nextSort;
6120
	var columns = settings.aoColumns;
6121
	var aSort = _fnSortFlatten( settings );
6122
	var oAria = settings.oLanguage.oAria;
6123

6124
	// ARIA attributes - need to loop all columns, to update all (removing old
6125
	// attributes as needed)
6126
	for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
6127
	{
6128
		var col = columns[i];
6129
		var asSorting = col.asSorting;
6130
		var sTitle = col.ariaTitle || col.sTitle.replace( /<.*?>/g, "" );
6131
		var th = col.nTh;
6132

6133
		// IE7 is throwing an error when setting these properties with jQuery's
6134
		// attr() and removeAttr() methods...
6135
		th.removeAttribute('aria-sort');
6136

6137
		/* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
6138
		if ( col.bSortable ) {
6139
			if ( aSort.length > 0 && aSort[0].col == i ) {
6140
				th.setAttribute('aria-sort', aSort[0].dir=="asc" ? "ascending" : "descending" );
6141
				nextSort = asSorting[ aSort[0].index+1 ] || asSorting[0];
6142
			}
6143
			else {
6144
				nextSort = asSorting[0];
6145
			}
6146

6147
			label = sTitle + ( nextSort === "asc" ?
6148
				oAria.sSortAscending :
6149
				oAria.sSortDescending
6150
			);
6151
		}
6152
		else {
6153
			label = sTitle;
6154
		}
6155

6156
		th.setAttribute('aria-label', label);
6157
	}
6158
}
6159

6160

6161
/**
6162
 * Function to run on user sort request
6163
 *  @param {object} settings dataTables settings object
6164
 *  @param {node} attachTo node to attach the handler to
6165
 *  @param {int} colIdx column sorting index
6166
 *  @param {boolean} [append=false] Append the requested sort to the existing
6167
 *    sort if true (i.e. multi-column sort)
6168
 *  @param {function} [callback] callback function
6169
 *  @memberof DataTable#oApi
6170
 */
6171
function _fnSortListener ( settings, colIdx, append, callback )
6172
{
6173
	var col = settings.aoColumns[ colIdx ];
6174
	var sorting = settings.aaSorting;
6175
	var asSorting = col.asSorting;
6176
	var nextSortIdx;
6177
	var next = function ( a, overflow ) {
6178
		var idx = a._idx;
6179
		if ( idx === undefined ) {
6180
			idx = $.inArray( a[1], asSorting );
6181
		}
6182

6183
		return idx+1 < asSorting.length ?
6184
			idx+1 :
6185
			overflow ?
6186
				null :
6187
				0;
6188
	};
6189

6190
	// Convert to 2D array if needed
6191
	if ( typeof sorting[0] === 'number' ) {
6192
		sorting = settings.aaSorting = [ sorting ];
6193
	}
6194

6195
	// If appending the sort then we are multi-column sorting
6196
	if ( append && settings.oFeatures.bSortMulti ) {
6197
		// Are we already doing some kind of sort on this column?
6198
		var sortIdx = $.inArray( colIdx, _pluck(sorting, '0') );
6199

6200
		if ( sortIdx !== -1 ) {
6201
			// Yes, modify the sort
6202
			nextSortIdx = next( sorting[sortIdx], true );
6203

6204
			if ( nextSortIdx === null && sorting.length === 1 ) {
6205
				nextSortIdx = 0; // can't remove sorting completely
6206
			}
6207

6208
			if ( nextSortIdx === null ) {
6209
				sorting.splice( sortIdx, 1 );
6210
			}
6211
			else {
6212
				sorting[sortIdx][1] = asSorting[ nextSortIdx ];
6213
				sorting[sortIdx]._idx = nextSortIdx;
6214
			}
6215
		}
6216
		else {
6217
			// No sort on this column yet
6218
			sorting.push( [ colIdx, asSorting[0], 0 ] );
6219
			sorting[sorting.length-1]._idx = 0;
6220
		}
6221
	}
6222
	else if ( sorting.length && sorting[0][0] == colIdx ) {
6223
		// Single column - already sorting on this column, modify the sort
6224
		nextSortIdx = next( sorting[0] );
6225

6226
		sorting.length = 1;
6227
		sorting[0][1] = asSorting[ nextSortIdx ];
6228
		sorting[0]._idx = nextSortIdx;
6229
	}
6230
	else {
6231
		// Single column - sort only on this column
6232
		sorting.length = 0;
6233
		sorting.push( [ colIdx, asSorting[0] ] );
6234
		sorting[0]._idx = 0;
6235
	}
6236

6237
	// Run the sort by calling a full redraw
6238
	_fnReDraw( settings );
6239

6240
	// callback used for async user interaction
6241
	if ( typeof callback == 'function' ) {
6242
		callback( settings );
6243
	}
6244
}
6245

6246

6247
/**
6248
 * Attach a sort handler (click) to a node
6249
 *  @param {object} settings dataTables settings object
6250
 *  @param {node} attachTo node to attach the handler to
6251
 *  @param {int} colIdx column sorting index
6252
 *  @param {function} [callback] callback function
6253
 *  @memberof DataTable#oApi
6254
 */
6255
function _fnSortAttachListener ( settings, attachTo, colIdx, callback )
6256
{
6257
	var col = settings.aoColumns[ colIdx ];
6258

6259
	_fnBindAction( attachTo, {}, function (e) {
6260
		/* If the column is not sortable - don't to anything */
6261
		if ( col.bSortable === false ) {
6262
			return;
6263
		}
6264

6265
		// If processing is enabled use a timeout to allow the processing
6266
		// display to be shown - otherwise to it synchronously
6267
		if ( settings.oFeatures.bProcessing ) {
6268
			_fnProcessingDisplay( settings, true );
6269

6270
			setTimeout( function() {
6271
				_fnSortListener( settings, colIdx, e.shiftKey, callback );
6272

6273
				// In server-side processing, the draw callback will remove the
6274
				// processing display
6275
				if ( _fnDataSource( settings ) !== 'ssp' ) {
6276
					_fnProcessingDisplay( settings, false );
6277
				}
6278
			}, 0 );
6279
		}
6280
		else {
6281
			_fnSortListener( settings, colIdx, e.shiftKey, callback );
6282
		}
6283
	} );
6284
}
6285

6286

6287
/**
6288
 * Set the sorting classes on table's body, Note: it is safe to call this function
6289
 * when bSort and bSortClasses are false
6290
 *  @param {object} oSettings dataTables settings object
6291
 *  @memberof DataTable#oApi
6292
 */
6293
function _fnSortingClasses( settings )
6294
{
6295
	var oldSort = settings.aLastSort;
6296
	var sortClass = settings.oClasses.sSortColumn;
6297
	var sort = _fnSortFlatten( settings );
6298
	var features = settings.oFeatures;
6299
	var i, ien, colIdx;
6300

6301
	if ( features.bSort && features.bSortClasses ) {
6302
		// Remove old sorting classes
6303
		for ( i=0, ien=oldSort.length ; i<ien ; i++ ) {
6304
			colIdx = oldSort[i].src;
6305

6306
			// Remove column sorting
6307
			$( _pluck( settings.aoData, 'anCells', colIdx ) )
6308
				.removeClass( sortClass + (i<2 ? i+1 : 3) );
6309
		}
6310

6311
		// Add new column sorting
6312
		for ( i=0, ien=sort.length ; i<ien ; i++ ) {
6313
			colIdx = sort[i].src;
6314

6315
			$( _pluck( settings.aoData, 'anCells', colIdx ) )
6316
				.addClass( sortClass + (i<2 ? i+1 : 3) );
6317
		}
6318
	}
6319

6320
	settings.aLastSort = sort;
6321
}
6322

6323

6324
// Get the data to sort a column, be it from cache, fresh (populating the
6325
// cache), or from a sort formatter
6326
function _fnSortData( settings, idx )
6327
{
6328
	// Custom sorting function - provided by the sort data type
6329
	var column = settings.aoColumns[ idx ];
6330
	var customSort = DataTable.ext.order[ column.sSortDataType ];
6331
	var customData;
6332

6333
	if ( customSort ) {
6334
		customData = customSort.call( settings.oInstance, settings, idx,
6335
			_fnColumnIndexToVisible( settings, idx )
6336
		);
6337
	}
6338

6339
	// Use / populate cache
6340
	var row, cellData;
6341
	var formatter = DataTable.ext.type.order[ column.sType+"-pre" ];
6342

6343
	for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
6344
		row = settings.aoData[i];
6345

6346
		if ( ! row._aSortData ) {
6347
			row._aSortData = [];
6348
		}
6349

6350
		if ( ! row._aSortData[idx] || customSort ) {
6351
			cellData = customSort ?
6352
				customData[i] : // If there was a custom sort function, use data from there
6353
				_fnGetCellData( settings, i, idx, 'sort' );
6354

6355
			row._aSortData[ idx ] = formatter ?
6356
				formatter( cellData ) :
6357
				cellData;
6358
		}
6359
	}
6360
}
6361

6362

6363

6364
/**
6365
 * Save the state of a table
6366
 *  @param {object} oSettings dataTables settings object
6367
 *  @memberof DataTable#oApi
6368
 */
6369
function _fnSaveState ( settings )
6370
{
6371
	if (settings._bLoadingState) {
6372
		return;
6373
	}
6374

6375
	/* Store the interesting variables */
6376
	var state = {
6377
		time:    +new Date(),
6378
		start:   settings._iDisplayStart,
6379
		length:  settings._iDisplayLength,
6380
		order:   $.extend( true, [], settings.aaSorting ),
6381
		search:  _fnSearchToCamel( settings.oPreviousSearch ),
6382
		columns: $.map( settings.aoColumns, function ( col, i ) {
6383
			return {
6384
				visible: col.bVisible,
6385
				search: _fnSearchToCamel( settings.aoPreSearchCols[i] )
6386
			};
6387
		} )
6388
	};
6389

6390
	settings.oSavedState = state;
6391
	_fnCallbackFire( settings, "aoStateSaveParams", 'stateSaveParams', [settings, state] );
6392
	
6393
	if ( settings.oFeatures.bStateSave && !settings.bDestroying )
6394
	{
6395
		settings.fnStateSaveCallback.call( settings.oInstance, settings, state );
6396
	}	
6397
}
6398

6399

6400
/**
6401
 * Attempt to load a saved table state
6402
 *  @param {object} oSettings dataTables settings object
6403
 *  @param {object} oInit DataTables init object so we can override settings
6404
 *  @param {function} callback Callback to execute when the state has been loaded
6405
 *  @memberof DataTable#oApi
6406
 */
6407
function _fnLoadState ( settings, oInit, callback )
6408
{
6409
	if ( ! settings.oFeatures.bStateSave ) {
6410
		callback();
6411
		return;
6412
	}
6413

6414
	var loaded = function(state) {
6415
		_fnImplementState(settings, state, callback);
6416
	}
6417

6418
	var state = settings.fnStateLoadCallback.call( settings.oInstance, settings, loaded );
6419

6420
	if ( state !== undefined ) {
6421
		_fnImplementState( settings, state, callback );
6422
	}
6423
	// otherwise, wait for the loaded callback to be executed
6424

6425
	return true;
6426
}
6427

6428
function _fnImplementState ( settings, s, callback) {
6429
	var i, ien;
6430
	var columns = settings.aoColumns;
6431
	settings._bLoadingState = true;
6432

6433
	// When StateRestore was introduced the state could now be implemented at any time
6434
	// Not just initialisation. To do this an api instance is required in some places
6435
	var api = settings._bInitComplete ? new DataTable.Api(settings) : null;
6436

6437
	if ( ! s || ! s.time ) {
6438
		settings._bLoadingState = false;
6439
		callback();
6440
		return;
6441
	}
6442

6443
	// Allow custom and plug-in manipulation functions to alter the saved data set and
6444
	// cancelling of loading by returning false
6445
	var abStateLoad = _fnCallbackFire( settings, 'aoStateLoadParams', 'stateLoadParams', [settings, s] );
6446
	if ( $.inArray( false, abStateLoad ) !== -1 ) {
6447
		settings._bLoadingState = false;
6448
		callback();
6449
		return;
6450
	}
6451

6452
	// Reject old data
6453
	var duration = settings.iStateDuration;
6454
	if ( duration > 0 && s.time < +new Date() - (duration*1000) ) {
6455
		settings._bLoadingState = false;
6456
		callback();
6457
		return;
6458
	}
6459

6460
	// Number of columns have changed - all bets are off, no restore of settings
6461
	if ( s.columns && columns.length !== s.columns.length ) {
6462
		settings._bLoadingState = false;
6463
		callback();
6464
		return;
6465
	}
6466

6467
	// Store the saved state so it might be accessed at any time
6468
	settings.oLoadedState = $.extend( true, {}, s );
6469

6470
	// Page Length
6471
	if ( s.length !== undefined ) {
6472
		// If already initialised just set the value directly so that the select element is also updated
6473
		if (api) {
6474
			api.page.len(s.length)
6475
		}
6476
		else {
6477
			settings._iDisplayLength   = s.length;
6478
		}
6479
	}
6480

6481
	// Restore key features - todo - for 1.11 this needs to be done by
6482
	// subscribed events
6483
	if ( s.start !== undefined ) {
6484
		if(api === null) {
6485
			settings._iDisplayStart    = s.start;
6486
			settings.iInitDisplayStart = s.start;
6487
		}
6488
		else {
6489
			_fnPageChange(settings, s.start/settings._iDisplayLength);
6490
		}
6491
	}
6492

6493
	// Order
6494
	if ( s.order !== undefined ) {
6495
		settings.aaSorting = [];
6496
		$.each( s.order, function ( i, col ) {
6497
			settings.aaSorting.push( col[0] >= columns.length ?
6498
				[ 0, col[1] ] :
6499
				col
6500
			);
6501
		} );
6502
	}
6503

6504
	// Search
6505
	if ( s.search !== undefined ) {
6506
		$.extend( settings.oPreviousSearch, _fnSearchToHung( s.search ) );
6507
	}
6508

6509
	// Columns
6510
	if ( s.columns ) {
6511
		for ( i=0, ien=s.columns.length ; i<ien ; i++ ) {
6512
			var col = s.columns[i];
6513

6514
			// Visibility
6515
			if ( col.visible !== undefined ) {
6516
				// If the api is defined, the table has been initialised so we need to use it rather than internal settings
6517
				if (api) {
6518
					// Don't redraw the columns on every iteration of this loop, we will do this at the end instead
6519
					api.column(i).visible(col.visible, false);
6520
				}
6521
				else {
6522
					columns[i].bVisible = col.visible;
6523
				}
6524
			}
6525

6526
			// Search
6527
			if ( col.search !== undefined ) {
6528
				$.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) );
6529
			}
6530
		}
6531
		
6532
		// If the api is defined then we need to adjust the columns once the visibility has been changed
6533
		if (api) {
6534
			api.columns.adjust();
6535
		}
6536
	}
6537

6538
	settings._bLoadingState = false;
6539
	_fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, s] );
6540
	callback();
6541
};
6542

6543

6544
/**
6545
 * Return the settings object for a particular table
6546
 *  @param {node} table table we are using as a dataTable
6547
 *  @returns {object} Settings object - or null if not found
6548
 *  @memberof DataTable#oApi
6549
 */
6550
function _fnSettingsFromNode ( table )
6551
{
6552
	var settings = DataTable.settings;
6553
	var idx = $.inArray( table, _pluck( settings, 'nTable' ) );
6554

6555
	return idx !== -1 ?
6556
		settings[ idx ] :
6557
		null;
6558
}
6559

6560

6561
/**
6562
 * Log an error message
6563
 *  @param {object} settings dataTables settings object
6564
 *  @param {int} level log error messages, or display them to the user
6565
 *  @param {string} msg error message
6566
 *  @param {int} tn Technical note id to get more information about the error.
6567
 *  @memberof DataTable#oApi
6568
 */
6569
function _fnLog( settings, level, msg, tn )
6570
{
6571
	msg = 'DataTables warning: '+
6572
		(settings ? 'table id='+settings.sTableId+' - ' : '')+msg;
6573

6574
	if ( tn ) {
6575
		msg += '. For more information about this error, please see '+
6576
		'http://datatables.net/tn/'+tn;
6577
	}
6578

6579
	if ( ! level  ) {
6580
		// Backwards compatibility pre 1.10
6581
		var ext = DataTable.ext;
6582
		var type = ext.sErrMode || ext.errMode;
6583

6584
		if ( settings ) {
6585
			_fnCallbackFire( settings, null, 'error', [ settings, tn, msg ] );
6586
		}
6587

6588
		if ( type == 'alert' ) {
6589
			alert( msg );
6590
		}
6591
		else if ( type == 'throw' ) {
6592
			throw new Error(msg);
6593
		}
6594
		else if ( typeof type == 'function' ) {
6595
			type( settings, tn, msg );
6596
		}
6597
	}
6598
	else if ( window.console && console.log ) {
6599
		console.log( msg );
6600
	}
6601
}
6602

6603

6604
/**
6605
 * See if a property is defined on one object, if so assign it to the other object
6606
 *  @param {object} ret target object
6607
 *  @param {object} src source object
6608
 *  @param {string} name property
6609
 *  @param {string} [mappedName] name to map too - optional, name used if not given
6610
 *  @memberof DataTable#oApi
6611
 */
6612
function _fnMap( ret, src, name, mappedName )
6613
{
6614
	if ( Array.isArray( name ) ) {
6615
		$.each( name, function (i, val) {
6616
			if ( Array.isArray( val ) ) {
6617
				_fnMap( ret, src, val[0], val[1] );
6618
			}
6619
			else {
6620
				_fnMap( ret, src, val );
6621
			}
6622
		} );
6623

6624
		return;
6625
	}
6626

6627
	if ( mappedName === undefined ) {
6628
		mappedName = name;
6629
	}
6630

6631
	if ( src[name] !== undefined ) {
6632
		ret[mappedName] = src[name];
6633
	}
6634
}
6635

6636

6637
/**
6638
 * Extend objects - very similar to jQuery.extend, but deep copy objects, and
6639
 * shallow copy arrays. The reason we need to do this, is that we don't want to
6640
 * deep copy array init values (such as aaSorting) since the dev wouldn't be
6641
 * able to override them, but we do want to deep copy arrays.
6642
 *  @param {object} out Object to extend
6643
 *  @param {object} extender Object from which the properties will be applied to
6644
 *      out
6645
 *  @param {boolean} breakRefs If true, then arrays will be sliced to take an
6646
 *      independent copy with the exception of the `data` or `aaData` parameters
6647
 *      if they are present. This is so you can pass in a collection to
6648
 *      DataTables and have that used as your data source without breaking the
6649
 *      references
6650
 *  @returns {object} out Reference, just for convenience - out === the return.
6651
 *  @memberof DataTable#oApi
6652
 *  @todo This doesn't take account of arrays inside the deep copied objects.
6653
 */
6654
function _fnExtend( out, extender, breakRefs )
6655
{
6656
	var val;
6657

6658
	for ( var prop in extender ) {
6659
		if ( extender.hasOwnProperty(prop) ) {
6660
			val = extender[prop];
6661

6662
			if ( $.isPlainObject( val ) ) {
6663
				if ( ! $.isPlainObject( out[prop] ) ) {
6664
					out[prop] = {};
6665
				}
6666
				$.extend( true, out[prop], val );
6667
			}
6668
			else if ( breakRefs && prop !== 'data' && prop !== 'aaData' && Array.isArray(val) ) {
6669
				out[prop] = val.slice();
6670
			}
6671
			else {
6672
				out[prop] = val;
6673
			}
6674
		}
6675
	}
6676

6677
	return out;
6678
}
6679

6680

6681
/**
6682
 * Bind an event handers to allow a click or return key to activate the callback.
6683
 * This is good for accessibility since a return on the keyboard will have the
6684
 * same effect as a click, if the element has focus.
6685
 *  @param {element} n Element to bind the action to
6686
 *  @param {object} oData Data object to pass to the triggered function
6687
 *  @param {function} fn Callback function for when the event is triggered
6688
 *  @memberof DataTable#oApi
6689
 */
6690
function _fnBindAction( n, oData, fn )
6691
{
6692
	$(n)
6693
		.on( 'click.DT', oData, function (e) {
6694
				$(n).trigger('blur'); // Remove focus outline for mouse users
6695
				fn(e);
6696
			} )
6697
		.on( 'keypress.DT', oData, function (e){
6698
				if ( e.which === 13 ) {
6699
					e.preventDefault();
6700
					fn(e);
6701
				}
6702
			} )
6703
		.on( 'selectstart.DT', function () {
6704
				/* Take the brutal approach to cancelling text selection */
6705
				return false;
6706
			} );
6707
}
6708

6709

6710
/**
6711
 * Register a callback function. Easily allows a callback function to be added to
6712
 * an array store of callback functions that can then all be called together.
6713
 *  @param {object} oSettings dataTables settings object
6714
 *  @param {string} sStore Name of the array storage for the callbacks in oSettings
6715
 *  @param {function} fn Function to be called back
6716
 *  @param {string} sName Identifying name for the callback (i.e. a label)
6717
 *  @memberof DataTable#oApi
6718
 */
6719
function _fnCallbackReg( oSettings, sStore, fn, sName )
6720
{
6721
	if ( fn )
6722
	{
6723
		oSettings[sStore].push( {
6724
			"fn": fn,
6725
			"sName": sName
6726
		} );
6727
	}
6728
}
6729

6730

6731
/**
6732
 * Fire callback functions and trigger events. Note that the loop over the
6733
 * callback array store is done backwards! Further note that you do not want to
6734
 * fire off triggers in time sensitive applications (for example cell creation)
6735
 * as its slow.
6736
 *  @param {object} settings dataTables settings object
6737
 *  @param {string} callbackArr Name of the array storage for the callbacks in
6738
 *      oSettings
6739
 *  @param {string} eventName Name of the jQuery custom event to trigger. If
6740
 *      null no trigger is fired
6741
 *  @param {array} args Array of arguments to pass to the callback function /
6742
 *      trigger
6743
 *  @memberof DataTable#oApi
6744
 */
6745
function _fnCallbackFire( settings, callbackArr, eventName, args )
6746
{
6747
	var ret = [];
6748

6749
	if ( callbackArr ) {
6750
		ret = $.map( settings[callbackArr].slice().reverse(), function (val, i) {
6751
			return val.fn.apply( settings.oInstance, args );
6752
		} );
6753
	}
6754

6755
	if ( eventName !== null ) {
6756
		var e = $.Event( eventName+'.dt' );
6757
		var table = $(settings.nTable);
6758

6759
		table.trigger( e, args );
6760

6761
		// If not yet attached to the document, trigger the event
6762
		// on the body directly to sort of simulate the bubble
6763
		if (table.parents('body').length === 0) {
6764
			$('body').trigger( e, args );
6765
		}
6766

6767
		ret.push( e.result );
6768
	}
6769

6770
	return ret;
6771
}
6772

6773

6774
function _fnLengthOverflow ( settings )
6775
{
6776
	var
6777
		start = settings._iDisplayStart,
6778
		end = settings.fnDisplayEnd(),
6779
		len = settings._iDisplayLength;
6780

6781
	/* If we have space to show extra rows (backing up from the end point - then do so */
6782
	if ( start >= end )
6783
	{
6784
		start = end - len;
6785
	}
6786

6787
	// Keep the start record on the current page
6788
	start -= (start % len);
6789

6790
	if ( len === -1 || start < 0 )
6791
	{
6792
		start = 0;
6793
	}
6794

6795
	settings._iDisplayStart = start;
6796
}
6797

6798

6799
function _fnRenderer( settings, type )
6800
{
6801
	var renderer = settings.renderer;
6802
	var host = DataTable.ext.renderer[type];
6803

6804
	if ( $.isPlainObject( renderer ) && renderer[type] ) {
6805
		// Specific renderer for this type. If available use it, otherwise use
6806
		// the default.
6807
		return host[renderer[type]] || host._;
6808
	}
6809
	else if ( typeof renderer === 'string' ) {
6810
		// Common renderer - if there is one available for this type use it,
6811
		// otherwise use the default
6812
		return host[renderer] || host._;
6813
	}
6814

6815
	// Use the default
6816
	return host._;
6817
}
6818

6819

6820
/**
6821
 * Detect the data source being used for the table. Used to simplify the code
6822
 * a little (ajax) and to make it compress a little smaller.
6823
 *
6824
 *  @param {object} settings dataTables settings object
6825
 *  @returns {string} Data source
6826
 *  @memberof DataTable#oApi
6827
 */
6828
function _fnDataSource ( settings )
6829
{
6830
	if ( settings.oFeatures.bServerSide ) {
6831
		return 'ssp';
6832
	}
6833
	else if ( settings.ajax || settings.sAjaxSource ) {
6834
		return 'ajax';
6835
	}
6836
	return 'dom';
6837
}
6838

6839

6840

6841

6842
/**
6843
 * Computed structure of the DataTables API, defined by the options passed to
6844
 * `DataTable.Api.register()` when building the API.
6845
 *
6846
 * The structure is built in order to speed creation and extension of the Api
6847
 * objects since the extensions are effectively pre-parsed.
6848
 *
6849
 * The array is an array of objects with the following structure, where this
6850
 * base array represents the Api prototype base:
6851
 *
6852
 *     [
6853
 *       {
6854
 *         name:      'data'                -- string   - Property name
6855
 *         val:       function () {},       -- function - Api method (or undefined if just an object
6856
 *         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
6857
 *         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
6858
 *       },
6859
 *       {
6860
 *         name:     'row'
6861
 *         val:       {},
6862
 *         methodExt: [ ... ],
6863
 *         propExt:   [
6864
 *           {
6865
 *             name:      'data'
6866
 *             val:       function () {},
6867
 *             methodExt: [ ... ],
6868
 *             propExt:   [ ... ]
6869
 *           },
6870
 *           ...
6871
 *         ]
6872
 *       }
6873
 *     ]
6874
 *
6875
 * @type {Array}
6876
 * @ignore
6877
 */
6878
var __apiStruct = [];
6879

6880

6881
/**
6882
 * `Array.prototype` reference.
6883
 *
6884
 * @type object
6885
 * @ignore
6886
 */
6887
var __arrayProto = Array.prototype;
6888

6889

6890
/**
6891
 * Abstraction for `context` parameter of the `Api` constructor to allow it to
6892
 * take several different forms for ease of use.
6893
 *
6894
 * Each of the input parameter types will be converted to a DataTables settings
6895
 * object where possible.
6896
 *
6897
 * @param  {string|node|jQuery|object} mixed DataTable identifier. Can be one
6898
 *   of:
6899
 *
6900
 *   * `string` - jQuery selector. Any DataTables' matching the given selector
6901
 *     with be found and used.
6902
 *   * `node` - `TABLE` node which has already been formed into a DataTable.
6903
 *   * `jQuery` - A jQuery object of `TABLE` nodes.
6904
 *   * `object` - DataTables settings object
6905
 *   * `DataTables.Api` - API instance
6906
 * @return {array|null} Matching DataTables settings objects. `null` or
6907
 *   `undefined` is returned if no matching DataTable is found.
6908
 * @ignore
6909
 */
6910
var _toSettings = function ( mixed )
6911
{
6912
	var idx, jq;
6913
	var settings = DataTable.settings;
6914
	var tables = $.map( settings, function (el, i) {
6915
		return el.nTable;
6916
	} );
6917

6918
	if ( ! mixed ) {
6919
		return [];
6920
	}
6921
	else if ( mixed.nTable && mixed.oApi ) {
6922
		// DataTables settings object
6923
		return [ mixed ];
6924
	}
6925
	else if ( mixed.nodeName && mixed.nodeName.toLowerCase() === 'table' ) {
6926
		// Table node
6927
		idx = $.inArray( mixed, tables );
6928
		return idx !== -1 ? [ settings[idx] ] : null;
6929
	}
6930
	else if ( mixed && typeof mixed.settings === 'function' ) {
6931
		return mixed.settings().toArray();
6932
	}
6933
	else if ( typeof mixed === 'string' ) {
6934
		// jQuery selector
6935
		jq = $(mixed);
6936
	}
6937
	else if ( mixed instanceof $ ) {
6938
		// jQuery object (also DataTables instance)
6939
		jq = mixed;
6940
	}
6941

6942
	if ( jq ) {
6943
		return jq.map( function(i) {
6944
			idx = $.inArray( this, tables );
6945
			return idx !== -1 ? settings[idx] : null;
6946
		} ).toArray();
6947
	}
6948
};
6949

6950

6951
/**
6952
 * DataTables API class - used to control and interface with  one or more
6953
 * DataTables enhanced tables.
6954
 *
6955
 * The API class is heavily based on jQuery, presenting a chainable interface
6956
 * that you can use to interact with tables. Each instance of the API class has
6957
 * a "context" - i.e. the tables that it will operate on. This could be a single
6958
 * table, all tables on a page or a sub-set thereof.
6959
 *
6960
 * Additionally the API is designed to allow you to easily work with the data in
6961
 * the tables, retrieving and manipulating it as required. This is done by
6962
 * presenting the API class as an array like interface. The contents of the
6963
 * array depend upon the actions requested by each method (for example
6964
 * `rows().nodes()` will return an array of nodes, while `rows().data()` will
6965
 * return an array of objects or arrays depending upon your table's
6966
 * configuration). The API object has a number of array like methods (`push`,
6967
 * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`,
6968
 * `unique` etc) to assist your working with the data held in a table.
6969
 *
6970
 * Most methods (those which return an Api instance) are chainable, which means
6971
 * the return from a method call also has all of the methods available that the
6972
 * top level object had. For example, these two calls are equivalent:
6973
 *
6974
 *     // Not chained
6975
 *     api.row.add( {...} );
6976
 *     api.draw();
6977
 *
6978
 *     // Chained
6979
 *     api.row.add( {...} ).draw();
6980
 *
6981
 * @class DataTable.Api
6982
 * @param {array|object|string|jQuery} context DataTable identifier. This is
6983
 *   used to define which DataTables enhanced tables this API will operate on.
6984
 *   Can be one of:
6985
 *
6986
 *   * `string` - jQuery selector. Any DataTables' matching the given selector
6987
 *     with be found and used.
6988
 *   * `node` - `TABLE` node which has already been formed into a DataTable.
6989
 *   * `jQuery` - A jQuery object of `TABLE` nodes.
6990
 *   * `object` - DataTables settings object
6991
 * @param {array} [data] Data to initialise the Api instance with.
6992
 *
6993
 * @example
6994
 *   // Direct initialisation during DataTables construction
6995
 *   var api = $('#example').DataTable();
6996
 *
6997
 * @example
6998
 *   // Initialisation using a DataTables jQuery object
6999
 *   var api = $('#example').dataTable().api();
7000
 *
7001
 * @example
7002
 *   // Initialisation as a constructor
7003
 *   var api = new $.fn.DataTable.Api( 'table.dataTable' );
7004
 */
7005
_Api = function ( context, data )
7006
{
7007
	if ( ! (this instanceof _Api) ) {
7008
		return new _Api( context, data );
7009
	}
7010

7011
	var settings = [];
7012
	var ctxSettings = function ( o ) {
7013
		var a = _toSettings( o );
7014
		if ( a ) {
7015
			settings.push.apply( settings, a );
7016
		}
7017
	};
7018

7019
	if ( Array.isArray( context ) ) {
7020
		for ( var i=0, ien=context.length ; i<ien ; i++ ) {
7021
			ctxSettings( context[i] );
7022
		}
7023
	}
7024
	else {
7025
		ctxSettings( context );
7026
	}
7027

7028
	// Remove duplicates
7029
	this.context = _unique( settings );
7030

7031
	// Initial data
7032
	if ( data ) {
7033
		$.merge( this, data );
7034
	}
7035

7036
	// selector
7037
	this.selector = {
7038
		rows: null,
7039
		cols: null,
7040
		opts: null
7041
	};
7042

7043
	_Api.extend( this, this, __apiStruct );
7044
};
7045

7046
DataTable.Api = _Api;
7047

7048
// Don't destroy the existing prototype, just extend it. Required for jQuery 2's
7049
// isPlainObject.
7050
$.extend( _Api.prototype, {
7051
	any: function ()
7052
	{
7053
		return this.count() !== 0;
7054
	},
7055

7056

7057
	concat:  __arrayProto.concat,
7058

7059

7060
	context: [], // array of table settings objects
7061

7062

7063
	count: function ()
7064
	{
7065
		return this.flatten().length;
7066
	},
7067

7068

7069
	each: function ( fn )
7070
	{
7071
		for ( var i=0, ien=this.length ; i<ien; i++ ) {
7072
			fn.call( this, this[i], i, this );
7073
		}
7074

7075
		return this;
7076
	},
7077

7078

7079
	eq: function ( idx )
7080
	{
7081
		var ctx = this.context;
7082

7083
		return ctx.length > idx ?
7084
			new _Api( ctx[idx], this[idx] ) :
7085
			null;
7086
	},
7087

7088

7089
	filter: function ( fn )
7090
	{
7091
		var a = [];
7092

7093
		if ( __arrayProto.filter ) {
7094
			a = __arrayProto.filter.call( this, fn, this );
7095
		}
7096
		else {
7097
			// Compatibility for browsers without EMCA-252-5 (JS 1.6)
7098
			for ( var i=0, ien=this.length ; i<ien ; i++ ) {
7099
				if ( fn.call( this, this[i], i, this ) ) {
7100
					a.push( this[i] );
7101
				}
7102
			}
7103
		}
7104

7105
		return new _Api( this.context, a );
7106
	},
7107

7108

7109
	flatten: function ()
7110
	{
7111
		var a = [];
7112
		return new _Api( this.context, a.concat.apply( a, this.toArray() ) );
7113
	},
7114

7115

7116
	join:    __arrayProto.join,
7117

7118

7119
	indexOf: __arrayProto.indexOf || function (obj, start)
7120
	{
7121
		for ( var i=(start || 0), ien=this.length ; i<ien ; i++ ) {
7122
			if ( this[i] === obj ) {
7123
				return i;
7124
			}
7125
		}
7126
		return -1;
7127
	},
7128

7129
	iterator: function ( flatten, type, fn, alwaysNew ) {
7130
		var
7131
			a = [], ret,
7132
			i, ien, j, jen,
7133
			context = this.context,
7134
			rows, items, item,
7135
			selector = this.selector;
7136

7137
		// Argument shifting
7138
		if ( typeof flatten === 'string' ) {
7139
			alwaysNew = fn;
7140
			fn = type;
7141
			type = flatten;
7142
			flatten = false;
7143
		}
7144

7145
		for ( i=0, ien=context.length ; i<ien ; i++ ) {
7146
			var apiInst = new _Api( context[i] );
7147

7148
			if ( type === 'table' ) {
7149
				ret = fn.call( apiInst, context[i], i );
7150

7151
				if ( ret !== undefined ) {
7152
					a.push( ret );
7153
				}
7154
			}
7155
			else if ( type === 'columns' || type === 'rows' ) {
7156
				// this has same length as context - one entry for each table
7157
				ret = fn.call( apiInst, context[i], this[i], i );
7158

7159
				if ( ret !== undefined ) {
7160
					a.push( ret );
7161
				}
7162
			}
7163
			else if ( type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell' ) {
7164
				// columns and rows share the same structure.
7165
				// 'this' is an array of column indexes for each context
7166
				items = this[i];
7167

7168
				if ( type === 'column-rows' ) {
7169
					rows = _selector_row_indexes( context[i], selector.opts );
7170
				}
7171

7172
				for ( j=0, jen=items.length ; j<jen ; j++ ) {
7173
					item = items[j];
7174

7175
					if ( type === 'cell' ) {
7176
						ret = fn.call( apiInst, context[i], item.row, item.column, i, j );
7177
					}
7178
					else {
7179
						ret = fn.call( apiInst, context[i], item, i, j, rows );
7180
					}
7181

7182
					if ( ret !== undefined ) {
7183
						a.push( ret );
7184
					}
7185
				}
7186
			}
7187
		}
7188

7189
		if ( a.length || alwaysNew ) {
7190
			var api = new _Api( context, flatten ? a.concat.apply( [], a ) : a );
7191
			var apiSelector = api.selector;
7192
			apiSelector.rows = selector.rows;
7193
			apiSelector.cols = selector.cols;
7194
			apiSelector.opts = selector.opts;
7195
			return api;
7196
		}
7197
		return this;
7198
	},
7199

7200

7201
	lastIndexOf: __arrayProto.lastIndexOf || function (obj, start)
7202
	{
7203
		// Bit cheeky...
7204
		return this.indexOf.apply( this.toArray.reverse(), arguments );
7205
	},
7206

7207

7208
	length:  0,
7209

7210

7211
	map: function ( fn )
7212
	{
7213
		var a = [];
7214

7215
		if ( __arrayProto.map ) {
7216
			a = __arrayProto.map.call( this, fn, this );
7217
		}
7218
		else {
7219
			// Compatibility for browsers without EMCA-252-5 (JS 1.6)
7220
			for ( var i=0, ien=this.length ; i<ien ; i++ ) {
7221
				a.push( fn.call( this, this[i], i ) );
7222
			}
7223
		}
7224

7225
		return new _Api( this.context, a );
7226
	},
7227

7228

7229
	pluck: function ( prop )
7230
	{
7231
		var fn = DataTable.util.get(prop);
7232

7233
		return this.map( function ( el ) {
7234
			return fn(el);
7235
		} );
7236
	},
7237

7238
	pop:     __arrayProto.pop,
7239

7240

7241
	push:    __arrayProto.push,
7242

7243

7244
	// Does not return an API instance
7245
	reduce: __arrayProto.reduce || function ( fn, init )
7246
	{
7247
		return _fnReduce( this, fn, init, 0, this.length, 1 );
7248
	},
7249

7250

7251
	reduceRight: __arrayProto.reduceRight || function ( fn, init )
7252
	{
7253
		return _fnReduce( this, fn, init, this.length-1, -1, -1 );
7254
	},
7255

7256

7257
	reverse: __arrayProto.reverse,
7258

7259

7260
	// Object with rows, columns and opts
7261
	selector: null,
7262

7263

7264
	shift:   __arrayProto.shift,
7265

7266

7267
	slice: function () {
7268
		return new _Api( this.context, this );
7269
	},
7270

7271

7272
	sort:    __arrayProto.sort, // ? name - order?
7273

7274

7275
	splice:  __arrayProto.splice,
7276

7277

7278
	toArray: function ()
7279
	{
7280
		return __arrayProto.slice.call( this );
7281
	},
7282

7283

7284
	to$: function ()
7285
	{
7286
		return $( this );
7287
	},
7288

7289

7290
	toJQuery: function ()
7291
	{
7292
		return $( this );
7293
	},
7294

7295

7296
	unique: function ()
7297
	{
7298
		return new _Api( this.context, _unique(this) );
7299
	},
7300

7301

7302
	unshift: __arrayProto.unshift
7303
} );
7304

7305

7306
_Api.extend = function ( scope, obj, ext )
7307
{
7308
	// Only extend API instances and static properties of the API
7309
	if ( ! ext.length || ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) {
7310
		return;
7311
	}
7312

7313
	var
7314
		i, ien,
7315
		struct,
7316
		methodScoping = function ( scope, fn, struc ) {
7317
			return function () {
7318
				var ret = fn.apply( scope, arguments );
7319

7320
				// Method extension
7321
				_Api.extend( ret, ret, struc.methodExt );
7322
				return ret;
7323
			};
7324
		};
7325

7326
	for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7327
		struct = ext[i];
7328

7329
		// Value
7330
		obj[ struct.name ] = struct.type === 'function' ?
7331
			methodScoping( scope, struct.val, struct ) :
7332
			struct.type === 'object' ?
7333
				{} :
7334
				struct.val;
7335

7336
		obj[ struct.name ].__dt_wrapper = true;
7337

7338
		// Property extension
7339
		_Api.extend( scope, obj[ struct.name ], struct.propExt );
7340
	}
7341
};
7342

7343

7344
// @todo - Is there need for an augment function?
7345
// _Api.augment = function ( inst, name )
7346
// {
7347
// 	// Find src object in the structure from the name
7348
// 	var parts = name.split('.');
7349

7350
// 	_Api.extend( inst, obj );
7351
// };
7352

7353

7354
//     [
7355
//       {
7356
//         name:      'data'                -- string   - Property name
7357
//         val:       function () {},       -- function - Api method (or undefined if just an object
7358
//         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
7359
//         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
7360
//       },
7361
//       {
7362
//         name:     'row'
7363
//         val:       {},
7364
//         methodExt: [ ... ],
7365
//         propExt:   [
7366
//           {
7367
//             name:      'data'
7368
//             val:       function () {},
7369
//             methodExt: [ ... ],
7370
//             propExt:   [ ... ]
7371
//           },
7372
//           ...
7373
//         ]
7374
//       }
7375
//     ]
7376

7377
_Api.register = _api_register = function ( name, val )
7378
{
7379
	if ( Array.isArray( name ) ) {
7380
		for ( var j=0, jen=name.length ; j<jen ; j++ ) {
7381
			_Api.register( name[j], val );
7382
		}
7383
		return;
7384
	}
7385

7386
	var
7387
		i, ien,
7388
		heir = name.split('.'),
7389
		struct = __apiStruct,
7390
		key, method;
7391

7392
	var find = function ( src, name ) {
7393
		for ( var i=0, ien=src.length ; i<ien ; i++ ) {
7394
			if ( src[i].name === name ) {
7395
				return src[i];
7396
			}
7397
		}
7398
		return null;
7399
	};
7400

7401
	for ( i=0, ien=heir.length ; i<ien ; i++ ) {
7402
		method = heir[i].indexOf('()') !== -1;
7403
		key = method ?
7404
			heir[i].replace('()', '') :
7405
			heir[i];
7406

7407
		var src = find( struct, key );
7408
		if ( ! src ) {
7409
			src = {
7410
				name:      key,
7411
				val:       {},
7412
				methodExt: [],
7413
				propExt:   [],
7414
				type:      'object'
7415
			};
7416
			struct.push( src );
7417
		}
7418

7419
		if ( i === ien-1 ) {
7420
			src.val = val;
7421
			src.type = typeof val === 'function' ?
7422
				'function' :
7423
				$.isPlainObject( val ) ?
7424
					'object' :
7425
					'other';
7426
		}
7427
		else {
7428
			struct = method ?
7429
				src.methodExt :
7430
				src.propExt;
7431
		}
7432
	}
7433
};
7434

7435
_Api.registerPlural = _api_registerPlural = function ( pluralName, singularName, val ) {
7436
	_Api.register( pluralName, val );
7437

7438
	_Api.register( singularName, function () {
7439
		var ret = val.apply( this, arguments );
7440

7441
		if ( ret === this ) {
7442
			// Returned item is the API instance that was passed in, return it
7443
			return this;
7444
		}
7445
		else if ( ret instanceof _Api ) {
7446
			// New API instance returned, want the value from the first item
7447
			// in the returned array for the singular result.
7448
			return ret.length ?
7449
				Array.isArray( ret[0] ) ?
7450
					new _Api( ret.context, ret[0] ) : // Array results are 'enhanced'
7451
					ret[0] :
7452
				undefined;
7453
		}
7454

7455
		// Non-API return - just fire it back
7456
		return ret;
7457
	} );
7458
};
7459

7460

7461
/**
7462
 * Selector for HTML tables. Apply the given selector to the give array of
7463
 * DataTables settings objects.
7464
 *
7465
 * @param {string|integer} [selector] jQuery selector string or integer
7466
 * @param  {array} Array of DataTables settings objects to be filtered
7467
 * @return {array}
7468
 * @ignore
7469
 */
7470
var __table_selector = function ( selector, a )
7471
{
7472
	if ( Array.isArray(selector) ) {
7473
		return $.map( selector, function (item) {
7474
			return __table_selector(item, a);
7475
		} );
7476
	}
7477

7478
	// Integer is used to pick out a table by index
7479
	if ( typeof selector === 'number' ) {
7480
		return [ a[ selector ] ];
7481
	}
7482

7483
	// Perform a jQuery selector on the table nodes
7484
	var nodes = $.map( a, function (el, i) {
7485
		return el.nTable;
7486
	} );
7487

7488
	return $(nodes)
7489
		.filter( selector )
7490
		.map( function (i) {
7491
			// Need to translate back from the table node to the settings
7492
			var idx = $.inArray( this, nodes );
7493
			return a[ idx ];
7494
		} )
7495
		.toArray();
7496
};
7497

7498

7499

7500
/**
7501
 * Context selector for the API's context (i.e. the tables the API instance
7502
 * refers to.
7503
 *
7504
 * @name    DataTable.Api#tables
7505
 * @param {string|integer} [selector] Selector to pick which tables the iterator
7506
 *   should operate on. If not given, all tables in the current context are
7507
 *   used. This can be given as a jQuery selector (for example `':gt(0)'`) to
7508
 *   select multiple tables or as an integer to select a single table.
7509
 * @returns {DataTable.Api} Returns a new API instance if a selector is given.
7510
 */
7511
_api_register( 'tables()', function ( selector ) {
7512
	// A new instance is created if there was a selector specified
7513
	return selector !== undefined && selector !== null ?
7514
		new _Api( __table_selector( selector, this.context ) ) :
7515
		this;
7516
} );
7517

7518

7519
_api_register( 'table()', function ( selector ) {
7520
	var tables = this.tables( selector );
7521
	var ctx = tables.context;
7522

7523
	// Truncate to the first matched table
7524
	return ctx.length ?
7525
		new _Api( ctx[0] ) :
7526
		tables;
7527
} );
7528

7529

7530
_api_registerPlural( 'tables().nodes()', 'table().node()' , function () {
7531
	return this.iterator( 'table', function ( ctx ) {
7532
		return ctx.nTable;
7533
	}, 1 );
7534
} );
7535

7536

7537
_api_registerPlural( 'tables().body()', 'table().body()' , function () {
7538
	return this.iterator( 'table', function ( ctx ) {
7539
		return ctx.nTBody;
7540
	}, 1 );
7541
} );
7542

7543

7544
_api_registerPlural( 'tables().header()', 'table().header()' , function () {
7545
	return this.iterator( 'table', function ( ctx ) {
7546
		return ctx.nTHead;
7547
	}, 1 );
7548
} );
7549

7550

7551
_api_registerPlural( 'tables().footer()', 'table().footer()' , function () {
7552
	return this.iterator( 'table', function ( ctx ) {
7553
		return ctx.nTFoot;
7554
	}, 1 );
7555
} );
7556

7557

7558
_api_registerPlural( 'tables().containers()', 'table().container()' , function () {
7559
	return this.iterator( 'table', function ( ctx ) {
7560
		return ctx.nTableWrapper;
7561
	}, 1 );
7562
} );
7563

7564

7565

7566
/**
7567
 * Redraw the tables in the current context.
7568
 */
7569
_api_register( 'draw()', function ( paging ) {
7570
	return this.iterator( 'table', function ( settings ) {
7571
		if ( paging === 'page' ) {
7572
			_fnDraw( settings );
7573
		}
7574
		else {
7575
			if ( typeof paging === 'string' ) {
7576
				paging = paging === 'full-hold' ?
7577
					false :
7578
					true;
7579
			}
7580

7581
			_fnReDraw( settings, paging===false );
7582
		}
7583
	} );
7584
} );
7585

7586

7587

7588
/**
7589
 * Get the current page index.
7590
 *
7591
 * @return {integer} Current page index (zero based)
7592
 *//**
7593
 * Set the current page.
7594
 *
7595
 * Note that if you attempt to show a page which does not exist, DataTables will
7596
 * not throw an error, but rather reset the paging.
7597
 *
7598
 * @param {integer|string} action The paging action to take. This can be one of:
7599
 *  * `integer` - The page index to jump to
7600
 *  * `string` - An action to take:
7601
 *    * `first` - Jump to first page.
7602
 *    * `next` - Jump to the next page
7603
 *    * `previous` - Jump to previous page
7604
 *    * `last` - Jump to the last page.
7605
 * @returns {DataTables.Api} this
7606
 */
7607
_api_register( 'page()', function ( action ) {
7608
	if ( action === undefined ) {
7609
		return this.page.info().page; // not an expensive call
7610
	}
7611

7612
	// else, have an action to take on all tables
7613
	return this.iterator( 'table', function ( settings ) {
7614
		_fnPageChange( settings, action );
7615
	} );
7616
} );
7617

7618

7619
/**
7620
 * Paging information for the first table in the current context.
7621
 *
7622
 * If you require paging information for another table, use the `table()` method
7623
 * with a suitable selector.
7624
 *
7625
 * @return {object} Object with the following properties set:
7626
 *  * `page` - Current page index (zero based - i.e. the first page is `0`)
7627
 *  * `pages` - Total number of pages
7628
 *  * `start` - Display index for the first record shown on the current page
7629
 *  * `end` - Display index for the last record shown on the current page
7630
 *  * `length` - Display length (number of records). Note that generally `start
7631
 *    + length = end`, but this is not always true, for example if there are
7632
 *    only 2 records to show on the final page, with a length of 10.
7633
 *  * `recordsTotal` - Full data set length
7634
 *  * `recordsDisplay` - Data set length once the current filtering criterion
7635
 *    are applied.
7636
 */
7637
_api_register( 'page.info()', function ( action ) {
7638
	if ( this.context.length === 0 ) {
7639
		return undefined;
7640
	}
7641

7642
	var
7643
		settings   = this.context[0],
7644
		start      = settings._iDisplayStart,
7645
		len        = settings.oFeatures.bPaginate ? settings._iDisplayLength : -1,
7646
		visRecords = settings.fnRecordsDisplay(),
7647
		all        = len === -1;
7648

7649
	return {
7650
		"page":           all ? 0 : Math.floor( start / len ),
7651
		"pages":          all ? 1 : Math.ceil( visRecords / len ),
7652
		"start":          start,
7653
		"end":            settings.fnDisplayEnd(),
7654
		"length":         len,
7655
		"recordsTotal":   settings.fnRecordsTotal(),
7656
		"recordsDisplay": visRecords,
7657
		"serverSide":     _fnDataSource( settings ) === 'ssp'
7658
	};
7659
} );
7660

7661

7662
/**
7663
 * Get the current page length.
7664
 *
7665
 * @return {integer} Current page length. Note `-1` indicates that all records
7666
 *   are to be shown.
7667
 *//**
7668
 * Set the current page length.
7669
 *
7670
 * @param {integer} Page length to set. Use `-1` to show all records.
7671
 * @returns {DataTables.Api} this
7672
 */
7673
_api_register( 'page.len()', function ( len ) {
7674
	// Note that we can't call this function 'length()' because `length`
7675
	// is a Javascript property of functions which defines how many arguments
7676
	// the function expects.
7677
	if ( len === undefined ) {
7678
		return this.context.length !== 0 ?
7679
			this.context[0]._iDisplayLength :
7680
			undefined;
7681
	}
7682

7683
	// else, set the page length
7684
	return this.iterator( 'table', function ( settings ) {
7685
		_fnLengthChange( settings, len );
7686
	} );
7687
} );
7688

7689

7690

7691
var __reload = function ( settings, holdPosition, callback ) {
7692
	// Use the draw event to trigger a callback
7693
	if ( callback ) {
7694
		var api = new _Api( settings );
7695

7696
		api.one( 'draw', function () {
7697
			callback( api.ajax.json() );
7698
		} );
7699
	}
7700

7701
	if ( _fnDataSource( settings ) == 'ssp' ) {
7702
		_fnReDraw( settings, holdPosition );
7703
	}
7704
	else {
7705
		_fnProcessingDisplay( settings, true );
7706

7707
		// Cancel an existing request
7708
		var xhr = settings.jqXHR;
7709
		if ( xhr && xhr.readyState !== 4 ) {
7710
			xhr.abort();
7711
		}
7712

7713
		// Trigger xhr
7714
		_fnBuildAjax( settings, [], function( json ) {
7715
			_fnClearTable( settings );
7716

7717
			var data = _fnAjaxDataSrc( settings, json );
7718
			for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7719
				_fnAddData( settings, data[i] );
7720
			}
7721

7722
			_fnReDraw( settings, holdPosition );
7723
			_fnProcessingDisplay( settings, false );
7724
		} );
7725
	}
7726
};
7727

7728

7729
/**
7730
 * Get the JSON response from the last Ajax request that DataTables made to the
7731
 * server. Note that this returns the JSON from the first table in the current
7732
 * context.
7733
 *
7734
 * @return {object} JSON received from the server.
7735
 */
7736
_api_register( 'ajax.json()', function () {
7737
	var ctx = this.context;
7738

7739
	if ( ctx.length > 0 ) {
7740
		return ctx[0].json;
7741
	}
7742

7743
	// else return undefined;
7744
} );
7745

7746

7747
/**
7748
 * Get the data submitted in the last Ajax request
7749
 */
7750
_api_register( 'ajax.params()', function () {
7751
	var ctx = this.context;
7752

7753
	if ( ctx.length > 0 ) {
7754
		return ctx[0].oAjaxData;
7755
	}
7756

7757
	// else return undefined;
7758
} );
7759

7760

7761
/**
7762
 * Reload tables from the Ajax data source. Note that this function will
7763
 * automatically re-draw the table when the remote data has been loaded.
7764
 *
7765
 * @param {boolean} [reset=true] Reset (default) or hold the current paging
7766
 *   position. A full re-sort and re-filter is performed when this method is
7767
 *   called, which is why the pagination reset is the default action.
7768
 * @returns {DataTables.Api} this
7769
 */
7770
_api_register( 'ajax.reload()', function ( callback, resetPaging ) {
7771
	return this.iterator( 'table', function (settings) {
7772
		__reload( settings, resetPaging===false, callback );
7773
	} );
7774
} );
7775

7776

7777
/**
7778
 * Get the current Ajax URL. Note that this returns the URL from the first
7779
 * table in the current context.
7780
 *
7781
 * @return {string} Current Ajax source URL
7782
 *//**
7783
 * Set the Ajax URL. Note that this will set the URL for all tables in the
7784
 * current context.
7785
 *
7786
 * @param {string} url URL to set.
7787
 * @returns {DataTables.Api} this
7788
 */
7789
_api_register( 'ajax.url()', function ( url ) {
7790
	var ctx = this.context;
7791

7792
	if ( url === undefined ) {
7793
		// get
7794
		if ( ctx.length === 0 ) {
7795
			return undefined;
7796
		}
7797
		ctx = ctx[0];
7798

7799
		return ctx.ajax ?
7800
			$.isPlainObject( ctx.ajax ) ?
7801
				ctx.ajax.url :
7802
				ctx.ajax :
7803
			ctx.sAjaxSource;
7804
	}
7805

7806
	// set
7807
	return this.iterator( 'table', function ( settings ) {
7808
		if ( $.isPlainObject( settings.ajax ) ) {
7809
			settings.ajax.url = url;
7810
		}
7811
		else {
7812
			settings.ajax = url;
7813
		}
7814
		// No need to consider sAjaxSource here since DataTables gives priority
7815
		// to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any
7816
		// value of `sAjaxSource` redundant.
7817
	} );
7818
} );
7819

7820

7821
/**
7822
 * Load data from the newly set Ajax URL. Note that this method is only
7823
 * available when `ajax.url()` is used to set a URL. Additionally, this method
7824
 * has the same effect as calling `ajax.reload()` but is provided for
7825
 * convenience when setting a new URL. Like `ajax.reload()` it will
7826
 * automatically redraw the table once the remote data has been loaded.
7827
 *
7828
 * @returns {DataTables.Api} this
7829
 */
7830
_api_register( 'ajax.url().load()', function ( callback, resetPaging ) {
7831
	// Same as a reload, but makes sense to present it for easy access after a
7832
	// url change
7833
	return this.iterator( 'table', function ( ctx ) {
7834
		__reload( ctx, resetPaging===false, callback );
7835
	} );
7836
} );
7837

7838

7839

7840

7841
var _selector_run = function ( type, selector, selectFn, settings, opts )
7842
{
7843
	var
7844
		out = [], res,
7845
		a, i, ien, j, jen,
7846
		selectorType = typeof selector;
7847

7848
	// Can't just check for isArray here, as an API or jQuery instance might be
7849
	// given with their array like look
7850
	if ( ! selector || selectorType === 'string' || selectorType === 'function' || selector.length === undefined ) {
7851
		selector = [ selector ];
7852
	}
7853

7854
	for ( i=0, ien=selector.length ; i<ien ; i++ ) {
7855
		// Only split on simple strings - complex expressions will be jQuery selectors
7856
		a = selector[i] && selector[i].split && ! selector[i].match(/[\[\(:]/) ?
7857
			selector[i].split(',') :
7858
			[ selector[i] ];
7859

7860
		for ( j=0, jen=a.length ; j<jen ; j++ ) {
7861
			res = selectFn( typeof a[j] === 'string' ? (a[j]).trim() : a[j] );
7862

7863
			if ( res && res.length ) {
7864
				out = out.concat( res );
7865
			}
7866
		}
7867
	}
7868

7869
	// selector extensions
7870
	var ext = _ext.selector[ type ];
7871
	if ( ext.length ) {
7872
		for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7873
			out = ext[i]( settings, opts, out );
7874
		}
7875
	}
7876

7877
	return _unique( out );
7878
};
7879

7880

7881
var _selector_opts = function ( opts )
7882
{
7883
	if ( ! opts ) {
7884
		opts = {};
7885
	}
7886

7887
	// Backwards compatibility for 1.9- which used the terminology filter rather
7888
	// than search
7889
	if ( opts.filter && opts.search === undefined ) {
7890
		opts.search = opts.filter;
7891
	}
7892

7893
	return $.extend( {
7894
		search: 'none',
7895
		order: 'current',
7896
		page: 'all'
7897
	}, opts );
7898
};
7899

7900

7901
var _selector_first = function ( inst )
7902
{
7903
	// Reduce the API instance to the first item found
7904
	for ( var i=0, ien=inst.length ; i<ien ; i++ ) {
7905
		if ( inst[i].length > 0 ) {
7906
			// Assign the first element to the first item in the instance
7907
			// and truncate the instance and context
7908
			inst[0] = inst[i];
7909
			inst[0].length = 1;
7910
			inst.length = 1;
7911
			inst.context = [ inst.context[i] ];
7912

7913
			return inst;
7914
		}
7915
	}
7916

7917
	// Not found - return an empty instance
7918
	inst.length = 0;
7919
	return inst;
7920
};
7921

7922

7923
var _selector_row_indexes = function ( settings, opts )
7924
{
7925
	var
7926
		i, ien, tmp, a=[],
7927
		displayFiltered = settings.aiDisplay,
7928
		displayMaster = settings.aiDisplayMaster;
7929

7930
	var
7931
		search = opts.search,  // none, applied, removed
7932
		order  = opts.order,   // applied, current, index (original - compatibility with 1.9)
7933
		page   = opts.page;    // all, current
7934

7935
	if ( _fnDataSource( settings ) == 'ssp' ) {
7936
		// In server-side processing mode, most options are irrelevant since
7937
		// rows not shown don't exist and the index order is the applied order
7938
		// Removed is a special case - for consistency just return an empty
7939
		// array
7940
		return search === 'removed' ?
7941
			[] :
7942
			_range( 0, displayMaster.length );
7943
	}
7944
	else if ( page == 'current' ) {
7945
		// Current page implies that order=current and filter=applied, since it is
7946
		// fairly senseless otherwise, regardless of what order and search actually
7947
		// are
7948
		for ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i<ien ; i++ ) {
7949
			a.push( displayFiltered[i] );
7950
		}
7951
	}
7952
	else if ( order == 'current' || order == 'applied' ) {
7953
		if ( search == 'none') {
7954
			a = displayMaster.slice();
7955
		}
7956
		else if ( search == 'applied' ) {
7957
			a = displayFiltered.slice();
7958
		}
7959
		else if ( search == 'removed' ) {
7960
			// O(n+m) solution by creating a hash map
7961
			var displayFilteredMap = {};
7962

7963
			for ( var i=0, ien=displayFiltered.length ; i<ien ; i++ ) {
7964
				displayFilteredMap[displayFiltered[i]] = null;
7965
			}
7966

7967
			a = $.map( displayMaster, function (el) {
7968
				return ! displayFilteredMap.hasOwnProperty(el) ?
7969
					el :
7970
					null;
7971
			} );
7972
		}
7973
	}
7974
	else if ( order == 'index' || order == 'original' ) {
7975
		for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
7976
			if ( search == 'none' ) {
7977
				a.push( i );
7978
			}
7979
			else { // applied | removed
7980
				tmp = $.inArray( i, displayFiltered );
7981

7982
				if ((tmp === -1 && search == 'removed') ||
7983
					(tmp >= 0   && search == 'applied') )
7984
				{
7985
					a.push( i );
7986
				}
7987
			}
7988
		}
7989
	}
7990

7991
	return a;
7992
};
7993

7994

7995
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
7996
 * Rows
7997
 *
7998
 * {}          - no selector - use all available rows
7999
 * {integer}   - row aoData index
8000
 * {node}      - TR node
8001
 * {string}    - jQuery selector to apply to the TR elements
8002
 * {array}     - jQuery array of nodes, or simply an array of TR nodes
8003
 *
8004
 */
8005
var __row_selector = function ( settings, selector, opts )
8006
{
8007
	var rows;
8008
	var run = function ( sel ) {
8009
		var selInt = _intVal( sel );
8010
		var i, ien;
8011
		var aoData = settings.aoData;
8012

8013
		// Short cut - selector is a number and no options provided (default is
8014
		// all records, so no need to check if the index is in there, since it
8015
		// must be - dev error if the index doesn't exist).
8016
		if ( selInt !== null && ! opts ) {
8017
			return [ selInt ];
8018
		}
8019

8020
		if ( ! rows ) {
8021
			rows = _selector_row_indexes( settings, opts );
8022
		}
8023

8024
		if ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) {
8025
			// Selector - integer
8026
			return [ selInt ];
8027
		}
8028
		else if ( sel === null || sel === undefined || sel === '' ) {
8029
			// Selector - none
8030
			return rows;
8031
		}
8032

8033
		// Selector - function
8034
		if ( typeof sel === 'function' ) {
8035
			return $.map( rows, function (idx) {
8036
				var row = aoData[ idx ];
8037
				return sel( idx, row._aData, row.nTr ) ? idx : null;
8038
			} );
8039
		}
8040

8041
		// Selector - node
8042
		if ( sel.nodeName ) {
8043
			var rowIdx = sel._DT_RowIndex;  // Property added by DT for fast lookup
8044
			var cellIdx = sel._DT_CellIndex;
8045

8046
			if ( rowIdx !== undefined ) {
8047
				// Make sure that the row is actually still present in the table
8048
				return aoData[ rowIdx ] && aoData[ rowIdx ].nTr === sel ?
8049
					[ rowIdx ] :
8050
					[];
8051
			}
8052
			else if ( cellIdx ) {
8053
				return aoData[ cellIdx.row ] && aoData[ cellIdx.row ].nTr === sel.parentNode ?
8054
					[ cellIdx.row ] :
8055
					[];
8056
			}
8057
			else {
8058
				var host = $(sel).closest('*[data-dt-row]');
8059
				return host.length ?
8060
					[ host.data('dt-row') ] :
8061
					[];
8062
			}
8063
		}
8064

8065
		// ID selector. Want to always be able to select rows by id, regardless
8066
		// of if the tr element has been created or not, so can't rely upon
8067
		// jQuery here - hence a custom implementation. This does not match
8068
		// Sizzle's fast selector or HTML4 - in HTML5 the ID can be anything,
8069
		// but to select it using a CSS selector engine (like Sizzle or
8070
		// querySelect) it would need to need to be escaped for some characters.
8071
		// DataTables simplifies this for row selectors since you can select
8072
		// only a row. A # indicates an id any anything that follows is the id -
8073
		// unescaped.
8074
		if ( typeof sel === 'string' && sel.charAt(0) === '#' ) {
8075
			// get row index from id
8076
			var rowObj = settings.aIds[ sel.replace( /^#/, '' ) ];
8077
			if ( rowObj !== undefined ) {
8078
				return [ rowObj.idx ];
8079
			}
8080

8081
			// need to fall through to jQuery in case there is DOM id that
8082
			// matches
8083
		}
8084
		
8085
		// Get nodes in the order from the `rows` array with null values removed
8086
		var nodes = _removeEmpty(
8087
			_pluck_order( settings.aoData, rows, 'nTr' )
8088
		);
8089

8090
		// Selector - jQuery selector string, array of nodes or jQuery object/
8091
		// As jQuery's .filter() allows jQuery objects to be passed in filter,
8092
		// it also allows arrays, so this will cope with all three options
8093
		return $(nodes)
8094
			.filter( sel )
8095
			.map( function () {
8096
				return this._DT_RowIndex;
8097
			} )
8098
			.toArray();
8099
	};
8100

8101
	return _selector_run( 'row', selector, run, settings, opts );
8102
};
8103

8104

8105
_api_register( 'rows()', function ( selector, opts ) {
8106
	// argument shifting
8107
	if ( selector === undefined ) {
8108
		selector = '';
8109
	}
8110
	else if ( $.isPlainObject( selector ) ) {
8111
		opts = selector;
8112
		selector = '';
8113
	}
8114

8115
	opts = _selector_opts( opts );
8116

8117
	var inst = this.iterator( 'table', function ( settings ) {
8118
		return __row_selector( settings, selector, opts );
8119
	}, 1 );
8120

8121
	// Want argument shifting here and in __row_selector?
8122
	inst.selector.rows = selector;
8123
	inst.selector.opts = opts;
8124

8125
	return inst;
8126
} );
8127

8128
_api_register( 'rows().nodes()', function () {
8129
	return this.iterator( 'row', function ( settings, row ) {
8130
		return settings.aoData[ row ].nTr || undefined;
8131
	}, 1 );
8132
} );
8133

8134
_api_register( 'rows().data()', function () {
8135
	return this.iterator( true, 'rows', function ( settings, rows ) {
8136
		return _pluck_order( settings.aoData, rows, '_aData' );
8137
	}, 1 );
8138
} );
8139

8140
_api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) {
8141
	return this.iterator( 'row', function ( settings, row ) {
8142
		var r = settings.aoData[ row ];
8143
		return type === 'search' ? r._aFilterData : r._aSortData;
8144
	}, 1 );
8145
} );
8146

8147
_api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) {
8148
	return this.iterator( 'row', function ( settings, row ) {
8149
		_fnInvalidate( settings, row, src );
8150
	} );
8151
} );
8152

8153
_api_registerPlural( 'rows().indexes()', 'row().index()', function () {
8154
	return this.iterator( 'row', function ( settings, row ) {
8155
		return row;
8156
	}, 1 );
8157
} );
8158

8159
_api_registerPlural( 'rows().ids()', 'row().id()', function ( hash ) {
8160
	var a = [];
8161
	var context = this.context;
8162

8163
	// `iterator` will drop undefined values, but in this case we want them
8164
	for ( var i=0, ien=context.length ; i<ien ; i++ ) {
8165
		for ( var j=0, jen=this[i].length ; j<jen ; j++ ) {
8166
			var id = context[i].rowIdFn( context[i].aoData[ this[i][j] ]._aData );
8167
			a.push( (hash === true ? '#' : '' )+ id );
8168
		}
8169
	}
8170

8171
	return new _Api( context, a );
8172
} );
8173

8174
_api_registerPlural( 'rows().remove()', 'row().remove()', function () {
8175
	var that = this;
8176

8177
	this.iterator( 'row', function ( settings, row, thatIdx ) {
8178
		var data = settings.aoData;
8179
		var rowData = data[ row ];
8180
		var i, ien, j, jen;
8181
		var loopRow, loopCells;
8182

8183
		data.splice( row, 1 );
8184

8185
		// Update the cached indexes
8186
		for ( i=0, ien=data.length ; i<ien ; i++ ) {
8187
			loopRow = data[i];
8188
			loopCells = loopRow.anCells;
8189

8190
			// Rows
8191
			if ( loopRow.nTr !== null ) {
8192
				loopRow.nTr._DT_RowIndex = i;
8193
			}
8194

8195
			// Cells
8196
			if ( loopCells !== null ) {
8197
				for ( j=0, jen=loopCells.length ; j<jen ; j++ ) {
8198
					loopCells[j]._DT_CellIndex.row = i;
8199
				}
8200
			}
8201
		}
8202

8203
		// Delete from the display arrays
8204
		_fnDeleteIndex( settings.aiDisplayMaster, row );
8205
		_fnDeleteIndex( settings.aiDisplay, row );
8206
		_fnDeleteIndex( that[ thatIdx ], row, false ); // maintain local indexes
8207

8208
		// For server-side processing tables - subtract the deleted row from the count
8209
		if ( settings._iRecordsDisplay > 0 ) {
8210
			settings._iRecordsDisplay--;
8211
		}
8212

8213
		// Check for an 'overflow' they case for displaying the table
8214
		_fnLengthOverflow( settings );
8215

8216
		// Remove the row's ID reference if there is one
8217
		var id = settings.rowIdFn( rowData._aData );
8218
		if ( id !== undefined ) {
8219
			delete settings.aIds[ id ];
8220
		}
8221
	} );
8222

8223
	this.iterator( 'table', function ( settings ) {
8224
		for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
8225
			settings.aoData[i].idx = i;
8226
		}
8227
	} );
8228

8229
	return this;
8230
} );
8231

8232

8233
_api_register( 'rows.add()', function ( rows ) {
8234
	var newRows = this.iterator( 'table', function ( settings ) {
8235
			var row, i, ien;
8236
			var out = [];
8237

8238
			for ( i=0, ien=rows.length ; i<ien ; i++ ) {
8239
				row = rows[i];
8240

8241
				if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
8242
					out.push( _fnAddTr( settings, row )[0] );
8243
				}
8244
				else {
8245
					out.push( _fnAddData( settings, row ) );
8246
				}
8247
			}
8248

8249
			return out;
8250
		}, 1 );
8251

8252
	// Return an Api.rows() extended instance, so rows().nodes() etc can be used
8253
	var modRows = this.rows( -1 );
8254
	modRows.pop();
8255
	$.merge( modRows, newRows );
8256

8257
	return modRows;
8258
} );
8259

8260

8261

8262

8263

8264
/**
8265
 *
8266
 */
8267
_api_register( 'row()', function ( selector, opts ) {
8268
	return _selector_first( this.rows( selector, opts ) );
8269
} );
8270

8271

8272
_api_register( 'row().data()', function ( data ) {
8273
	var ctx = this.context;
8274

8275
	if ( data === undefined ) {
8276
		// Get
8277
		return ctx.length && this.length ?
8278
			ctx[0].aoData[ this[0] ]._aData :
8279
			undefined;
8280
	}
8281

8282
	// Set
8283
	var row = ctx[0].aoData[ this[0] ];
8284
	row._aData = data;
8285

8286
	// If the DOM has an id, and the data source is an array
8287
	if ( Array.isArray( data ) && row.nTr && row.nTr.id ) {
8288
		_fnSetObjectDataFn( ctx[0].rowId )( data, row.nTr.id );
8289
	}
8290

8291
	// Automatically invalidate
8292
	_fnInvalidate( ctx[0], this[0], 'data' );
8293

8294
	return this;
8295
} );
8296

8297

8298
_api_register( 'row().node()', function () {
8299
	var ctx = this.context;
8300

8301
	return ctx.length && this.length ?
8302
		ctx[0].aoData[ this[0] ].nTr || null :
8303
		null;
8304
} );
8305

8306

8307
_api_register( 'row.add()', function ( row ) {
8308
	// Allow a jQuery object to be passed in - only a single row is added from
8309
	// it though - the first element in the set
8310
	if ( row instanceof $ && row.length ) {
8311
		row = row[0];
8312
	}
8313

8314
	var rows = this.iterator( 'table', function ( settings ) {
8315
		if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
8316
			return _fnAddTr( settings, row )[0];
8317
		}
8318
		return _fnAddData( settings, row );
8319
	} );
8320

8321
	// Return an Api.rows() extended instance, with the newly added row selected
8322
	return this.row( rows[0] );
8323
} );
8324

8325

8326
$(document).on('plugin-init.dt', function (e, context) {
8327
	var api = new _Api( context );
8328
	var namespace = 'on-plugin-init';
8329
	var stateSaveParamsEvent = 'stateSaveParams.' + namespace;
8330
	var destroyEvent = 'destroy. ' + namespace;
8331

8332
	api.on( stateSaveParamsEvent, function ( e, settings, d ) {
8333
		// This could be more compact with the API, but it is a lot faster as a simple
8334
		// internal loop
8335
		var idFn = settings.rowIdFn;
8336
		var data = settings.aoData;
8337
		var ids = [];
8338

8339
		for (var i=0 ; i<data.length ; i++) {
8340
			if (data[i]._detailsShow) {
8341
				ids.push( '#' + idFn(data[i]._aData) );
8342
			}
8343
		}
8344

8345
		d.childRows = ids;
8346
	});
8347

8348
	api.on( destroyEvent, function () {
8349
		api.off(stateSaveParamsEvent + ' ' + destroyEvent);
8350
	});
8351

8352
	var loaded = api.state.loaded();
8353

8354
	if ( loaded && loaded.childRows ) {
8355
		api
8356
			.rows( $.map(loaded.childRows, function (id){
8357
				return id.replace(/:/g, '\\:')
8358
			}) )
8359
			.every( function () {
8360
				_fnCallbackFire( context, null, 'requestChild', [ this ] )
8361
			});
8362
	}
8363
});
8364

8365
var __details_add = function ( ctx, row, data, klass )
8366
{
8367
	// Convert to array of TR elements
8368
	var rows = [];
8369
	var addRow = function ( r, k ) {
8370
		// Recursion to allow for arrays of jQuery objects
8371
		if ( Array.isArray( r ) || r instanceof $ ) {
8372
			for ( var i=0, ien=r.length ; i<ien ; i++ ) {
8373
				addRow( r[i], k );
8374
			}
8375
			return;
8376
		}
8377

8378
		// If we get a TR element, then just add it directly - up to the dev
8379
		// to add the correct number of columns etc
8380
		if ( r.nodeName && r.nodeName.toLowerCase() === 'tr' ) {
8381
			rows.push( r );
8382
		}
8383
		else {
8384
			// Otherwise create a row with a wrapper
8385
			var created = $('<tr><td></td></tr>').addClass( k );
8386
			$('td', created)
8387
				.addClass( k )
8388
				.html( r )
8389
				[0].colSpan = _fnVisbleColumns( ctx );
8390

8391
			rows.push( created[0] );
8392
		}
8393
	};
8394

8395
	addRow( data, klass );
8396

8397
	if ( row._details ) {
8398
		row._details.detach();
8399
	}
8400

8401
	row._details = $(rows);
8402

8403
	// If the children were already shown, that state should be retained
8404
	if ( row._detailsShow ) {
8405
		row._details.insertAfter( row.nTr );
8406
	}
8407
};
8408

8409

8410
// Make state saving of child row details async to allow them to be batch processed
8411
var __details_state = DataTable.util.throttle(
8412
	function (ctx) {
8413
		_fnSaveState( ctx[0] )
8414
	},
8415
	500
8416
);
8417

8418

8419
var __details_remove = function ( api, idx )
8420
{
8421
	var ctx = api.context;
8422

8423
	if ( ctx.length ) {
8424
		var row = ctx[0].aoData[ idx !== undefined ? idx : api[0] ];
8425

8426
		if ( row && row._details ) {
8427
			row._details.remove();
8428

8429
			row._detailsShow = undefined;
8430
			row._details = undefined;
8431
			$( row.nTr ).removeClass( 'dt-hasChild' );
8432
			__details_state( ctx );
8433
		}
8434
	}
8435
};
8436

8437

8438
var __details_display = function ( api, show ) {
8439
	var ctx = api.context;
8440

8441
	if ( ctx.length && api.length ) {
8442
		var row = ctx[0].aoData[ api[0] ];
8443

8444
		if ( row._details ) {
8445
			row._detailsShow = show;
8446

8447
			if ( show ) {
8448
				row._details.insertAfter( row.nTr );
8449
				$( row.nTr ).addClass( 'dt-hasChild' );
8450
			}
8451
			else {
8452
				row._details.detach();
8453
				$( row.nTr ).removeClass( 'dt-hasChild' );
8454
			}
8455

8456
			_fnCallbackFire( ctx[0], null, 'childRow', [ show, api.row( api[0] ) ] )
8457

8458
			__details_events( ctx[0] );
8459
			__details_state( ctx );
8460
		}
8461
	}
8462
};
8463

8464

8465
var __details_events = function ( settings )
8466
{
8467
	var api = new _Api( settings );
8468
	var namespace = '.dt.DT_details';
8469
	var drawEvent = 'draw'+namespace;
8470
	var colvisEvent = 'column-sizing'+namespace;
8471
	var destroyEvent = 'destroy'+namespace;
8472
	var data = settings.aoData;
8473

8474
	api.off( drawEvent +' '+ colvisEvent +' '+ destroyEvent );
8475

8476
	if ( _pluck( data, '_details' ).length > 0 ) {
8477
		// On each draw, insert the required elements into the document
8478
		api.on( drawEvent, function ( e, ctx ) {
8479
			if ( settings !== ctx ) {
8480
				return;
8481
			}
8482

8483
			api.rows( {page:'current'} ).eq(0).each( function (idx) {
8484
				// Internal data grab
8485
				var row = data[ idx ];
8486

8487
				if ( row._detailsShow ) {
8488
					row._details.insertAfter( row.nTr );
8489
				}
8490
			} );
8491
		} );
8492

8493
		// Column visibility change - update the colspan
8494
		api.on( colvisEvent, function ( e, ctx, idx, vis ) {
8495
			if ( settings !== ctx ) {
8496
				return;
8497
			}
8498

8499
			// Update the colspan for the details rows (note, only if it already has
8500
			// a colspan)
8501
			var row, visible = _fnVisbleColumns( ctx );
8502

8503
			for ( var i=0, ien=data.length ; i<ien ; i++ ) {
8504
				row = data[i];
8505

8506
				if ( row._details ) {
8507
					row._details.children('td[colspan]').attr('colspan', visible );
8508
				}
8509
			}
8510
		} );
8511

8512
		// Table destroyed - nuke any child rows
8513
		api.on( destroyEvent, function ( e, ctx ) {
8514
			if ( settings !== ctx ) {
8515
				return;
8516
			}
8517

8518
			for ( var i=0, ien=data.length ; i<ien ; i++ ) {
8519
				if ( data[i]._details ) {
8520
					__details_remove( api, i );
8521
				}
8522
			}
8523
		} );
8524
	}
8525
};
8526

8527
// Strings for the method names to help minification
8528
var _emp = '';
8529
var _child_obj = _emp+'row().child';
8530
var _child_mth = _child_obj+'()';
8531

8532
// data can be:
8533
//  tr
8534
//  string
8535
//  jQuery or array of any of the above
8536
_api_register( _child_mth, function ( data, klass ) {
8537
	var ctx = this.context;
8538

8539
	if ( data === undefined ) {
8540
		// get
8541
		return ctx.length && this.length ?
8542
			ctx[0].aoData[ this[0] ]._details :
8543
			undefined;
8544
	}
8545
	else if ( data === true ) {
8546
		// show
8547
		this.child.show();
8548
	}
8549
	else if ( data === false ) {
8550
		// remove
8551
		__details_remove( this );
8552
	}
8553
	else if ( ctx.length && this.length ) {
8554
		// set
8555
		__details_add( ctx[0], ctx[0].aoData[ this[0] ], data, klass );
8556
	}
8557

8558
	return this;
8559
} );
8560

8561

8562
_api_register( [
8563
	_child_obj+'.show()',
8564
	_child_mth+'.show()' // only when `child()` was called with parameters (without
8565
], function ( show ) {   // it returns an object and this method is not executed)
8566
	__details_display( this, true );
8567
	return this;
8568
} );
8569

8570

8571
_api_register( [
8572
	_child_obj+'.hide()',
8573
	_child_mth+'.hide()' // only when `child()` was called with parameters (without
8574
], function () {         // it returns an object and this method is not executed)
8575
	__details_display( this, false );
8576
	return this;
8577
} );
8578

8579

8580
_api_register( [
8581
	_child_obj+'.remove()',
8582
	_child_mth+'.remove()' // only when `child()` was called with parameters (without
8583
], function () {           // it returns an object and this method is not executed)
8584
	__details_remove( this );
8585
	return this;
8586
} );
8587

8588

8589
_api_register( _child_obj+'.isShown()', function () {
8590
	var ctx = this.context;
8591

8592
	if ( ctx.length && this.length ) {
8593
		// _detailsShown as false or undefined will fall through to return false
8594
		return ctx[0].aoData[ this[0] ]._detailsShow || false;
8595
	}
8596
	return false;
8597
} );
8598

8599

8600

8601
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
8602
 * Columns
8603
 *
8604
 * {integer}           - column index (>=0 count from left, <0 count from right)
8605
 * "{integer}:visIdx"  - visible column index (i.e. translate to column index)  (>=0 count from left, <0 count from right)
8606
 * "{integer}:visible" - alias for {integer}:visIdx  (>=0 count from left, <0 count from right)
8607
 * "{string}:name"     - column name
8608
 * "{string}"          - jQuery selector on column header nodes
8609
 *
8610
 */
8611

8612
// can be an array of these items, comma separated list, or an array of comma
8613
// separated lists
8614

8615
var __re_column_selector = /^([^:]+):(name|visIdx|visible)$/;
8616

8617

8618
// r1 and r2 are redundant - but it means that the parameters match for the
8619
// iterator callback in columns().data()
8620
var __columnData = function ( settings, column, r1, r2, rows ) {
8621
	var a = [];
8622
	for ( var row=0, ien=rows.length ; row<ien ; row++ ) {
8623
		a.push( _fnGetCellData( settings, rows[row], column ) );
8624
	}
8625
	return a;
8626
};
8627

8628

8629
var __column_selector = function ( settings, selector, opts )
8630
{
8631
	var
8632
		columns = settings.aoColumns,
8633
		names = _pluck( columns, 'sName' ),
8634
		nodes = _pluck( columns, 'nTh' );
8635

8636
	var run = function ( s ) {
8637
		var selInt = _intVal( s );
8638

8639
		// Selector - all
8640
		if ( s === '' ) {
8641
			return _range( columns.length );
8642
		}
8643

8644
		// Selector - index
8645
		if ( selInt !== null ) {
8646
			return [ selInt >= 0 ?
8647
				selInt : // Count from left
8648
				columns.length + selInt // Count from right (+ because its a negative value)
8649
			];
8650
		}
8651

8652
		// Selector = function
8653
		if ( typeof s === 'function' ) {
8654
			var rows = _selector_row_indexes( settings, opts );
8655

8656
			return $.map( columns, function (col, idx) {
8657
				return s(
8658
						idx,
8659
						__columnData( settings, idx, 0, 0, rows ),
8660
						nodes[ idx ]
8661
					) ? idx : null;
8662
			} );
8663
		}
8664

8665
		// jQuery or string selector
8666
		var match = typeof s === 'string' ?
8667
			s.match( __re_column_selector ) :
8668
			'';
8669

8670
		if ( match ) {
8671
			switch( match[2] ) {
8672
				case 'visIdx':
8673
				case 'visible':
8674
					var idx = parseInt( match[1], 10 );
8675
					// Visible index given, convert to column index
8676
					if ( idx < 0 ) {
8677
						// Counting from the right
8678
						var visColumns = $.map( columns, function (col,i) {
8679
							return col.bVisible ? i : null;
8680
						} );
8681
						return [ visColumns[ visColumns.length + idx ] ];
8682
					}
8683
					// Counting from the left
8684
					return [ _fnVisibleToColumnIndex( settings, idx ) ];
8685

8686
				case 'name':
8687
					// match by name. `names` is column index complete and in order
8688
					return $.map( names, function (name, i) {
8689
						return name === match[1] ? i : null;
8690
					} );
8691

8692
				default:
8693
					return [];
8694
			}
8695
		}
8696

8697
		// Cell in the table body
8698
		if ( s.nodeName && s._DT_CellIndex ) {
8699
			return [ s._DT_CellIndex.column ];
8700
		}
8701

8702
		// jQuery selector on the TH elements for the columns
8703
		var jqResult = $( nodes )
8704
			.filter( s )
8705
			.map( function () {
8706
				return $.inArray( this, nodes ); // `nodes` is column index complete and in order
8707
			} )
8708
			.toArray();
8709

8710
		if ( jqResult.length || ! s.nodeName ) {
8711
			return jqResult;
8712
		}
8713

8714
		// Otherwise a node which might have a `dt-column` data attribute, or be
8715
		// a child or such an element
8716
		var host = $(s).closest('*[data-dt-column]');
8717
		return host.length ?
8718
			[ host.data('dt-column') ] :
8719
			[];
8720
	};
8721

8722
	return _selector_run( 'column', selector, run, settings, opts );
8723
};
8724

8725

8726
var __setColumnVis = function ( settings, column, vis ) {
8727
	var
8728
		cols = settings.aoColumns,
8729
		col  = cols[ column ],
8730
		data = settings.aoData,
8731
		row, cells, i, ien, tr;
8732

8733
	// Get
8734
	if ( vis === undefined ) {
8735
		return col.bVisible;
8736
	}
8737

8738
	// Set
8739
	// No change
8740
	if ( col.bVisible === vis ) {
8741
		return;
8742
	}
8743

8744
	if ( vis ) {
8745
		// Insert column
8746
		// Need to decide if we should use appendChild or insertBefore
8747
		var insertBefore = $.inArray( true, _pluck(cols, 'bVisible'), column+1 );
8748

8749
		for ( i=0, ien=data.length ; i<ien ; i++ ) {
8750
			tr = data[i].nTr;
8751
			cells = data[i].anCells;
8752

8753
			if ( tr ) {
8754
				// insertBefore can act like appendChild if 2nd arg is null
8755
				tr.insertBefore( cells[ column ], cells[ insertBefore ] || null );
8756
			}
8757
		}
8758
	}
8759
	else {
8760
		// Remove column
8761
		$( _pluck( settings.aoData, 'anCells', column ) ).detach();
8762
	}
8763

8764
	// Common actions
8765
	col.bVisible = vis;
8766
};
8767

8768

8769
_api_register( 'columns()', function ( selector, opts ) {
8770
	// argument shifting
8771
	if ( selector === undefined ) {
8772
		selector = '';
8773
	}
8774
	else if ( $.isPlainObject( selector ) ) {
8775
		opts = selector;
8776
		selector = '';
8777
	}
8778

8779
	opts = _selector_opts( opts );
8780

8781
	var inst = this.iterator( 'table', function ( settings ) {
8782
		return __column_selector( settings, selector, opts );
8783
	}, 1 );
8784

8785
	// Want argument shifting here and in _row_selector?
8786
	inst.selector.cols = selector;
8787
	inst.selector.opts = opts;
8788

8789
	return inst;
8790
} );
8791

8792
_api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) {
8793
	return this.iterator( 'column', function ( settings, column ) {
8794
		return settings.aoColumns[column].nTh;
8795
	}, 1 );
8796
} );
8797

8798
_api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) {
8799
	return this.iterator( 'column', function ( settings, column ) {
8800
		return settings.aoColumns[column].nTf;
8801
	}, 1 );
8802
} );
8803

8804
_api_registerPlural( 'columns().data()', 'column().data()', function () {
8805
	return this.iterator( 'column-rows', __columnData, 1 );
8806
} );
8807

8808
_api_registerPlural( 'columns().dataSrc()', 'column().dataSrc()', function () {
8809
	return this.iterator( 'column', function ( settings, column ) {
8810
		return settings.aoColumns[column].mData;
8811
	}, 1 );
8812
} );
8813

8814
_api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) {
8815
	return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8816
		return _pluck_order( settings.aoData, rows,
8817
			type === 'search' ? '_aFilterData' : '_aSortData', column
8818
		);
8819
	}, 1 );
8820
} );
8821

8822
_api_registerPlural( 'columns().nodes()', 'column().nodes()', function () {
8823
	return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8824
		return _pluck_order( settings.aoData, rows, 'anCells', column ) ;
8825
	}, 1 );
8826
} );
8827

8828
_api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis, calc ) {
8829
	var that = this;
8830
	var ret = this.iterator( 'column', function ( settings, column ) {
8831
		if ( vis === undefined ) {
8832
			return settings.aoColumns[ column ].bVisible;
8833
		} // else
8834
		__setColumnVis( settings, column, vis );
8835
	} );
8836

8837
	// Group the column visibility changes
8838
	if ( vis !== undefined ) {
8839
		this.iterator( 'table', function ( settings ) {
8840
			// Redraw the header after changes
8841
			_fnDrawHead( settings, settings.aoHeader );
8842
			_fnDrawHead( settings, settings.aoFooter );
8843
	
8844
			// Update colspan for no records display. Child rows and extensions will use their own
8845
			// listeners to do this - only need to update the empty table item here
8846
			if ( ! settings.aiDisplay.length ) {
8847
				$(settings.nTBody).find('td[colspan]').attr('colspan', _fnVisbleColumns(settings));
8848
			}
8849
	
8850
			_fnSaveState( settings );
8851

8852
			// Second loop once the first is done for events
8853
			that.iterator( 'column', function ( settings, column ) {
8854
				_fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis, calc] );
8855
			} );
8856

8857
			if ( calc === undefined || calc ) {
8858
				that.columns.adjust();
8859
			}
8860
		});
8861
	}
8862

8863
	return ret;
8864
} );
8865

8866
_api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) {
8867
	return this.iterator( 'column', function ( settings, column ) {
8868
		return type === 'visible' ?
8869
			_fnColumnIndexToVisible( settings, column ) :
8870
			column;
8871
	}, 1 );
8872
} );
8873

8874
_api_register( 'columns.adjust()', function () {
8875
	return this.iterator( 'table', function ( settings ) {
8876
		_fnAdjustColumnSizing( settings );
8877
	}, 1 );
8878
} );
8879

8880
_api_register( 'column.index()', function ( type, idx ) {
8881
	if ( this.context.length !== 0 ) {
8882
		var ctx = this.context[0];
8883

8884
		if ( type === 'fromVisible' || type === 'toData' ) {
8885
			return _fnVisibleToColumnIndex( ctx, idx );
8886
		}
8887
		else if ( type === 'fromData' || type === 'toVisible' ) {
8888
			return _fnColumnIndexToVisible( ctx, idx );
8889
		}
8890
	}
8891
} );
8892

8893
_api_register( 'column()', function ( selector, opts ) {
8894
	return _selector_first( this.columns( selector, opts ) );
8895
} );
8896

8897
var __cell_selector = function ( settings, selector, opts )
8898
{
8899
	var data = settings.aoData;
8900
	var rows = _selector_row_indexes( settings, opts );
8901
	var cells = _removeEmpty( _pluck_order( data, rows, 'anCells' ) );
8902
	var allCells = $(_flatten( [], cells ));
8903
	var row;
8904
	var columns = settings.aoColumns.length;
8905
	var a, i, ien, j, o, host;
8906

8907
	var run = function ( s ) {
8908
		var fnSelector = typeof s === 'function';
8909

8910
		if ( s === null || s === undefined || fnSelector ) {
8911
			// All cells and function selectors
8912
			a = [];
8913

8914
			for ( i=0, ien=rows.length ; i<ien ; i++ ) {
8915
				row = rows[i];
8916

8917
				for ( j=0 ; j<columns ; j++ ) {
8918
					o = {
8919
						row: row,
8920
						column: j
8921
					};
8922

8923
					if ( fnSelector ) {
8924
						// Selector - function
8925
						host = data[ row ];
8926

8927
						if ( s( o, _fnGetCellData(settings, row, j), host.anCells ? host.anCells[j] : null ) ) {
8928
							a.push( o );
8929
						}
8930
					}
8931
					else {
8932
						// Selector - all
8933
						a.push( o );
8934
					}
8935
				}
8936
			}
8937

8938
			return a;
8939
		}
8940
		
8941
		// Selector - index
8942
		if ( $.isPlainObject( s ) ) {
8943
			// Valid cell index and its in the array of selectable rows
8944
			return s.column !== undefined && s.row !== undefined && $.inArray( s.row, rows ) !== -1 ?
8945
				[s] :
8946
				[];
8947
		}
8948

8949
		// Selector - jQuery filtered cells
8950
		var jqResult = allCells
8951
			.filter( s )
8952
			.map( function (i, el) {
8953
				return { // use a new object, in case someone changes the values
8954
					row:    el._DT_CellIndex.row,
8955
					column: el._DT_CellIndex.column
8956
 				};
8957
			} )
8958
			.toArray();
8959

8960
		if ( jqResult.length || ! s.nodeName ) {
8961
			return jqResult;
8962
		}
8963

8964
		// Otherwise the selector is a node, and there is one last option - the
8965
		// element might be a child of an element which has dt-row and dt-column
8966
		// data attributes
8967
		host = $(s).closest('*[data-dt-row]');
8968
		return host.length ?
8969
			[ {
8970
				row: host.data('dt-row'),
8971
				column: host.data('dt-column')
8972
			} ] :
8973
			[];
8974
	};
8975

8976
	return _selector_run( 'cell', selector, run, settings, opts );
8977
};
8978

8979

8980

8981

8982
_api_register( 'cells()', function ( rowSelector, columnSelector, opts ) {
8983
	// Argument shifting
8984
	if ( $.isPlainObject( rowSelector ) ) {
8985
		// Indexes
8986
		if ( rowSelector.row === undefined ) {
8987
			// Selector options in first parameter
8988
			opts = rowSelector;
8989
			rowSelector = null;
8990
		}
8991
		else {
8992
			// Cell index objects in first parameter
8993
			opts = columnSelector;
8994
			columnSelector = null;
8995
		}
8996
	}
8997
	if ( $.isPlainObject( columnSelector ) ) {
8998
		opts = columnSelector;
8999
		columnSelector = null;
9000
	}
9001

9002
	// Cell selector
9003
	if ( columnSelector === null || columnSelector === undefined ) {
9004
		return this.iterator( 'table', function ( settings ) {
9005
			return __cell_selector( settings, rowSelector, _selector_opts( opts ) );
9006
		} );
9007
	}
9008

9009
	// The default built in options need to apply to row and columns
9010
	var internalOpts = opts ? {
9011
		page: opts.page,
9012
		order: opts.order,
9013
		search: opts.search
9014
	} : {};
9015

9016
	// Row + column selector
9017
	var columns = this.columns( columnSelector, internalOpts );
9018
	var rows = this.rows( rowSelector, internalOpts );
9019
	var i, ien, j, jen;
9020

9021
	var cellsNoOpts = this.iterator( 'table', function ( settings, idx ) {
9022
		var a = [];
9023

9024
		for ( i=0, ien=rows[idx].length ; i<ien ; i++ ) {
9025
			for ( j=0, jen=columns[idx].length ; j<jen ; j++ ) {
9026
				a.push( {
9027
					row:    rows[idx][i],
9028
					column: columns[idx][j]
9029
				} );
9030
			}
9031
		}
9032

9033
		return a;
9034
	}, 1 );
9035

9036
	// There is currently only one extension which uses a cell selector extension
9037
	// It is a _major_ performance drag to run this if it isn't needed, so this is
9038
	// an extension specific check at the moment
9039
	var cells = opts && opts.selected ?
9040
		this.cells( cellsNoOpts, opts ) :
9041
		cellsNoOpts;
9042

9043
	$.extend( cells.selector, {
9044
		cols: columnSelector,
9045
		rows: rowSelector,
9046
		opts: opts
9047
	} );
9048

9049
	return cells;
9050
} );
9051

9052

9053
_api_registerPlural( 'cells().nodes()', 'cell().node()', function () {
9054
	return this.iterator( 'cell', function ( settings, row, column ) {
9055
		var data = settings.aoData[ row ];
9056

9057
		return data && data.anCells ?
9058
			data.anCells[ column ] :
9059
			undefined;
9060
	}, 1 );
9061
} );
9062

9063

9064
_api_register( 'cells().data()', function () {
9065
	return this.iterator( 'cell', function ( settings, row, column ) {
9066
		return _fnGetCellData( settings, row, column );
9067
	}, 1 );
9068
} );
9069

9070

9071
_api_registerPlural( 'cells().cache()', 'cell().cache()', function ( type ) {
9072
	type = type === 'search' ? '_aFilterData' : '_aSortData';
9073

9074
	return this.iterator( 'cell', function ( settings, row, column ) {
9075
		return settings.aoData[ row ][ type ][ column ];
9076
	}, 1 );
9077
} );
9078

9079

9080
_api_registerPlural( 'cells().render()', 'cell().render()', function ( type ) {
9081
	return this.iterator( 'cell', function ( settings, row, column ) {
9082
		return _fnGetCellData( settings, row, column, type );
9083
	}, 1 );
9084
} );
9085

9086

9087
_api_registerPlural( 'cells().indexes()', 'cell().index()', function () {
9088
	return this.iterator( 'cell', function ( settings, row, column ) {
9089
		return {
9090
			row: row,
9091
			column: column,
9092
			columnVisible: _fnColumnIndexToVisible( settings, column )
9093
		};
9094
	}, 1 );
9095
} );
9096

9097

9098
_api_registerPlural( 'cells().invalidate()', 'cell().invalidate()', function ( src ) {
9099
	return this.iterator( 'cell', function ( settings, row, column ) {
9100
		_fnInvalidate( settings, row, src, column );
9101
	} );
9102
} );
9103

9104

9105

9106
_api_register( 'cell()', function ( rowSelector, columnSelector, opts ) {
9107
	return _selector_first( this.cells( rowSelector, columnSelector, opts ) );
9108
} );
9109

9110

9111
_api_register( 'cell().data()', function ( data ) {
9112
	var ctx = this.context;
9113
	var cell = this[0];
9114

9115
	if ( data === undefined ) {
9116
		// Get
9117
		return ctx.length && cell.length ?
9118
			_fnGetCellData( ctx[0], cell[0].row, cell[0].column ) :
9119
			undefined;
9120
	}
9121

9122
	// Set
9123
	_fnSetCellData( ctx[0], cell[0].row, cell[0].column, data );
9124
	_fnInvalidate( ctx[0], cell[0].row, 'data', cell[0].column );
9125

9126
	return this;
9127
} );
9128

9129

9130

9131
/**
9132
 * Get current ordering (sorting) that has been applied to the table.
9133
 *
9134
 * @returns {array} 2D array containing the sorting information for the first
9135
 *   table in the current context. Each element in the parent array represents
9136
 *   a column being sorted upon (i.e. multi-sorting with two columns would have
9137
 *   2 inner arrays). The inner arrays may have 2 or 3 elements. The first is
9138
 *   the column index that the sorting condition applies to, the second is the
9139
 *   direction of the sort (`desc` or `asc`) and, optionally, the third is the
9140
 *   index of the sorting order from the `column.sorting` initialisation array.
9141
 *//**
9142
 * Set the ordering for the table.
9143
 *
9144
 * @param {integer} order Column index to sort upon.
9145
 * @param {string} direction Direction of the sort to be applied (`asc` or `desc`)
9146
 * @returns {DataTables.Api} this
9147
 *//**
9148
 * Set the ordering for the table.
9149
 *
9150
 * @param {array} order 1D array of sorting information to be applied.
9151
 * @param {array} [...] Optional additional sorting conditions
9152
 * @returns {DataTables.Api} this
9153
 *//**
9154
 * Set the ordering for the table.
9155
 *
9156
 * @param {array} order 2D array of sorting information to be applied.
9157
 * @returns {DataTables.Api} this
9158
 */
9159
_api_register( 'order()', function ( order, dir ) {
9160
	var ctx = this.context;
9161

9162
	if ( order === undefined ) {
9163
		// get
9164
		return ctx.length !== 0 ?
9165
			ctx[0].aaSorting :
9166
			undefined;
9167
	}
9168

9169
	// set
9170
	if ( typeof order === 'number' ) {
9171
		// Simple column / direction passed in
9172
		order = [ [ order, dir ] ];
9173
	}
9174
	else if ( order.length && ! Array.isArray( order[0] ) ) {
9175
		// Arguments passed in (list of 1D arrays)
9176
		order = Array.prototype.slice.call( arguments );
9177
	}
9178
	// otherwise a 2D array was passed in
9179

9180
	return this.iterator( 'table', function ( settings ) {
9181
		settings.aaSorting = order.slice();
9182
	} );
9183
} );
9184

9185

9186
/**
9187
 * Attach a sort listener to an element for a given column
9188
 *
9189
 * @param {node|jQuery|string} node Identifier for the element(s) to attach the
9190
 *   listener to. This can take the form of a single DOM node, a jQuery
9191
 *   collection of nodes or a jQuery selector which will identify the node(s).
9192
 * @param {integer} column the column that a click on this node will sort on
9193
 * @param {function} [callback] callback function when sort is run
9194
 * @returns {DataTables.Api} this
9195
 */
9196
_api_register( 'order.listener()', function ( node, column, callback ) {
9197
	return this.iterator( 'table', function ( settings ) {
9198
		_fnSortAttachListener( settings, node, column, callback );
9199
	} );
9200
} );
9201

9202

9203
_api_register( 'order.fixed()', function ( set ) {
9204
	if ( ! set ) {
9205
		var ctx = this.context;
9206
		var fixed = ctx.length ?
9207
			ctx[0].aaSortingFixed :
9208
			undefined;
9209

9210
		return Array.isArray( fixed ) ?
9211
			{ pre: fixed } :
9212
			fixed;
9213
	}
9214

9215
	return this.iterator( 'table', function ( settings ) {
9216
		settings.aaSortingFixed = $.extend( true, {}, set );
9217
	} );
9218
} );
9219

9220

9221
// Order by the selected column(s)
9222
_api_register( [
9223
	'columns().order()',
9224
	'column().order()'
9225
], function ( dir ) {
9226
	var that = this;
9227

9228
	return this.iterator( 'table', function ( settings, i ) {
9229
		var sort = [];
9230

9231
		$.each( that[i], function (j, col) {
9232
			sort.push( [ col, dir ] );
9233
		} );
9234

9235
		settings.aaSorting = sort;
9236
	} );
9237
} );
9238

9239

9240

9241
_api_register( 'search()', function ( input, regex, smart, caseInsen ) {
9242
	var ctx = this.context;
9243

9244
	if ( input === undefined ) {
9245
		// get
9246
		return ctx.length !== 0 ?
9247
			ctx[0].oPreviousSearch.sSearch :
9248
			undefined;
9249
	}
9250

9251
	// set
9252
	return this.iterator( 'table', function ( settings ) {
9253
		if ( ! settings.oFeatures.bFilter ) {
9254
			return;
9255
		}
9256

9257
		_fnFilterComplete( settings, $.extend( {}, settings.oPreviousSearch, {
9258
			"sSearch": input+"",
9259
			"bRegex":  regex === null ? false : regex,
9260
			"bSmart":  smart === null ? true  : smart,
9261
			"bCaseInsensitive": caseInsen === null ? true : caseInsen
9262
		} ), 1 );
9263
	} );
9264
} );
9265

9266

9267
_api_registerPlural(
9268
	'columns().search()',
9269
	'column().search()',
9270
	function ( input, regex, smart, caseInsen ) {
9271
		return this.iterator( 'column', function ( settings, column ) {
9272
			var preSearch = settings.aoPreSearchCols;
9273

9274
			if ( input === undefined ) {
9275
				// get
9276
				return preSearch[ column ].sSearch;
9277
			}
9278

9279
			// set
9280
			if ( ! settings.oFeatures.bFilter ) {
9281
				return;
9282
			}
9283

9284
			$.extend( preSearch[ column ], {
9285
				"sSearch": input+"",
9286
				"bRegex":  regex === null ? false : regex,
9287
				"bSmart":  smart === null ? true  : smart,
9288
				"bCaseInsensitive": caseInsen === null ? true : caseInsen
9289
			} );
9290

9291
			_fnFilterComplete( settings, settings.oPreviousSearch, 1 );
9292
		} );
9293
	}
9294
);
9295

9296
/*
9297
 * State API methods
9298
 */
9299

9300
_api_register( 'state()', function () {
9301
	return this.context.length ?
9302
		this.context[0].oSavedState :
9303
		null;
9304
} );
9305

9306

9307
_api_register( 'state.clear()', function () {
9308
	return this.iterator( 'table', function ( settings ) {
9309
		// Save an empty object
9310
		settings.fnStateSaveCallback.call( settings.oInstance, settings, {} );
9311
	} );
9312
} );
9313

9314

9315
_api_register( 'state.loaded()', function () {
9316
	return this.context.length ?
9317
		this.context[0].oLoadedState :
9318
		null;
9319
} );
9320

9321

9322
_api_register( 'state.save()', function () {
9323
	return this.iterator( 'table', function ( settings ) {
9324
		_fnSaveState( settings );
9325
	} );
9326
} );
9327

9328

9329

9330
/**
9331
 * Set the jQuery or window object to be used by DataTables
9332
 *
9333
 * @param {*} module Library / container object
9334
 * @param {string} [type] Library or container type `lib`, `win` or `datetime`.
9335
 *   If not provided, automatic detection is attempted.
9336
 */
9337
DataTable.use = function (module, type) {
9338
	if (type === 'lib' || module.fn) {
9339
		$ = module;
9340
	}
9341
	else if (type == 'win' || module.document) {
9342
		window = module;
9343
		document = module.document;
9344
	}
9345
	else if (type === 'datetime' || module.type === 'DateTime') {
9346
		DataTable.DateTime = module;
9347
	}
9348
}
9349

9350
/**
9351
 * CommonJS factory function pass through. This will check if the arguments
9352
 * given are a window object or a jQuery object. If so they are set
9353
 * accordingly.
9354
 * @param {*} root Window
9355
 * @param {*} jq jQUery
9356
 * @returns {boolean} Indicator
9357
 */
9358
DataTable.factory = function (root, jq) {
9359
	var is = false;
9360

9361
	// Test if the first parameter is a window object
9362
	if (root && root.document) {
9363
		window = root;
9364
		document = root.document;
9365
	}
9366

9367
	// Test if the second parameter is a jQuery object
9368
	if (jq && jq.fn && jq.fn.jquery) {
9369
		$ = jq;
9370
		is = true;
9371
	}
9372

9373
	return is;
9374
}
9375

9376
/**
9377
 * Provide a common method for plug-ins to check the version of DataTables being
9378
 * used, in order to ensure compatibility.
9379
 *
9380
 *  @param {string} version Version string to check for, in the format "X.Y.Z".
9381
 *    Note that the formats "X" and "X.Y" are also acceptable.
9382
 *  @returns {boolean} true if this version of DataTables is greater or equal to
9383
 *    the required version, or false if this version of DataTales is not
9384
 *    suitable
9385
 *  @static
9386
 *  @dtopt API-Static
9387
 *
9388
 *  @example
9389
 *    alert( $.fn.dataTable.versionCheck( '1.9.0' ) );
9390
 */
9391
DataTable.versionCheck = DataTable.fnVersionCheck = function( version )
9392
{
9393
	var aThis = DataTable.version.split('.');
9394
	var aThat = version.split('.');
9395
	var iThis, iThat;
9396

9397
	for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) {
9398
		iThis = parseInt( aThis[i], 10 ) || 0;
9399
		iThat = parseInt( aThat[i], 10 ) || 0;
9400

9401
		// Parts are the same, keep comparing
9402
		if (iThis === iThat) {
9403
			continue;
9404
		}
9405

9406
		// Parts are different, return immediately
9407
		return iThis > iThat;
9408
	}
9409

9410
	return true;
9411
};
9412

9413

9414
/**
9415
 * Check if a `<table>` node is a DataTable table already or not.
9416
 *
9417
 *  @param {node|jquery|string} table Table node, jQuery object or jQuery
9418
 *      selector for the table to test. Note that if more than more than one
9419
 *      table is passed on, only the first will be checked
9420
 *  @returns {boolean} true the table given is a DataTable, or false otherwise
9421
 *  @static
9422
 *  @dtopt API-Static
9423
 *
9424
 *  @example
9425
 *    if ( ! $.fn.DataTable.isDataTable( '#example' ) ) {
9426
 *      $('#example').dataTable();
9427
 *    }
9428
 */
9429
DataTable.isDataTable = DataTable.fnIsDataTable = function ( table )
9430
{
9431
	var t = $(table).get(0);
9432
	var is = false;
9433

9434
	if ( table instanceof DataTable.Api ) {
9435
		return true;
9436
	}
9437

9438
	$.each( DataTable.settings, function (i, o) {
9439
		var head = o.nScrollHead ? $('table', o.nScrollHead)[0] : null;
9440
		var foot = o.nScrollFoot ? $('table', o.nScrollFoot)[0] : null;
9441

9442
		if ( o.nTable === t || head === t || foot === t ) {
9443
			is = true;
9444
		}
9445
	} );
9446

9447
	return is;
9448
};
9449

9450

9451
/**
9452
 * Get all DataTable tables that have been initialised - optionally you can
9453
 * select to get only currently visible tables.
9454
 *
9455
 *  @param {boolean} [visible=false] Flag to indicate if you want all (default)
9456
 *    or visible tables only.
9457
 *  @returns {array} Array of `table` nodes (not DataTable instances) which are
9458
 *    DataTables
9459
 *  @static
9460
 *  @dtopt API-Static
9461
 *
9462
 *  @example
9463
 *    $.each( $.fn.dataTable.tables(true), function () {
9464
 *      $(table).DataTable().columns.adjust();
9465
 *    } );
9466
 */
9467
DataTable.tables = DataTable.fnTables = function ( visible )
9468
{
9469
	var api = false;
9470

9471
	if ( $.isPlainObject( visible ) ) {
9472
		api = visible.api;
9473
		visible = visible.visible;
9474
	}
9475

9476
	var a = $.map( DataTable.settings, function (o) {
9477
		if ( !visible || (visible && $(o.nTable).is(':visible')) ) {
9478
			return o.nTable;
9479
		}
9480
	} );
9481

9482
	return api ?
9483
		new _Api( a ) :
9484
		a;
9485
};
9486

9487

9488
/**
9489
 * Convert from camel case parameters to Hungarian notation. This is made public
9490
 * for the extensions to provide the same ability as DataTables core to accept
9491
 * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase
9492
 * parameters.
9493
 *
9494
 *  @param {object} src The model object which holds all parameters that can be
9495
 *    mapped.
9496
 *  @param {object} user The object to convert from camel case to Hungarian.
9497
 *  @param {boolean} force When set to `true`, properties which already have a
9498
 *    Hungarian value in the `user` object will be overwritten. Otherwise they
9499
 *    won't be.
9500
 */
9501
DataTable.camelToHungarian = _fnCamelToHungarian;
9502

9503

9504

9505
/**
9506
 *
9507
 */
9508
_api_register( '$()', function ( selector, opts ) {
9509
	var
9510
		rows   = this.rows( opts ).nodes(), // Get all rows
9511
		jqRows = $(rows);
9512

9513
	return $( [].concat(
9514
		jqRows.filter( selector ).toArray(),
9515
		jqRows.find( selector ).toArray()
9516
	) );
9517
} );
9518

9519

9520
// jQuery functions to operate on the tables
9521
$.each( [ 'on', 'one', 'off' ], function (i, key) {
9522
	_api_register( key+'()', function ( /* event, handler */ ) {
9523
		var args = Array.prototype.slice.call(arguments);
9524

9525
		// Add the `dt` namespace automatically if it isn't already present
9526
		args[0] = $.map( args[0].split( /\s/ ), function ( e ) {
9527
			return ! e.match(/\.dt\b/) ?
9528
				e+'.dt' :
9529
				e;
9530
			} ).join( ' ' );
9531

9532
		var inst = $( this.tables().nodes() );
9533
		inst[key].apply( inst, args );
9534
		return this;
9535
	} );
9536
} );
9537

9538

9539
_api_register( 'clear()', function () {
9540
	return this.iterator( 'table', function ( settings ) {
9541
		_fnClearTable( settings );
9542
	} );
9543
} );
9544

9545

9546
_api_register( 'settings()', function () {
9547
	return new _Api( this.context, this.context );
9548
} );
9549

9550

9551
_api_register( 'init()', function () {
9552
	var ctx = this.context;
9553
	return ctx.length ? ctx[0].oInit : null;
9554
} );
9555

9556

9557
_api_register( 'data()', function () {
9558
	return this.iterator( 'table', function ( settings ) {
9559
		return _pluck( settings.aoData, '_aData' );
9560
	} ).flatten();
9561
} );
9562

9563

9564
_api_register( 'destroy()', function ( remove ) {
9565
	remove = remove || false;
9566

9567
	return this.iterator( 'table', function ( settings ) {
9568
		var classes   = settings.oClasses;
9569
		var table     = settings.nTable;
9570
		var tbody     = settings.nTBody;
9571
		var thead     = settings.nTHead;
9572
		var tfoot     = settings.nTFoot;
9573
		var jqTable   = $(table);
9574
		var jqTbody   = $(tbody);
9575
		var jqWrapper = $(settings.nTableWrapper);
9576
		var rows      = $.map( settings.aoData, function (r) { return r.nTr; } );
9577
		var i, ien;
9578

9579
		// Flag to note that the table is currently being destroyed - no action
9580
		// should be taken
9581
		settings.bDestroying = true;
9582

9583
		// Fire off the destroy callbacks for plug-ins etc
9584
		_fnCallbackFire( settings, "aoDestroyCallback", "destroy", [settings] );
9585

9586
		// If not being removed from the document, make all columns visible
9587
		if ( ! remove ) {
9588
			new _Api( settings ).columns().visible( true );
9589
		}
9590

9591
		// Blitz all `DT` namespaced events (these are internal events, the
9592
		// lowercase, `dt` events are user subscribed and they are responsible
9593
		// for removing them
9594
		jqWrapper.off('.DT').find(':not(tbody *)').off('.DT');
9595
		$(window).off('.DT-'+settings.sInstance);
9596

9597
		// When scrolling we had to break the table up - restore it
9598
		if ( table != thead.parentNode ) {
9599
			jqTable.children('thead').detach();
9600
			jqTable.append( thead );
9601
		}
9602

9603
		if ( tfoot && table != tfoot.parentNode ) {
9604
			jqTable.children('tfoot').detach();
9605
			jqTable.append( tfoot );
9606
		}
9607

9608
		settings.aaSorting = [];
9609
		settings.aaSortingFixed = [];
9610
		_fnSortingClasses( settings );
9611

9612
		$( rows ).removeClass( settings.asStripeClasses.join(' ') );
9613

9614
		$('th, td', thead).removeClass( classes.sSortable+' '+
9615
			classes.sSortableAsc+' '+classes.sSortableDesc+' '+classes.sSortableNone
9616
		);
9617

9618
		// Add the TR elements back into the table in their original order
9619
		jqTbody.children().detach();
9620
		jqTbody.append( rows );
9621

9622
		var orig = settings.nTableWrapper.parentNode;
9623

9624
		// Remove the DataTables generated nodes, events and classes
9625
		var removedMethod = remove ? 'remove' : 'detach';
9626
		jqTable[ removedMethod ]();
9627
		jqWrapper[ removedMethod ]();
9628

9629
		// If we need to reattach the table to the document
9630
		if ( ! remove && orig ) {
9631
			// insertBefore acts like appendChild if !arg[1]
9632
			orig.insertBefore( table, settings.nTableReinsertBefore );
9633

9634
			// Restore the width of the original table - was read from the style property,
9635
			// so we can restore directly to that
9636
			jqTable
9637
				.css( 'width', settings.sDestroyWidth )
9638
				.removeClass( classes.sTable );
9639

9640
			// If the were originally stripe classes - then we add them back here.
9641
			// Note this is not fool proof (for example if not all rows had stripe
9642
			// classes - but it's a good effort without getting carried away
9643
			ien = settings.asDestroyStripes.length;
9644

9645
			if ( ien ) {
9646
				jqTbody.children().each( function (i) {
9647
					$(this).addClass( settings.asDestroyStripes[i % ien] );
9648
				} );
9649
			}
9650
		}
9651

9652
		/* Remove the settings object from the settings array */
9653
		var idx = $.inArray( settings, DataTable.settings );
9654
		if ( idx !== -1 ) {
9655
			DataTable.settings.splice( idx, 1 );
9656
		}
9657
	} );
9658
} );
9659

9660

9661
// Add the `every()` method for rows, columns and cells in a compact form
9662
$.each( [ 'column', 'row', 'cell' ], function ( i, type ) {
9663
	_api_register( type+'s().every()', function ( fn ) {
9664
		var opts = this.selector.opts;
9665
		var api = this;
9666

9667
		return this.iterator( type, function ( settings, arg1, arg2, arg3, arg4 ) {
9668
			// Rows and columns:
9669
			//  arg1 - index
9670
			//  arg2 - table counter
9671
			//  arg3 - loop counter
9672
			//  arg4 - undefined
9673
			// Cells:
9674
			//  arg1 - row index
9675
			//  arg2 - column index
9676
			//  arg3 - table counter
9677
			//  arg4 - loop counter
9678
			fn.call(
9679
				api[ type ](
9680
					arg1,
9681
					type==='cell' ? arg2 : opts,
9682
					type==='cell' ? opts : undefined
9683
				),
9684
				arg1, arg2, arg3, arg4
9685
			);
9686
		} );
9687
	} );
9688
} );
9689

9690

9691
// i18n method for extensions to be able to use the language object from the
9692
// DataTable
9693
_api_register( 'i18n()', function ( token, def, plural ) {
9694
	var ctx = this.context[0];
9695
	var resolved = _fnGetObjectDataFn( token )( ctx.oLanguage );
9696

9697
	if ( resolved === undefined ) {
9698
		resolved = def;
9699
	}
9700

9701
	if ( plural !== undefined && $.isPlainObject( resolved ) ) {
9702
		resolved = resolved[ plural ] !== undefined ?
9703
			resolved[ plural ] :
9704
			resolved._;
9705
	}
9706

9707
	return typeof resolved === 'string'
9708
		? resolved.replace( '%d', plural ) // nb: plural might be undefined,
9709
		: resolved;
9710
} );
9711
/**
9712
 * Version string for plug-ins to check compatibility. Allowed format is
9713
 * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used
9714
 * only for non-release builds. See http://semver.org/ for more information.
9715
 *  @member
9716
 *  @type string
9717
 *  @default Version number
9718
 */
9719
DataTable.version = "1.13.5";
9720

9721
/**
9722
 * Private data store, containing all of the settings objects that are
9723
 * created for the tables on a given page.
9724
 *
9725
 * Note that the `DataTable.settings` object is aliased to
9726
 * `jQuery.fn.dataTableExt` through which it may be accessed and
9727
 * manipulated, or `jQuery.fn.dataTable.settings`.
9728
 *  @member
9729
 *  @type array
9730
 *  @default []
9731
 *  @private
9732
 */
9733
DataTable.settings = [];
9734

9735
/**
9736
 * Object models container, for the various models that DataTables has
9737
 * available to it. These models define the objects that are used to hold
9738
 * the active state and configuration of the table.
9739
 *  @namespace
9740
 */
9741
DataTable.models = {};
9742

9743

9744

9745
/**
9746
 * Template object for the way in which DataTables holds information about
9747
 * search information for the global filter and individual column filters.
9748
 *  @namespace
9749
 */
9750
DataTable.models.oSearch = {
9751
	/**
9752
	 * Flag to indicate if the filtering should be case insensitive or not
9753
	 *  @type boolean
9754
	 *  @default true
9755
	 */
9756
	"bCaseInsensitive": true,
9757

9758
	/**
9759
	 * Applied search term
9760
	 *  @type string
9761
	 *  @default <i>Empty string</i>
9762
	 */
9763
	"sSearch": "",
9764

9765
	/**
9766
	 * Flag to indicate if the search term should be interpreted as a
9767
	 * regular expression (true) or not (false) and therefore and special
9768
	 * regex characters escaped.
9769
	 *  @type boolean
9770
	 *  @default false
9771
	 */
9772
	"bRegex": false,
9773

9774
	/**
9775
	 * Flag to indicate if DataTables is to use its smart filtering or not.
9776
	 *  @type boolean
9777
	 *  @default true
9778
	 */
9779
	"bSmart": true,
9780

9781
	/**
9782
	 * Flag to indicate if DataTables should only trigger a search when
9783
	 * the return key is pressed.
9784
	 *  @type boolean
9785
	 *  @default false
9786
	 */
9787
	"return": false
9788
};
9789

9790

9791

9792

9793
/**
9794
 * Template object for the way in which DataTables holds information about
9795
 * each individual row. This is the object format used for the settings
9796
 * aoData array.
9797
 *  @namespace
9798
 */
9799
DataTable.models.oRow = {
9800
	/**
9801
	 * TR element for the row
9802
	 *  @type node
9803
	 *  @default null
9804
	 */
9805
	"nTr": null,
9806

9807
	/**
9808
	 * Array of TD elements for each row. This is null until the row has been
9809
	 * created.
9810
	 *  @type array nodes
9811
	 *  @default []
9812
	 */
9813
	"anCells": null,
9814

9815
	/**
9816
	 * Data object from the original data source for the row. This is either
9817
	 * an array if using the traditional form of DataTables, or an object if
9818
	 * using mData options. The exact type will depend on the passed in
9819
	 * data from the data source, or will be an array if using DOM a data
9820
	 * source.
9821
	 *  @type array|object
9822
	 *  @default []
9823
	 */
9824
	"_aData": [],
9825

9826
	/**
9827
	 * Sorting data cache - this array is ostensibly the same length as the
9828
	 * number of columns (although each index is generated only as it is
9829
	 * needed), and holds the data that is used for sorting each column in the
9830
	 * row. We do this cache generation at the start of the sort in order that
9831
	 * the formatting of the sort data need be done only once for each cell
9832
	 * per sort. This array should not be read from or written to by anything
9833
	 * other than the master sorting methods.
9834
	 *  @type array
9835
	 *  @default null
9836
	 *  @private
9837
	 */
9838
	"_aSortData": null,
9839

9840
	/**
9841
	 * Per cell filtering data cache. As per the sort data cache, used to
9842
	 * increase the performance of the filtering in DataTables
9843
	 *  @type array
9844
	 *  @default null
9845
	 *  @private
9846
	 */
9847
	"_aFilterData": null,
9848

9849
	/**
9850
	 * Filtering data cache. This is the same as the cell filtering cache, but
9851
	 * in this case a string rather than an array. This is easily computed with
9852
	 * a join on `_aFilterData`, but is provided as a cache so the join isn't
9853
	 * needed on every search (memory traded for performance)
9854
	 *  @type array
9855
	 *  @default null
9856
	 *  @private
9857
	 */
9858
	"_sFilterRow": null,
9859

9860
	/**
9861
	 * Cache of the class name that DataTables has applied to the row, so we
9862
	 * can quickly look at this variable rather than needing to do a DOM check
9863
	 * on className for the nTr property.
9864
	 *  @type string
9865
	 *  @default <i>Empty string</i>
9866
	 *  @private
9867
	 */
9868
	"_sRowStripe": "",
9869

9870
	/**
9871
	 * Denote if the original data source was from the DOM, or the data source
9872
	 * object. This is used for invalidating data, so DataTables can
9873
	 * automatically read data from the original source, unless uninstructed
9874
	 * otherwise.
9875
	 *  @type string
9876
	 *  @default null
9877
	 *  @private
9878
	 */
9879
	"src": null,
9880

9881
	/**
9882
	 * Index in the aoData array. This saves an indexOf lookup when we have the
9883
	 * object, but want to know the index
9884
	 *  @type integer
9885
	 *  @default -1
9886
	 *  @private
9887
	 */
9888
	"idx": -1
9889
};
9890

9891

9892
/**
9893
 * Template object for the column information object in DataTables. This object
9894
 * is held in the settings aoColumns array and contains all the information that
9895
 * DataTables needs about each individual column.
9896
 *
9897
 * Note that this object is related to {@link DataTable.defaults.column}
9898
 * but this one is the internal data store for DataTables's cache of columns.
9899
 * It should NOT be manipulated outside of DataTables. Any configuration should
9900
 * be done through the initialisation options.
9901
 *  @namespace
9902
 */
9903
DataTable.models.oColumn = {
9904
	/**
9905
	 * Column index. This could be worked out on-the-fly with $.inArray, but it
9906
	 * is faster to just hold it as a variable
9907
	 *  @type integer
9908
	 *  @default null
9909
	 */
9910
	"idx": null,
9911

9912
	/**
9913
	 * A list of the columns that sorting should occur on when this column
9914
	 * is sorted. That this property is an array allows multi-column sorting
9915
	 * to be defined for a column (for example first name / last name columns
9916
	 * would benefit from this). The values are integers pointing to the
9917
	 * columns to be sorted on (typically it will be a single integer pointing
9918
	 * at itself, but that doesn't need to be the case).
9919
	 *  @type array
9920
	 */
9921
	"aDataSort": null,
9922

9923
	/**
9924
	 * Define the sorting directions that are applied to the column, in sequence
9925
	 * as the column is repeatedly sorted upon - i.e. the first value is used
9926
	 * as the sorting direction when the column if first sorted (clicked on).
9927
	 * Sort it again (click again) and it will move on to the next index.
9928
	 * Repeat until loop.
9929
	 *  @type array
9930
	 */
9931
	"asSorting": null,
9932

9933
	/**
9934
	 * Flag to indicate if the column is searchable, and thus should be included
9935
	 * in the filtering or not.
9936
	 *  @type boolean
9937
	 */
9938
	"bSearchable": null,
9939

9940
	/**
9941
	 * Flag to indicate if the column is sortable or not.
9942
	 *  @type boolean
9943
	 */
9944
	"bSortable": null,
9945

9946
	/**
9947
	 * Flag to indicate if the column is currently visible in the table or not
9948
	 *  @type boolean
9949
	 */
9950
	"bVisible": null,
9951

9952
	/**
9953
	 * Store for manual type assignment using the `column.type` option. This
9954
	 * is held in store so we can manipulate the column's `sType` property.
9955
	 *  @type string
9956
	 *  @default null
9957
	 *  @private
9958
	 */
9959
	"_sManualType": null,
9960

9961
	/**
9962
	 * Flag to indicate if HTML5 data attributes should be used as the data
9963
	 * source for filtering or sorting. True is either are.
9964
	 *  @type boolean
9965
	 *  @default false
9966
	 *  @private
9967
	 */
9968
	"_bAttrSrc": false,
9969

9970
	/**
9971
	 * Developer definable function that is called whenever a cell is created (Ajax source,
9972
	 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
9973
	 * allowing you to modify the DOM element (add background colour for example) when the
9974
	 * element is available.
9975
	 *  @type function
9976
	 *  @param {element} nTd The TD node that has been created
9977
	 *  @param {*} sData The Data for the cell
9978
	 *  @param {array|object} oData The data for the whole row
9979
	 *  @param {int} iRow The row index for the aoData data store
9980
	 *  @default null
9981
	 */
9982
	"fnCreatedCell": null,
9983

9984
	/**
9985
	 * Function to get data from a cell in a column. You should <b>never</b>
9986
	 * access data directly through _aData internally in DataTables - always use
9987
	 * the method attached to this property. It allows mData to function as
9988
	 * required. This function is automatically assigned by the column
9989
	 * initialisation method
9990
	 *  @type function
9991
	 *  @param {array|object} oData The data array/object for the array
9992
	 *    (i.e. aoData[]._aData)
9993
	 *  @param {string} sSpecific The specific data type you want to get -
9994
	 *    'display', 'type' 'filter' 'sort'
9995
	 *  @returns {*} The data for the cell from the given row's data
9996
	 *  @default null
9997
	 */
9998
	"fnGetData": null,
9999

10000
	/**
10001
	 * Function to set data for a cell in the column. You should <b>never</b>
10002
	 * set the data directly to _aData internally in DataTables - always use
10003
	 * this method. It allows mData to function as required. This function
10004
	 * is automatically assigned by the column initialisation method
10005
	 *  @type function
10006
	 *  @param {array|object} oData The data array/object for the array
10007
	 *    (i.e. aoData[]._aData)
10008
	 *  @param {*} sValue Value to set
10009
	 *  @default null
10010
	 */
10011
	"fnSetData": null,
10012

10013
	/**
10014
	 * Property to read the value for the cells in the column from the data
10015
	 * source array / object. If null, then the default content is used, if a
10016
	 * function is given then the return from the function is used.
10017
	 *  @type function|int|string|null
10018
	 *  @default null
10019
	 */
10020
	"mData": null,
10021

10022
	/**
10023
	 * Partner property to mData which is used (only when defined) to get
10024
	 * the data - i.e. it is basically the same as mData, but without the
10025
	 * 'set' option, and also the data fed to it is the result from mData.
10026
	 * This is the rendering method to match the data method of mData.
10027
	 *  @type function|int|string|null
10028
	 *  @default null
10029
	 */
10030
	"mRender": null,
10031

10032
	/**
10033
	 * Unique header TH/TD element for this column - this is what the sorting
10034
	 * listener is attached to (if sorting is enabled.)
10035
	 *  @type node
10036
	 *  @default null
10037
	 */
10038
	"nTh": null,
10039

10040
	/**
10041
	 * Unique footer TH/TD element for this column (if there is one). Not used
10042
	 * in DataTables as such, but can be used for plug-ins to reference the
10043
	 * footer for each column.
10044
	 *  @type node
10045
	 *  @default null
10046
	 */
10047
	"nTf": null,
10048

10049
	/**
10050
	 * The class to apply to all TD elements in the table's TBODY for the column
10051
	 *  @type string
10052
	 *  @default null
10053
	 */
10054
	"sClass": null,
10055

10056
	/**
10057
	 * When DataTables calculates the column widths to assign to each column,
10058
	 * it finds the longest string in each column and then constructs a
10059
	 * temporary table and reads the widths from that. The problem with this
10060
	 * is that "mmm" is much wider then "iiii", but the latter is a longer
10061
	 * string - thus the calculation can go wrong (doing it properly and putting
10062
	 * it into an DOM object and measuring that is horribly(!) slow). Thus as
10063
	 * a "work around" we provide this option. It will append its value to the
10064
	 * text that is found to be the longest string for the column - i.e. padding.
10065
	 *  @type string
10066
	 */
10067
	"sContentPadding": null,
10068

10069
	/**
10070
	 * Allows a default value to be given for a column's data, and will be used
10071
	 * whenever a null data source is encountered (this can be because mData
10072
	 * is set to null, or because the data source itself is null).
10073
	 *  @type string
10074
	 *  @default null
10075
	 */
10076
	"sDefaultContent": null,
10077

10078
	/**
10079
	 * Name for the column, allowing reference to the column by name as well as
10080
	 * by index (needs a lookup to work by name).
10081
	 *  @type string
10082
	 */
10083
	"sName": null,
10084

10085
	/**
10086
	 * Custom sorting data type - defines which of the available plug-ins in
10087
	 * afnSortData the custom sorting will use - if any is defined.
10088
	 *  @type string
10089
	 *  @default std
10090
	 */
10091
	"sSortDataType": 'std',
10092

10093
	/**
10094
	 * Class to be applied to the header element when sorting on this column
10095
	 *  @type string
10096
	 *  @default null
10097
	 */
10098
	"sSortingClass": null,
10099

10100
	/**
10101
	 * Class to be applied to the header element when sorting on this column -
10102
	 * when jQuery UI theming is used.
10103
	 *  @type string
10104
	 *  @default null
10105
	 */
10106
	"sSortingClassJUI": null,
10107

10108
	/**
10109
	 * Title of the column - what is seen in the TH element (nTh).
10110
	 *  @type string
10111
	 */
10112
	"sTitle": null,
10113

10114
	/**
10115
	 * Column sorting and filtering type
10116
	 *  @type string
10117
	 *  @default null
10118
	 */
10119
	"sType": null,
10120

10121
	/**
10122
	 * Width of the column
10123
	 *  @type string
10124
	 *  @default null
10125
	 */
10126
	"sWidth": null,
10127

10128
	/**
10129
	 * Width of the column when it was first "encountered"
10130
	 *  @type string
10131
	 *  @default null
10132
	 */
10133
	"sWidthOrig": null
10134
};
10135

10136

10137
/*
10138
 * Developer note: The properties of the object below are given in Hungarian
10139
 * notation, that was used as the interface for DataTables prior to v1.10, however
10140
 * from v1.10 onwards the primary interface is camel case. In order to avoid
10141
 * breaking backwards compatibility utterly with this change, the Hungarian
10142
 * version is still, internally the primary interface, but is is not documented
10143
 * - hence the @name tags in each doc comment. This allows a Javascript function
10144
 * to create a map from Hungarian notation to camel case (going the other direction
10145
 * would require each property to be listed, which would add around 3K to the size
10146
 * of DataTables, while this method is about a 0.5K hit).
10147
 *
10148
 * Ultimately this does pave the way for Hungarian notation to be dropped
10149
 * completely, but that is a massive amount of work and will break current
10150
 * installs (therefore is on-hold until v2).
10151
 */
10152

10153
/**
10154
 * Initialisation options that can be given to DataTables at initialisation
10155
 * time.
10156
 *  @namespace
10157
 */
10158
DataTable.defaults = {
10159
	/**
10160
	 * An array of data to use for the table, passed in at initialisation which
10161
	 * will be used in preference to any data which is already in the DOM. This is
10162
	 * particularly useful for constructing tables purely in Javascript, for
10163
	 * example with a custom Ajax call.
10164
	 *  @type array
10165
	 *  @default null
10166
	 *
10167
	 *  @dtopt Option
10168
	 *  @name DataTable.defaults.data
10169
	 *
10170
	 *  @example
10171
	 *    // Using a 2D array data source
10172
	 *    $(document).ready( function () {
10173
	 *      $('#example').dataTable( {
10174
	 *        "data": [
10175
	 *          ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
10176
	 *          ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
10177
	 *        ],
10178
	 *        "columns": [
10179
	 *          { "title": "Engine" },
10180
	 *          { "title": "Browser" },
10181
	 *          { "title": "Platform" },
10182
	 *          { "title": "Version" },
10183
	 *          { "title": "Grade" }
10184
	 *        ]
10185
	 *      } );
10186
	 *    } );
10187
	 *
10188
	 *  @example
10189
	 *    // Using an array of objects as a data source (`data`)
10190
	 *    $(document).ready( function () {
10191
	 *      $('#example').dataTable( {
10192
	 *        "data": [
10193
	 *          {
10194
	 *            "engine":   "Trident",
10195
	 *            "browser":  "Internet Explorer 4.0",
10196
	 *            "platform": "Win 95+",
10197
	 *            "version":  4,
10198
	 *            "grade":    "X"
10199
	 *          },
10200
	 *          {
10201
	 *            "engine":   "Trident",
10202
	 *            "browser":  "Internet Explorer 5.0",
10203
	 *            "platform": "Win 95+",
10204
	 *            "version":  5,
10205
	 *            "grade":    "C"
10206
	 *          }
10207
	 *        ],
10208
	 *        "columns": [
10209
	 *          { "title": "Engine",   "data": "engine" },
10210
	 *          { "title": "Browser",  "data": "browser" },
10211
	 *          { "title": "Platform", "data": "platform" },
10212
	 *          { "title": "Version",  "data": "version" },
10213
	 *          { "title": "Grade",    "data": "grade" }
10214
	 *        ]
10215
	 *      } );
10216
	 *    } );
10217
	 */
10218
	"aaData": null,
10219

10220

10221
	/**
10222
	 * If ordering is enabled, then DataTables will perform a first pass sort on
10223
	 * initialisation. You can define which column(s) the sort is performed
10224
	 * upon, and the sorting direction, with this variable. The `sorting` array
10225
	 * should contain an array for each column to be sorted initially containing
10226
	 * the column's index and a direction string ('asc' or 'desc').
10227
	 *  @type array
10228
	 *  @default [[0,'asc']]
10229
	 *
10230
	 *  @dtopt Option
10231
	 *  @name DataTable.defaults.order
10232
	 *
10233
	 *  @example
10234
	 *    // Sort by 3rd column first, and then 4th column
10235
	 *    $(document).ready( function() {
10236
	 *      $('#example').dataTable( {
10237
	 *        "order": [[2,'asc'], [3,'desc']]
10238
	 *      } );
10239
	 *    } );
10240
	 *
10241
	 *    // No initial sorting
10242
	 *    $(document).ready( function() {
10243
	 *      $('#example').dataTable( {
10244
	 *        "order": []
10245
	 *      } );
10246
	 *    } );
10247
	 */
10248
	"aaSorting": [[0,'asc']],
10249

10250

10251
	/**
10252
	 * This parameter is basically identical to the `sorting` parameter, but
10253
	 * cannot be overridden by user interaction with the table. What this means
10254
	 * is that you could have a column (visible or hidden) which the sorting
10255
	 * will always be forced on first - any sorting after that (from the user)
10256
	 * will then be performed as required. This can be useful for grouping rows
10257
	 * together.
10258
	 *  @type array
10259
	 *  @default null
10260
	 *
10261
	 *  @dtopt Option
10262
	 *  @name DataTable.defaults.orderFixed
10263
	 *
10264
	 *  @example
10265
	 *    $(document).ready( function() {
10266
	 *      $('#example').dataTable( {
10267
	 *        "orderFixed": [[0,'asc']]
10268
	 *      } );
10269
	 *    } )
10270
	 */
10271
	"aaSortingFixed": [],
10272

10273

10274
	/**
10275
	 * DataTables can be instructed to load data to display in the table from a
10276
	 * Ajax source. This option defines how that Ajax call is made and where to.
10277
	 *
10278
	 * The `ajax` property has three different modes of operation, depending on
10279
	 * how it is defined. These are:
10280
	 *
10281
	 * * `string` - Set the URL from where the data should be loaded from.
10282
	 * * `object` - Define properties for `jQuery.ajax`.
10283
	 * * `function` - Custom data get function
10284
	 *
10285
	 * `string`
10286
	 * --------
10287
	 *
10288
	 * As a string, the `ajax` property simply defines the URL from which
10289
	 * DataTables will load data.
10290
	 *
10291
	 * `object`
10292
	 * --------
10293
	 *
10294
	 * As an object, the parameters in the object are passed to
10295
	 * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control
10296
	 * of the Ajax request. DataTables has a number of default parameters which
10297
	 * you can override using this option. Please refer to the jQuery
10298
	 * documentation for a full description of the options available, although
10299
	 * the following parameters provide additional options in DataTables or
10300
	 * require special consideration:
10301
	 *
10302
	 * * `data` - As with jQuery, `data` can be provided as an object, but it
10303
	 *   can also be used as a function to manipulate the data DataTables sends
10304
	 *   to the server. The function takes a single parameter, an object of
10305
	 *   parameters with the values that DataTables has readied for sending. An
10306
	 *   object may be returned which will be merged into the DataTables
10307
	 *   defaults, or you can add the items to the object that was passed in and
10308
	 *   not return anything from the function. This supersedes `fnServerParams`
10309
	 *   from DataTables 1.9-.
10310
	 *
10311
	 * * `dataSrc` - By default DataTables will look for the property `data` (or
10312
	 *   `aaData` for compatibility with DataTables 1.9-) when obtaining data
10313
	 *   from an Ajax source or for server-side processing - this parameter
10314
	 *   allows that property to be changed. You can use Javascript dotted
10315
	 *   object notation to get a data source for multiple levels of nesting, or
10316
	 *   it my be used as a function. As a function it takes a single parameter,
10317
	 *   the JSON returned from the server, which can be manipulated as
10318
	 *   required, with the returned value being that used by DataTables as the
10319
	 *   data source for the table. This supersedes `sAjaxDataProp` from
10320
	 *   DataTables 1.9-.
10321
	 *
10322
	 * * `success` - Should not be overridden it is used internally in
10323
	 *   DataTables. To manipulate / transform the data returned by the server
10324
	 *   use `ajax.dataSrc`, or use `ajax` as a function (see below).
10325
	 *
10326
	 * `function`
10327
	 * ----------
10328
	 *
10329
	 * As a function, making the Ajax call is left up to yourself allowing
10330
	 * complete control of the Ajax request. Indeed, if desired, a method other
10331
	 * than Ajax could be used to obtain the required data, such as Web storage
10332
	 * or an AIR database.
10333
	 *
10334
	 * The function is given four parameters and no return is required. The
10335
	 * parameters are:
10336
	 *
10337
	 * 1. _object_ - Data to send to the server
10338
	 * 2. _function_ - Callback function that must be executed when the required
10339
	 *    data has been obtained. That data should be passed into the callback
10340
	 *    as the only parameter
10341
	 * 3. _object_ - DataTables settings object for the table
10342
	 *
10343
	 * Note that this supersedes `fnServerData` from DataTables 1.9-.
10344
	 *
10345
	 *  @type string|object|function
10346
	 *  @default null
10347
	 *
10348
	 *  @dtopt Option
10349
	 *  @name DataTable.defaults.ajax
10350
	 *  @since 1.10.0
10351
	 *
10352
	 * @example
10353
	 *   // Get JSON data from a file via Ajax.
10354
	 *   // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default).
10355
	 *   $('#example').dataTable( {
10356
	 *     "ajax": "data.json"
10357
	 *   } );
10358
	 *
10359
	 * @example
10360
	 *   // Get JSON data from a file via Ajax, using `dataSrc` to change
10361
	 *   // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`)
10362
	 *   $('#example').dataTable( {
10363
	 *     "ajax": {
10364
	 *       "url": "data.json",
10365
	 *       "dataSrc": "tableData"
10366
	 *     }
10367
	 *   } );
10368
	 *
10369
	 * @example
10370
	 *   // Get JSON data from a file via Ajax, using `dataSrc` to read data
10371
	 *   // from a plain array rather than an array in an object
10372
	 *   $('#example').dataTable( {
10373
	 *     "ajax": {
10374
	 *       "url": "data.json",
10375
	 *       "dataSrc": ""
10376
	 *     }
10377
	 *   } );
10378
	 *
10379
	 * @example
10380
	 *   // Manipulate the data returned from the server - add a link to data
10381
	 *   // (note this can, should, be done using `render` for the column - this
10382
	 *   // is just a simple example of how the data can be manipulated).
10383
	 *   $('#example').dataTable( {
10384
	 *     "ajax": {
10385
	 *       "url": "data.json",
10386
	 *       "dataSrc": function ( json ) {
10387
	 *         for ( var i=0, ien=json.length ; i<ien ; i++ ) {
10388
	 *           json[i][0] = '<a href="/message/'+json[i][0]+'>View message</a>';
10389
	 *         }
10390
	 *         return json;
10391
	 *       }
10392
	 *     }
10393
	 *   } );
10394
	 *
10395
	 * @example
10396
	 *   // Add data to the request
10397
	 *   $('#example').dataTable( {
10398
	 *     "ajax": {
10399
	 *       "url": "data.json",
10400
	 *       "data": function ( d ) {
10401
	 *         return {
10402
	 *           "extra_search": $('#extra').val()
10403
	 *         };
10404
	 *       }
10405
	 *     }
10406
	 *   } );
10407
	 *
10408
	 * @example
10409
	 *   // Send request as POST
10410
	 *   $('#example').dataTable( {
10411
	 *     "ajax": {
10412
	 *       "url": "data.json",
10413
	 *       "type": "POST"
10414
	 *     }
10415
	 *   } );
10416
	 *
10417
	 * @example
10418
	 *   // Get the data from localStorage (could interface with a form for
10419
	 *   // adding, editing and removing rows).
10420
	 *   $('#example').dataTable( {
10421
	 *     "ajax": function (data, callback, settings) {
10422
	 *       callback(
10423
	 *         JSON.parse( localStorage.getItem('dataTablesData') )
10424
	 *       );
10425
	 *     }
10426
	 *   } );
10427
	 */
10428
	"ajax": null,
10429

10430

10431
	/**
10432
	 * This parameter allows you to readily specify the entries in the length drop
10433
	 * down menu that DataTables shows when pagination is enabled. It can be
10434
	 * either a 1D array of options which will be used for both the displayed
10435
	 * option and the value, or a 2D array which will use the array in the first
10436
	 * position as the value, and the array in the second position as the
10437
	 * displayed options (useful for language strings such as 'All').
10438
	 *
10439
	 * Note that the `pageLength` property will be automatically set to the
10440
	 * first value given in this array, unless `pageLength` is also provided.
10441
	 *  @type array
10442
	 *  @default [ 10, 25, 50, 100 ]
10443
	 *
10444
	 *  @dtopt Option
10445
	 *  @name DataTable.defaults.lengthMenu
10446
	 *
10447
	 *  @example
10448
	 *    $(document).ready( function() {
10449
	 *      $('#example').dataTable( {
10450
	 *        "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
10451
	 *      } );
10452
	 *    } );
10453
	 */
10454
	"aLengthMenu": [ 10, 25, 50, 100 ],
10455

10456

10457
	/**
10458
	 * The `columns` option in the initialisation parameter allows you to define
10459
	 * details about the way individual columns behave. For a full list of
10460
	 * column options that can be set, please see
10461
	 * {@link DataTable.defaults.column}. Note that if you use `columns` to
10462
	 * define your columns, you must have an entry in the array for every single
10463
	 * column that you have in your table (these can be null if you don't which
10464
	 * to specify any options).
10465
	 *  @member
10466
	 *
10467
	 *  @name DataTable.defaults.column
10468
	 */
10469
	"aoColumns": null,
10470

10471
	/**
10472
	 * Very similar to `columns`, `columnDefs` allows you to target a specific
10473
	 * column, multiple columns, or all columns, using the `targets` property of
10474
	 * each object in the array. This allows great flexibility when creating
10475
	 * tables, as the `columnDefs` arrays can be of any length, targeting the
10476
	 * columns you specifically want. `columnDefs` may use any of the column
10477
	 * options available: {@link DataTable.defaults.column}, but it _must_
10478
	 * have `targets` defined in each object in the array. Values in the `targets`
10479
	 * array may be:
10480
	 *   <ul>
10481
	 *     <li>a string - class name will be matched on the TH for the column</li>
10482
	 *     <li>0 or a positive integer - column index counting from the left</li>
10483
	 *     <li>a negative integer - column index counting from the right</li>
10484
	 *     <li>the string "_all" - all columns (i.e. assign a default)</li>
10485
	 *   </ul>
10486
	 *  @member
10487
	 *
10488
	 *  @name DataTable.defaults.columnDefs
10489
	 */
10490
	"aoColumnDefs": null,
10491

10492

10493
	/**
10494
	 * Basically the same as `search`, this parameter defines the individual column
10495
	 * filtering state at initialisation time. The array must be of the same size
10496
	 * as the number of columns, and each element be an object with the parameters
10497
	 * `search` and `escapeRegex` (the latter is optional). 'null' is also
10498
	 * accepted and the default will be used.
10499
	 *  @type array
10500
	 *  @default []
10501
	 *
10502
	 *  @dtopt Option
10503
	 *  @name DataTable.defaults.searchCols
10504
	 *
10505
	 *  @example
10506
	 *    $(document).ready( function() {
10507
	 *      $('#example').dataTable( {
10508
	 *        "searchCols": [
10509
	 *          null,
10510
	 *          { "search": "My filter" },
10511
	 *          null,
10512
	 *          { "search": "^[0-9]", "escapeRegex": false }
10513
	 *        ]
10514
	 *      } );
10515
	 *    } )
10516
	 */
10517
	"aoSearchCols": [],
10518

10519

10520
	/**
10521
	 * An array of CSS classes that should be applied to displayed rows. This
10522
	 * array may be of any length, and DataTables will apply each class
10523
	 * sequentially, looping when required.
10524
	 *  @type array
10525
	 *  @default null <i>Will take the values determined by the `oClasses.stripe*`
10526
	 *    options</i>
10527
	 *
10528
	 *  @dtopt Option
10529
	 *  @name DataTable.defaults.stripeClasses
10530
	 *
10531
	 *  @example
10532
	 *    $(document).ready( function() {
10533
	 *      $('#example').dataTable( {
10534
	 *        "stripeClasses": [ 'strip1', 'strip2', 'strip3' ]
10535
	 *      } );
10536
	 *    } )
10537
	 */
10538
	"asStripeClasses": null,
10539

10540

10541
	/**
10542
	 * Enable or disable automatic column width calculation. This can be disabled
10543
	 * as an optimisation (it takes some time to calculate the widths) if the
10544
	 * tables widths are passed in using `columns`.
10545
	 *  @type boolean
10546
	 *  @default true
10547
	 *
10548
	 *  @dtopt Features
10549
	 *  @name DataTable.defaults.autoWidth
10550
	 *
10551
	 *  @example
10552
	 *    $(document).ready( function () {
10553
	 *      $('#example').dataTable( {
10554
	 *        "autoWidth": false
10555
	 *      } );
10556
	 *    } );
10557
	 */
10558
	"bAutoWidth": true,
10559

10560

10561
	/**
10562
	 * Deferred rendering can provide DataTables with a huge speed boost when you
10563
	 * are using an Ajax or JS data source for the table. This option, when set to
10564
	 * true, will cause DataTables to defer the creation of the table elements for
10565
	 * each row until they are needed for a draw - saving a significant amount of
10566
	 * time.
10567
	 *  @type boolean
10568
	 *  @default false
10569
	 *
10570
	 *  @dtopt Features
10571
	 *  @name DataTable.defaults.deferRender
10572
	 *
10573
	 *  @example
10574
	 *    $(document).ready( function() {
10575
	 *      $('#example').dataTable( {
10576
	 *        "ajax": "sources/arrays.txt",
10577
	 *        "deferRender": true
10578
	 *      } );
10579
	 *    } );
10580
	 */
10581
	"bDeferRender": false,
10582

10583

10584
	/**
10585
	 * Replace a DataTable which matches the given selector and replace it with
10586
	 * one which has the properties of the new initialisation object passed. If no
10587
	 * table matches the selector, then the new DataTable will be constructed as
10588
	 * per normal.
10589
	 *  @type boolean
10590
	 *  @default false
10591
	 *
10592
	 *  @dtopt Options
10593
	 *  @name DataTable.defaults.destroy
10594
	 *
10595
	 *  @example
10596
	 *    $(document).ready( function() {
10597
	 *      $('#example').dataTable( {
10598
	 *        "srollY": "200px",
10599
	 *        "paginate": false
10600
	 *      } );
10601
	 *
10602
	 *      // Some time later....
10603
	 *      $('#example').dataTable( {
10604
	 *        "filter": false,
10605
	 *        "destroy": true
10606
	 *      } );
10607
	 *    } );
10608
	 */
10609
	"bDestroy": false,
10610

10611

10612
	/**
10613
	 * Enable or disable filtering of data. Filtering in DataTables is "smart" in
10614
	 * that it allows the end user to input multiple words (space separated) and
10615
	 * will match a row containing those words, even if not in the order that was
10616
	 * specified (this allow matching across multiple columns). Note that if you
10617
	 * wish to use filtering in DataTables this must remain 'true' - to remove the
10618
	 * default filtering input box and retain filtering abilities, please use
10619
	 * {@link DataTable.defaults.dom}.
10620
	 *  @type boolean
10621
	 *  @default true
10622
	 *
10623
	 *  @dtopt Features
10624
	 *  @name DataTable.defaults.searching
10625
	 *
10626
	 *  @example
10627
	 *    $(document).ready( function () {
10628
	 *      $('#example').dataTable( {
10629
	 *        "searching": false
10630
	 *      } );
10631
	 *    } );
10632
	 */
10633
	"bFilter": true,
10634

10635

10636
	/**
10637
	 * Enable or disable the table information display. This shows information
10638
	 * about the data that is currently visible on the page, including information
10639
	 * about filtered data if that action is being performed.
10640
	 *  @type boolean
10641
	 *  @default true
10642
	 *
10643
	 *  @dtopt Features
10644
	 *  @name DataTable.defaults.info
10645
	 *
10646
	 *  @example
10647
	 *    $(document).ready( function () {
10648
	 *      $('#example').dataTable( {
10649
	 *        "info": false
10650
	 *      } );
10651
	 *    } );
10652
	 */
10653
	"bInfo": true,
10654

10655

10656
	/**
10657
	 * Allows the end user to select the size of a formatted page from a select
10658
	 * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`).
10659
	 *  @type boolean
10660
	 *  @default true
10661
	 *
10662
	 *  @dtopt Features
10663
	 *  @name DataTable.defaults.lengthChange
10664
	 *
10665
	 *  @example
10666
	 *    $(document).ready( function () {
10667
	 *      $('#example').dataTable( {
10668
	 *        "lengthChange": false
10669
	 *      } );
10670
	 *    } );
10671
	 */
10672
	"bLengthChange": true,
10673

10674

10675
	/**
10676
	 * Enable or disable pagination.
10677
	 *  @type boolean
10678
	 *  @default true
10679
	 *
10680
	 *  @dtopt Features
10681
	 *  @name DataTable.defaults.paging
10682
	 *
10683
	 *  @example
10684
	 *    $(document).ready( function () {
10685
	 *      $('#example').dataTable( {
10686
	 *        "paging": false
10687
	 *      } );
10688
	 *    } );
10689
	 */
10690
	"bPaginate": true,
10691

10692

10693
	/**
10694
	 * Enable or disable the display of a 'processing' indicator when the table is
10695
	 * being processed (e.g. a sort). This is particularly useful for tables with
10696
	 * large amounts of data where it can take a noticeable amount of time to sort
10697
	 * the entries.
10698
	 *  @type boolean
10699
	 *  @default false
10700
	 *
10701
	 *  @dtopt Features
10702
	 *  @name DataTable.defaults.processing
10703
	 *
10704
	 *  @example
10705
	 *    $(document).ready( function () {
10706
	 *      $('#example').dataTable( {
10707
	 *        "processing": true
10708
	 *      } );
10709
	 *    } );
10710
	 */
10711
	"bProcessing": false,
10712

10713

10714
	/**
10715
	 * Retrieve the DataTables object for the given selector. Note that if the
10716
	 * table has already been initialised, this parameter will cause DataTables
10717
	 * to simply return the object that has already been set up - it will not take
10718
	 * account of any changes you might have made to the initialisation object
10719
	 * passed to DataTables (setting this parameter to true is an acknowledgement
10720
	 * that you understand this). `destroy` can be used to reinitialise a table if
10721
	 * you need.
10722
	 *  @type boolean
10723
	 *  @default false
10724
	 *
10725
	 *  @dtopt Options
10726
	 *  @name DataTable.defaults.retrieve
10727
	 *
10728
	 *  @example
10729
	 *    $(document).ready( function() {
10730
	 *      initTable();
10731
	 *      tableActions();
10732
	 *    } );
10733
	 *
10734
	 *    function initTable ()
10735
	 *    {
10736
	 *      return $('#example').dataTable( {
10737
	 *        "scrollY": "200px",
10738
	 *        "paginate": false,
10739
	 *        "retrieve": true
10740
	 *      } );
10741
	 *    }
10742
	 *
10743
	 *    function tableActions ()
10744
	 *    {
10745
	 *      var table = initTable();
10746
	 *      // perform API operations with oTable
10747
	 *    }
10748
	 */
10749
	"bRetrieve": false,
10750

10751

10752
	/**
10753
	 * When vertical (y) scrolling is enabled, DataTables will force the height of
10754
	 * the table's viewport to the given height at all times (useful for layout).
10755
	 * However, this can look odd when filtering data down to a small data set,
10756
	 * and the footer is left "floating" further down. This parameter (when
10757
	 * enabled) will cause DataTables to collapse the table's viewport down when
10758
	 * the result set will fit within the given Y height.
10759
	 *  @type boolean
10760
	 *  @default false
10761
	 *
10762
	 *  @dtopt Options
10763
	 *  @name DataTable.defaults.scrollCollapse
10764
	 *
10765
	 *  @example
10766
	 *    $(document).ready( function() {
10767
	 *      $('#example').dataTable( {
10768
	 *        "scrollY": "200",
10769
	 *        "scrollCollapse": true
10770
	 *      } );
10771
	 *    } );
10772
	 */
10773
	"bScrollCollapse": false,
10774

10775

10776
	/**
10777
	 * Configure DataTables to use server-side processing. Note that the
10778
	 * `ajax` parameter must also be given in order to give DataTables a
10779
	 * source to obtain the required data for each draw.
10780
	 *  @type boolean
10781
	 *  @default false
10782
	 *
10783
	 *  @dtopt Features
10784
	 *  @dtopt Server-side
10785
	 *  @name DataTable.defaults.serverSide
10786
	 *
10787
	 *  @example
10788
	 *    $(document).ready( function () {
10789
	 *      $('#example').dataTable( {
10790
	 *        "serverSide": true,
10791
	 *        "ajax": "xhr.php"
10792
	 *      } );
10793
	 *    } );
10794
	 */
10795
	"bServerSide": false,
10796

10797

10798
	/**
10799
	 * Enable or disable sorting of columns. Sorting of individual columns can be
10800
	 * disabled by the `sortable` option for each column.
10801
	 *  @type boolean
10802
	 *  @default true
10803
	 *
10804
	 *  @dtopt Features
10805
	 *  @name DataTable.defaults.ordering
10806
	 *
10807
	 *  @example
10808
	 *    $(document).ready( function () {
10809
	 *      $('#example').dataTable( {
10810
	 *        "ordering": false
10811
	 *      } );
10812
	 *    } );
10813
	 */
10814
	"bSort": true,
10815

10816

10817
	/**
10818
	 * Enable or display DataTables' ability to sort multiple columns at the
10819
	 * same time (activated by shift-click by the user).
10820
	 *  @type boolean
10821
	 *  @default true
10822
	 *
10823
	 *  @dtopt Options
10824
	 *  @name DataTable.defaults.orderMulti
10825
	 *
10826
	 *  @example
10827
	 *    // Disable multiple column sorting ability
10828
	 *    $(document).ready( function () {
10829
	 *      $('#example').dataTable( {
10830
	 *        "orderMulti": false
10831
	 *      } );
10832
	 *    } );
10833
	 */
10834
	"bSortMulti": true,
10835

10836

10837
	/**
10838
	 * Allows control over whether DataTables should use the top (true) unique
10839
	 * cell that is found for a single column, or the bottom (false - default).
10840
	 * This is useful when using complex headers.
10841
	 *  @type boolean
10842
	 *  @default false
10843
	 *
10844
	 *  @dtopt Options
10845
	 *  @name DataTable.defaults.orderCellsTop
10846
	 *
10847
	 *  @example
10848
	 *    $(document).ready( function() {
10849
	 *      $('#example').dataTable( {
10850
	 *        "orderCellsTop": true
10851
	 *      } );
10852
	 *    } );
10853
	 */
10854
	"bSortCellsTop": false,
10855

10856

10857
	/**
10858
	 * Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and
10859
	 * `sorting\_3` to the columns which are currently being sorted on. This is
10860
	 * presented as a feature switch as it can increase processing time (while
10861
	 * classes are removed and added) so for large data sets you might want to
10862
	 * turn this off.
10863
	 *  @type boolean
10864
	 *  @default true
10865
	 *
10866
	 *  @dtopt Features
10867
	 *  @name DataTable.defaults.orderClasses
10868
	 *
10869
	 *  @example
10870
	 *    $(document).ready( function () {
10871
	 *      $('#example').dataTable( {
10872
	 *        "orderClasses": false
10873
	 *      } );
10874
	 *    } );
10875
	 */
10876
	"bSortClasses": true,
10877

10878

10879
	/**
10880
	 * Enable or disable state saving. When enabled HTML5 `localStorage` will be
10881
	 * used to save table display information such as pagination information,
10882
	 * display length, filtering and sorting. As such when the end user reloads
10883
	 * the page the display display will match what thy had previously set up.
10884
	 *
10885
	 * Due to the use of `localStorage` the default state saving is not supported
10886
	 * in IE6 or 7. If state saving is required in those browsers, use
10887
	 * `stateSaveCallback` to provide a storage solution such as cookies.
10888
	 *  @type boolean
10889
	 *  @default false
10890
	 *
10891
	 *  @dtopt Features
10892
	 *  @name DataTable.defaults.stateSave
10893
	 *
10894
	 *  @example
10895
	 *    $(document).ready( function () {
10896
	 *      $('#example').dataTable( {
10897
	 *        "stateSave": true
10898
	 *      } );
10899
	 *    } );
10900
	 */
10901
	"bStateSave": false,
10902

10903

10904
	/**
10905
	 * This function is called when a TR element is created (and all TD child
10906
	 * elements have been inserted), or registered if using a DOM source, allowing
10907
	 * manipulation of the TR element (adding classes etc).
10908
	 *  @type function
10909
	 *  @param {node} row "TR" element for the current row
10910
	 *  @param {array} data Raw data array for this row
10911
	 *  @param {int} dataIndex The index of this row in the internal aoData array
10912
	 *
10913
	 *  @dtopt Callbacks
10914
	 *  @name DataTable.defaults.createdRow
10915
	 *
10916
	 *  @example
10917
	 *    $(document).ready( function() {
10918
	 *      $('#example').dataTable( {
10919
	 *        "createdRow": function( row, data, dataIndex ) {
10920
	 *          // Bold the grade for all 'A' grade browsers
10921
	 *          if ( data[4] == "A" )
10922
	 *          {
10923
	 *            $('td:eq(4)', row).html( '<b>A</b>' );
10924
	 *          }
10925
	 *        }
10926
	 *      } );
10927
	 *    } );
10928
	 */
10929
	"fnCreatedRow": null,
10930

10931

10932
	/**
10933
	 * This function is called on every 'draw' event, and allows you to
10934
	 * dynamically modify any aspect you want about the created DOM.
10935
	 *  @type function
10936
	 *  @param {object} settings DataTables settings object
10937
	 *
10938
	 *  @dtopt Callbacks
10939
	 *  @name DataTable.defaults.drawCallback
10940
	 *
10941
	 *  @example
10942
	 *    $(document).ready( function() {
10943
	 *      $('#example').dataTable( {
10944
	 *        "drawCallback": function( settings ) {
10945
	 *          alert( 'DataTables has redrawn the table' );
10946
	 *        }
10947
	 *      } );
10948
	 *    } );
10949
	 */
10950
	"fnDrawCallback": null,
10951

10952

10953
	/**
10954
	 * Identical to fnHeaderCallback() but for the table footer this function
10955
	 * allows you to modify the table footer on every 'draw' event.
10956
	 *  @type function
10957
	 *  @param {node} foot "TR" element for the footer
10958
	 *  @param {array} data Full table data (as derived from the original HTML)
10959
	 *  @param {int} start Index for the current display starting point in the
10960
	 *    display array
10961
	 *  @param {int} end Index for the current display ending point in the
10962
	 *    display array
10963
	 *  @param {array int} display Index array to translate the visual position
10964
	 *    to the full data array
10965
	 *
10966
	 *  @dtopt Callbacks
10967
	 *  @name DataTable.defaults.footerCallback
10968
	 *
10969
	 *  @example
10970
	 *    $(document).ready( function() {
10971
	 *      $('#example').dataTable( {
10972
	 *        "footerCallback": function( tfoot, data, start, end, display ) {
10973
	 *          tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start;
10974
	 *        }
10975
	 *      } );
10976
	 *    } )
10977
	 */
10978
	"fnFooterCallback": null,
10979

10980

10981
	/**
10982
	 * When rendering large numbers in the information element for the table
10983
	 * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
10984
	 * to have a comma separator for the 'thousands' units (e.g. 1 million is
10985
	 * rendered as "1,000,000") to help readability for the end user. This
10986
	 * function will override the default method DataTables uses.
10987
	 *  @type function
10988
	 *  @member
10989
	 *  @param {int} toFormat number to be formatted
10990
	 *  @returns {string} formatted string for DataTables to show the number
10991
	 *
10992
	 *  @dtopt Callbacks
10993
	 *  @name DataTable.defaults.formatNumber
10994
	 *
10995
	 *  @example
10996
	 *    // Format a number using a single quote for the separator (note that
10997
	 *    // this can also be done with the language.thousands option)
10998
	 *    $(document).ready( function() {
10999
	 *      $('#example').dataTable( {
11000
	 *        "formatNumber": function ( toFormat ) {
11001
	 *          return toFormat.toString().replace(
11002
	 *            /\B(?=(\d{3})+(?!\d))/g, "'"
11003
	 *          );
11004
	 *        };
11005
	 *      } );
11006
	 *    } );
11007
	 */
11008
	"fnFormatNumber": function ( toFormat ) {
11009
		return toFormat.toString().replace(
11010
			/\B(?=(\d{3})+(?!\d))/g,
11011
			this.oLanguage.sThousands
11012
		);
11013
	},
11014

11015

11016
	/**
11017
	 * This function is called on every 'draw' event, and allows you to
11018
	 * dynamically modify the header row. This can be used to calculate and
11019
	 * display useful information about the table.
11020
	 *  @type function
11021
	 *  @param {node} head "TR" element for the header
11022
	 *  @param {array} data Full table data (as derived from the original HTML)
11023
	 *  @param {int} start Index for the current display starting point in the
11024
	 *    display array
11025
	 *  @param {int} end Index for the current display ending point in the
11026
	 *    display array
11027
	 *  @param {array int} display Index array to translate the visual position
11028
	 *    to the full data array
11029
	 *
11030
	 *  @dtopt Callbacks
11031
	 *  @name DataTable.defaults.headerCallback
11032
	 *
11033
	 *  @example
11034
	 *    $(document).ready( function() {
11035
	 *      $('#example').dataTable( {
11036
	 *        "fheaderCallback": function( head, data, start, end, display ) {
11037
	 *          head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records";
11038
	 *        }
11039
	 *      } );
11040
	 *    } )
11041
	 */
11042
	"fnHeaderCallback": null,
11043

11044

11045
	/**
11046
	 * The information element can be used to convey information about the current
11047
	 * state of the table. Although the internationalisation options presented by
11048
	 * DataTables are quite capable of dealing with most customisations, there may
11049
	 * be times where you wish to customise the string further. This callback
11050
	 * allows you to do exactly that.
11051
	 *  @type function
11052
	 *  @param {object} oSettings DataTables settings object
11053
	 *  @param {int} start Starting position in data for the draw
11054
	 *  @param {int} end End position in data for the draw
11055
	 *  @param {int} max Total number of rows in the table (regardless of
11056
	 *    filtering)
11057
	 *  @param {int} total Total number of rows in the data set, after filtering
11058
	 *  @param {string} pre The string that DataTables has formatted using it's
11059
	 *    own rules
11060
	 *  @returns {string} The string to be displayed in the information element.
11061
	 *
11062
	 *  @dtopt Callbacks
11063
	 *  @name DataTable.defaults.infoCallback
11064
	 *
11065
	 *  @example
11066
	 *    $('#example').dataTable( {
11067
	 *      "infoCallback": function( settings, start, end, max, total, pre ) {
11068
	 *        return start +" to "+ end;
11069
	 *      }
11070
	 *    } );
11071
	 */
11072
	"fnInfoCallback": null,
11073

11074

11075
	/**
11076
	 * Called when the table has been initialised. Normally DataTables will
11077
	 * initialise sequentially and there will be no need for this function,
11078
	 * however, this does not hold true when using external language information
11079
	 * since that is obtained using an async XHR call.
11080
	 *  @type function
11081
	 *  @param {object} settings DataTables settings object
11082
	 *  @param {object} json The JSON object request from the server - only
11083
	 *    present if client-side Ajax sourced data is used
11084
	 *
11085
	 *  @dtopt Callbacks
11086
	 *  @name DataTable.defaults.initComplete
11087
	 *
11088
	 *  @example
11089
	 *    $(document).ready( function() {
11090
	 *      $('#example').dataTable( {
11091
	 *        "initComplete": function(settings, json) {
11092
	 *          alert( 'DataTables has finished its initialisation.' );
11093
	 *        }
11094
	 *      } );
11095
	 *    } )
11096
	 */
11097
	"fnInitComplete": null,
11098

11099

11100
	/**
11101
	 * Called at the very start of each table draw and can be used to cancel the
11102
	 * draw by returning false, any other return (including undefined) results in
11103
	 * the full draw occurring).
11104
	 *  @type function
11105
	 *  @param {object} settings DataTables settings object
11106
	 *  @returns {boolean} False will cancel the draw, anything else (including no
11107
	 *    return) will allow it to complete.
11108
	 *
11109
	 *  @dtopt Callbacks
11110
	 *  @name DataTable.defaults.preDrawCallback
11111
	 *
11112
	 *  @example
11113
	 *    $(document).ready( function() {
11114
	 *      $('#example').dataTable( {
11115
	 *        "preDrawCallback": function( settings ) {
11116
	 *          if ( $('#test').val() == 1 ) {
11117
	 *            return false;
11118
	 *          }
11119
	 *        }
11120
	 *      } );
11121
	 *    } );
11122
	 */
11123
	"fnPreDrawCallback": null,
11124

11125

11126
	/**
11127
	 * This function allows you to 'post process' each row after it have been
11128
	 * generated for each table draw, but before it is rendered on screen. This
11129
	 * function might be used for setting the row class name etc.
11130
	 *  @type function
11131
	 *  @param {node} row "TR" element for the current row
11132
	 *  @param {array} data Raw data array for this row
11133
	 *  @param {int} displayIndex The display index for the current table draw
11134
	 *  @param {int} displayIndexFull The index of the data in the full list of
11135
	 *    rows (after filtering)
11136
	 *
11137
	 *  @dtopt Callbacks
11138
	 *  @name DataTable.defaults.rowCallback
11139
	 *
11140
	 *  @example
11141
	 *    $(document).ready( function() {
11142
	 *      $('#example').dataTable( {
11143
	 *        "rowCallback": function( row, data, displayIndex, displayIndexFull ) {
11144
	 *          // Bold the grade for all 'A' grade browsers
11145
	 *          if ( data[4] == "A" ) {
11146
	 *            $('td:eq(4)', row).html( '<b>A</b>' );
11147
	 *          }
11148
	 *        }
11149
	 *      } );
11150
	 *    } );
11151
	 */
11152
	"fnRowCallback": null,
11153

11154

11155
	/**
11156
	 * __Deprecated__ The functionality provided by this parameter has now been
11157
	 * superseded by that provided through `ajax`, which should be used instead.
11158
	 *
11159
	 * This parameter allows you to override the default function which obtains
11160
	 * the data from the server so something more suitable for your application.
11161
	 * For example you could use POST data, or pull information from a Gears or
11162
	 * AIR database.
11163
	 *  @type function
11164
	 *  @member
11165
	 *  @param {string} source HTTP source to obtain the data from (`ajax`)
11166
	 *  @param {array} data A key/value pair object containing the data to send
11167
	 *    to the server
11168
	 *  @param {function} callback to be called on completion of the data get
11169
	 *    process that will draw the data on the page.
11170
	 *  @param {object} settings DataTables settings object
11171
	 *
11172
	 *  @dtopt Callbacks
11173
	 *  @dtopt Server-side
11174
	 *  @name DataTable.defaults.serverData
11175
	 *
11176
	 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11177
	 */
11178
	"fnServerData": null,
11179

11180

11181
	/**
11182
	 * __Deprecated__ The functionality provided by this parameter has now been
11183
	 * superseded by that provided through `ajax`, which should be used instead.
11184
	 *
11185
	 *  It is often useful to send extra data to the server when making an Ajax
11186
	 * request - for example custom filtering information, and this callback
11187
	 * function makes it trivial to send extra information to the server. The
11188
	 * passed in parameter is the data set that has been constructed by
11189
	 * DataTables, and you can add to this or modify it as you require.
11190
	 *  @type function
11191
	 *  @param {array} data Data array (array of objects which are name/value
11192
	 *    pairs) that has been constructed by DataTables and will be sent to the
11193
	 *    server. In the case of Ajax sourced data with server-side processing
11194
	 *    this will be an empty array, for server-side processing there will be a
11195
	 *    significant number of parameters!
11196
	 *  @returns {undefined} Ensure that you modify the data array passed in,
11197
	 *    as this is passed by reference.
11198
	 *
11199
	 *  @dtopt Callbacks
11200
	 *  @dtopt Server-side
11201
	 *  @name DataTable.defaults.serverParams
11202
	 *
11203
	 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11204
	 */
11205
	"fnServerParams": null,
11206

11207

11208
	/**
11209
	 * Load the table state. With this function you can define from where, and how, the
11210
	 * state of a table is loaded. By default DataTables will load from `localStorage`
11211
	 * but you might wish to use a server-side database or cookies.
11212
	 *  @type function
11213
	 *  @member
11214
	 *  @param {object} settings DataTables settings object
11215
	 *  @param {object} callback Callback that can be executed when done. It
11216
	 *    should be passed the loaded state object.
11217
	 *  @return {object} The DataTables state object to be loaded
11218
	 *
11219
	 *  @dtopt Callbacks
11220
	 *  @name DataTable.defaults.stateLoadCallback
11221
	 *
11222
	 *  @example
11223
	 *    $(document).ready( function() {
11224
	 *      $('#example').dataTable( {
11225
	 *        "stateSave": true,
11226
	 *        "stateLoadCallback": function (settings, callback) {
11227
	 *          $.ajax( {
11228
	 *            "url": "/state_load",
11229
	 *            "dataType": "json",
11230
	 *            "success": function (json) {
11231
	 *              callback( json );
11232
	 *            }
11233
	 *          } );
11234
	 *        }
11235
	 *      } );
11236
	 *    } );
11237
	 */
11238
	"fnStateLoadCallback": function ( settings ) {
11239
		try {
11240
			return JSON.parse(
11241
				(settings.iStateDuration === -1 ? sessionStorage : localStorage).getItem(
11242
					'DataTables_'+settings.sInstance+'_'+location.pathname
11243
				)
11244
			);
11245
		} catch (e) {
11246
			return {};
11247
		}
11248
	},
11249

11250

11251
	/**
11252
	 * Callback which allows modification of the saved state prior to loading that state.
11253
	 * This callback is called when the table is loading state from the stored data, but
11254
	 * prior to the settings object being modified by the saved state. Note that for
11255
	 * plug-in authors, you should use the `stateLoadParams` event to load parameters for
11256
	 * a plug-in.
11257
	 *  @type function
11258
	 *  @param {object} settings DataTables settings object
11259
	 *  @param {object} data The state object that is to be loaded
11260
	 *
11261
	 *  @dtopt Callbacks
11262
	 *  @name DataTable.defaults.stateLoadParams
11263
	 *
11264
	 *  @example
11265
	 *    // Remove a saved filter, so filtering is never loaded
11266
	 *    $(document).ready( function() {
11267
	 *      $('#example').dataTable( {
11268
	 *        "stateSave": true,
11269
	 *        "stateLoadParams": function (settings, data) {
11270
	 *          data.oSearch.sSearch = "";
11271
	 *        }
11272
	 *      } );
11273
	 *    } );
11274
	 *
11275
	 *  @example
11276
	 *    // Disallow state loading by returning false
11277
	 *    $(document).ready( function() {
11278
	 *      $('#example').dataTable( {
11279
	 *        "stateSave": true,
11280
	 *        "stateLoadParams": function (settings, data) {
11281
	 *          return false;
11282
	 *        }
11283
	 *      } );
11284
	 *    } );
11285
	 */
11286
	"fnStateLoadParams": null,
11287

11288

11289
	/**
11290
	 * Callback that is called when the state has been loaded from the state saving method
11291
	 * and the DataTables settings object has been modified as a result of the loaded state.
11292
	 *  @type function
11293
	 *  @param {object} settings DataTables settings object
11294
	 *  @param {object} data The state object that was loaded
11295
	 *
11296
	 *  @dtopt Callbacks
11297
	 *  @name DataTable.defaults.stateLoaded
11298
	 *
11299
	 *  @example
11300
	 *    // Show an alert with the filtering value that was saved
11301
	 *    $(document).ready( function() {
11302
	 *      $('#example').dataTable( {
11303
	 *        "stateSave": true,
11304
	 *        "stateLoaded": function (settings, data) {
11305
	 *          alert( 'Saved filter was: '+data.oSearch.sSearch );
11306
	 *        }
11307
	 *      } );
11308
	 *    } );
11309
	 */
11310
	"fnStateLoaded": null,
11311

11312

11313
	/**
11314
	 * Save the table state. This function allows you to define where and how the state
11315
	 * information for the table is stored By default DataTables will use `localStorage`
11316
	 * but you might wish to use a server-side database or cookies.
11317
	 *  @type function
11318
	 *  @member
11319
	 *  @param {object} settings DataTables settings object
11320
	 *  @param {object} data The state object to be saved
11321
	 *
11322
	 *  @dtopt Callbacks
11323
	 *  @name DataTable.defaults.stateSaveCallback
11324
	 *
11325
	 *  @example
11326
	 *    $(document).ready( function() {
11327
	 *      $('#example').dataTable( {
11328
	 *        "stateSave": true,
11329
	 *        "stateSaveCallback": function (settings, data) {
11330
	 *          // Send an Ajax request to the server with the state object
11331
	 *          $.ajax( {
11332
	 *            "url": "/state_save",
11333
	 *            "data": data,
11334
	 *            "dataType": "json",
11335
	 *            "method": "POST"
11336
	 *            "success": function () {}
11337
	 *          } );
11338
	 *        }
11339
	 *      } );
11340
	 *    } );
11341
	 */
11342
	"fnStateSaveCallback": function ( settings, data ) {
11343
		try {
11344
			(settings.iStateDuration === -1 ? sessionStorage : localStorage).setItem(
11345
				'DataTables_'+settings.sInstance+'_'+location.pathname,
11346
				JSON.stringify( data )
11347
			);
11348
		} catch (e) {}
11349
	},
11350

11351

11352
	/**
11353
	 * Callback which allows modification of the state to be saved. Called when the table
11354
	 * has changed state a new state save is required. This method allows modification of
11355
	 * the state saving object prior to actually doing the save, including addition or
11356
	 * other state properties or modification. Note that for plug-in authors, you should
11357
	 * use the `stateSaveParams` event to save parameters for a plug-in.
11358
	 *  @type function
11359
	 *  @param {object} settings DataTables settings object
11360
	 *  @param {object} data The state object to be saved
11361
	 *
11362
	 *  @dtopt Callbacks
11363
	 *  @name DataTable.defaults.stateSaveParams
11364
	 *
11365
	 *  @example
11366
	 *    // Remove a saved filter, so filtering is never saved
11367
	 *    $(document).ready( function() {
11368
	 *      $('#example').dataTable( {
11369
	 *        "stateSave": true,
11370
	 *        "stateSaveParams": function (settings, data) {
11371
	 *          data.oSearch.sSearch = "";
11372
	 *        }
11373
	 *      } );
11374
	 *    } );
11375
	 */
11376
	"fnStateSaveParams": null,
11377

11378

11379
	/**
11380
	 * Duration for which the saved state information is considered valid. After this period
11381
	 * has elapsed the state will be returned to the default.
11382
	 * Value is given in seconds.
11383
	 *  @type int
11384
	 *  @default 7200 <i>(2 hours)</i>
11385
	 *
11386
	 *  @dtopt Options
11387
	 *  @name DataTable.defaults.stateDuration
11388
	 *
11389
	 *  @example
11390
	 *    $(document).ready( function() {
11391
	 *      $('#example').dataTable( {
11392
	 *        "stateDuration": 60*60*24; // 1 day
11393
	 *      } );
11394
	 *    } )
11395
	 */
11396
	"iStateDuration": 7200,
11397

11398

11399
	/**
11400
	 * When enabled DataTables will not make a request to the server for the first
11401
	 * page draw - rather it will use the data already on the page (no sorting etc
11402
	 * will be applied to it), thus saving on an XHR at load time. `deferLoading`
11403
	 * is used to indicate that deferred loading is required, but it is also used
11404
	 * to tell DataTables how many records there are in the full table (allowing
11405
	 * the information element and pagination to be displayed correctly). In the case
11406
	 * where a filtering is applied to the table on initial load, this can be
11407
	 * indicated by giving the parameter as an array, where the first element is
11408
	 * the number of records available after filtering and the second element is the
11409
	 * number of records without filtering (allowing the table information element
11410
	 * to be shown correctly).
11411
	 *  @type int | array
11412
	 *  @default null
11413
	 *
11414
	 *  @dtopt Options
11415
	 *  @name DataTable.defaults.deferLoading
11416
	 *
11417
	 *  @example
11418
	 *    // 57 records available in the table, no filtering applied
11419
	 *    $(document).ready( function() {
11420
	 *      $('#example').dataTable( {
11421
	 *        "serverSide": true,
11422
	 *        "ajax": "scripts/server_processing.php",
11423
	 *        "deferLoading": 57
11424
	 *      } );
11425
	 *    } );
11426
	 *
11427
	 *  @example
11428
	 *    // 57 records after filtering, 100 without filtering (an initial filter applied)
11429
	 *    $(document).ready( function() {
11430
	 *      $('#example').dataTable( {
11431
	 *        "serverSide": true,
11432
	 *        "ajax": "scripts/server_processing.php",
11433
	 *        "deferLoading": [ 57, 100 ],
11434
	 *        "search": {
11435
	 *          "search": "my_filter"
11436
	 *        }
11437
	 *      } );
11438
	 *    } );
11439
	 */
11440
	"iDeferLoading": null,
11441

11442

11443
	/**
11444
	 * Number of rows to display on a single page when using pagination. If
11445
	 * feature enabled (`lengthChange`) then the end user will be able to override
11446
	 * this to a custom setting using a pop-up menu.
11447
	 *  @type int
11448
	 *  @default 10
11449
	 *
11450
	 *  @dtopt Options
11451
	 *  @name DataTable.defaults.pageLength
11452
	 *
11453
	 *  @example
11454
	 *    $(document).ready( function() {
11455
	 *      $('#example').dataTable( {
11456
	 *        "pageLength": 50
11457
	 *      } );
11458
	 *    } )
11459
	 */
11460
	"iDisplayLength": 10,
11461

11462

11463
	/**
11464
	 * Define the starting point for data display when using DataTables with
11465
	 * pagination. Note that this parameter is the number of records, rather than
11466
	 * the page number, so if you have 10 records per page and want to start on
11467
	 * the third page, it should be "20".
11468
	 *  @type int
11469
	 *  @default 0
11470
	 *
11471
	 *  @dtopt Options
11472
	 *  @name DataTable.defaults.displayStart
11473
	 *
11474
	 *  @example
11475
	 *    $(document).ready( function() {
11476
	 *      $('#example').dataTable( {
11477
	 *        "displayStart": 20
11478
	 *      } );
11479
	 *    } )
11480
	 */
11481
	"iDisplayStart": 0,
11482

11483

11484
	/**
11485
	 * By default DataTables allows keyboard navigation of the table (sorting, paging,
11486
	 * and filtering) by adding a `tabindex` attribute to the required elements. This
11487
	 * allows you to tab through the controls and press the enter key to activate them.
11488
	 * The tabindex is default 0, meaning that the tab follows the flow of the document.
11489
	 * You can overrule this using this parameter if you wish. Use a value of -1 to
11490
	 * disable built-in keyboard navigation.
11491
	 *  @type int
11492
	 *  @default 0
11493
	 *
11494
	 *  @dtopt Options
11495
	 *  @name DataTable.defaults.tabIndex
11496
	 *
11497
	 *  @example
11498
	 *    $(document).ready( function() {
11499
	 *      $('#example').dataTable( {
11500
	 *        "tabIndex": 1
11501
	 *      } );
11502
	 *    } );
11503
	 */
11504
	"iTabIndex": 0,
11505

11506

11507
	/**
11508
	 * Classes that DataTables assigns to the various components and features
11509
	 * that it adds to the HTML table. This allows classes to be configured
11510
	 * during initialisation in addition to through the static
11511
	 * {@link DataTable.ext.oStdClasses} object).
11512
	 *  @namespace
11513
	 *  @name DataTable.defaults.classes
11514
	 */
11515
	"oClasses": {},
11516

11517

11518
	/**
11519
	 * All strings that DataTables uses in the user interface that it creates
11520
	 * are defined in this object, allowing you to modified them individually or
11521
	 * completely replace them all as required.
11522
	 *  @namespace
11523
	 *  @name DataTable.defaults.language
11524
	 */
11525
	"oLanguage": {
11526
		/**
11527
		 * Strings that are used for WAI-ARIA labels and controls only (these are not
11528
		 * actually visible on the page, but will be read by screenreaders, and thus
11529
		 * must be internationalised as well).
11530
		 *  @namespace
11531
		 *  @name DataTable.defaults.language.aria
11532
		 */
11533
		"oAria": {
11534
			/**
11535
			 * ARIA label that is added to the table headers when the column may be
11536
			 * sorted ascending by activing the column (click or return when focused).
11537
			 * Note that the column header is prefixed to this string.
11538
			 *  @type string
11539
			 *  @default : activate to sort column ascending
11540
			 *
11541
			 *  @dtopt Language
11542
			 *  @name DataTable.defaults.language.aria.sortAscending
11543
			 *
11544
			 *  @example
11545
			 *    $(document).ready( function() {
11546
			 *      $('#example').dataTable( {
11547
			 *        "language": {
11548
			 *          "aria": {
11549
			 *            "sortAscending": " - click/return to sort ascending"
11550
			 *          }
11551
			 *        }
11552
			 *      } );
11553
			 *    } );
11554
			 */
11555
			"sSortAscending": ": activate to sort column ascending",
11556

11557
			/**
11558
			 * ARIA label that is added to the table headers when the column may be
11559
			 * sorted descending by activing the column (click or return when focused).
11560
			 * Note that the column header is prefixed to this string.
11561
			 *  @type string
11562
			 *  @default : activate to sort column ascending
11563
			 *
11564
			 *  @dtopt Language
11565
			 *  @name DataTable.defaults.language.aria.sortDescending
11566
			 *
11567
			 *  @example
11568
			 *    $(document).ready( function() {
11569
			 *      $('#example').dataTable( {
11570
			 *        "language": {
11571
			 *          "aria": {
11572
			 *            "sortDescending": " - click/return to sort descending"
11573
			 *          }
11574
			 *        }
11575
			 *      } );
11576
			 *    } );
11577
			 */
11578
			"sSortDescending": ": activate to sort column descending"
11579
		},
11580

11581
		/**
11582
		 * Pagination string used by DataTables for the built-in pagination
11583
		 * control types.
11584
		 *  @namespace
11585
		 *  @name DataTable.defaults.language.paginate
11586
		 */
11587
		"oPaginate": {
11588
			/**
11589
			 * Text to use when using the 'full_numbers' type of pagination for the
11590
			 * button to take the user to the first page.
11591
			 *  @type string
11592
			 *  @default First
11593
			 *
11594
			 *  @dtopt Language
11595
			 *  @name DataTable.defaults.language.paginate.first
11596
			 *
11597
			 *  @example
11598
			 *    $(document).ready( function() {
11599
			 *      $('#example').dataTable( {
11600
			 *        "language": {
11601
			 *          "paginate": {
11602
			 *            "first": "First page"
11603
			 *          }
11604
			 *        }
11605
			 *      } );
11606
			 *    } );
11607
			 */
11608
			"sFirst": "First",
11609

11610

11611
			/**
11612
			 * Text to use when using the 'full_numbers' type of pagination for the
11613
			 * button to take the user to the last page.
11614
			 *  @type string
11615
			 *  @default Last
11616
			 *
11617
			 *  @dtopt Language
11618
			 *  @name DataTable.defaults.language.paginate.last
11619
			 *
11620
			 *  @example
11621
			 *    $(document).ready( function() {
11622
			 *      $('#example').dataTable( {
11623
			 *        "language": {
11624
			 *          "paginate": {
11625
			 *            "last": "Last page"
11626
			 *          }
11627
			 *        }
11628
			 *      } );
11629
			 *    } );
11630
			 */
11631
			"sLast": "Last",
11632

11633

11634
			/**
11635
			 * Text to use for the 'next' pagination button (to take the user to the
11636
			 * next page).
11637
			 *  @type string
11638
			 *  @default Next
11639
			 *
11640
			 *  @dtopt Language
11641
			 *  @name DataTable.defaults.language.paginate.next
11642
			 *
11643
			 *  @example
11644
			 *    $(document).ready( function() {
11645
			 *      $('#example').dataTable( {
11646
			 *        "language": {
11647
			 *          "paginate": {
11648
			 *            "next": "Next page"
11649
			 *          }
11650
			 *        }
11651
			 *      } );
11652
			 *    } );
11653
			 */
11654
			"sNext": "Next",
11655

11656

11657
			/**
11658
			 * Text to use for the 'previous' pagination button (to take the user to
11659
			 * the previous page).
11660
			 *  @type string
11661
			 *  @default Previous
11662
			 *
11663
			 *  @dtopt Language
11664
			 *  @name DataTable.defaults.language.paginate.previous
11665
			 *
11666
			 *  @example
11667
			 *    $(document).ready( function() {
11668
			 *      $('#example').dataTable( {
11669
			 *        "language": {
11670
			 *          "paginate": {
11671
			 *            "previous": "Previous page"
11672
			 *          }
11673
			 *        }
11674
			 *      } );
11675
			 *    } );
11676
			 */
11677
			"sPrevious": "Previous"
11678
		},
11679

11680
		/**
11681
		 * This string is shown in preference to `zeroRecords` when the table is
11682
		 * empty of data (regardless of filtering). Note that this is an optional
11683
		 * parameter - if it is not given, the value of `zeroRecords` will be used
11684
		 * instead (either the default or given value).
11685
		 *  @type string
11686
		 *  @default No data available in table
11687
		 *
11688
		 *  @dtopt Language
11689
		 *  @name DataTable.defaults.language.emptyTable
11690
		 *
11691
		 *  @example
11692
		 *    $(document).ready( function() {
11693
		 *      $('#example').dataTable( {
11694
		 *        "language": {
11695
		 *          "emptyTable": "No data available in table"
11696
		 *        }
11697
		 *      } );
11698
		 *    } );
11699
		 */
11700
		"sEmptyTable": "No data available in table",
11701

11702

11703
		/**
11704
		 * This string gives information to the end user about the information
11705
		 * that is current on display on the page. The following tokens can be
11706
		 * used in the string and will be dynamically replaced as the table
11707
		 * display updates. This tokens can be placed anywhere in the string, or
11708
		 * removed as needed by the language requires:
11709
		 *
11710
		 * * `\_START\_` - Display index of the first record on the current page
11711
		 * * `\_END\_` - Display index of the last record on the current page
11712
		 * * `\_TOTAL\_` - Number of records in the table after filtering
11713
		 * * `\_MAX\_` - Number of records in the table without filtering
11714
		 * * `\_PAGE\_` - Current page number
11715
		 * * `\_PAGES\_` - Total number of pages of data in the table
11716
		 *
11717
		 *  @type string
11718
		 *  @default Showing _START_ to _END_ of _TOTAL_ entries
11719
		 *
11720
		 *  @dtopt Language
11721
		 *  @name DataTable.defaults.language.info
11722
		 *
11723
		 *  @example
11724
		 *    $(document).ready( function() {
11725
		 *      $('#example').dataTable( {
11726
		 *        "language": {
11727
		 *          "info": "Showing page _PAGE_ of _PAGES_"
11728
		 *        }
11729
		 *      } );
11730
		 *    } );
11731
		 */
11732
		"sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
11733

11734

11735
		/**
11736
		 * Display information string for when the table is empty. Typically the
11737
		 * format of this string should match `info`.
11738
		 *  @type string
11739
		 *  @default Showing 0 to 0 of 0 entries
11740
		 *
11741
		 *  @dtopt Language
11742
		 *  @name DataTable.defaults.language.infoEmpty
11743
		 *
11744
		 *  @example
11745
		 *    $(document).ready( function() {
11746
		 *      $('#example').dataTable( {
11747
		 *        "language": {
11748
		 *          "infoEmpty": "No entries to show"
11749
		 *        }
11750
		 *      } );
11751
		 *    } );
11752
		 */
11753
		"sInfoEmpty": "Showing 0 to 0 of 0 entries",
11754

11755

11756
		/**
11757
		 * When a user filters the information in a table, this string is appended
11758
		 * to the information (`info`) to give an idea of how strong the filtering
11759
		 * is. The variable _MAX_ is dynamically updated.
11760
		 *  @type string
11761
		 *  @default (filtered from _MAX_ total entries)
11762
		 *
11763
		 *  @dtopt Language
11764
		 *  @name DataTable.defaults.language.infoFiltered
11765
		 *
11766
		 *  @example
11767
		 *    $(document).ready( function() {
11768
		 *      $('#example').dataTable( {
11769
		 *        "language": {
11770
		 *          "infoFiltered": " - filtering from _MAX_ records"
11771
		 *        }
11772
		 *      } );
11773
		 *    } );
11774
		 */
11775
		"sInfoFiltered": "(filtered from _MAX_ total entries)",
11776

11777

11778
		/**
11779
		 * If can be useful to append extra information to the info string at times,
11780
		 * and this variable does exactly that. This information will be appended to
11781
		 * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are
11782
		 * being used) at all times.
11783
		 *  @type string
11784
		 *  @default <i>Empty string</i>
11785
		 *
11786
		 *  @dtopt Language
11787
		 *  @name DataTable.defaults.language.infoPostFix
11788
		 *
11789
		 *  @example
11790
		 *    $(document).ready( function() {
11791
		 *      $('#example').dataTable( {
11792
		 *        "language": {
11793
		 *          "infoPostFix": "All records shown are derived from real information."
11794
		 *        }
11795
		 *      } );
11796
		 *    } );
11797
		 */
11798
		"sInfoPostFix": "",
11799

11800

11801
		/**
11802
		 * This decimal place operator is a little different from the other
11803
		 * language options since DataTables doesn't output floating point
11804
		 * numbers, so it won't ever use this for display of a number. Rather,
11805
		 * what this parameter does is modify the sort methods of the table so
11806
		 * that numbers which are in a format which has a character other than
11807
		 * a period (`.`) as a decimal place will be sorted numerically.
11808
		 *
11809
		 * Note that numbers with different decimal places cannot be shown in
11810
		 * the same table and still be sortable, the table must be consistent.
11811
		 * However, multiple different tables on the page can use different
11812
		 * decimal place characters.
11813
		 *  @type string
11814
		 *  @default 
11815
		 *
11816
		 *  @dtopt Language
11817
		 *  @name DataTable.defaults.language.decimal
11818
		 *
11819
		 *  @example
11820
		 *    $(document).ready( function() {
11821
		 *      $('#example').dataTable( {
11822
		 *        "language": {
11823
		 *          "decimal": ","
11824
		 *          "thousands": "."
11825
		 *        }
11826
		 *      } );
11827
		 *    } );
11828
		 */
11829
		"sDecimal": "",
11830

11831

11832
		/**
11833
		 * DataTables has a build in number formatter (`formatNumber`) which is
11834
		 * used to format large numbers that are used in the table information.
11835
		 * By default a comma is used, but this can be trivially changed to any
11836
		 * character you wish with this parameter.
11837
		 *  @type string
11838
		 *  @default ,
11839
		 *
11840
		 *  @dtopt Language
11841
		 *  @name DataTable.defaults.language.thousands
11842
		 *
11843
		 *  @example
11844
		 *    $(document).ready( function() {
11845
		 *      $('#example').dataTable( {
11846
		 *        "language": {
11847
		 *          "thousands": "'"
11848
		 *        }
11849
		 *      } );
11850
		 *    } );
11851
		 */
11852
		"sThousands": ",",
11853

11854

11855
		/**
11856
		 * Detail the action that will be taken when the drop down menu for the
11857
		 * pagination length option is changed. The '_MENU_' variable is replaced
11858
		 * with a default select list of 10, 25, 50 and 100, and can be replaced
11859
		 * with a custom select box if required.
11860
		 *  @type string
11861
		 *  @default Show _MENU_ entries
11862
		 *
11863
		 *  @dtopt Language
11864
		 *  @name DataTable.defaults.language.lengthMenu
11865
		 *
11866
		 *  @example
11867
		 *    // Language change only
11868
		 *    $(document).ready( function() {
11869
		 *      $('#example').dataTable( {
11870
		 *        "language": {
11871
		 *          "lengthMenu": "Display _MENU_ records"
11872
		 *        }
11873
		 *      } );
11874
		 *    } );
11875
		 *
11876
		 *  @example
11877
		 *    // Language and options change
11878
		 *    $(document).ready( function() {
11879
		 *      $('#example').dataTable( {
11880
		 *        "language": {
11881
		 *          "lengthMenu": 'Display <select>'+
11882
		 *            '<option value="10">10</option>'+
11883
		 *            '<option value="20">20</option>'+
11884
		 *            '<option value="30">30</option>'+
11885
		 *            '<option value="40">40</option>'+
11886
		 *            '<option value="50">50</option>'+
11887
		 *            '<option value="-1">All</option>'+
11888
		 *            '</select> records'
11889
		 *        }
11890
		 *      } );
11891
		 *    } );
11892
		 */
11893
		"sLengthMenu": "Show _MENU_ entries",
11894

11895

11896
		/**
11897
		 * When using Ajax sourced data and during the first draw when DataTables is
11898
		 * gathering the data, this message is shown in an empty row in the table to
11899
		 * indicate to the end user the the data is being loaded. Note that this
11900
		 * parameter is not used when loading data by server-side processing, just
11901
		 * Ajax sourced data with client-side processing.
11902
		 *  @type string
11903
		 *  @default Loading...
11904
		 *
11905
		 *  @dtopt Language
11906
		 *  @name DataTable.defaults.language.loadingRecords
11907
		 *
11908
		 *  @example
11909
		 *    $(document).ready( function() {
11910
		 *      $('#example').dataTable( {
11911
		 *        "language": {
11912
		 *          "loadingRecords": "Please wait - loading..."
11913
		 *        }
11914
		 *      } );
11915
		 *    } );
11916
		 */
11917
		"sLoadingRecords": "Loading...",
11918

11919

11920
		/**
11921
		 * Text which is displayed when the table is processing a user action
11922
		 * (usually a sort command or similar).
11923
		 *  @type string
11924
		 *
11925
		 *  @dtopt Language
11926
		 *  @name DataTable.defaults.language.processing
11927
		 *
11928
		 *  @example
11929
		 *    $(document).ready( function() {
11930
		 *      $('#example').dataTable( {
11931
		 *        "language": {
11932
		 *          "processing": "DataTables is currently busy"
11933
		 *        }
11934
		 *      } );
11935
		 *    } );
11936
		 */
11937
		"sProcessing": "",
11938

11939

11940
		/**
11941
		 * Details the actions that will be taken when the user types into the
11942
		 * filtering input text box. The variable "_INPUT_", if used in the string,
11943
		 * is replaced with the HTML text box for the filtering input allowing
11944
		 * control over where it appears in the string. If "_INPUT_" is not given
11945
		 * then the input box is appended to the string automatically.
11946
		 *  @type string
11947
		 *  @default Search:
11948
		 *
11949
		 *  @dtopt Language
11950
		 *  @name DataTable.defaults.language.search
11951
		 *
11952
		 *  @example
11953
		 *    // Input text box will be appended at the end automatically
11954
		 *    $(document).ready( function() {
11955
		 *      $('#example').dataTable( {
11956
		 *        "language": {
11957
		 *          "search": "Filter records:"
11958
		 *        }
11959
		 *      } );
11960
		 *    } );
11961
		 *
11962
		 *  @example
11963
		 *    // Specify where the filter should appear
11964
		 *    $(document).ready( function() {
11965
		 *      $('#example').dataTable( {
11966
		 *        "language": {
11967
		 *          "search": "Apply filter _INPUT_ to table"
11968
		 *        }
11969
		 *      } );
11970
		 *    } );
11971
		 */
11972
		"sSearch": "Search:",
11973

11974

11975
		/**
11976
		 * Assign a `placeholder` attribute to the search `input` element
11977
		 *  @type string
11978
		 *  @default 
11979
		 *
11980
		 *  @dtopt Language
11981
		 *  @name DataTable.defaults.language.searchPlaceholder
11982
		 */
11983
		"sSearchPlaceholder": "",
11984

11985

11986
		/**
11987
		 * All of the language information can be stored in a file on the
11988
		 * server-side, which DataTables will look up if this parameter is passed.
11989
		 * It must store the URL of the language file, which is in a JSON format,
11990
		 * and the object has the same properties as the oLanguage object in the
11991
		 * initialiser object (i.e. the above parameters). Please refer to one of
11992
		 * the example language files to see how this works in action.
11993
		 *  @type string
11994
		 *  @default <i>Empty string - i.e. disabled</i>
11995
		 *
11996
		 *  @dtopt Language
11997
		 *  @name DataTable.defaults.language.url
11998
		 *
11999
		 *  @example
12000
		 *    $(document).ready( function() {
12001
		 *      $('#example').dataTable( {
12002
		 *        "language": {
12003
		 *          "url": "http://www.sprymedia.co.uk/dataTables/lang.txt"
12004
		 *        }
12005
		 *      } );
12006
		 *    } );
12007
		 */
12008
		"sUrl": "",
12009

12010

12011
		/**
12012
		 * Text shown inside the table records when the is no information to be
12013
		 * displayed after filtering. `emptyTable` is shown when there is simply no
12014
		 * information in the table at all (regardless of filtering).
12015
		 *  @type string
12016
		 *  @default No matching records found
12017
		 *
12018
		 *  @dtopt Language
12019
		 *  @name DataTable.defaults.language.zeroRecords
12020
		 *
12021
		 *  @example
12022
		 *    $(document).ready( function() {
12023
		 *      $('#example').dataTable( {
12024
		 *        "language": {
12025
		 *          "zeroRecords": "No records to display"
12026
		 *        }
12027
		 *      } );
12028
		 *    } );
12029
		 */
12030
		"sZeroRecords": "No matching records found"
12031
	},
12032

12033

12034
	/**
12035
	 * This parameter allows you to have define the global filtering state at
12036
	 * initialisation time. As an object the `search` parameter must be
12037
	 * defined, but all other parameters are optional. When `regex` is true,
12038
	 * the search string will be treated as a regular expression, when false
12039
	 * (default) it will be treated as a straight string. When `smart`
12040
	 * DataTables will use it's smart filtering methods (to word match at
12041
	 * any point in the data), when false this will not be done.
12042
	 *  @namespace
12043
	 *  @extends DataTable.models.oSearch
12044
	 *
12045
	 *  @dtopt Options
12046
	 *  @name DataTable.defaults.search
12047
	 *
12048
	 *  @example
12049
	 *    $(document).ready( function() {
12050
	 *      $('#example').dataTable( {
12051
	 *        "search": {"search": "Initial search"}
12052
	 *      } );
12053
	 *    } )
12054
	 */
12055
	"oSearch": $.extend( {}, DataTable.models.oSearch ),
12056

12057

12058
	/**
12059
	 * __Deprecated__ The functionality provided by this parameter has now been
12060
	 * superseded by that provided through `ajax`, which should be used instead.
12061
	 *
12062
	 * By default DataTables will look for the property `data` (or `aaData` for
12063
	 * compatibility with DataTables 1.9-) when obtaining data from an Ajax
12064
	 * source or for server-side processing - this parameter allows that
12065
	 * property to be changed. You can use Javascript dotted object notation to
12066
	 * get a data source for multiple levels of nesting.
12067
	 *  @type string
12068
	 *  @default data
12069
	 *
12070
	 *  @dtopt Options
12071
	 *  @dtopt Server-side
12072
	 *  @name DataTable.defaults.ajaxDataProp
12073
	 *
12074
	 *  @deprecated 1.10. Please use `ajax` for this functionality now.
12075
	 */
12076
	"sAjaxDataProp": "data",
12077

12078

12079
	/**
12080
	 * __Deprecated__ The functionality provided by this parameter has now been
12081
	 * superseded by that provided through `ajax`, which should be used instead.
12082
	 *
12083
	 * You can instruct DataTables to load data from an external
12084
	 * source using this parameter (use aData if you want to pass data in you
12085
	 * already have). Simply provide a url a JSON object can be obtained from.
12086
	 *  @type string
12087
	 *  @default null
12088
	 *
12089
	 *  @dtopt Options
12090
	 *  @dtopt Server-side
12091
	 *  @name DataTable.defaults.ajaxSource
12092
	 *
12093
	 *  @deprecated 1.10. Please use `ajax` for this functionality now.
12094
	 */
12095
	"sAjaxSource": null,
12096

12097

12098
	/**
12099
	 * This initialisation variable allows you to specify exactly where in the
12100
	 * DOM you want DataTables to inject the various controls it adds to the page
12101
	 * (for example you might want the pagination controls at the top of the
12102
	 * table). DIV elements (with or without a custom class) can also be added to
12103
	 * aid styling. The follow syntax is used:
12104
	 *   <ul>
12105
	 *     <li>The following options are allowed:
12106
	 *       <ul>
12107
	 *         <li>'l' - Length changing</li>
12108
	 *         <li>'f' - Filtering input</li>
12109
	 *         <li>'t' - The table!</li>
12110
	 *         <li>'i' - Information</li>
12111
	 *         <li>'p' - Pagination</li>
12112
	 *         <li>'r' - pRocessing</li>
12113
	 *       </ul>
12114
	 *     </li>
12115
	 *     <li>The following constants are allowed:
12116
	 *       <ul>
12117
	 *         <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>
12118
	 *         <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>
12119
	 *       </ul>
12120
	 *     </li>
12121
	 *     <li>The following syntax is expected:
12122
	 *       <ul>
12123
	 *         <li>'&lt;' and '&gt;' - div elements</li>
12124
	 *         <li>'&lt;"class" and '&gt;' - div with a class</li>
12125
	 *         <li>'&lt;"#id" and '&gt;' - div with an ID</li>
12126
	 *       </ul>
12127
	 *     </li>
12128
	 *     <li>Examples:
12129
	 *       <ul>
12130
	 *         <li>'&lt;"wrapper"flipt&gt;'</li>
12131
	 *         <li>'&lt;lf&lt;t&gt;ip&gt;'</li>
12132
	 *       </ul>
12133
	 *     </li>
12134
	 *   </ul>
12135
	 *  @type string
12136
	 *  @default lfrtip <i>(when `jQueryUI` is false)</i> <b>or</b>
12137
	 *    <"H"lfr>t<"F"ip> <i>(when `jQueryUI` is true)</i>
12138
	 *
12139
	 *  @dtopt Options
12140
	 *  @name DataTable.defaults.dom
12141
	 *
12142
	 *  @example
12143
	 *    $(document).ready( function() {
12144
	 *      $('#example').dataTable( {
12145
	 *        "dom": '&lt;"top"i&gt;rt&lt;"bottom"flp&gt;&lt;"clear"&gt;'
12146
	 *      } );
12147
	 *    } );
12148
	 */
12149
	"sDom": "lfrtip",
12150

12151

12152
	/**
12153
	 * Search delay option. This will throttle full table searches that use the
12154
	 * DataTables provided search input element (it does not effect calls to
12155
	 * `dt-api search()`, providing a delay before the search is made.
12156
	 *  @type integer
12157
	 *  @default 0
12158
	 *
12159
	 *  @dtopt Options
12160
	 *  @name DataTable.defaults.searchDelay
12161
	 *
12162
	 *  @example
12163
	 *    $(document).ready( function() {
12164
	 *      $('#example').dataTable( {
12165
	 *        "searchDelay": 200
12166
	 *      } );
12167
	 *    } )
12168
	 */
12169
	"searchDelay": null,
12170

12171

12172
	/**
12173
	 * DataTables features six different built-in options for the buttons to
12174
	 * display for pagination control:
12175
	 *
12176
	 * * `numbers` - Page number buttons only
12177
	 * * `simple` - 'Previous' and 'Next' buttons only
12178
	 * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers
12179
	 * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons
12180
	 * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus page numbers
12181
	 * * `first_last_numbers` - 'First' and 'Last' buttons, plus page numbers
12182
	 *  
12183
	 * Further methods can be added using {@link DataTable.ext.oPagination}.
12184
	 *  @type string
12185
	 *  @default simple_numbers
12186
	 *
12187
	 *  @dtopt Options
12188
	 *  @name DataTable.defaults.pagingType
12189
	 *
12190
	 *  @example
12191
	 *    $(document).ready( function() {
12192
	 *      $('#example').dataTable( {
12193
	 *        "pagingType": "full_numbers"
12194
	 *      } );
12195
	 *    } )
12196
	 */
12197
	"sPaginationType": "simple_numbers",
12198

12199

12200
	/**
12201
	 * Enable horizontal scrolling. When a table is too wide to fit into a
12202
	 * certain layout, or you have a large number of columns in the table, you
12203
	 * can enable x-scrolling to show the table in a viewport, which can be
12204
	 * scrolled. This property can be `true` which will allow the table to
12205
	 * scroll horizontally when needed, or any CSS unit, or a number (in which
12206
	 * case it will be treated as a pixel measurement). Setting as simply `true`
12207
	 * is recommended.
12208
	 *  @type boolean|string
12209
	 *  @default <i>blank string - i.e. disabled</i>
12210
	 *
12211
	 *  @dtopt Features
12212
	 *  @name DataTable.defaults.scrollX
12213
	 *
12214
	 *  @example
12215
	 *    $(document).ready( function() {
12216
	 *      $('#example').dataTable( {
12217
	 *        "scrollX": true,
12218
	 *        "scrollCollapse": true
12219
	 *      } );
12220
	 *    } );
12221
	 */
12222
	"sScrollX": "",
12223

12224

12225
	/**
12226
	 * This property can be used to force a DataTable to use more width than it
12227
	 * might otherwise do when x-scrolling is enabled. For example if you have a
12228
	 * table which requires to be well spaced, this parameter is useful for
12229
	 * "over-sizing" the table, and thus forcing scrolling. This property can by
12230
	 * any CSS unit, or a number (in which case it will be treated as a pixel
12231
	 * measurement).
12232
	 *  @type string
12233
	 *  @default <i>blank string - i.e. disabled</i>
12234
	 *
12235
	 *  @dtopt Options
12236
	 *  @name DataTable.defaults.scrollXInner
12237
	 *
12238
	 *  @example
12239
	 *    $(document).ready( function() {
12240
	 *      $('#example').dataTable( {
12241
	 *        "scrollX": "100%",
12242
	 *        "scrollXInner": "110%"
12243
	 *      } );
12244
	 *    } );
12245
	 */
12246
	"sScrollXInner": "",
12247

12248

12249
	/**
12250
	 * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
12251
	 * to the given height, and enable scrolling for any data which overflows the
12252
	 * current viewport. This can be used as an alternative to paging to display
12253
	 * a lot of data in a small area (although paging and scrolling can both be
12254
	 * enabled at the same time). This property can be any CSS unit, or a number
12255
	 * (in which case it will be treated as a pixel measurement).
12256
	 *  @type string
12257
	 *  @default <i>blank string - i.e. disabled</i>
12258
	 *
12259
	 *  @dtopt Features
12260
	 *  @name DataTable.defaults.scrollY
12261
	 *
12262
	 *  @example
12263
	 *    $(document).ready( function() {
12264
	 *      $('#example').dataTable( {
12265
	 *        "scrollY": "200px",
12266
	 *        "paginate": false
12267
	 *      } );
12268
	 *    } );
12269
	 */
12270
	"sScrollY": "",
12271

12272

12273
	/**
12274
	 * __Deprecated__ The functionality provided by this parameter has now been
12275
	 * superseded by that provided through `ajax`, which should be used instead.
12276
	 *
12277
	 * Set the HTTP method that is used to make the Ajax call for server-side
12278
	 * processing or Ajax sourced data.
12279
	 *  @type string
12280
	 *  @default GET
12281
	 *
12282
	 *  @dtopt Options
12283
	 *  @dtopt Server-side
12284
	 *  @name DataTable.defaults.serverMethod
12285
	 *
12286
	 *  @deprecated 1.10. Please use `ajax` for this functionality now.
12287
	 */
12288
	"sServerMethod": "GET",
12289

12290

12291
	/**
12292
	 * DataTables makes use of renderers when displaying HTML elements for
12293
	 * a table. These renderers can be added or modified by plug-ins to
12294
	 * generate suitable mark-up for a site. For example the Bootstrap
12295
	 * integration plug-in for DataTables uses a paging button renderer to
12296
	 * display pagination buttons in the mark-up required by Bootstrap.
12297
	 *
12298
	 * For further information about the renderers available see
12299
	 * DataTable.ext.renderer
12300
	 *  @type string|object
12301
	 *  @default null
12302
	 *
12303
	 *  @name DataTable.defaults.renderer
12304
	 *
12305
	 */
12306
	"renderer": null,
12307

12308

12309
	/**
12310
	 * Set the data property name that DataTables should use to get a row's id
12311
	 * to set as the `id` property in the node.
12312
	 *  @type string
12313
	 *  @default DT_RowId
12314
	 *
12315
	 *  @name DataTable.defaults.rowId
12316
	 */
12317
	"rowId": "DT_RowId"
12318
};
12319

12320
_fnHungarianMap( DataTable.defaults );
12321

12322

12323

12324
/*
12325
 * Developer note - See note in model.defaults.js about the use of Hungarian
12326
 * notation and camel case.
12327
 */
12328

12329
/**
12330
 * Column options that can be given to DataTables at initialisation time.
12331
 *  @namespace
12332
 */
12333
DataTable.defaults.column = {
12334
	/**
12335
	 * Define which column(s) an order will occur on for this column. This
12336
	 * allows a column's ordering to take multiple columns into account when
12337
	 * doing a sort or use the data from a different column. For example first
12338
	 * name / last name columns make sense to do a multi-column sort over the
12339
	 * two columns.
12340
	 *  @type array|int
12341
	 *  @default null <i>Takes the value of the column index automatically</i>
12342
	 *
12343
	 *  @name DataTable.defaults.column.orderData
12344
	 *  @dtopt Columns
12345
	 *
12346
	 *  @example
12347
	 *    // Using `columnDefs`
12348
	 *    $(document).ready( function() {
12349
	 *      $('#example').dataTable( {
12350
	 *        "columnDefs": [
12351
	 *          { "orderData": [ 0, 1 ], "targets": [ 0 ] },
12352
	 *          { "orderData": [ 1, 0 ], "targets": [ 1 ] },
12353
	 *          { "orderData": 2, "targets": [ 2 ] }
12354
	 *        ]
12355
	 *      } );
12356
	 *    } );
12357
	 *
12358
	 *  @example
12359
	 *    // Using `columns`
12360
	 *    $(document).ready( function() {
12361
	 *      $('#example').dataTable( {
12362
	 *        "columns": [
12363
	 *          { "orderData": [ 0, 1 ] },
12364
	 *          { "orderData": [ 1, 0 ] },
12365
	 *          { "orderData": 2 },
12366
	 *          null,
12367
	 *          null
12368
	 *        ]
12369
	 *      } );
12370
	 *    } );
12371
	 */
12372
	"aDataSort": null,
12373
	"iDataSort": -1,
12374

12375

12376
	/**
12377
	 * You can control the default ordering direction, and even alter the
12378
	 * behaviour of the sort handler (i.e. only allow ascending ordering etc)
12379
	 * using this parameter.
12380
	 *  @type array
12381
	 *  @default [ 'asc', 'desc' ]
12382
	 *
12383
	 *  @name DataTable.defaults.column.orderSequence
12384
	 *  @dtopt Columns
12385
	 *
12386
	 *  @example
12387
	 *    // Using `columnDefs`
12388
	 *    $(document).ready( function() {
12389
	 *      $('#example').dataTable( {
12390
	 *        "columnDefs": [
12391
	 *          { "orderSequence": [ "asc" ], "targets": [ 1 ] },
12392
	 *          { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] },
12393
	 *          { "orderSequence": [ "desc" ], "targets": [ 3 ] }
12394
	 *        ]
12395
	 *      } );
12396
	 *    } );
12397
	 *
12398
	 *  @example
12399
	 *    // Using `columns`
12400
	 *    $(document).ready( function() {
12401
	 *      $('#example').dataTable( {
12402
	 *        "columns": [
12403
	 *          null,
12404
	 *          { "orderSequence": [ "asc" ] },
12405
	 *          { "orderSequence": [ "desc", "asc", "asc" ] },
12406
	 *          { "orderSequence": [ "desc" ] },
12407
	 *          null
12408
	 *        ]
12409
	 *      } );
12410
	 *    } );
12411
	 */
12412
	"asSorting": [ 'asc', 'desc' ],
12413

12414

12415
	/**
12416
	 * Enable or disable filtering on the data in this column.
12417
	 *  @type boolean
12418
	 *  @default true
12419
	 *
12420
	 *  @name DataTable.defaults.column.searchable
12421
	 *  @dtopt Columns
12422
	 *
12423
	 *  @example
12424
	 *    // Using `columnDefs`
12425
	 *    $(document).ready( function() {
12426
	 *      $('#example').dataTable( {
12427
	 *        "columnDefs": [
12428
	 *          { "searchable": false, "targets": [ 0 ] }
12429
	 *        ] } );
12430
	 *    } );
12431
	 *
12432
	 *  @example
12433
	 *    // Using `columns`
12434
	 *    $(document).ready( function() {
12435
	 *      $('#example').dataTable( {
12436
	 *        "columns": [
12437
	 *          { "searchable": false },
12438
	 *          null,
12439
	 *          null,
12440
	 *          null,
12441
	 *          null
12442
	 *        ] } );
12443
	 *    } );
12444
	 */
12445
	"bSearchable": true,
12446

12447

12448
	/**
12449
	 * Enable or disable ordering on this column.
12450
	 *  @type boolean
12451
	 *  @default true
12452
	 *
12453
	 *  @name DataTable.defaults.column.orderable
12454
	 *  @dtopt Columns
12455
	 *
12456
	 *  @example
12457
	 *    // Using `columnDefs`
12458
	 *    $(document).ready( function() {
12459
	 *      $('#example').dataTable( {
12460
	 *        "columnDefs": [
12461
	 *          { "orderable": false, "targets": [ 0 ] }
12462
	 *        ] } );
12463
	 *    } );
12464
	 *
12465
	 *  @example
12466
	 *    // Using `columns`
12467
	 *    $(document).ready( function() {
12468
	 *      $('#example').dataTable( {
12469
	 *        "columns": [
12470
	 *          { "orderable": false },
12471
	 *          null,
12472
	 *          null,
12473
	 *          null,
12474
	 *          null
12475
	 *        ] } );
12476
	 *    } );
12477
	 */
12478
	"bSortable": true,
12479

12480

12481
	/**
12482
	 * Enable or disable the display of this column.
12483
	 *  @type boolean
12484
	 *  @default true
12485
	 *
12486
	 *  @name DataTable.defaults.column.visible
12487
	 *  @dtopt Columns
12488
	 *
12489
	 *  @example
12490
	 *    // Using `columnDefs`
12491
	 *    $(document).ready( function() {
12492
	 *      $('#example').dataTable( {
12493
	 *        "columnDefs": [
12494
	 *          { "visible": false, "targets": [ 0 ] }
12495
	 *        ] } );
12496
	 *    } );
12497
	 *
12498
	 *  @example
12499
	 *    // Using `columns`
12500
	 *    $(document).ready( function() {
12501
	 *      $('#example').dataTable( {
12502
	 *        "columns": [
12503
	 *          { "visible": false },
12504
	 *          null,
12505
	 *          null,
12506
	 *          null,
12507
	 *          null
12508
	 *        ] } );
12509
	 *    } );
12510
	 */
12511
	"bVisible": true,
12512

12513

12514
	/**
12515
	 * Developer definable function that is called whenever a cell is created (Ajax source,
12516
	 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
12517
	 * allowing you to modify the DOM element (add background colour for example) when the
12518
	 * element is available.
12519
	 *  @type function
12520
	 *  @param {element} td The TD node that has been created
12521
	 *  @param {*} cellData The Data for the cell
12522
	 *  @param {array|object} rowData The data for the whole row
12523
	 *  @param {int} row The row index for the aoData data store
12524
	 *  @param {int} col The column index for aoColumns
12525
	 *
12526
	 *  @name DataTable.defaults.column.createdCell
12527
	 *  @dtopt Columns
12528
	 *
12529
	 *  @example
12530
	 *    $(document).ready( function() {
12531
	 *      $('#example').dataTable( {
12532
	 *        "columnDefs": [ {
12533
	 *          "targets": [3],
12534
	 *          "createdCell": function (td, cellData, rowData, row, col) {
12535
	 *            if ( cellData == "1.7" ) {
12536
	 *              $(td).css('color', 'blue')
12537
	 *            }
12538
	 *          }
12539
	 *        } ]
12540
	 *      });
12541
	 *    } );
12542
	 */
12543
	"fnCreatedCell": null,
12544

12545

12546
	/**
12547
	 * This parameter has been replaced by `data` in DataTables to ensure naming
12548
	 * consistency. `dataProp` can still be used, as there is backwards
12549
	 * compatibility in DataTables for this option, but it is strongly
12550
	 * recommended that you use `data` in preference to `dataProp`.
12551
	 *  @name DataTable.defaults.column.dataProp
12552
	 */
12553

12554

12555
	/**
12556
	 * This property can be used to read data from any data source property,
12557
	 * including deeply nested objects / properties. `data` can be given in a
12558
	 * number of different ways which effect its behaviour:
12559
	 *
12560
	 * * `integer` - treated as an array index for the data source. This is the
12561
	 *   default that DataTables uses (incrementally increased for each column).
12562
	 * * `string` - read an object property from the data source. There are
12563
	 *   three 'special' options that can be used in the string to alter how
12564
	 *   DataTables reads the data from the source object:
12565
	 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
12566
	 *      Javascript to read from nested objects, so to can the options
12567
	 *      specified in `data`. For example: `browser.version` or
12568
	 *      `browser.name`. If your object parameter name contains a period, use
12569
	 *      `\\` to escape it - i.e. `first\\.name`.
12570
	 *    * `[]` - Array notation. DataTables can automatically combine data
12571
	 *      from and array source, joining the data with the characters provided
12572
	 *      between the two brackets. For example: `name[, ]` would provide a
12573
	 *      comma-space separated list from the source array. If no characters
12574
	 *      are provided between the brackets, the original array source is
12575
	 *      returned.
12576
	 *    * `()` - Function notation. Adding `()` to the end of a parameter will
12577
	 *      execute a function of the name given. For example: `browser()` for a
12578
	 *      simple function on the data source, `browser.version()` for a
12579
	 *      function in a nested property or even `browser().version` to get an
12580
	 *      object property if the function called returns an object. Note that
12581
	 *      function notation is recommended for use in `render` rather than
12582
	 *      `data` as it is much simpler to use as a renderer.
12583
	 * * `null` - use the original data source for the row rather than plucking
12584
	 *   data directly from it. This action has effects on two other
12585
	 *   initialisation options:
12586
	 *    * `defaultContent` - When null is given as the `data` option and
12587
	 *      `defaultContent` is specified for the column, the value defined by
12588
	 *      `defaultContent` will be used for the cell.
12589
	 *    * `render` - When null is used for the `data` option and the `render`
12590
	 *      option is specified for the column, the whole data source for the
12591
	 *      row is used for the renderer.
12592
	 * * `function` - the function given will be executed whenever DataTables
12593
	 *   needs to set or get the data for a cell in the column. The function
12594
	 *   takes three parameters:
12595
	 *    * Parameters:
12596
	 *      * `{array|object}` The data source for the row
12597
	 *      * `{string}` The type call data requested - this will be 'set' when
12598
	 *        setting data or 'filter', 'display', 'type', 'sort' or undefined
12599
	 *        when gathering data. Note that when `undefined` is given for the
12600
	 *        type DataTables expects to get the raw data for the object back<
12601
	 *      * `{*}` Data to set when the second parameter is 'set'.
12602
	 *    * Return:
12603
	 *      * The return value from the function is not required when 'set' is
12604
	 *        the type of call, but otherwise the return is what will be used
12605
	 *        for the data requested.
12606
	 *
12607
	 * Note that `data` is a getter and setter option. If you just require
12608
	 * formatting of data for output, you will likely want to use `render` which
12609
	 * is simply a getter and thus simpler to use.
12610
	 *
12611
	 * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The
12612
	 * name change reflects the flexibility of this property and is consistent
12613
	 * with the naming of mRender. If 'mDataProp' is given, then it will still
12614
	 * be used by DataTables, as it automatically maps the old name to the new
12615
	 * if required.
12616
	 *
12617
	 *  @type string|int|function|null
12618
	 *  @default null <i>Use automatically calculated column index</i>
12619
	 *
12620
	 *  @name DataTable.defaults.column.data
12621
	 *  @dtopt Columns
12622
	 *
12623
	 *  @example
12624
	 *    // Read table data from objects
12625
	 *    // JSON structure for each row:
12626
	 *    //   {
12627
	 *    //      "engine": {value},
12628
	 *    //      "browser": {value},
12629
	 *    //      "platform": {value},
12630
	 *    //      "version": {value},
12631
	 *    //      "grade": {value}
12632
	 *    //   }
12633
	 *    $(document).ready( function() {
12634
	 *      $('#example').dataTable( {
12635
	 *        "ajaxSource": "sources/objects.txt",
12636
	 *        "columns": [
12637
	 *          { "data": "engine" },
12638
	 *          { "data": "browser" },
12639
	 *          { "data": "platform" },
12640
	 *          { "data": "version" },
12641
	 *          { "data": "grade" }
12642
	 *        ]
12643
	 *      } );
12644
	 *    } );
12645
	 *
12646
	 *  @example
12647
	 *    // Read information from deeply nested objects
12648
	 *    // JSON structure for each row:
12649
	 *    //   {
12650
	 *    //      "engine": {value},
12651
	 *    //      "browser": {value},
12652
	 *    //      "platform": {
12653
	 *    //         "inner": {value}
12654
	 *    //      },
12655
	 *    //      "details": [
12656
	 *    //         {value}, {value}
12657
	 *    //      ]
12658
	 *    //   }
12659
	 *    $(document).ready( function() {
12660
	 *      $('#example').dataTable( {
12661
	 *        "ajaxSource": "sources/deep.txt",
12662
	 *        "columns": [
12663
	 *          { "data": "engine" },
12664
	 *          { "data": "browser" },
12665
	 *          { "data": "platform.inner" },
12666
	 *          { "data": "details.0" },
12667
	 *          { "data": "details.1" }
12668
	 *        ]
12669
	 *      } );
12670
	 *    } );
12671
	 *
12672
	 *  @example
12673
	 *    // Using `data` as a function to provide different information for
12674
	 *    // sorting, filtering and display. In this case, currency (price)
12675
	 *    $(document).ready( function() {
12676
	 *      $('#example').dataTable( {
12677
	 *        "columnDefs": [ {
12678
	 *          "targets": [ 0 ],
12679
	 *          "data": function ( source, type, val ) {
12680
	 *            if (type === 'set') {
12681
	 *              source.price = val;
12682
	 *              // Store the computed display and filter values for efficiency
12683
	 *              source.price_display = val=="" ? "" : "$"+numberFormat(val);
12684
	 *              source.price_filter  = val=="" ? "" : "$"+numberFormat(val)+" "+val;
12685
	 *              return;
12686
	 *            }
12687
	 *            else if (type === 'display') {
12688
	 *              return source.price_display;
12689
	 *            }
12690
	 *            else if (type === 'filter') {
12691
	 *              return source.price_filter;
12692
	 *            }
12693
	 *            // 'sort', 'type' and undefined all just use the integer
12694
	 *            return source.price;
12695
	 *          }
12696
	 *        } ]
12697
	 *      } );
12698
	 *    } );
12699
	 *
12700
	 *  @example
12701
	 *    // Using default content
12702
	 *    $(document).ready( function() {
12703
	 *      $('#example').dataTable( {
12704
	 *        "columnDefs": [ {
12705
	 *          "targets": [ 0 ],
12706
	 *          "data": null,
12707
	 *          "defaultContent": "Click to edit"
12708
	 *        } ]
12709
	 *      } );
12710
	 *    } );
12711
	 *
12712
	 *  @example
12713
	 *    // Using array notation - outputting a list from an array
12714
	 *    $(document).ready( function() {
12715
	 *      $('#example').dataTable( {
12716
	 *        "columnDefs": [ {
12717
	 *          "targets": [ 0 ],
12718
	 *          "data": "name[, ]"
12719
	 *        } ]
12720
	 *      } );
12721
	 *    } );
12722
	 *
12723
	 */
12724
	"mData": null,
12725

12726

12727
	/**
12728
	 * This property is the rendering partner to `data` and it is suggested that
12729
	 * when you want to manipulate data for display (including filtering,
12730
	 * sorting etc) without altering the underlying data for the table, use this
12731
	 * property. `render` can be considered to be the the read only companion to
12732
	 * `data` which is read / write (then as such more complex). Like `data`
12733
	 * this option can be given in a number of different ways to effect its
12734
	 * behaviour:
12735
	 *
12736
	 * * `integer` - treated as an array index for the data source. This is the
12737
	 *   default that DataTables uses (incrementally increased for each column).
12738
	 * * `string` - read an object property from the data source. There are
12739
	 *   three 'special' options that can be used in the string to alter how
12740
	 *   DataTables reads the data from the source object:
12741
	 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
12742
	 *      Javascript to read from nested objects, so to can the options
12743
	 *      specified in `data`. For example: `browser.version` or
12744
	 *      `browser.name`. If your object parameter name contains a period, use
12745
	 *      `\\` to escape it - i.e. `first\\.name`.
12746
	 *    * `[]` - Array notation. DataTables can automatically combine data
12747
	 *      from and array source, joining the data with the characters provided
12748
	 *      between the two brackets. For example: `name[, ]` would provide a
12749
	 *      comma-space separated list from the source array. If no characters
12750
	 *      are provided between the brackets, the original array source is
12751
	 *      returned.
12752
	 *    * `()` - Function notation. Adding `()` to the end of a parameter will
12753
	 *      execute a function of the name given. For example: `browser()` for a
12754
	 *      simple function on the data source, `browser.version()` for a
12755
	 *      function in a nested property or even `browser().version` to get an
12756
	 *      object property if the function called returns an object.
12757
	 * * `object` - use different data for the different data types requested by
12758
	 *   DataTables ('filter', 'display', 'type' or 'sort'). The property names
12759
	 *   of the object is the data type the property refers to and the value can
12760
	 *   defined using an integer, string or function using the same rules as
12761
	 *   `render` normally does. Note that an `_` option _must_ be specified.
12762
	 *   This is the default value to use if you haven't specified a value for
12763
	 *   the data type requested by DataTables.
12764
	 * * `function` - the function given will be executed whenever DataTables
12765
	 *   needs to set or get the data for a cell in the column. The function
12766
	 *   takes three parameters:
12767
	 *    * Parameters:
12768
	 *      * {array|object} The data source for the row (based on `data`)
12769
	 *      * {string} The type call data requested - this will be 'filter',
12770
	 *        'display', 'type' or 'sort'.
12771
	 *      * {array|object} The full data source for the row (not based on
12772
	 *        `data`)
12773
	 *    * Return:
12774
	 *      * The return value from the function is what will be used for the
12775
	 *        data requested.
12776
	 *
12777
	 *  @type string|int|function|object|null
12778
	 *  @default null Use the data source value.
12779
	 *
12780
	 *  @name DataTable.defaults.column.render
12781
	 *  @dtopt Columns
12782
	 *
12783
	 *  @example
12784
	 *    // Create a comma separated list from an array of objects
12785
	 *    $(document).ready( function() {
12786
	 *      $('#example').dataTable( {
12787
	 *        "ajaxSource": "sources/deep.txt",
12788
	 *        "columns": [
12789
	 *          { "data": "engine" },
12790
	 *          { "data": "browser" },
12791
	 *          {
12792
	 *            "data": "platform",
12793
	 *            "render": "[, ].name"
12794
	 *          }
12795
	 *        ]
12796
	 *      } );
12797
	 *    } );
12798
	 *
12799
	 *  @example
12800
	 *    // Execute a function to obtain data
12801
	 *    $(document).ready( function() {
12802
	 *      $('#example').dataTable( {
12803
	 *        "columnDefs": [ {
12804
	 *          "targets": [ 0 ],
12805
	 *          "data": null, // Use the full data source object for the renderer's source
12806
	 *          "render": "browserName()"
12807
	 *        } ]
12808
	 *      } );
12809
	 *    } );
12810
	 *
12811
	 *  @example
12812
	 *    // As an object, extracting different data for the different types
12813
	 *    // This would be used with a data source such as:
12814
	 *    //   { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" }
12815
	 *    // Here the `phone` integer is used for sorting and type detection, while `phone_filter`
12816
	 *    // (which has both forms) is used for filtering for if a user inputs either format, while
12817
	 *    // the formatted phone number is the one that is shown in the table.
12818
	 *    $(document).ready( function() {
12819
	 *      $('#example').dataTable( {
12820
	 *        "columnDefs": [ {
12821
	 *          "targets": [ 0 ],
12822
	 *          "data": null, // Use the full data source object for the renderer's source
12823
	 *          "render": {
12824
	 *            "_": "phone",
12825
	 *            "filter": "phone_filter",
12826
	 *            "display": "phone_display"
12827
	 *          }
12828
	 *        } ]
12829
	 *      } );
12830
	 *    } );
12831
	 *
12832
	 *  @example
12833
	 *    // Use as a function to create a link from the data source
12834
	 *    $(document).ready( function() {
12835
	 *      $('#example').dataTable( {
12836
	 *        "columnDefs": [ {
12837
	 *          "targets": [ 0 ],
12838
	 *          "data": "download_link",
12839
	 *          "render": function ( data, type, full ) {
12840
	 *            return '<a href="'+data+'">Download</a>';
12841
	 *          }
12842
	 *        } ]
12843
	 *      } );
12844
	 *    } );
12845
	 */
12846
	"mRender": null,
12847

12848

12849
	/**
12850
	 * Change the cell type created for the column - either TD cells or TH cells. This
12851
	 * can be useful as TH cells have semantic meaning in the table body, allowing them
12852
	 * to act as a header for a row (you may wish to add scope='row' to the TH elements).
12853
	 *  @type string
12854
	 *  @default td
12855
	 *
12856
	 *  @name DataTable.defaults.column.cellType
12857
	 *  @dtopt Columns
12858
	 *
12859
	 *  @example
12860
	 *    // Make the first column use TH cells
12861
	 *    $(document).ready( function() {
12862
	 *      $('#example').dataTable( {
12863
	 *        "columnDefs": [ {
12864
	 *          "targets": [ 0 ],
12865
	 *          "cellType": "th"
12866
	 *        } ]
12867
	 *      } );
12868
	 *    } );
12869
	 */
12870
	"sCellType": "td",
12871

12872

12873
	/**
12874
	 * Class to give to each cell in this column.
12875
	 *  @type string
12876
	 *  @default <i>Empty string</i>
12877
	 *
12878
	 *  @name DataTable.defaults.column.class
12879
	 *  @dtopt Columns
12880
	 *
12881
	 *  @example
12882
	 *    // Using `columnDefs`
12883
	 *    $(document).ready( function() {
12884
	 *      $('#example').dataTable( {
12885
	 *        "columnDefs": [
12886
	 *          { "class": "my_class", "targets": [ 0 ] }
12887
	 *        ]
12888
	 *      } );
12889
	 *    } );
12890
	 *
12891
	 *  @example
12892
	 *    // Using `columns`
12893
	 *    $(document).ready( function() {
12894
	 *      $('#example').dataTable( {
12895
	 *        "columns": [
12896
	 *          { "class": "my_class" },
12897
	 *          null,
12898
	 *          null,
12899
	 *          null,
12900
	 *          null
12901
	 *        ]
12902
	 *      } );
12903
	 *    } );
12904
	 */
12905
	"sClass": "",
12906

12907
	/**
12908
	 * When DataTables calculates the column widths to assign to each column,
12909
	 * it finds the longest string in each column and then constructs a
12910
	 * temporary table and reads the widths from that. The problem with this
12911
	 * is that "mmm" is much wider then "iiii", but the latter is a longer
12912
	 * string - thus the calculation can go wrong (doing it properly and putting
12913
	 * it into an DOM object and measuring that is horribly(!) slow). Thus as
12914
	 * a "work around" we provide this option. It will append its value to the
12915
	 * text that is found to be the longest string for the column - i.e. padding.
12916
	 * Generally you shouldn't need this!
12917
	 *  @type string
12918
	 *  @default <i>Empty string<i>
12919
	 *
12920
	 *  @name DataTable.defaults.column.contentPadding
12921
	 *  @dtopt Columns
12922
	 *
12923
	 *  @example
12924
	 *    // Using `columns`
12925
	 *    $(document).ready( function() {
12926
	 *      $('#example').dataTable( {
12927
	 *        "columns": [
12928
	 *          null,
12929
	 *          null,
12930
	 *          null,
12931
	 *          {
12932
	 *            "contentPadding": "mmm"
12933
	 *          }
12934
	 *        ]
12935
	 *      } );
12936
	 *    } );
12937
	 */
12938
	"sContentPadding": "",
12939

12940

12941
	/**
12942
	 * Allows a default value to be given for a column's data, and will be used
12943
	 * whenever a null data source is encountered (this can be because `data`
12944
	 * is set to null, or because the data source itself is null).
12945
	 *  @type string
12946
	 *  @default null
12947
	 *
12948
	 *  @name DataTable.defaults.column.defaultContent
12949
	 *  @dtopt Columns
12950
	 *
12951
	 *  @example
12952
	 *    // Using `columnDefs`
12953
	 *    $(document).ready( function() {
12954
	 *      $('#example').dataTable( {
12955
	 *        "columnDefs": [
12956
	 *          {
12957
	 *            "data": null,
12958
	 *            "defaultContent": "Edit",
12959
	 *            "targets": [ -1 ]
12960
	 *          }
12961
	 *        ]
12962
	 *      } );
12963
	 *    } );
12964
	 *
12965
	 *  @example
12966
	 *    // Using `columns`
12967
	 *    $(document).ready( function() {
12968
	 *      $('#example').dataTable( {
12969
	 *        "columns": [
12970
	 *          null,
12971
	 *          null,
12972
	 *          null,
12973
	 *          {
12974
	 *            "data": null,
12975
	 *            "defaultContent": "Edit"
12976
	 *          }
12977
	 *        ]
12978
	 *      } );
12979
	 *    } );
12980
	 */
12981
	"sDefaultContent": null,
12982

12983

12984
	/**
12985
	 * This parameter is only used in DataTables' server-side processing. It can
12986
	 * be exceptionally useful to know what columns are being displayed on the
12987
	 * client side, and to map these to database fields. When defined, the names
12988
	 * also allow DataTables to reorder information from the server if it comes
12989
	 * back in an unexpected order (i.e. if you switch your columns around on the
12990
	 * client-side, your server-side code does not also need updating).
12991
	 *  @type string
12992
	 *  @default <i>Empty string</i>
12993
	 *
12994
	 *  @name DataTable.defaults.column.name
12995
	 *  @dtopt Columns
12996
	 *
12997
	 *  @example
12998
	 *    // Using `columnDefs`
12999
	 *    $(document).ready( function() {
13000
	 *      $('#example').dataTable( {
13001
	 *        "columnDefs": [
13002
	 *          { "name": "engine", "targets": [ 0 ] },
13003
	 *          { "name": "browser", "targets": [ 1 ] },
13004
	 *          { "name": "platform", "targets": [ 2 ] },
13005
	 *          { "name": "version", "targets": [ 3 ] },
13006
	 *          { "name": "grade", "targets": [ 4 ] }
13007
	 *        ]
13008
	 *      } );
13009
	 *    } );
13010
	 *
13011
	 *  @example
13012
	 *    // Using `columns`
13013
	 *    $(document).ready( function() {
13014
	 *      $('#example').dataTable( {
13015
	 *        "columns": [
13016
	 *          { "name": "engine" },
13017
	 *          { "name": "browser" },
13018
	 *          { "name": "platform" },
13019
	 *          { "name": "version" },
13020
	 *          { "name": "grade" }
13021
	 *        ]
13022
	 *      } );
13023
	 *    } );
13024
	 */
13025
	"sName": "",
13026

13027

13028
	/**
13029
	 * Defines a data source type for the ordering which can be used to read
13030
	 * real-time information from the table (updating the internally cached
13031
	 * version) prior to ordering. This allows ordering to occur on user
13032
	 * editable elements such as form inputs.
13033
	 *  @type string
13034
	 *  @default std
13035
	 *
13036
	 *  @name DataTable.defaults.column.orderDataType
13037
	 *  @dtopt Columns
13038
	 *
13039
	 *  @example
13040
	 *    // Using `columnDefs`
13041
	 *    $(document).ready( function() {
13042
	 *      $('#example').dataTable( {
13043
	 *        "columnDefs": [
13044
	 *          { "orderDataType": "dom-text", "targets": [ 2, 3 ] },
13045
	 *          { "type": "numeric", "targets": [ 3 ] },
13046
	 *          { "orderDataType": "dom-select", "targets": [ 4 ] },
13047
	 *          { "orderDataType": "dom-checkbox", "targets": [ 5 ] }
13048
	 *        ]
13049
	 *      } );
13050
	 *    } );
13051
	 *
13052
	 *  @example
13053
	 *    // Using `columns`
13054
	 *    $(document).ready( function() {
13055
	 *      $('#example').dataTable( {
13056
	 *        "columns": [
13057
	 *          null,
13058
	 *          null,
13059
	 *          { "orderDataType": "dom-text" },
13060
	 *          { "orderDataType": "dom-text", "type": "numeric" },
13061
	 *          { "orderDataType": "dom-select" },
13062
	 *          { "orderDataType": "dom-checkbox" }
13063
	 *        ]
13064
	 *      } );
13065
	 *    } );
13066
	 */
13067
	"sSortDataType": "std",
13068

13069

13070
	/**
13071
	 * The title of this column.
13072
	 *  @type string
13073
	 *  @default null <i>Derived from the 'TH' value for this column in the
13074
	 *    original HTML table.</i>
13075
	 *
13076
	 *  @name DataTable.defaults.column.title
13077
	 *  @dtopt Columns
13078
	 *
13079
	 *  @example
13080
	 *    // Using `columnDefs`
13081
	 *    $(document).ready( function() {
13082
	 *      $('#example').dataTable( {
13083
	 *        "columnDefs": [
13084
	 *          { "title": "My column title", "targets": [ 0 ] }
13085
	 *        ]
13086
	 *      } );
13087
	 *    } );
13088
	 *
13089
	 *  @example
13090
	 *    // Using `columns`
13091
	 *    $(document).ready( function() {
13092
	 *      $('#example').dataTable( {
13093
	 *        "columns": [
13094
	 *          { "title": "My column title" },
13095
	 *          null,
13096
	 *          null,
13097
	 *          null,
13098
	 *          null
13099
	 *        ]
13100
	 *      } );
13101
	 *    } );
13102
	 */
13103
	"sTitle": null,
13104

13105

13106
	/**
13107
	 * The type allows you to specify how the data for this column will be
13108
	 * ordered. Four types (string, numeric, date and html (which will strip
13109
	 * HTML tags before ordering)) are currently available. Note that only date
13110
	 * formats understood by Javascript's Date() object will be accepted as type
13111
	 * date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string',
13112
	 * 'numeric', 'date' or 'html' (by default). Further types can be adding
13113
	 * through plug-ins.
13114
	 *  @type string
13115
	 *  @default null <i>Auto-detected from raw data</i>
13116
	 *
13117
	 *  @name DataTable.defaults.column.type
13118
	 *  @dtopt Columns
13119
	 *
13120
	 *  @example
13121
	 *    // Using `columnDefs`
13122
	 *    $(document).ready( function() {
13123
	 *      $('#example').dataTable( {
13124
	 *        "columnDefs": [
13125
	 *          { "type": "html", "targets": [ 0 ] }
13126
	 *        ]
13127
	 *      } );
13128
	 *    } );
13129
	 *
13130
	 *  @example
13131
	 *    // Using `columns`
13132
	 *    $(document).ready( function() {
13133
	 *      $('#example').dataTable( {
13134
	 *        "columns": [
13135
	 *          { "type": "html" },
13136
	 *          null,
13137
	 *          null,
13138
	 *          null,
13139
	 *          null
13140
	 *        ]
13141
	 *      } );
13142
	 *    } );
13143
	 */
13144
	"sType": null,
13145

13146

13147
	/**
13148
	 * Defining the width of the column, this parameter may take any CSS value
13149
	 * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not
13150
	 * been given a specific width through this interface ensuring that the table
13151
	 * remains readable.
13152
	 *  @type string
13153
	 *  @default null <i>Automatic</i>
13154
	 *
13155
	 *  @name DataTable.defaults.column.width
13156
	 *  @dtopt Columns
13157
	 *
13158
	 *  @example
13159
	 *    // Using `columnDefs`
13160
	 *    $(document).ready( function() {
13161
	 *      $('#example').dataTable( {
13162
	 *        "columnDefs": [
13163
	 *          { "width": "20%", "targets": [ 0 ] }
13164
	 *        ]
13165
	 *      } );
13166
	 *    } );
13167
	 *
13168
	 *  @example
13169
	 *    // Using `columns`
13170
	 *    $(document).ready( function() {
13171
	 *      $('#example').dataTable( {
13172
	 *        "columns": [
13173
	 *          { "width": "20%" },
13174
	 *          null,
13175
	 *          null,
13176
	 *          null,
13177
	 *          null
13178
	 *        ]
13179
	 *      } );
13180
	 *    } );
13181
	 */
13182
	"sWidth": null
13183
};
13184

13185
_fnHungarianMap( DataTable.defaults.column );
13186

13187

13188

13189
/**
13190
 * DataTables settings object - this holds all the information needed for a
13191
 * given table, including configuration, data and current application of the
13192
 * table options. DataTables does not have a single instance for each DataTable
13193
 * with the settings attached to that instance, but rather instances of the
13194
 * DataTable "class" are created on-the-fly as needed (typically by a
13195
 * $().dataTable() call) and the settings object is then applied to that
13196
 * instance.
13197
 *
13198
 * Note that this object is related to {@link DataTable.defaults} but this
13199
 * one is the internal data store for DataTables's cache of columns. It should
13200
 * NOT be manipulated outside of DataTables. Any configuration should be done
13201
 * through the initialisation options.
13202
 *  @namespace
13203
 *  @todo Really should attach the settings object to individual instances so we
13204
 *    don't need to create new instances on each $().dataTable() call (if the
13205
 *    table already exists). It would also save passing oSettings around and
13206
 *    into every single function. However, this is a very significant
13207
 *    architecture change for DataTables and will almost certainly break
13208
 *    backwards compatibility with older installations. This is something that
13209
 *    will be done in 2.0.
13210
 */
13211
DataTable.models.oSettings = {
13212
	/**
13213
	 * Primary features of DataTables and their enablement state.
13214
	 *  @namespace
13215
	 */
13216
	"oFeatures": {
13217

13218
		/**
13219
		 * Flag to say if DataTables should automatically try to calculate the
13220
		 * optimum table and columns widths (true) or not (false).
13221
		 * Note that this parameter will be set by the initialisation routine. To
13222
		 * set a default use {@link DataTable.defaults}.
13223
		 *  @type boolean
13224
		 */
13225
		"bAutoWidth": null,
13226

13227
		/**
13228
		 * Delay the creation of TR and TD elements until they are actually
13229
		 * needed by a driven page draw. This can give a significant speed
13230
		 * increase for Ajax source and Javascript source data, but makes no
13231
		 * difference at all for DOM and server-side processing tables.
13232
		 * Note that this parameter will be set by the initialisation routine. To
13233
		 * set a default use {@link DataTable.defaults}.
13234
		 *  @type boolean
13235
		 */
13236
		"bDeferRender": null,
13237

13238
		/**
13239
		 * Enable filtering on the table or not. Note that if this is disabled
13240
		 * then there is no filtering at all on the table, including fnFilter.
13241
		 * To just remove the filtering input use sDom and remove the 'f' option.
13242
		 * Note that this parameter will be set by the initialisation routine. To
13243
		 * set a default use {@link DataTable.defaults}.
13244
		 *  @type boolean
13245
		 */
13246
		"bFilter": null,
13247

13248
		/**
13249
		 * Table information element (the 'Showing x of y records' div) enable
13250
		 * flag.
13251
		 * Note that this parameter will be set by the initialisation routine. To
13252
		 * set a default use {@link DataTable.defaults}.
13253
		 *  @type boolean
13254
		 */
13255
		"bInfo": null,
13256

13257
		/**
13258
		 * Present a user control allowing the end user to change the page size
13259
		 * when pagination is enabled.
13260
		 * Note that this parameter will be set by the initialisation routine. To
13261
		 * set a default use {@link DataTable.defaults}.
13262
		 *  @type boolean
13263
		 */
13264
		"bLengthChange": null,
13265

13266
		/**
13267
		 * Pagination enabled or not. Note that if this is disabled then length
13268
		 * changing must also be disabled.
13269
		 * Note that this parameter will be set by the initialisation routine. To
13270
		 * set a default use {@link DataTable.defaults}.
13271
		 *  @type boolean
13272
		 */
13273
		"bPaginate": null,
13274

13275
		/**
13276
		 * Processing indicator enable flag whenever DataTables is enacting a
13277
		 * user request - typically an Ajax request for server-side processing.
13278
		 * Note that this parameter will be set by the initialisation routine. To
13279
		 * set a default use {@link DataTable.defaults}.
13280
		 *  @type boolean
13281
		 */
13282
		"bProcessing": null,
13283

13284
		/**
13285
		 * Server-side processing enabled flag - when enabled DataTables will
13286
		 * get all data from the server for every draw - there is no filtering,
13287
		 * sorting or paging done on the client-side.
13288
		 * Note that this parameter will be set by the initialisation routine. To
13289
		 * set a default use {@link DataTable.defaults}.
13290
		 *  @type boolean
13291
		 */
13292
		"bServerSide": null,
13293

13294
		/**
13295
		 * Sorting enablement flag.
13296
		 * Note that this parameter will be set by the initialisation routine. To
13297
		 * set a default use {@link DataTable.defaults}.
13298
		 *  @type boolean
13299
		 */
13300
		"bSort": null,
13301

13302
		/**
13303
		 * Multi-column sorting
13304
		 * Note that this parameter will be set by the initialisation routine. To
13305
		 * set a default use {@link DataTable.defaults}.
13306
		 *  @type boolean
13307
		 */
13308
		"bSortMulti": null,
13309

13310
		/**
13311
		 * Apply a class to the columns which are being sorted to provide a
13312
		 * visual highlight or not. This can slow things down when enabled since
13313
		 * there is a lot of DOM interaction.
13314
		 * Note that this parameter will be set by the initialisation routine. To
13315
		 * set a default use {@link DataTable.defaults}.
13316
		 *  @type boolean
13317
		 */
13318
		"bSortClasses": null,
13319

13320
		/**
13321
		 * State saving enablement flag.
13322
		 * Note that this parameter will be set by the initialisation routine. To
13323
		 * set a default use {@link DataTable.defaults}.
13324
		 *  @type boolean
13325
		 */
13326
		"bStateSave": null
13327
	},
13328

13329

13330
	/**
13331
	 * Scrolling settings for a table.
13332
	 *  @namespace
13333
	 */
13334
	"oScroll": {
13335
		/**
13336
		 * When the table is shorter in height than sScrollY, collapse the
13337
		 * table container down to the height of the table (when true).
13338
		 * Note that this parameter will be set by the initialisation routine. To
13339
		 * set a default use {@link DataTable.defaults}.
13340
		 *  @type boolean
13341
		 */
13342
		"bCollapse": null,
13343

13344
		/**
13345
		 * Width of the scrollbar for the web-browser's platform. Calculated
13346
		 * during table initialisation.
13347
		 *  @type int
13348
		 *  @default 0
13349
		 */
13350
		"iBarWidth": 0,
13351

13352
		/**
13353
		 * Viewport width for horizontal scrolling. Horizontal scrolling is
13354
		 * disabled if an empty string.
13355
		 * Note that this parameter will be set by the initialisation routine. To
13356
		 * set a default use {@link DataTable.defaults}.
13357
		 *  @type string
13358
		 */
13359
		"sX": null,
13360

13361
		/**
13362
		 * Width to expand the table to when using x-scrolling. Typically you
13363
		 * should not need to use this.
13364
		 * Note that this parameter will be set by the initialisation routine. To
13365
		 * set a default use {@link DataTable.defaults}.
13366
		 *  @type string
13367
		 *  @deprecated
13368
		 */
13369
		"sXInner": null,
13370

13371
		/**
13372
		 * Viewport height for vertical scrolling. Vertical scrolling is disabled
13373
		 * if an empty string.
13374
		 * Note that this parameter will be set by the initialisation routine. To
13375
		 * set a default use {@link DataTable.defaults}.
13376
		 *  @type string
13377
		 */
13378
		"sY": null
13379
	},
13380

13381
	/**
13382
	 * Language information for the table.
13383
	 *  @namespace
13384
	 *  @extends DataTable.defaults.oLanguage
13385
	 */
13386
	"oLanguage": {
13387
		/**
13388
		 * Information callback function. See
13389
		 * {@link DataTable.defaults.fnInfoCallback}
13390
		 *  @type function
13391
		 *  @default null
13392
		 */
13393
		"fnInfoCallback": null
13394
	},
13395

13396
	/**
13397
	 * Browser support parameters
13398
	 *  @namespace
13399
	 */
13400
	"oBrowser": {
13401
		/**
13402
		 * Indicate if the browser incorrectly calculates width:100% inside a
13403
		 * scrolling element (IE6/7)
13404
		 *  @type boolean
13405
		 *  @default false
13406
		 */
13407
		"bScrollOversize": false,
13408

13409
		/**
13410
		 * Determine if the vertical scrollbar is on the right or left of the
13411
		 * scrolling container - needed for rtl language layout, although not
13412
		 * all browsers move the scrollbar (Safari).
13413
		 *  @type boolean
13414
		 *  @default false
13415
		 */
13416
		"bScrollbarLeft": false,
13417

13418
		/**
13419
		 * Flag for if `getBoundingClientRect` is fully supported or not
13420
		 *  @type boolean
13421
		 *  @default false
13422
		 */
13423
		"bBounding": false,
13424

13425
		/**
13426
		 * Browser scrollbar width
13427
		 *  @type integer
13428
		 *  @default 0
13429
		 */
13430
		"barWidth": 0
13431
	},
13432

13433

13434
	"ajax": null,
13435

13436

13437
	/**
13438
	 * Array referencing the nodes which are used for the features. The
13439
	 * parameters of this object match what is allowed by sDom - i.e.
13440
	 *   <ul>
13441
	 *     <li>'l' - Length changing</li>
13442
	 *     <li>'f' - Filtering input</li>
13443
	 *     <li>'t' - The table!</li>
13444
	 *     <li>'i' - Information</li>
13445
	 *     <li>'p' - Pagination</li>
13446
	 *     <li>'r' - pRocessing</li>
13447
	 *   </ul>
13448
	 *  @type array
13449
	 *  @default []
13450
	 */
13451
	"aanFeatures": [],
13452

13453
	/**
13454
	 * Store data information - see {@link DataTable.models.oRow} for detailed
13455
	 * information.
13456
	 *  @type array
13457
	 *  @default []
13458
	 */
13459
	"aoData": [],
13460

13461
	/**
13462
	 * Array of indexes which are in the current display (after filtering etc)
13463
	 *  @type array
13464
	 *  @default []
13465
	 */
13466
	"aiDisplay": [],
13467

13468
	/**
13469
	 * Array of indexes for display - no filtering
13470
	 *  @type array
13471
	 *  @default []
13472
	 */
13473
	"aiDisplayMaster": [],
13474

13475
	/**
13476
	 * Map of row ids to data indexes
13477
	 *  @type object
13478
	 *  @default {}
13479
	 */
13480
	"aIds": {},
13481

13482
	/**
13483
	 * Store information about each column that is in use
13484
	 *  @type array
13485
	 *  @default []
13486
	 */
13487
	"aoColumns": [],
13488

13489
	/**
13490
	 * Store information about the table's header
13491
	 *  @type array
13492
	 *  @default []
13493
	 */
13494
	"aoHeader": [],
13495

13496
	/**
13497
	 * Store information about the table's footer
13498
	 *  @type array
13499
	 *  @default []
13500
	 */
13501
	"aoFooter": [],
13502

13503
	/**
13504
	 * Store the applied global search information in case we want to force a
13505
	 * research or compare the old search to a new one.
13506
	 * Note that this parameter will be set by the initialisation routine. To
13507
	 * set a default use {@link DataTable.defaults}.
13508
	 *  @namespace
13509
	 *  @extends DataTable.models.oSearch
13510
	 */
13511
	"oPreviousSearch": {},
13512

13513
	/**
13514
	 * Store the applied search for each column - see
13515
	 * {@link DataTable.models.oSearch} for the format that is used for the
13516
	 * filtering information for each column.
13517
	 *  @type array
13518
	 *  @default []
13519
	 */
13520
	"aoPreSearchCols": [],
13521

13522
	/**
13523
	 * Sorting that is applied to the table. Note that the inner arrays are
13524
	 * used in the following manner:
13525
	 * <ul>
13526
	 *   <li>Index 0 - column number</li>
13527
	 *   <li>Index 1 - current sorting direction</li>
13528
	 * </ul>
13529
	 * Note that this parameter will be set by the initialisation routine. To
13530
	 * set a default use {@link DataTable.defaults}.
13531
	 *  @type array
13532
	 *  @todo These inner arrays should really be objects
13533
	 */
13534
	"aaSorting": null,
13535

13536
	/**
13537
	 * Sorting that is always applied to the table (i.e. prefixed in front of
13538
	 * aaSorting).
13539
	 * Note that this parameter will be set by the initialisation routine. To
13540
	 * set a default use {@link DataTable.defaults}.
13541
	 *  @type array
13542
	 *  @default []
13543
	 */
13544
	"aaSortingFixed": [],
13545

13546
	/**
13547
	 * Classes to use for the striping of a table.
13548
	 * Note that this parameter will be set by the initialisation routine. To
13549
	 * set a default use {@link DataTable.defaults}.
13550
	 *  @type array
13551
	 *  @default []
13552
	 */
13553
	"asStripeClasses": null,
13554

13555
	/**
13556
	 * If restoring a table - we should restore its striping classes as well
13557
	 *  @type array
13558
	 *  @default []
13559
	 */
13560
	"asDestroyStripes": [],
13561

13562
	/**
13563
	 * If restoring a table - we should restore its width
13564
	 *  @type int
13565
	 *  @default 0
13566
	 */
13567
	"sDestroyWidth": 0,
13568

13569
	/**
13570
	 * Callback functions array for every time a row is inserted (i.e. on a draw).
13571
	 *  @type array
13572
	 *  @default []
13573
	 */
13574
	"aoRowCallback": [],
13575

13576
	/**
13577
	 * Callback functions for the header on each draw.
13578
	 *  @type array
13579
	 *  @default []
13580
	 */
13581
	"aoHeaderCallback": [],
13582

13583
	/**
13584
	 * Callback function for the footer on each draw.
13585
	 *  @type array
13586
	 *  @default []
13587
	 */
13588
	"aoFooterCallback": [],
13589

13590
	/**
13591
	 * Array of callback functions for draw callback functions
13592
	 *  @type array
13593
	 *  @default []
13594
	 */
13595
	"aoDrawCallback": [],
13596

13597
	/**
13598
	 * Array of callback functions for row created function
13599
	 *  @type array
13600
	 *  @default []
13601
	 */
13602
	"aoRowCreatedCallback": [],
13603

13604
	/**
13605
	 * Callback functions for just before the table is redrawn. A return of
13606
	 * false will be used to cancel the draw.
13607
	 *  @type array
13608
	 *  @default []
13609
	 */
13610
	"aoPreDrawCallback": [],
13611

13612
	/**
13613
	 * Callback functions for when the table has been initialised.
13614
	 *  @type array
13615
	 *  @default []
13616
	 */
13617
	"aoInitComplete": [],
13618

13619

13620
	/**
13621
	 * Callbacks for modifying the settings to be stored for state saving, prior to
13622
	 * saving state.
13623
	 *  @type array
13624
	 *  @default []
13625
	 */
13626
	"aoStateSaveParams": [],
13627

13628
	/**
13629
	 * Callbacks for modifying the settings that have been stored for state saving
13630
	 * prior to using the stored values to restore the state.
13631
	 *  @type array
13632
	 *  @default []
13633
	 */
13634
	"aoStateLoadParams": [],
13635

13636
	/**
13637
	 * Callbacks for operating on the settings object once the saved state has been
13638
	 * loaded
13639
	 *  @type array
13640
	 *  @default []
13641
	 */
13642
	"aoStateLoaded": [],
13643

13644
	/**
13645
	 * Cache the table ID for quick access
13646
	 *  @type string
13647
	 *  @default <i>Empty string</i>
13648
	 */
13649
	"sTableId": "",
13650

13651
	/**
13652
	 * The TABLE node for the main table
13653
	 *  @type node
13654
	 *  @default null
13655
	 */
13656
	"nTable": null,
13657

13658
	/**
13659
	 * Permanent ref to the thead element
13660
	 *  @type node
13661
	 *  @default null
13662
	 */
13663
	"nTHead": null,
13664

13665
	/**
13666
	 * Permanent ref to the tfoot element - if it exists
13667
	 *  @type node
13668
	 *  @default null
13669
	 */
13670
	"nTFoot": null,
13671

13672
	/**
13673
	 * Permanent ref to the tbody element
13674
	 *  @type node
13675
	 *  @default null
13676
	 */
13677
	"nTBody": null,
13678

13679
	/**
13680
	 * Cache the wrapper node (contains all DataTables controlled elements)
13681
	 *  @type node
13682
	 *  @default null
13683
	 */
13684
	"nTableWrapper": null,
13685

13686
	/**
13687
	 * Indicate if when using server-side processing the loading of data
13688
	 * should be deferred until the second draw.
13689
	 * Note that this parameter will be set by the initialisation routine. To
13690
	 * set a default use {@link DataTable.defaults}.
13691
	 *  @type boolean
13692
	 *  @default false
13693
	 */
13694
	"bDeferLoading": false,
13695

13696
	/**
13697
	 * Indicate if all required information has been read in
13698
	 *  @type boolean
13699
	 *  @default false
13700
	 */
13701
	"bInitialised": false,
13702

13703
	/**
13704
	 * Information about open rows. Each object in the array has the parameters
13705
	 * 'nTr' and 'nParent'
13706
	 *  @type array
13707
	 *  @default []
13708
	 */
13709
	"aoOpenRows": [],
13710

13711
	/**
13712
	 * Dictate the positioning of DataTables' control elements - see
13713
	 * {@link DataTable.model.oInit.sDom}.
13714
	 * Note that this parameter will be set by the initialisation routine. To
13715
	 * set a default use {@link DataTable.defaults}.
13716
	 *  @type string
13717
	 *  @default null
13718
	 */
13719
	"sDom": null,
13720

13721
	/**
13722
	 * Search delay (in mS)
13723
	 *  @type integer
13724
	 *  @default null
13725
	 */
13726
	"searchDelay": null,
13727

13728
	/**
13729
	 * Which type of pagination should be used.
13730
	 * Note that this parameter will be set by the initialisation routine. To
13731
	 * set a default use {@link DataTable.defaults}.
13732
	 *  @type string
13733
	 *  @default two_button
13734
	 */
13735
	"sPaginationType": "two_button",
13736

13737
	/**
13738
	 * The state duration (for `stateSave`) in seconds.
13739
	 * Note that this parameter will be set by the initialisation routine. To
13740
	 * set a default use {@link DataTable.defaults}.
13741
	 *  @type int
13742
	 *  @default 0
13743
	 */
13744
	"iStateDuration": 0,
13745

13746
	/**
13747
	 * Array of callback functions for state saving. Each array element is an
13748
	 * object with the following parameters:
13749
	 *   <ul>
13750
	 *     <li>function:fn - function to call. Takes two parameters, oSettings
13751
	 *       and the JSON string to save that has been thus far created. Returns
13752
	 *       a JSON string to be inserted into a json object
13753
	 *       (i.e. '"param": [ 0, 1, 2]')</li>
13754
	 *     <li>string:sName - name of callback</li>
13755
	 *   </ul>
13756
	 *  @type array
13757
	 *  @default []
13758
	 */
13759
	"aoStateSave": [],
13760

13761
	/**
13762
	 * Array of callback functions for state loading. Each array element is an
13763
	 * object with the following parameters:
13764
	 *   <ul>
13765
	 *     <li>function:fn - function to call. Takes two parameters, oSettings
13766
	 *       and the object stored. May return false to cancel state loading</li>
13767
	 *     <li>string:sName - name of callback</li>
13768
	 *   </ul>
13769
	 *  @type array
13770
	 *  @default []
13771
	 */
13772
	"aoStateLoad": [],
13773

13774
	/**
13775
	 * State that was saved. Useful for back reference
13776
	 *  @type object
13777
	 *  @default null
13778
	 */
13779
	"oSavedState": null,
13780

13781
	/**
13782
	 * State that was loaded. Useful for back reference
13783
	 *  @type object
13784
	 *  @default null
13785
	 */
13786
	"oLoadedState": null,
13787

13788
	/**
13789
	 * Source url for AJAX data for the table.
13790
	 * Note that this parameter will be set by the initialisation routine. To
13791
	 * set a default use {@link DataTable.defaults}.
13792
	 *  @type string
13793
	 *  @default null
13794
	 */
13795
	"sAjaxSource": null,
13796

13797
	/**
13798
	 * Property from a given object from which to read the table data from. This
13799
	 * can be an empty string (when not server-side processing), in which case
13800
	 * it is  assumed an an array is given directly.
13801
	 * Note that this parameter will be set by the initialisation routine. To
13802
	 * set a default use {@link DataTable.defaults}.
13803
	 *  @type string
13804
	 */
13805
	"sAjaxDataProp": null,
13806

13807
	/**
13808
	 * The last jQuery XHR object that was used for server-side data gathering.
13809
	 * This can be used for working with the XHR information in one of the
13810
	 * callbacks
13811
	 *  @type object
13812
	 *  @default null
13813
	 */
13814
	"jqXHR": null,
13815

13816
	/**
13817
	 * JSON returned from the server in the last Ajax request
13818
	 *  @type object
13819
	 *  @default undefined
13820
	 */
13821
	"json": undefined,
13822

13823
	/**
13824
	 * Data submitted as part of the last Ajax request
13825
	 *  @type object
13826
	 *  @default undefined
13827
	 */
13828
	"oAjaxData": undefined,
13829

13830
	/**
13831
	 * Function to get the server-side data.
13832
	 * Note that this parameter will be set by the initialisation routine. To
13833
	 * set a default use {@link DataTable.defaults}.
13834
	 *  @type function
13835
	 */
13836
	"fnServerData": null,
13837

13838
	/**
13839
	 * Functions which are called prior to sending an Ajax request so extra
13840
	 * parameters can easily be sent to the server
13841
	 *  @type array
13842
	 *  @default []
13843
	 */
13844
	"aoServerParams": [],
13845

13846
	/**
13847
	 * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
13848
	 * required).
13849
	 * Note that this parameter will be set by the initialisation routine. To
13850
	 * set a default use {@link DataTable.defaults}.
13851
	 *  @type string
13852
	 */
13853
	"sServerMethod": null,
13854

13855
	/**
13856
	 * Format numbers for display.
13857
	 * Note that this parameter will be set by the initialisation routine. To
13858
	 * set a default use {@link DataTable.defaults}.
13859
	 *  @type function
13860
	 */
13861
	"fnFormatNumber": null,
13862

13863
	/**
13864
	 * List of options that can be used for the user selectable length menu.
13865
	 * Note that this parameter will be set by the initialisation routine. To
13866
	 * set a default use {@link DataTable.defaults}.
13867
	 *  @type array
13868
	 *  @default []
13869
	 */
13870
	"aLengthMenu": null,
13871

13872
	/**
13873
	 * Counter for the draws that the table does. Also used as a tracker for
13874
	 * server-side processing
13875
	 *  @type int
13876
	 *  @default 0
13877
	 */
13878
	"iDraw": 0,
13879

13880
	/**
13881
	 * Indicate if a redraw is being done - useful for Ajax
13882
	 *  @type boolean
13883
	 *  @default false
13884
	 */
13885
	"bDrawing": false,
13886

13887
	/**
13888
	 * Draw index (iDraw) of the last error when parsing the returned data
13889
	 *  @type int
13890
	 *  @default -1
13891
	 */
13892
	"iDrawError": -1,
13893

13894
	/**
13895
	 * Paging display length
13896
	 *  @type int
13897
	 *  @default 10
13898
	 */
13899
	"_iDisplayLength": 10,
13900

13901
	/**
13902
	 * Paging start point - aiDisplay index
13903
	 *  @type int
13904
	 *  @default 0
13905
	 */
13906
	"_iDisplayStart": 0,
13907

13908
	/**
13909
	 * Server-side processing - number of records in the result set
13910
	 * (i.e. before filtering), Use fnRecordsTotal rather than
13911
	 * this property to get the value of the number of records, regardless of
13912
	 * the server-side processing setting.
13913
	 *  @type int
13914
	 *  @default 0
13915
	 *  @private
13916
	 */
13917
	"_iRecordsTotal": 0,
13918

13919
	/**
13920
	 * Server-side processing - number of records in the current display set
13921
	 * (i.e. after filtering). Use fnRecordsDisplay rather than
13922
	 * this property to get the value of the number of records, regardless of
13923
	 * the server-side processing setting.
13924
	 *  @type boolean
13925
	 *  @default 0
13926
	 *  @private
13927
	 */
13928
	"_iRecordsDisplay": 0,
13929

13930
	/**
13931
	 * The classes to use for the table
13932
	 *  @type object
13933
	 *  @default {}
13934
	 */
13935
	"oClasses": {},
13936

13937
	/**
13938
	 * Flag attached to the settings object so you can check in the draw
13939
	 * callback if filtering has been done in the draw. Deprecated in favour of
13940
	 * events.
13941
	 *  @type boolean
13942
	 *  @default false
13943
	 *  @deprecated
13944
	 */
13945
	"bFiltered": false,
13946

13947
	/**
13948
	 * Flag attached to the settings object so you can check in the draw
13949
	 * callback if sorting has been done in the draw. Deprecated in favour of
13950
	 * events.
13951
	 *  @type boolean
13952
	 *  @default false
13953
	 *  @deprecated
13954
	 */
13955
	"bSorted": false,
13956

13957
	/**
13958
	 * Indicate that if multiple rows are in the header and there is more than
13959
	 * one unique cell per column, if the top one (true) or bottom one (false)
13960
	 * should be used for sorting / title by DataTables.
13961
	 * Note that this parameter will be set by the initialisation routine. To
13962
	 * set a default use {@link DataTable.defaults}.
13963
	 *  @type boolean
13964
	 */
13965
	"bSortCellsTop": null,
13966

13967
	/**
13968
	 * Initialisation object that is used for the table
13969
	 *  @type object
13970
	 *  @default null
13971
	 */
13972
	"oInit": null,
13973

13974
	/**
13975
	 * Destroy callback functions - for plug-ins to attach themselves to the
13976
	 * destroy so they can clean up markup and events.
13977
	 *  @type array
13978
	 *  @default []
13979
	 */
13980
	"aoDestroyCallback": [],
13981

13982

13983
	/**
13984
	 * Get the number of records in the current record set, before filtering
13985
	 *  @type function
13986
	 */
13987
	"fnRecordsTotal": function ()
13988
	{
13989
		return _fnDataSource( this ) == 'ssp' ?
13990
			this._iRecordsTotal * 1 :
13991
			this.aiDisplayMaster.length;
13992
	},
13993

13994
	/**
13995
	 * Get the number of records in the current record set, after filtering
13996
	 *  @type function
13997
	 */
13998
	"fnRecordsDisplay": function ()
13999
	{
14000
		return _fnDataSource( this ) == 'ssp' ?
14001
			this._iRecordsDisplay * 1 :
14002
			this.aiDisplay.length;
14003
	},
14004

14005
	/**
14006
	 * Get the display end point - aiDisplay index
14007
	 *  @type function
14008
	 */
14009
	"fnDisplayEnd": function ()
14010
	{
14011
		var
14012
			len      = this._iDisplayLength,
14013
			start    = this._iDisplayStart,
14014
			calc     = start + len,
14015
			records  = this.aiDisplay.length,
14016
			features = this.oFeatures,
14017
			paginate = features.bPaginate;
14018

14019
		if ( features.bServerSide ) {
14020
			return paginate === false || len === -1 ?
14021
				start + records :
14022
				Math.min( start+len, this._iRecordsDisplay );
14023
		}
14024
		else {
14025
			return ! paginate || calc>records || len===-1 ?
14026
				records :
14027
				calc;
14028
		}
14029
	},
14030

14031
	/**
14032
	 * The DataTables object for this table
14033
	 *  @type object
14034
	 *  @default null
14035
	 */
14036
	"oInstance": null,
14037

14038
	/**
14039
	 * Unique identifier for each instance of the DataTables object. If there
14040
	 * is an ID on the table node, then it takes that value, otherwise an
14041
	 * incrementing internal counter is used.
14042
	 *  @type string
14043
	 *  @default null
14044
	 */
14045
	"sInstance": null,
14046

14047
	/**
14048
	 * tabindex attribute value that is added to DataTables control elements, allowing
14049
	 * keyboard navigation of the table and its controls.
14050
	 */
14051
	"iTabIndex": 0,
14052

14053
	/**
14054
	 * DIV container for the footer scrolling table if scrolling
14055
	 */
14056
	"nScrollHead": null,
14057

14058
	/**
14059
	 * DIV container for the footer scrolling table if scrolling
14060
	 */
14061
	"nScrollFoot": null,
14062

14063
	/**
14064
	 * Last applied sort
14065
	 *  @type array
14066
	 *  @default []
14067
	 */
14068
	"aLastSort": [],
14069

14070
	/**
14071
	 * Stored plug-in instances
14072
	 *  @type object
14073
	 *  @default {}
14074
	 */
14075
	"oPlugins": {},
14076

14077
	/**
14078
	 * Function used to get a row's id from the row's data
14079
	 *  @type function
14080
	 *  @default null
14081
	 */
14082
	"rowIdFn": null,
14083

14084
	/**
14085
	 * Data location where to store a row's id
14086
	 *  @type string
14087
	 *  @default null
14088
	 */
14089
	"rowId": null
14090
};
14091

14092
/**
14093
 * Extension object for DataTables that is used to provide all extension
14094
 * options.
14095
 *
14096
 * Note that the `DataTable.ext` object is available through
14097
 * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is
14098
 * also aliased to `jQuery.fn.dataTableExt` for historic reasons.
14099
 *  @namespace
14100
 *  @extends DataTable.models.ext
14101
 */
14102

14103

14104
/**
14105
 * DataTables extensions
14106
 * 
14107
 * This namespace acts as a collection area for plug-ins that can be used to
14108
 * extend DataTables capabilities. Indeed many of the build in methods
14109
 * use this method to provide their own capabilities (sorting methods for
14110
 * example).
14111
 *
14112
 * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy
14113
 * reasons
14114
 *
14115
 *  @namespace
14116
 */
14117
DataTable.ext = _ext = {
14118
	/**
14119
	 * Buttons. For use with the Buttons extension for DataTables. This is
14120
	 * defined here so other extensions can define buttons regardless of load
14121
	 * order. It is _not_ used by DataTables core.
14122
	 *
14123
	 *  @type object
14124
	 *  @default {}
14125
	 */
14126
	buttons: {},
14127

14128

14129
	/**
14130
	 * Element class names
14131
	 *
14132
	 *  @type object
14133
	 *  @default {}
14134
	 */
14135
	classes: {},
14136

14137

14138
	/**
14139
	 * DataTables build type (expanded by the download builder)
14140
	 *
14141
	 *  @type string
14142
	 */
14143
	builder: "-source-",
14144

14145

14146
	/**
14147
	 * Error reporting.
14148
	 * 
14149
	 * How should DataTables report an error. Can take the value 'alert',
14150
	 * 'throw', 'none' or a function.
14151
	 *
14152
	 *  @type string|function
14153
	 *  @default alert
14154
	 */
14155
	errMode: "alert",
14156

14157

14158
	/**
14159
	 * Feature plug-ins.
14160
	 * 
14161
	 * This is an array of objects which describe the feature plug-ins that are
14162
	 * available to DataTables. These feature plug-ins are then available for
14163
	 * use through the `dom` initialisation option.
14164
	 * 
14165
	 * Each feature plug-in is described by an object which must have the
14166
	 * following properties:
14167
	 * 
14168
	 * * `fnInit` - function that is used to initialise the plug-in,
14169
	 * * `cFeature` - a character so the feature can be enabled by the `dom`
14170
	 *   instillation option. This is case sensitive.
14171
	 *
14172
	 * The `fnInit` function has the following input parameters:
14173
	 *
14174
	 * 1. `{object}` DataTables settings object: see
14175
	 *    {@link DataTable.models.oSettings}
14176
	 *
14177
	 * And the following return is expected:
14178
	 * 
14179
	 * * {node|null} The element which contains your feature. Note that the
14180
	 *   return may also be void if your plug-in does not require to inject any
14181
	 *   DOM elements into DataTables control (`dom`) - for example this might
14182
	 *   be useful when developing a plug-in which allows table control via
14183
	 *   keyboard entry
14184
	 *
14185
	 *  @type array
14186
	 *
14187
	 *  @example
14188
	 *    $.fn.dataTable.ext.features.push( {
14189
	 *      "fnInit": function( oSettings ) {
14190
	 *        return new TableTools( { "oDTSettings": oSettings } );
14191
	 *      },
14192
	 *      "cFeature": "T"
14193
	 *    } );
14194
	 */
14195
	feature: [],
14196

14197

14198
	/**
14199
	 * Row searching.
14200
	 * 
14201
	 * This method of searching is complimentary to the default type based
14202
	 * searching, and a lot more comprehensive as it allows you complete control
14203
	 * over the searching logic. Each element in this array is a function
14204
	 * (parameters described below) that is called for every row in the table,
14205
	 * and your logic decides if it should be included in the searching data set
14206
	 * or not.
14207
	 *
14208
	 * Searching functions have the following input parameters:
14209
	 *
14210
	 * 1. `{object}` DataTables settings object: see
14211
	 *    {@link DataTable.models.oSettings}
14212
	 * 2. `{array|object}` Data for the row to be processed (same as the
14213
	 *    original format that was passed in as the data source, or an array
14214
	 *    from a DOM data source
14215
	 * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which
14216
	 *    can be useful to retrieve the `TR` element if you need DOM interaction.
14217
	 *
14218
	 * And the following return is expected:
14219
	 *
14220
	 * * {boolean} Include the row in the searched result set (true) or not
14221
	 *   (false)
14222
	 *
14223
	 * Note that as with the main search ability in DataTables, technically this
14224
	 * is "filtering", since it is subtractive. However, for consistency in
14225
	 * naming we call it searching here.
14226
	 *
14227
	 *  @type array
14228
	 *  @default []
14229
	 *
14230
	 *  @example
14231
	 *    // The following example shows custom search being applied to the
14232
	 *    // fourth column (i.e. the data[3] index) based on two input values
14233
	 *    // from the end-user, matching the data in a certain range.
14234
	 *    $.fn.dataTable.ext.search.push(
14235
	 *      function( settings, data, dataIndex ) {
14236
	 *        var min = document.getElementById('min').value * 1;
14237
	 *        var max = document.getElementById('max').value * 1;
14238
	 *        var version = data[3] == "-" ? 0 : data[3]*1;
14239
	 *
14240
	 *        if ( min == "" && max == "" ) {
14241
	 *          return true;
14242
	 *        }
14243
	 *        else if ( min == "" && version < max ) {
14244
	 *          return true;
14245
	 *        }
14246
	 *        else if ( min < version && "" == max ) {
14247
	 *          return true;
14248
	 *        }
14249
	 *        else if ( min < version && version < max ) {
14250
	 *          return true;
14251
	 *        }
14252
	 *        return false;
14253
	 *      }
14254
	 *    );
14255
	 */
14256
	search: [],
14257

14258

14259
	/**
14260
	 * Selector extensions
14261
	 *
14262
	 * The `selector` option can be used to extend the options available for the
14263
	 * selector modifier options (`selector-modifier` object data type) that
14264
	 * each of the three built in selector types offer (row, column and cell +
14265
	 * their plural counterparts). For example the Select extension uses this
14266
	 * mechanism to provide an option to select only rows, columns and cells
14267
	 * that have been marked as selected by the end user (`{selected: true}`),
14268
	 * which can be used in conjunction with the existing built in selector
14269
	 * options.
14270
	 *
14271
	 * Each property is an array to which functions can be pushed. The functions
14272
	 * take three attributes:
14273
	 *
14274
	 * * Settings object for the host table
14275
	 * * Options object (`selector-modifier` object type)
14276
	 * * Array of selected item indexes
14277
	 *
14278
	 * The return is an array of the resulting item indexes after the custom
14279
	 * selector has been applied.
14280
	 *
14281
	 *  @type object
14282
	 */
14283
	selector: {
14284
		cell: [],
14285
		column: [],
14286
		row: []
14287
	},
14288

14289

14290
	/**
14291
	 * Internal functions, exposed for used in plug-ins.
14292
	 * 
14293
	 * Please note that you should not need to use the internal methods for
14294
	 * anything other than a plug-in (and even then, try to avoid if possible).
14295
	 * The internal function may change between releases.
14296
	 *
14297
	 *  @type object
14298
	 *  @default {}
14299
	 */
14300
	internal: {},
14301

14302

14303
	/**
14304
	 * Legacy configuration options. Enable and disable legacy options that
14305
	 * are available in DataTables.
14306
	 *
14307
	 *  @type object
14308
	 */
14309
	legacy: {
14310
		/**
14311
		 * Enable / disable DataTables 1.9 compatible server-side processing
14312
		 * requests
14313
		 *
14314
		 *  @type boolean
14315
		 *  @default null
14316
		 */
14317
		ajax: null
14318
	},
14319

14320

14321
	/**
14322
	 * Pagination plug-in methods.
14323
	 * 
14324
	 * Each entry in this object is a function and defines which buttons should
14325
	 * be shown by the pagination rendering method that is used for the table:
14326
	 * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the
14327
	 * buttons are displayed in the document, while the functions here tell it
14328
	 * what buttons to display. This is done by returning an array of button
14329
	 * descriptions (what each button will do).
14330
	 *
14331
	 * Pagination types (the four built in options and any additional plug-in
14332
	 * options defined here) can be used through the `paginationType`
14333
	 * initialisation parameter.
14334
	 *
14335
	 * The functions defined take two parameters:
14336
	 *
14337
	 * 1. `{int} page` The current page index
14338
	 * 2. `{int} pages` The number of pages in the table
14339
	 *
14340
	 * Each function is expected to return an array where each element of the
14341
	 * array can be one of:
14342
	 *
14343
	 * * `first` - Jump to first page when activated
14344
	 * * `last` - Jump to last page when activated
14345
	 * * `previous` - Show previous page when activated
14346
	 * * `next` - Show next page when activated
14347
	 * * `{int}` - Show page of the index given
14348
	 * * `{array}` - A nested array containing the above elements to add a
14349
	 *   containing 'DIV' element (might be useful for styling).
14350
	 *
14351
	 * Note that DataTables v1.9- used this object slightly differently whereby
14352
	 * an object with two functions would be defined for each plug-in. That
14353
	 * ability is still supported by DataTables 1.10+ to provide backwards
14354
	 * compatibility, but this option of use is now decremented and no longer
14355
	 * documented in DataTables 1.10+.
14356
	 *
14357
	 *  @type object
14358
	 *  @default {}
14359
	 *
14360
	 *  @example
14361
	 *    // Show previous, next and current page buttons only
14362
	 *    $.fn.dataTableExt.oPagination.current = function ( page, pages ) {
14363
	 *      return [ 'previous', page, 'next' ];
14364
	 *    };
14365
	 */
14366
	pager: {},
14367

14368

14369
	renderer: {
14370
		pageButton: {},
14371
		header: {}
14372
	},
14373

14374

14375
	/**
14376
	 * Ordering plug-ins - custom data source
14377
	 * 
14378
	 * The extension options for ordering of data available here is complimentary
14379
	 * to the default type based ordering that DataTables typically uses. It
14380
	 * allows much greater control over the the data that is being used to
14381
	 * order a column, but is necessarily therefore more complex.
14382
	 * 
14383
	 * This type of ordering is useful if you want to do ordering based on data
14384
	 * live from the DOM (for example the contents of an 'input' element) rather
14385
	 * than just the static string that DataTables knows of.
14386
	 * 
14387
	 * The way these plug-ins work is that you create an array of the values you
14388
	 * wish to be ordering for the column in question and then return that
14389
	 * array. The data in the array much be in the index order of the rows in
14390
	 * the table (not the currently ordering order!). Which order data gathering
14391
	 * function is run here depends on the `dt-init columns.orderDataType`
14392
	 * parameter that is used for the column (if any).
14393
	 *
14394
	 * The functions defined take two parameters:
14395
	 *
14396
	 * 1. `{object}` DataTables settings object: see
14397
	 *    {@link DataTable.models.oSettings}
14398
	 * 2. `{int}` Target column index
14399
	 *
14400
	 * Each function is expected to return an array:
14401
	 *
14402
	 * * `{array}` Data for the column to be ordering upon
14403
	 *
14404
	 *  @type array
14405
	 *
14406
	 *  @example
14407
	 *    // Ordering using `input` node values
14408
	 *    $.fn.dataTable.ext.order['dom-text'] = function  ( settings, col )
14409
	 *    {
14410
	 *      return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
14411
	 *        return $('input', td).val();
14412
	 *      } );
14413
	 *    }
14414
	 */
14415
	order: {},
14416

14417

14418
	/**
14419
	 * Type based plug-ins.
14420
	 *
14421
	 * Each column in DataTables has a type assigned to it, either by automatic
14422
	 * detection or by direct assignment using the `type` option for the column.
14423
	 * The type of a column will effect how it is ordering and search (plug-ins
14424
	 * can also make use of the column type if required).
14425
	 *
14426
	 * @namespace
14427
	 */
14428
	type: {
14429
		/**
14430
		 * Type detection functions.
14431
		 *
14432
		 * The functions defined in this object are used to automatically detect
14433
		 * a column's type, making initialisation of DataTables super easy, even
14434
		 * when complex data is in the table.
14435
		 *
14436
		 * The functions defined take two parameters:
14437
		 *
14438
	     *  1. `{*}` Data from the column cell to be analysed
14439
	     *  2. `{settings}` DataTables settings object. This can be used to
14440
	     *     perform context specific type detection - for example detection
14441
	     *     based on language settings such as using a comma for a decimal
14442
	     *     place. Generally speaking the options from the settings will not
14443
	     *     be required
14444
		 *
14445
		 * Each function is expected to return:
14446
		 *
14447
		 * * `{string|null}` Data type detected, or null if unknown (and thus
14448
		 *   pass it on to the other type detection functions.
14449
		 *
14450
		 *  @type array
14451
		 *
14452
		 *  @example
14453
		 *    // Currency type detection plug-in:
14454
		 *    $.fn.dataTable.ext.type.detect.push(
14455
		 *      function ( data, settings ) {
14456
		 *        // Check the numeric part
14457
		 *        if ( ! data.substring(1).match(/[0-9]/) ) {
14458
		 *          return null;
14459
		 *        }
14460
		 *
14461
		 *        // Check prefixed by currency
14462
		 *        if ( data.charAt(0) == '$' || data.charAt(0) == '&pound;' ) {
14463
		 *          return 'currency';
14464
		 *        }
14465
		 *        return null;
14466
		 *      }
14467
		 *    );
14468
		 */
14469
		detect: [],
14470

14471

14472
		/**
14473
		 * Type based search formatting.
14474
		 *
14475
		 * The type based searching functions can be used to pre-format the
14476
		 * data to be search on. For example, it can be used to strip HTML
14477
		 * tags or to de-format telephone numbers for numeric only searching.
14478
		 *
14479
		 * Note that is a search is not defined for a column of a given type,
14480
		 * no search formatting will be performed.
14481
		 * 
14482
		 * Pre-processing of searching data plug-ins - When you assign the sType
14483
		 * for a column (or have it automatically detected for you by DataTables
14484
		 * or a type detection plug-in), you will typically be using this for
14485
		 * custom sorting, but it can also be used to provide custom searching
14486
		 * by allowing you to pre-processing the data and returning the data in
14487
		 * the format that should be searched upon. This is done by adding
14488
		 * functions this object with a parameter name which matches the sType
14489
		 * for that target column. This is the corollary of <i>afnSortData</i>
14490
		 * for searching data.
14491
		 *
14492
		 * The functions defined take a single parameter:
14493
		 *
14494
	     *  1. `{*}` Data from the column cell to be prepared for searching
14495
		 *
14496
		 * Each function is expected to return:
14497
		 *
14498
		 * * `{string|null}` Formatted string that will be used for the searching.
14499
		 *
14500
		 *  @type object
14501
		 *  @default {}
14502
		 *
14503
		 *  @example
14504
		 *    $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) {
14505
		 *      return d.replace(/\n/g," ").replace( /<.*?>/g, "" );
14506
		 *    }
14507
		 */
14508
		search: {},
14509

14510

14511
		/**
14512
		 * Type based ordering.
14513
		 *
14514
		 * The column type tells DataTables what ordering to apply to the table
14515
		 * when a column is sorted upon. The order for each type that is defined,
14516
		 * is defined by the functions available in this object.
14517
		 *
14518
		 * Each ordering option can be described by three properties added to
14519
		 * this object:
14520
		 *
14521
		 * * `{type}-pre` - Pre-formatting function
14522
		 * * `{type}-asc` - Ascending order function
14523
		 * * `{type}-desc` - Descending order function
14524
		 *
14525
		 * All three can be used together, only `{type}-pre` or only
14526
		 * `{type}-asc` and `{type}-desc` together. It is generally recommended
14527
		 * that only `{type}-pre` is used, as this provides the optimal
14528
		 * implementation in terms of speed, although the others are provided
14529
		 * for compatibility with existing Javascript sort functions.
14530
		 *
14531
		 * `{type}-pre`: Functions defined take a single parameter:
14532
		 *
14533
	     *  1. `{*}` Data from the column cell to be prepared for ordering
14534
		 *
14535
		 * And return:
14536
		 *
14537
		 * * `{*}` Data to be sorted upon
14538
		 *
14539
		 * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort
14540
		 * functions, taking two parameters:
14541
		 *
14542
	     *  1. `{*}` Data to compare to the second parameter
14543
	     *  2. `{*}` Data to compare to the first parameter
14544
		 *
14545
		 * And returning:
14546
		 *
14547
		 * * `{*}` Ordering match: <0 if first parameter should be sorted lower
14548
		 *   than the second parameter, ===0 if the two parameters are equal and
14549
		 *   >0 if the first parameter should be sorted height than the second
14550
		 *   parameter.
14551
		 * 
14552
		 *  @type object
14553
		 *  @default {}
14554
		 *
14555
		 *  @example
14556
		 *    // Numeric ordering of formatted numbers with a pre-formatter
14557
		 *    $.extend( $.fn.dataTable.ext.type.order, {
14558
		 *      "string-pre": function(x) {
14559
		 *        a = (a === "-" || a === "") ? 0 : a.replace( /[^\d\-\.]/g, "" );
14560
		 *        return parseFloat( a );
14561
		 *      }
14562
		 *    } );
14563
		 *
14564
		 *  @example
14565
		 *    // Case-sensitive string ordering, with no pre-formatting method
14566
		 *    $.extend( $.fn.dataTable.ext.order, {
14567
		 *      "string-case-asc": function(x,y) {
14568
		 *        return ((x < y) ? -1 : ((x > y) ? 1 : 0));
14569
		 *      },
14570
		 *      "string-case-desc": function(x,y) {
14571
		 *        return ((x < y) ? 1 : ((x > y) ? -1 : 0));
14572
		 *      }
14573
		 *    } );
14574
		 */
14575
		order: {}
14576
	},
14577

14578
	/**
14579
	 * Unique DataTables instance counter
14580
	 *
14581
	 * @type int
14582
	 * @private
14583
	 */
14584
	_unique: 0,
14585

14586

14587
	//
14588
	// Depreciated
14589
	// The following properties are retained for backwards compatibility only.
14590
	// The should not be used in new projects and will be removed in a future
14591
	// version
14592
	//
14593

14594
	/**
14595
	 * Version check function.
14596
	 *  @type function
14597
	 *  @depreciated Since 1.10
14598
	 */
14599
	fnVersionCheck: DataTable.fnVersionCheck,
14600

14601

14602
	/**
14603
	 * Index for what 'this' index API functions should use
14604
	 *  @type int
14605
	 *  @deprecated Since v1.10
14606
	 */
14607
	iApiIndex: 0,
14608

14609

14610
	/**
14611
	 * jQuery UI class container
14612
	 *  @type object
14613
	 *  @deprecated Since v1.10
14614
	 */
14615
	oJUIClasses: {},
14616

14617

14618
	/**
14619
	 * Software version
14620
	 *  @type string
14621
	 *  @deprecated Since v1.10
14622
	 */
14623
	sVersion: DataTable.version
14624
};
14625

14626

14627
//
14628
// Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts
14629
//
14630
$.extend( _ext, {
14631
	afnFiltering: _ext.search,
14632
	aTypes:       _ext.type.detect,
14633
	ofnSearch:    _ext.type.search,
14634
	oSort:        _ext.type.order,
14635
	afnSortData:  _ext.order,
14636
	aoFeatures:   _ext.feature,
14637
	oApi:         _ext.internal,
14638
	oStdClasses:  _ext.classes,
14639
	oPagination:  _ext.pager
14640
} );
14641

14642

14643
$.extend( DataTable.ext.classes, {
14644
	"sTable": "dataTable",
14645
	"sNoFooter": "no-footer",
14646

14647
	/* Paging buttons */
14648
	"sPageButton": "paginate_button",
14649
	"sPageButtonActive": "current",
14650
	"sPageButtonDisabled": "disabled",
14651

14652
	/* Striping classes */
14653
	"sStripeOdd": "odd",
14654
	"sStripeEven": "even",
14655

14656
	/* Empty row */
14657
	"sRowEmpty": "dataTables_empty",
14658

14659
	/* Features */
14660
	"sWrapper": "dataTables_wrapper",
14661
	"sFilter": "dataTables_filter",
14662
	"sInfo": "dataTables_info",
14663
	"sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
14664
	"sLength": "dataTables_length",
14665
	"sProcessing": "dataTables_processing",
14666

14667
	/* Sorting */
14668
	"sSortAsc": "sorting_asc",
14669
	"sSortDesc": "sorting_desc",
14670
	"sSortable": "sorting", /* Sortable in both directions */
14671
	"sSortableAsc": "sorting_desc_disabled",
14672
	"sSortableDesc": "sorting_asc_disabled",
14673
	"sSortableNone": "sorting_disabled",
14674
	"sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
14675

14676
	/* Filtering */
14677
	"sFilterInput": "",
14678

14679
	/* Page length */
14680
	"sLengthSelect": "",
14681

14682
	/* Scrolling */
14683
	"sScrollWrapper": "dataTables_scroll",
14684
	"sScrollHead": "dataTables_scrollHead",
14685
	"sScrollHeadInner": "dataTables_scrollHeadInner",
14686
	"sScrollBody": "dataTables_scrollBody",
14687
	"sScrollFoot": "dataTables_scrollFoot",
14688
	"sScrollFootInner": "dataTables_scrollFootInner",
14689

14690
	/* Misc */
14691
	"sHeaderTH": "",
14692
	"sFooterTH": "",
14693

14694
	// Deprecated
14695
	"sSortJUIAsc": "",
14696
	"sSortJUIDesc": "",
14697
	"sSortJUI": "",
14698
	"sSortJUIAscAllowed": "",
14699
	"sSortJUIDescAllowed": "",
14700
	"sSortJUIWrapper": "",
14701
	"sSortIcon": "",
14702
	"sJUIHeader": "",
14703
	"sJUIFooter": ""
14704
} );
14705

14706

14707
var extPagination = DataTable.ext.pager;
14708

14709
function _numbers ( page, pages ) {
14710
	var
14711
		numbers = [],
14712
		buttons = extPagination.numbers_length,
14713
		half = Math.floor( buttons / 2 ),
14714
		i = 1;
14715

14716
	if ( pages <= buttons ) {
14717
		numbers = _range( 0, pages );
14718
	}
14719
	else if ( page <= half ) {
14720
		numbers = _range( 0, buttons-2 );
14721
		numbers.push( 'ellipsis' );
14722
		numbers.push( pages-1 );
14723
	}
14724
	else if ( page >= pages - 1 - half ) {
14725
		numbers = _range( pages-(buttons-2), pages );
14726
		numbers.splice( 0, 0, 'ellipsis' ); // no unshift in ie6
14727
		numbers.splice( 0, 0, 0 );
14728
	}
14729
	else {
14730
		numbers = _range( page-half+2, page+half-1 );
14731
		numbers.push( 'ellipsis' );
14732
		numbers.push( pages-1 );
14733
		numbers.splice( 0, 0, 'ellipsis' );
14734
		numbers.splice( 0, 0, 0 );
14735
	}
14736

14737
	numbers.DT_el = 'span';
14738
	return numbers;
14739
}
14740

14741

14742
$.extend( extPagination, {
14743
	simple: function ( page, pages ) {
14744
		return [ 'previous', 'next' ];
14745
	},
14746

14747
	full: function ( page, pages ) {
14748
		return [  'first', 'previous', 'next', 'last' ];
14749
	},
14750

14751
	numbers: function ( page, pages ) {
14752
		return [ _numbers(page, pages) ];
14753
	},
14754

14755
	simple_numbers: function ( page, pages ) {
14756
		return [ 'previous', _numbers(page, pages), 'next' ];
14757
	},
14758

14759
	full_numbers: function ( page, pages ) {
14760
		return [ 'first', 'previous', _numbers(page, pages), 'next', 'last' ];
14761
	},
14762
	
14763
	first_last_numbers: function (page, pages) {
14764
 		return ['first', _numbers(page, pages), 'last'];
14765
 	},
14766

14767
	// For testing and plug-ins to use
14768
	_numbers: _numbers,
14769

14770
	// Number of number buttons (including ellipsis) to show. _Must be odd!_
14771
	numbers_length: 7
14772
} );
14773

14774

14775
$.extend( true, DataTable.ext.renderer, {
14776
	pageButton: {
14777
		_: function ( settings, host, idx, buttons, page, pages ) {
14778
			var classes = settings.oClasses;
14779
			var lang = settings.oLanguage.oPaginate;
14780
			var aria = settings.oLanguage.oAria.paginate || {};
14781
			var btnDisplay, btnClass;
14782

14783
			var attach = function( container, buttons ) {
14784
				var i, ien, node, button, tabIndex;
14785
				var disabledClass = classes.sPageButtonDisabled;
14786
				var clickHandler = function ( e ) {
14787
					_fnPageChange( settings, e.data.action, true );
14788
				};
14789

14790
				for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
14791
					button = buttons[i];
14792

14793
					if ( Array.isArray( button ) ) {
14794
						var inner = $( '<'+(button.DT_el || 'div')+'/>' )
14795
							.appendTo( container );
14796
						attach( inner, button );
14797
					}
14798
					else {
14799
						btnDisplay = null;
14800
						btnClass = button;
14801
						tabIndex = settings.iTabIndex;
14802

14803
						switch ( button ) {
14804
							case 'ellipsis':
14805
								container.append('<span class="ellipsis">&#x2026;</span>');
14806
								break;
14807

14808
							case 'first':
14809
								btnDisplay = lang.sFirst;
14810

14811
								if ( page === 0 ) {
14812
									tabIndex = -1;
14813
									btnClass += ' ' + disabledClass;
14814
								}
14815
								break;
14816

14817
							case 'previous':
14818
								btnDisplay = lang.sPrevious;
14819

14820
								if ( page === 0 ) {
14821
									tabIndex = -1;
14822
									btnClass += ' ' + disabledClass;
14823
								}
14824
								break;
14825

14826
							case 'next':
14827
								btnDisplay = lang.sNext;
14828

14829
								if ( pages === 0 || page === pages-1 ) {
14830
									tabIndex = -1;
14831
									btnClass += ' ' + disabledClass;
14832
								}
14833
								break;
14834

14835
							case 'last':
14836
								btnDisplay = lang.sLast;
14837

14838
								if ( pages === 0 || page === pages-1 ) {
14839
									tabIndex = -1;
14840
									btnClass += ' ' + disabledClass;
14841
								}
14842
								break;
14843

14844
							default:
14845
								btnDisplay = settings.fnFormatNumber( button + 1 );
14846
								btnClass = page === button ?
14847
									classes.sPageButtonActive : '';
14848
								break;
14849
						}
14850

14851
						if ( btnDisplay !== null ) {
14852
							var tag = settings.oInit.pagingTag || 'a';
14853
							var disabled = btnClass.indexOf(disabledClass) !== -1;
14854
		
14855

14856
							node = $('<'+tag+'>', {
14857
									'class': classes.sPageButton+' '+btnClass,
14858
									'aria-controls': settings.sTableId,
14859
									'aria-disabled': disabled ? 'true' : null,
14860
									'aria-label': aria[ button ],
14861
									'role': 'link',
14862
									'aria-current': btnClass === classes.sPageButtonActive ? 'page' : null,
14863
									'data-dt-idx': button,
14864
									'tabindex': tabIndex,
14865
									'id': idx === 0 && typeof button === 'string' ?
14866
										settings.sTableId +'_'+ button :
14867
										null
14868
								} )
14869
								.html( btnDisplay )
14870
								.appendTo( container );
14871

14872
							_fnBindAction(
14873
								node, {action: button}, clickHandler
14874
							);
14875
						}
14876
					}
14877
				}
14878
			};
14879

14880
			// IE9 throws an 'unknown error' if document.activeElement is used
14881
			// inside an iframe or frame. Try / catch the error. Not good for
14882
			// accessibility, but neither are frames.
14883
			var activeEl;
14884

14885
			try {
14886
				// Because this approach is destroying and recreating the paging
14887
				// elements, focus is lost on the select button which is bad for
14888
				// accessibility. So we want to restore focus once the draw has
14889
				// completed
14890
				activeEl = $(host).find(document.activeElement).data('dt-idx');
14891
			}
14892
			catch (e) {}
14893

14894
			attach( $(host).empty(), buttons );
14895

14896
			if ( activeEl !== undefined ) {
14897
				$(host).find( '[data-dt-idx='+activeEl+']' ).trigger('focus');
14898
			}
14899
		}
14900
	}
14901
} );
14902

14903

14904

14905
// Built in type detection. See model.ext.aTypes for information about
14906
// what is required from this methods.
14907
$.extend( DataTable.ext.type.detect, [
14908
	// Plain numbers - first since V8 detects some plain numbers as dates
14909
	// e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...).
14910
	function ( d, settings )
14911
	{
14912
		var decimal = settings.oLanguage.sDecimal;
14913
		return _isNumber( d, decimal ) ? 'num'+decimal : null;
14914
	},
14915

14916
	// Dates (only those recognised by the browser's Date.parse)
14917
	function ( d, settings )
14918
	{
14919
		// V8 tries _very_ hard to make a string passed into `Date.parse()`
14920
		// valid, so we need to use a regex to restrict date formats. Use a
14921
		// plug-in for anything other than ISO8601 style strings
14922
		if ( d && !(d instanceof Date) && ! _re_date.test(d) ) {
14923
			return null;
14924
		}
14925
		var parsed = Date.parse(d);
14926
		return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null;
14927
	},
14928

14929
	// Formatted numbers
14930
	function ( d, settings )
14931
	{
14932
		var decimal = settings.oLanguage.sDecimal;
14933
		return _isNumber( d, decimal, true ) ? 'num-fmt'+decimal : null;
14934
	},
14935

14936
	// HTML numeric
14937
	function ( d, settings )
14938
	{
14939
		var decimal = settings.oLanguage.sDecimal;
14940
		return _htmlNumeric( d, decimal ) ? 'html-num'+decimal : null;
14941
	},
14942

14943
	// HTML numeric, formatted
14944
	function ( d, settings )
14945
	{
14946
		var decimal = settings.oLanguage.sDecimal;
14947
		return _htmlNumeric( d, decimal, true ) ? 'html-num-fmt'+decimal : null;
14948
	},
14949

14950
	// HTML (this is strict checking - there must be html)
14951
	function ( d, settings )
14952
	{
14953
		return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ?
14954
			'html' : null;
14955
	}
14956
] );
14957

14958

14959

14960
// Filter formatting functions. See model.ext.ofnSearch for information about
14961
// what is required from these methods.
14962
// 
14963
// Note that additional search methods are added for the html numbers and
14964
// html formatted numbers by `_addNumericSort()` when we know what the decimal
14965
// place is
14966

14967

14968
$.extend( DataTable.ext.type.search, {
14969
	html: function ( data ) {
14970
		return _empty(data) ?
14971
			data :
14972
			typeof data === 'string' ?
14973
				data
14974
					.replace( _re_new_lines, " " )
14975
					.replace( _re_html, "" ) :
14976
				'';
14977
	},
14978

14979
	string: function ( data ) {
14980
		return _empty(data) ?
14981
			data :
14982
			typeof data === 'string' ?
14983
				data.replace( _re_new_lines, " " ) :
14984
				data;
14985
	}
14986
} );
14987

14988

14989

14990
var __numericReplace = function ( d, decimalPlace, re1, re2 ) {
14991
	if ( d !== 0 && (!d || d === '-') ) {
14992
		return -Infinity;
14993
	}
14994
	
14995
	var type = typeof d;
14996

14997
	if (type === 'number' || type === 'bigint') {
14998
		return d;
14999
	}
15000

15001
	// If a decimal place other than `.` is used, it needs to be given to the
15002
	// function so we can detect it and replace with a `.` which is the only
15003
	// decimal place Javascript recognises - it is not locale aware.
15004
	if ( decimalPlace ) {
15005
		d = _numToDecimal( d, decimalPlace );
15006
	}
15007

15008
	if ( d.replace ) {
15009
		if ( re1 ) {
15010
			d = d.replace( re1, '' );
15011
		}
15012

15013
		if ( re2 ) {
15014
			d = d.replace( re2, '' );
15015
		}
15016
	}
15017

15018
	return d * 1;
15019
};
15020

15021

15022
// Add the numeric 'deformatting' functions for sorting and search. This is done
15023
// in a function to provide an easy ability for the language options to add
15024
// additional methods if a non-period decimal place is used.
15025
function _addNumericSort ( decimalPlace ) {
15026
	$.each(
15027
		{
15028
			// Plain numbers
15029
			"num": function ( d ) {
15030
				return __numericReplace( d, decimalPlace );
15031
			},
15032

15033
			// Formatted numbers
15034
			"num-fmt": function ( d ) {
15035
				return __numericReplace( d, decimalPlace, _re_formatted_numeric );
15036
			},
15037

15038
			// HTML numeric
15039
			"html-num": function ( d ) {
15040
				return __numericReplace( d, decimalPlace, _re_html );
15041
			},
15042

15043
			// HTML numeric, formatted
15044
			"html-num-fmt": function ( d ) {
15045
				return __numericReplace( d, decimalPlace, _re_html, _re_formatted_numeric );
15046
			}
15047
		},
15048
		function ( key, fn ) {
15049
			// Add the ordering method
15050
			_ext.type.order[ key+decimalPlace+'-pre' ] = fn;
15051

15052
			// For HTML types add a search formatter that will strip the HTML
15053
			if ( key.match(/^html\-/) ) {
15054
				_ext.type.search[ key+decimalPlace ] = _ext.type.search.html;
15055
			}
15056
		}
15057
	);
15058
}
15059

15060

15061
// Default sort methods
15062
$.extend( _ext.type.order, {
15063
	// Dates
15064
	"date-pre": function ( d ) {
15065
		var ts = Date.parse( d );
15066
		return isNaN(ts) ? -Infinity : ts;
15067
	},
15068

15069
	// html
15070
	"html-pre": function ( a ) {
15071
		return _empty(a) ?
15072
			'' :
15073
			a.replace ?
15074
				a.replace( /<.*?>/g, "" ).toLowerCase() :
15075
				a+'';
15076
	},
15077

15078
	// string
15079
	"string-pre": function ( a ) {
15080
		// This is a little complex, but faster than always calling toString,
15081
		// http://jsperf.com/tostring-v-check
15082
		return _empty(a) ?
15083
			'' :
15084
			typeof a === 'string' ?
15085
				a.toLowerCase() :
15086
				! a.toString ?
15087
					'' :
15088
					a.toString();
15089
	},
15090

15091
	// string-asc and -desc are retained only for compatibility with the old
15092
	// sort methods
15093
	"string-asc": function ( x, y ) {
15094
		return ((x < y) ? -1 : ((x > y) ? 1 : 0));
15095
	},
15096

15097
	"string-desc": function ( x, y ) {
15098
		return ((x < y) ? 1 : ((x > y) ? -1 : 0));
15099
	}
15100
} );
15101

15102

15103
// Numeric sorting types - order doesn't matter here
15104
_addNumericSort( '' );
15105

15106

15107
$.extend( true, DataTable.ext.renderer, {
15108
	header: {
15109
		_: function ( settings, cell, column, classes ) {
15110
			// No additional mark-up required
15111
			// Attach a sort listener to update on sort - note that using the
15112
			// `DT` namespace will allow the event to be removed automatically
15113
			// on destroy, while the `dt` namespaced event is the one we are
15114
			// listening for
15115
			$(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
15116
				if ( settings !== ctx ) { // need to check this this is the host
15117
					return;               // table, not a nested one
15118
				}
15119

15120
				var colIdx = column.idx;
15121

15122
				cell
15123
					.removeClass(
15124
						classes.sSortAsc +' '+
15125
						classes.sSortDesc
15126
					)
15127
					.addClass( columns[ colIdx ] == 'asc' ?
15128
						classes.sSortAsc : columns[ colIdx ] == 'desc' ?
15129
							classes.sSortDesc :
15130
							column.sSortingClass
15131
					);
15132
			} );
15133
		},
15134

15135
		jqueryui: function ( settings, cell, column, classes ) {
15136
			$('<div/>')
15137
				.addClass( classes.sSortJUIWrapper )
15138
				.append( cell.contents() )
15139
				.append( $('<span/>')
15140
					.addClass( classes.sSortIcon+' '+column.sSortingClassJUI )
15141
				)
15142
				.appendTo( cell );
15143

15144
			// Attach a sort listener to update on sort
15145
			$(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
15146
				if ( settings !== ctx ) {
15147
					return;
15148
				}
15149

15150
				var colIdx = column.idx;
15151

15152
				cell
15153
					.removeClass( classes.sSortAsc +" "+classes.sSortDesc )
15154
					.addClass( columns[ colIdx ] == 'asc' ?
15155
						classes.sSortAsc : columns[ colIdx ] == 'desc' ?
15156
							classes.sSortDesc :
15157
							column.sSortingClass
15158
					);
15159

15160
				cell
15161
					.find( 'span.'+classes.sSortIcon )
15162
					.removeClass(
15163
						classes.sSortJUIAsc +" "+
15164
						classes.sSortJUIDesc +" "+
15165
						classes.sSortJUI +" "+
15166
						classes.sSortJUIAscAllowed +" "+
15167
						classes.sSortJUIDescAllowed
15168
					)
15169
					.addClass( columns[ colIdx ] == 'asc' ?
15170
						classes.sSortJUIAsc : columns[ colIdx ] == 'desc' ?
15171
							classes.sSortJUIDesc :
15172
							column.sSortingClassJUI
15173
					);
15174
			} );
15175
		}
15176
	}
15177
} );
15178

15179
/*
15180
 * Public helper functions. These aren't used internally by DataTables, or
15181
 * called by any of the options passed into DataTables, but they can be used
15182
 * externally by developers working with DataTables. They are helper functions
15183
 * to make working with DataTables a little bit easier.
15184
 */
15185

15186
var __htmlEscapeEntities = function ( d ) {
15187
	if (Array.isArray(d)) {
15188
		d = d.join(',');
15189
	}
15190

15191
	return typeof d === 'string' ?
15192
		d
15193
			.replace(/&/g, '&amp;')
15194
			.replace(/</g, '&lt;')
15195
			.replace(/>/g, '&gt;')
15196
			.replace(/"/g, '&quot;') :
15197
		d;
15198
};
15199

15200
// Common logic for moment, luxon or a date action
15201
function __mld( dt, momentFn, luxonFn, dateFn, arg1 ) {
15202
	if (window.moment) {
15203
		return dt[momentFn]( arg1 );
15204
	}
15205
	else if (window.luxon) {
15206
		return dt[luxonFn]( arg1 );
15207
	}
15208
	
15209
	return dateFn ? dt[dateFn]( arg1 ) : dt;
15210
}
15211

15212

15213
var __mlWarning = false;
15214
function __mldObj (d, format, locale) {
15215
	var dt;
15216

15217
	if (window.moment) {
15218
		dt = window.moment.utc( d, format, locale, true );
15219

15220
		if (! dt.isValid()) {
15221
			return null;
15222
		}
15223
	}
15224
	else if (window.luxon) {
15225
		dt = format && typeof d === 'string'
15226
			? window.luxon.DateTime.fromFormat( d, format )
15227
			: window.luxon.DateTime.fromISO( d );
15228

15229
		if (! dt.isValid) {
15230
			return null;
15231
		}
15232

15233
		dt.setLocale(locale);
15234
	}
15235
	else if (! format) {
15236
		// No format given, must be ISO
15237
		dt = new Date(d);
15238
	}
15239
	else {
15240
		if (! __mlWarning) {
15241
			alert('DataTables warning: Formatted date without Moment.js or Luxon - https://datatables.net/tn/17');
15242
		}
15243

15244
		__mlWarning = true;
15245
	}
15246

15247
	return dt;
15248
}
15249

15250
// Wrapper for date, datetime and time which all operate the same way with the exception of
15251
// the output string for auto locale support
15252
function __mlHelper (localeString) {
15253
	return function ( from, to, locale, def ) {
15254
		// Luxon and Moment support
15255
		// Argument shifting
15256
		if ( arguments.length === 0 ) {
15257
			locale = 'en';
15258
			to = null; // means toLocaleString
15259
			from = null; // means iso8601
15260
		}
15261
		else if ( arguments.length === 1 ) {
15262
			locale = 'en';
15263
			to = from;
15264
			from = null;
15265
		}
15266
		else if ( arguments.length === 2 ) {
15267
			locale = to;
15268
			to = from;
15269
			from = null;
15270
		}
15271

15272
		var typeName = 'datetime-' + to;
15273

15274
		// Add type detection and sorting specific to this date format - we need to be able to identify
15275
		// date type columns as such, rather than as numbers in extensions. Hence the need for this.
15276
		if (! DataTable.ext.type.order[typeName]) {
15277
			// The renderer will give the value to type detect as the type!
15278
			DataTable.ext.type.detect.unshift(function (d) {
15279
				return d === typeName ? typeName : false;
15280
			});
15281

15282
			// The renderer gives us Moment, Luxon or Date obects for the sorting, all of which have a
15283
			// `valueOf` which gives milliseconds epoch
15284
			DataTable.ext.type.order[typeName + '-asc'] = function (a, b) {
15285
				var x = a.valueOf();
15286
				var y = b.valueOf();
15287

15288
				return x === y
15289
					? 0
15290
					: x < y
15291
						? -1
15292
						: 1;
15293
			}
15294

15295
			DataTable.ext.type.order[typeName + '-desc'] = function (a, b) {
15296
				var x = a.valueOf();
15297
				var y = b.valueOf();
15298

15299
				return x === y
15300
					? 0
15301
					: x > y
15302
						? -1
15303
						: 1;
15304
			}
15305
		}
15306
	
15307
		return function ( d, type ) {
15308
			// Allow for a default value
15309
			if (d === null || d === undefined) {
15310
				if (def === '--now') {
15311
					// We treat everything as UTC further down, so no changes are
15312
					// made, as such need to get the local date / time as if it were
15313
					// UTC
15314
					var local = new Date();
15315
					d = new Date( Date.UTC(
15316
						local.getFullYear(), local.getMonth(), local.getDate(),
15317
						local.getHours(), local.getMinutes(), local.getSeconds()
15318
					) );
15319
				}
15320
				else {
15321
					d = '';
15322
				}
15323
			}
15324

15325
			if (type === 'type') {
15326
				// Typing uses the type name for fast matching
15327
				return typeName;
15328
			}
15329

15330
			if (d === '') {
15331
				return type !== 'sort'
15332
					? ''
15333
					: __mldObj('0000-01-01 00:00:00', null, locale);
15334
			}
15335

15336
			// Shortcut. If `from` and `to` are the same, we are using the renderer to
15337
			// format for ordering, not display - its already in the display format.
15338
			if ( to !== null && from === to && type !== 'sort' && type !== 'type' && ! (d instanceof Date) ) {
15339
				return d;
15340
			}
15341

15342
			var dt = __mldObj(d, from, locale);
15343

15344
			if (dt === null) {
15345
				return d;
15346
			}
15347

15348
			if (type === 'sort') {
15349
				return dt;
15350
			}
15351
			
15352
			var formatted = to === null
15353
				? __mld(dt, 'toDate', 'toJSDate', '')[localeString]()
15354
				: __mld(dt, 'format', 'toFormat', 'toISOString', to);
15355

15356
			// XSS protection
15357
			return type === 'display' ?
15358
				__htmlEscapeEntities( formatted ) :
15359
				formatted;
15360
		};
15361
	}
15362
}
15363

15364
// Based on locale, determine standard number formatting
15365
// Fallback for legacy browsers is US English
15366
var __thousands = ',';
15367
var __decimal = '.';
15368

15369
if (window.Intl !== undefined) {
15370
	try {
15371
		var num = new Intl.NumberFormat().formatToParts(100000.1);
15372
	
15373
		for (var i=0 ; i<num.length ; i++) {
15374
			if (num[i].type === 'group') {
15375
				__thousands = num[i].value;
15376
			}
15377
			else if (num[i].type === 'decimal') {
15378
				__decimal = num[i].value;
15379
			}
15380
		}
15381
	}
15382
	catch (e) {
15383
		// noop
15384
	}
15385
}
15386

15387
// Formatted date time detection - use by declaring the formats you are going to use
15388
DataTable.datetime = function ( format, locale ) {
15389
	var typeName = 'datetime-detect-' + format;
15390

15391
	if (! locale) {
15392
		locale = 'en';
15393
	}
15394

15395
	if (! DataTable.ext.type.order[typeName]) {
15396
		DataTable.ext.type.detect.unshift(function (d) {
15397
			var dt = __mldObj(d, format, locale);
15398
			return d === '' || dt ? typeName : false;
15399
		});
15400

15401
		DataTable.ext.type.order[typeName + '-pre'] = function (d) {
15402
			return __mldObj(d, format, locale) || 0;
15403
		}
15404
	}
15405
}
15406

15407
/**
15408
 * Helpers for `columns.render`.
15409
 *
15410
 * The options defined here can be used with the `columns.render` initialisation
15411
 * option to provide a display renderer. The following functions are defined:
15412
 *
15413
 * * `number` - Will format numeric data (defined by `columns.data`) for
15414
 *   display, retaining the original unformatted data for sorting and filtering.
15415
 *   It takes 5 parameters:
15416
 *   * `string` - Thousands grouping separator
15417
 *   * `string` - Decimal point indicator
15418
 *   * `integer` - Number of decimal points to show
15419
 *   * `string` (optional) - Prefix.
15420
 *   * `string` (optional) - Postfix (/suffix).
15421
 * * `text` - Escape HTML to help prevent XSS attacks. It has no optional
15422
 *   parameters.
15423
 *
15424
 * @example
15425
 *   // Column definition using the number renderer
15426
 *   {
15427
 *     data: "salary",
15428
 *     render: $.fn.dataTable.render.number( '\'', '.', 0, '$' )
15429
 *   }
15430
 *
15431
 * @namespace
15432
 */
15433
DataTable.render = {
15434
	date: __mlHelper('toLocaleDateString'),
15435
	datetime: __mlHelper('toLocaleString'),
15436
	time: __mlHelper('toLocaleTimeString'),
15437
	number: function ( thousands, decimal, precision, prefix, postfix ) {
15438
		// Auto locale detection
15439
		if (thousands === null || thousands === undefined) {
15440
			thousands = __thousands;
15441
		}
15442

15443
		if (decimal === null || decimal === undefined) {
15444
			decimal = __decimal;
15445
		}
15446

15447
		return {
15448
			display: function ( d ) {
15449
				if ( typeof d !== 'number' && typeof d !== 'string' ) {
15450
					return d;
15451
				}
15452

15453
				if (d === '' || d === null) {
15454
					return d;
15455
				}
15456

15457
				var negative = d < 0 ? '-' : '';
15458
				var flo = parseFloat( d );
15459

15460
				// If NaN then there isn't much formatting that we can do - just
15461
				// return immediately, escaping any HTML (this was supposed to
15462
				// be a number after all)
15463
				if ( isNaN( flo ) ) {
15464
					return __htmlEscapeEntities( d );
15465
				}
15466

15467
				flo = flo.toFixed( precision );
15468
				d = Math.abs( flo );
15469

15470
				var intPart = parseInt( d, 10 );
15471
				var floatPart = precision ?
15472
					decimal+(d - intPart).toFixed( precision ).substring( 2 ):
15473
					'';
15474

15475
				// If zero, then can't have a negative prefix
15476
				if (intPart === 0 && parseFloat(floatPart) === 0) {
15477
					negative = '';
15478
				}
15479

15480
				return negative + (prefix||'') +
15481
					intPart.toString().replace(
15482
						/\B(?=(\d{3})+(?!\d))/g, thousands
15483
					) +
15484
					floatPart +
15485
					(postfix||'');
15486
			}
15487
		};
15488
	},
15489

15490
	text: function () {
15491
		return {
15492
			display: __htmlEscapeEntities,
15493
			filter: __htmlEscapeEntities
15494
		};
15495
	}
15496
};
15497

15498

15499
/*
15500
 * This is really a good bit rubbish this method of exposing the internal methods
15501
 * publicly... - To be fixed in 2.0 using methods on the prototype
15502
 */
15503

15504

15505
/**
15506
 * Create a wrapper function for exporting an internal functions to an external API.
15507
 *  @param {string} fn API function name
15508
 *  @returns {function} wrapped function
15509
 *  @memberof DataTable#internal
15510
 */
15511
function _fnExternApiFunc (fn)
15512
{
15513
	return function() {
15514
		var args = [_fnSettingsFromNode( this[DataTable.ext.iApiIndex] )].concat(
15515
			Array.prototype.slice.call(arguments)
15516
		);
15517
		return DataTable.ext.internal[fn].apply( this, args );
15518
	};
15519
}
15520

15521

15522
/**
15523
 * Reference to internal functions for use by plug-in developers. Note that
15524
 * these methods are references to internal functions and are considered to be
15525
 * private. If you use these methods, be aware that they are liable to change
15526
 * between versions.
15527
 *  @namespace
15528
 */
15529
$.extend( DataTable.ext.internal, {
15530
	_fnExternApiFunc: _fnExternApiFunc,
15531
	_fnBuildAjax: _fnBuildAjax,
15532
	_fnAjaxUpdate: _fnAjaxUpdate,
15533
	_fnAjaxParameters: _fnAjaxParameters,
15534
	_fnAjaxUpdateDraw: _fnAjaxUpdateDraw,
15535
	_fnAjaxDataSrc: _fnAjaxDataSrc,
15536
	_fnAddColumn: _fnAddColumn,
15537
	_fnColumnOptions: _fnColumnOptions,
15538
	_fnAdjustColumnSizing: _fnAdjustColumnSizing,
15539
	_fnVisibleToColumnIndex: _fnVisibleToColumnIndex,
15540
	_fnColumnIndexToVisible: _fnColumnIndexToVisible,
15541
	_fnVisbleColumns: _fnVisbleColumns,
15542
	_fnGetColumns: _fnGetColumns,
15543
	_fnColumnTypes: _fnColumnTypes,
15544
	_fnApplyColumnDefs: _fnApplyColumnDefs,
15545
	_fnHungarianMap: _fnHungarianMap,
15546
	_fnCamelToHungarian: _fnCamelToHungarian,
15547
	_fnLanguageCompat: _fnLanguageCompat,
15548
	_fnBrowserDetect: _fnBrowserDetect,
15549
	_fnAddData: _fnAddData,
15550
	_fnAddTr: _fnAddTr,
15551
	_fnNodeToDataIndex: _fnNodeToDataIndex,
15552
	_fnNodeToColumnIndex: _fnNodeToColumnIndex,
15553
	_fnGetCellData: _fnGetCellData,
15554
	_fnSetCellData: _fnSetCellData,
15555
	_fnSplitObjNotation: _fnSplitObjNotation,
15556
	_fnGetObjectDataFn: _fnGetObjectDataFn,
15557
	_fnSetObjectDataFn: _fnSetObjectDataFn,
15558
	_fnGetDataMaster: _fnGetDataMaster,
15559
	_fnClearTable: _fnClearTable,
15560
	_fnDeleteIndex: _fnDeleteIndex,
15561
	_fnInvalidate: _fnInvalidate,
15562
	_fnGetRowElements: _fnGetRowElements,
15563
	_fnCreateTr: _fnCreateTr,
15564
	_fnBuildHead: _fnBuildHead,
15565
	_fnDrawHead: _fnDrawHead,
15566
	_fnDraw: _fnDraw,
15567
	_fnReDraw: _fnReDraw,
15568
	_fnAddOptionsHtml: _fnAddOptionsHtml,
15569
	_fnDetectHeader: _fnDetectHeader,
15570
	_fnGetUniqueThs: _fnGetUniqueThs,
15571
	_fnFeatureHtmlFilter: _fnFeatureHtmlFilter,
15572
	_fnFilterComplete: _fnFilterComplete,
15573
	_fnFilterCustom: _fnFilterCustom,
15574
	_fnFilterColumn: _fnFilterColumn,
15575
	_fnFilter: _fnFilter,
15576
	_fnFilterCreateSearch: _fnFilterCreateSearch,
15577
	_fnEscapeRegex: _fnEscapeRegex,
15578
	_fnFilterData: _fnFilterData,
15579
	_fnFeatureHtmlInfo: _fnFeatureHtmlInfo,
15580
	_fnUpdateInfo: _fnUpdateInfo,
15581
	_fnInfoMacros: _fnInfoMacros,
15582
	_fnInitialise: _fnInitialise,
15583
	_fnInitComplete: _fnInitComplete,
15584
	_fnLengthChange: _fnLengthChange,
15585
	_fnFeatureHtmlLength: _fnFeatureHtmlLength,
15586
	_fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate,
15587
	_fnPageChange: _fnPageChange,
15588
	_fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing,
15589
	_fnProcessingDisplay: _fnProcessingDisplay,
15590
	_fnFeatureHtmlTable: _fnFeatureHtmlTable,
15591
	_fnScrollDraw: _fnScrollDraw,
15592
	_fnApplyToChildren: _fnApplyToChildren,
15593
	_fnCalculateColumnWidths: _fnCalculateColumnWidths,
15594
	_fnThrottle: _fnThrottle,
15595
	_fnConvertToWidth: _fnConvertToWidth,
15596
	_fnGetWidestNode: _fnGetWidestNode,
15597
	_fnGetMaxLenString: _fnGetMaxLenString,
15598
	_fnStringToCss: _fnStringToCss,
15599
	_fnSortFlatten: _fnSortFlatten,
15600
	_fnSort: _fnSort,
15601
	_fnSortAria: _fnSortAria,
15602
	_fnSortListener: _fnSortListener,
15603
	_fnSortAttachListener: _fnSortAttachListener,
15604
	_fnSortingClasses: _fnSortingClasses,
15605
	_fnSortData: _fnSortData,
15606
	_fnSaveState: _fnSaveState,
15607
	_fnLoadState: _fnLoadState,
15608
	_fnImplementState: _fnImplementState,
15609
	_fnSettingsFromNode: _fnSettingsFromNode,
15610
	_fnLog: _fnLog,
15611
	_fnMap: _fnMap,
15612
	_fnBindAction: _fnBindAction,
15613
	_fnCallbackReg: _fnCallbackReg,
15614
	_fnCallbackFire: _fnCallbackFire,
15615
	_fnLengthOverflow: _fnLengthOverflow,
15616
	_fnRenderer: _fnRenderer,
15617
	_fnDataSource: _fnDataSource,
15618
	_fnRowAttributes: _fnRowAttributes,
15619
	_fnExtend: _fnExtend,
15620
	_fnCalculateEnd: function () {} // Used by a lot of plug-ins, but redundant
15621
	                                // in 1.10, so this dead-end function is
15622
	                                // added to prevent errors
15623
} );
15624

15625

15626
// jQuery access
15627
$.fn.dataTable = DataTable;
15628

15629
// Provide access to the host jQuery object (circular reference)
15630
DataTable.$ = $;
15631

15632
// Legacy aliases
15633
$.fn.dataTableSettings = DataTable.settings;
15634
$.fn.dataTableExt = DataTable.ext;
15635

15636
// With a capital `D` we return a DataTables API instance rather than a
15637
// jQuery object
15638
$.fn.DataTable = function ( opts ) {
15639
	return $(this).dataTable( opts ).api();
15640
};
15641

15642
// All properties that are available to $.fn.dataTable should also be
15643
// available on $.fn.DataTable
15644
$.each( DataTable, function ( prop, val ) {
15645
	$.fn.DataTable[ prop ] = val;
15646
} );
15647

15648
export default DataTable;
15649

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

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

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

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