Test Failed
Push — master ( 656844...7b0727 )
by Justin
21:52 queued 17:47
created

styles/admin/bower_components/datatables.net/js/jquery.dataTables.js   F

Complexity

Total Complexity 1663
Complexity/F 3.52

Size

Lines of Code 15216
Function Count 472

Duplication

Duplicated Lines 355
Ratio 2.33 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 0
c 1
b 0
f 1
nc 0
dl 355
loc 15216
rs 2.4
wmc 1663
mnd 12
bc 1244
fnc 472
bpm 2.6355
cpm 3.5233
noi 121

3 Functions

Rating   Name   Duplication   Size   Complexity  
B jquery.dataTables.js ➔ ?!? 355 15184 1
A module.exports 0 15 4
A jquery.dataTables.js ➔ define 0 3 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complexity

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like styles/admin/bower_components/datatables.net/js/jquery.dataTables.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

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

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
864
			if ( fn ) {
865
				this[fn] = _fnExternApiFunc(fn);
866
			}
867
		}
868
869
		this.each(function() {
870
			// For each initialisation we want to give it a clean initialisation
871
			// object that can be bashed around
872
			var o = {};
873
			var oInit = len > 1 ? // optimisation for single table case
874
				_fnExtend( o, options, true ) :
875
				options;
876
877
			/*global oInit,_that,emptyInit*/
878
			var i=0, iLen, j, jLen, k, kLen;
0 ignored issues
show
Unused Code introduced by
The variable j seems to be never used. Consider removing it.
Loading history...
Unused Code introduced by
The variable jLen seems to be never used. Consider removing it.
Loading history...
Unused Code introduced by
The variable kLen seems to be never used. Consider removing it.
Loading history...
Unused Code introduced by
The variable k seems to be never used. Consider removing it.
Loading history...
879
			var sId = this.getAttribute( 'id' );
880
			var bInitHandedOff = false;
881
			var defaults = DataTable.defaults;
882
			var $this = $(this);
883
			
884
			
885
			/* Sanity check */
886
			if ( this.nodeName.toLowerCase() != 'table' )
887
			{
888
				_fnLog( null, 0, 'Non-table node initialisation ('+this.nodeName+')', 2 );
889
				return;
890
			}
891
			
892
			/* Backwards compatibility for the defaults */
893
			_fnCompatOpts( defaults );
894
			_fnCompatCols( defaults.column );
895
			
896
			/* Convert the camel-case defaults to Hungarian */
897
			_fnCamelToHungarian( defaults, defaults, true );
898
			_fnCamelToHungarian( defaults.column, defaults.column, true );
899
			
900
			/* Setting up the initialisation object */
901
			_fnCamelToHungarian( defaults, $.extend( oInit, $this.data() ) );
902
			
903
			
904
			
905
			/* Check to see if we are re-initialising a table */
906
			var allSettings = DataTable.settings;
907
			for ( i=0, iLen=allSettings.length ; i<iLen ; i++ )
908
			{
909
				var s = allSettings[i];
910
			
911
				/* Base check on table node */
912
				if ( s.nTable == this || s.nTHead.parentNode == this || (s.nTFoot && s.nTFoot.parentNode == this) )
913
				{
914
					var bRetrieve = oInit.bRetrieve !== undefined ? oInit.bRetrieve : defaults.bRetrieve;
915
					var bDestroy = oInit.bDestroy !== undefined ? oInit.bDestroy : defaults.bDestroy;
916
			
917
					if ( emptyInit || bRetrieve )
918
					{
919
						return s.oInstance;
920
					}
921
					else if ( bDestroy )
922
					{
923
						s.oInstance.fnDestroy();
924
						break;
925
					}
926
					else
927
					{
928
						_fnLog( s, 0, 'Cannot reinitialise DataTable', 3 );
929
						return;
930
					}
931
				}
932
			
933
				/* If the element we are initialising has the same ID as a table which was previously
934
				 * initialised, but the table nodes don't match (from before) then we destroy the old
935
				 * instance by simply deleting it. This is under the assumption that the table has been
936
				 * destroyed by other methods. Anyone using non-id selectors will need to do this manually
937
				 */
938
				if ( s.sTableId == this.id )
939
				{
940
					allSettings.splice( i, 1 );
941
					break;
942
				}
943
			}
944
			
945
			/* Ensure the table has an ID - required for accessibility */
946
			if ( sId === null || sId === "" )
947
			{
948
				sId = "DataTables_Table_"+(DataTable.ext._unique++);
949
				this.id = sId;
950
			}
951
			
952
			/* Create the settings object for this table and set some of the default parameters */
953
			var oSettings = $.extend( true, {}, DataTable.models.oSettings, {
954
				"sDestroyWidth": $this[0].style.width,
955
				"sInstance":     sId,
956
				"sTableId":      sId
957
			} );
958
			oSettings.nTable = this;
959
			oSettings.oApi   = _that.internal;
960
			oSettings.oInit  = oInit;
961
			
962
			allSettings.push( oSettings );
963
			
964
			// Need to add the instance after the instance after the settings object has been added
965
			// to the settings array, so we can self reference the table instance if more than one
966
			oSettings.oInstance = (_that.length===1) ? _that : $this.dataTable();
967
			
968
			// Backwards compatibility, before we apply all the defaults
969
			_fnCompatOpts( oInit );
970
			
971
			if ( oInit.oLanguage )
972
			{
973
				_fnLanguageCompat( oInit.oLanguage );
974
			}
975
			
976
			// If the length menu is given, but the init display length is not, use the length menu
977
			if ( oInit.aLengthMenu && ! oInit.iDisplayLength )
978
			{
979
				oInit.iDisplayLength = $.isArray( oInit.aLengthMenu[0] ) ?
980
					oInit.aLengthMenu[0][0] : oInit.aLengthMenu[0];
981
			}
982
			
983
			// Apply the defaults and init options to make a single init object will all
984
			// options defined from defaults and instance options.
985
			oInit = _fnExtend( $.extend( true, {}, defaults ), oInit );
986
			
987
			
988
			// Map the initialisation options onto the settings object
989
			_fnMap( oSettings.oFeatures, oInit, [
990
				"bPaginate",
991
				"bLengthChange",
992
				"bFilter",
993
				"bSort",
994
				"bSortMulti",
995
				"bInfo",
996
				"bProcessing",
997
				"bAutoWidth",
998
				"bSortClasses",
999
				"bServerSide",
1000
				"bDeferRender"
1001
			] );
1002
			_fnMap( oSettings, oInit, [
1003
				"asStripeClasses",
1004
				"ajax",
1005
				"fnServerData",
1006
				"fnFormatNumber",
1007
				"sServerMethod",
1008
				"aaSorting",
1009
				"aaSortingFixed",
1010
				"aLengthMenu",
1011
				"sPaginationType",
1012
				"sAjaxSource",
1013
				"sAjaxDataProp",
1014
				"iStateDuration",
1015
				"sDom",
1016
				"bSortCellsTop",
1017
				"iTabIndex",
1018
				"fnStateLoadCallback",
1019
				"fnStateSaveCallback",
1020
				"renderer",
1021
				"searchDelay",
1022
				"rowId",
1023
				[ "iCookieDuration", "iStateDuration" ], // backwards compat
1024
				[ "oSearch", "oPreviousSearch" ],
1025
				[ "aoSearchCols", "aoPreSearchCols" ],
1026
				[ "iDisplayLength", "_iDisplayLength" ]
1027
			] );
1028
			_fnMap( oSettings.oScroll, oInit, [
1029
				[ "sScrollX", "sX" ],
1030
				[ "sScrollXInner", "sXInner" ],
1031
				[ "sScrollY", "sY" ],
1032
				[ "bScrollCollapse", "bCollapse" ]
1033
			] );
1034
			_fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" );
1035
			
1036
			/* Callback functions which are array driven */
1037
			_fnCallbackReg( oSettings, 'aoDrawCallback',       oInit.fnDrawCallback,      'user' );
1038
			_fnCallbackReg( oSettings, 'aoServerParams',       oInit.fnServerParams,      'user' );
1039
			_fnCallbackReg( oSettings, 'aoStateSaveParams',    oInit.fnStateSaveParams,   'user' );
1040
			_fnCallbackReg( oSettings, 'aoStateLoadParams',    oInit.fnStateLoadParams,   'user' );
1041
			_fnCallbackReg( oSettings, 'aoStateLoaded',        oInit.fnStateLoaded,       'user' );
1042
			_fnCallbackReg( oSettings, 'aoRowCallback',        oInit.fnRowCallback,       'user' );
1043
			_fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow,        'user' );
1044
			_fnCallbackReg( oSettings, 'aoHeaderCallback',     oInit.fnHeaderCallback,    'user' );
1045
			_fnCallbackReg( oSettings, 'aoFooterCallback',     oInit.fnFooterCallback,    'user' );
1046
			_fnCallbackReg( oSettings, 'aoInitComplete',       oInit.fnInitComplete,      'user' );
1047
			_fnCallbackReg( oSettings, 'aoPreDrawCallback',    oInit.fnPreDrawCallback,   'user' );
1048
			
1049
			oSettings.rowIdFn = _fnGetObjectDataFn( oInit.rowId );
1050
			
1051
			/* Browser support detection */
1052
			_fnBrowserDetect( oSettings );
1053
			
1054
			var oClasses = oSettings.oClasses;
1055
			
1056
			$.extend( oClasses, DataTable.ext.classes, oInit.oClasses );
1057
			$this.addClass( oClasses.sTable );
1058
			
1059
			
1060
			if ( oSettings.iInitDisplayStart === undefined )
1061
			{
1062
				/* Display start point, taking into account the save saving */
1063
				oSettings.iInitDisplayStart = oInit.iDisplayStart;
1064
				oSettings._iDisplayStart = oInit.iDisplayStart;
1065
			}
1066
			
1067
			if ( oInit.iDeferLoading !== null )
1068
			{
1069
				oSettings.bDeferLoading = true;
1070
				var tmp = $.isArray( oInit.iDeferLoading );
1071
				oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading;
1072
				oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading;
1073
			}
1074
			
1075
			/* Language definitions */
1076
			var oLanguage = oSettings.oLanguage;
1077
			$.extend( true, oLanguage, oInit.oLanguage );
1078
			
1079
			if ( oLanguage.sUrl )
1080
			{
1081
				/* Get the language definitions from a file - because this Ajax call makes the language
1082
				 * get async to the remainder of this function we use bInitHandedOff to indicate that
1083
				 * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor
1084
				 */
1085
				$.ajax( {
1086
					dataType: 'json',
1087
					url: oLanguage.sUrl,
1088
					success: function ( json ) {
1089
						_fnLanguageCompat( json );
1090
						_fnCamelToHungarian( defaults.oLanguage, json );
1091
						$.extend( true, oLanguage, json );
1092
						_fnInitialise( oSettings );
1093
					},
1094
					error: function () {
1095
						// Error occurred loading language file, continue on as best we can
1096
						_fnInitialise( oSettings );
1097
					}
1098
				} );
1099
				bInitHandedOff = true;
1100
			}
1101
			
1102
			/*
1103
			 * Stripes
1104
			 */
1105
			if ( oInit.asStripeClasses === null )
1106
			{
1107
				oSettings.asStripeClasses =[
1108
					oClasses.sStripeOdd,
1109
					oClasses.sStripeEven
1110
				];
1111
			}
1112
			
1113
			/* Remove row stripe classes if they are already on the table row */
1114
			var stripeClasses = oSettings.asStripeClasses;
1115
			var rowOne = $this.children('tbody').find('tr').eq(0);
1116
			if ( $.inArray( true, $.map( stripeClasses, function(el, i) {
0 ignored issues
show
Unused Code introduced by
The parameter i is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
1117
				return rowOne.hasClass(el);
1118
			} ) ) !== -1 ) {
1119
				$('tbody tr', this).removeClass( stripeClasses.join(' ') );
1120
				oSettings.asDestroyStripes = stripeClasses.slice();
1121
			}
1122
			
1123
			/*
1124
			 * Columns
1125
			 * See if we should load columns automatically or use defined ones
1126
			 */
1127
			var anThs = [];
1128
			var aoColumnsInit;
1129
			var nThead = this.getElementsByTagName('thead');
1130
			if ( nThead.length !== 0 )
1131
			{
1132
				_fnDetectHeader( oSettings.aoHeader, nThead[0] );
1133
				anThs = _fnGetUniqueThs( oSettings );
1134
			}
1135
			
1136
			/* If not given a column array, generate one with nulls */
1137
			if ( oInit.aoColumns === null )
1138
			{
1139
				aoColumnsInit = [];
1140
				for ( i=0, iLen=anThs.length ; i<iLen ; i++ )
1141
				{
1142
					aoColumnsInit.push( null );
1143
				}
1144
			}
1145
			else
1146
			{
1147
				aoColumnsInit = oInit.aoColumns;
1148
			}
1149
			
1150
			/* Add the columns */
1151
			for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ )
1152
			{
1153
				_fnAddColumn( oSettings, anThs ? anThs[i] : null );
1154
			}
1155
			
1156
			/* Apply the column definitions */
1157
			_fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) {
1158
				_fnColumnOptions( oSettings, iCol, oDef );
1159
			} );
1160
			
1161
			/* HTML5 attribute detection - build an mData object automatically if the
1162
			 * attributes are found
1163
			 */
1164
			if ( rowOne.length ) {
1165
				var a = function ( cell, name ) {
1166
					return cell.getAttribute( 'data-'+name ) !== null ? name : null;
1167
				};
1168
			
1169
				$( rowOne[0] ).children('th, td').each( function (i, cell) {
1170
					var col = oSettings.aoColumns[i];
1171
			
1172
					if ( col.mData === i ) {
1173
						var sort = a( cell, 'sort' ) || a( cell, 'order' );
1174
						var filter = a( cell, 'filter' ) || a( cell, 'search' );
1175
			
1176
						if ( sort !== null || filter !== null ) {
1177
							col.mData = {
1178
								_:      i+'.display',
1179
								sort:   sort !== null   ? i+'.@data-'+sort   : undefined,
1180
								type:   sort !== null   ? i+'.@data-'+sort   : undefined,
1181
								filter: filter !== null ? i+'.@data-'+filter : undefined
1182
							};
1183
			
1184
							_fnColumnOptions( oSettings, i );
1185
						}
1186
					}
1187
				} );
1188
			}
1189
			
1190
			var features = oSettings.oFeatures;
1191
			var loadedInit = function () {
1192
				/*
1193
				 * Sorting
1194
				 * @todo For modularisation (1.11) this needs to do into a sort start up handler
1195
				 */
1196
			
1197
				// If aaSorting is not defined, then we use the first indicator in asSorting
1198
				// in case that has been altered, so the default sort reflects that option
1199
				if ( oInit.aaSorting === undefined ) {
1200
					var sorting = oSettings.aaSorting;
1201
					for ( i=0, iLen=sorting.length ; i<iLen ; i++ ) {
0 ignored issues
show
Bug introduced by
The variable i is changed as part of the for loop for example by i++ on line 1201. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
1202
						sorting[i][1] = oSettings.aoColumns[ i ].asSorting[0];
1203
					}
1204
				}
1205
			
1206
				/* Do a first pass on the sorting classes (allows any size changes to be taken into
1207
				 * account, and also will apply sorting disabled classes if disabled
1208
				 */
1209
				_fnSortingClasses( oSettings );
1210
			
1211
				if ( features.bSort ) {
1212
					_fnCallbackReg( oSettings, 'aoDrawCallback', function () {
1213
						if ( oSettings.bSorted ) {
1214
							var aSort = _fnSortFlatten( oSettings );
1215
							var sortedColumns = {};
1216
			
1217
							$.each( aSort, function (i, val) {
1218
								sortedColumns[ val.src ] = val.dir;
1219
							} );
1220
			
1221
							_fnCallbackFire( oSettings, null, 'order', [oSettings, aSort, sortedColumns] );
1222
							_fnSortAria( oSettings );
1223
						}
1224
					} );
1225
				}
1226
			
1227
				_fnCallbackReg( oSettings, 'aoDrawCallback', function () {
1228
					if ( oSettings.bSorted || _fnDataSource( oSettings ) === 'ssp' || features.bDeferRender ) {
1229
						_fnSortingClasses( oSettings );
1230
					}
1231
				}, 'sc' );
1232
			
1233
			
1234
				/*
1235
				 * Final init
1236
				 * Cache the header, body and footer as required, creating them if needed
1237
				 */
1238
			
1239
				// Work around for Webkit bug 83867 - store the caption-side before removing from doc
1240
				var captions = $this.children('caption').each( function () {
1241
					this._captionSide = $(this).css('caption-side');
1242
				} );
1243
			
1244
				var thead = $this.children('thead');
1245
				if ( thead.length === 0 ) {
1246
					thead = $('<thead/>').appendTo($this);
1247
				}
1248
				oSettings.nTHead = thead[0];
1249
			
1250
				var tbody = $this.children('tbody');
1251
				if ( tbody.length === 0 ) {
1252
					tbody = $('<tbody/>').appendTo($this);
1253
				}
1254
				oSettings.nTBody = tbody[0];
1255
			
1256
				var tfoot = $this.children('tfoot');
1257
				if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") ) {
1258
					// If we are a scrolling table, and no footer has been given, then we need to create
1259
					// a tfoot element for the caption element to be appended to
1260
					tfoot = $('<tfoot/>').appendTo($this);
1261
				}
1262
			
1263
				if ( tfoot.length === 0 || tfoot.children().length === 0 ) {
1264
					$this.addClass( oClasses.sNoFooter );
1265
				}
1266
				else if ( tfoot.length > 0 ) {
1267
					oSettings.nTFoot = tfoot[0];
1268
					_fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );
1269
				}
1270
			
1271
				/* Check if there is data passing into the constructor */
1272
				if ( oInit.aaData ) {
1273
					for ( i=0 ; i<oInit.aaData.length ; i++ ) {
0 ignored issues
show
Bug introduced by
The variable i is changed as part of the for loop for example by i++ on line 1273. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
1274
						_fnAddData( oSettings, oInit.aaData[ i ] );
1275
					}
1276
				}
1277
				else if ( oSettings.bDeferLoading || _fnDataSource( oSettings ) == 'dom' ) {
1278
					/* Grab the data from the page - only do this when deferred loading or no Ajax
1279
					 * source since there is no point in reading the DOM data if we are then going
1280
					 * to replace it with Ajax data
1281
					 */
1282
					_fnAddTr( oSettings, $(oSettings.nTBody).children('tr') );
1283
				}
1284
			
1285
				/* Copy the data index array */
1286
				oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
1287
			
1288
				/* Initialisation complete - table can be drawn */
1289
				oSettings.bInitialised = true;
1290
			
1291
				/* Check if we need to initialise the table (it might not have been handed off to the
1292
				 * language processor)
1293
				 */
1294
				if ( bInitHandedOff === false ) {
1295
					_fnInitialise( oSettings );
1296
				}
1297
			};
1298
			
1299
			/* Must be done after everything which can be overridden by the state saving! */
1300
			if ( oInit.bStateSave )
1301
			{
1302
				features.bStateSave = true;
1303
				_fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' );
1304
				_fnLoadState( oSettings, oInit, loadedInit );
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
1305
			}
1306
			else {
1307
				loadedInit();
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
1308
			}
1309
			
1310
		} );
1311
		_that = null;
0 ignored issues
show
Unused Code introduced by
The assignment to _that seems to be never used. If you intend to free memory here, this is not necessary since the variable leaves the scope anyway.
Loading history...
1312
		return this;
1313
	};
1314
1315
	
1316
	/*
1317
	 * It is useful to have variables which are scoped locally so only the
1318
	 * DataTables functions can access them and they don't leak into global space.
1319
	 * At the same time these functions are often useful over multiple files in the
1320
	 * core and API, so we list, or at least document, all variables which are used
1321
	 * by DataTables as private variables here. This also ensures that there is no
1322
	 * clashing of variable names and that they can easily referenced for reuse.
1323
	 */
1324
	
1325
	
1326
	// Defined else where
1327
	//  _selector_run
1328
	//  _selector_opts
1329
	//  _selector_first
1330
	//  _selector_row_indexes
1331
	
1332
	var _ext; // DataTable.ext
1333
	var _Api; // DataTable.Api
1334
	var _api_register; // DataTable.Api.register
1335
	var _api_registerPlural; // DataTable.Api.registerPlural
1336
	
1337
	var _re_dic = {};
1338
	var _re_new_lines = /[\r\n]/g;
1339
	var _re_html = /<.*?>/g;
1340
	
1341
	// This is not strict ISO8601 - Date.parse() is quite lax, although
1342
	// implementations differ between browsers.
1343
	var _re_date = /^\d{2,4}[\.\/\-]\d{1,2}[\.\/\-]\d{1,2}([T ]{1}\d{1,2}[:\.]\d{2}([\.:]\d{2})?)?$/;
1344
	
1345
	// Escape regular expression special characters
1346
	var _re_escape_regex = new RegExp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' );
1347
	
1348
	// http://en.wikipedia.org/wiki/Foreign_exchange_market
1349
	// - \u20BD - Russian ruble.
1350
	// - \u20a9 - South Korean Won
1351
	// - \u20BA - Turkish Lira
1352
	// - \u20B9 - Indian Rupee
1353
	// - R - Brazil (R$) and South Africa
1354
	// - fr - Swiss Franc
1355
	// - kr - Swedish krona, Norwegian krone and Danish krone
1356
	// - \u2009 is thin space and \u202F is narrow no-break space, both used in many
1357
	//   standards as thousands separators.
1358
	var _re_formatted_numeric = /[',$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfk]/gi;
1359
	
1360
	
1361
	var _empty = function ( d ) {
1362
		return !d || d === true || d === '-' ? true : false;
1363
	};
1364
	
1365
	
1366
	var _intVal = function ( s ) {
1367
		var integer = parseInt( s, 10 );
1368
		return !isNaN(integer) && isFinite(s) ? integer : null;
1369
	};
1370
	
1371
	// Convert from a formatted number with characters other than `.` as the
1372
	// decimal place, to a Javascript number
1373
	var _numToDecimal = function ( num, decimalPoint ) {
1374
		// Cache created regular expressions for speed as this function is called often
1375
		if ( ! _re_dic[ decimalPoint ] ) {
1376
			_re_dic[ decimalPoint ] = new RegExp( _fnEscapeRegex( decimalPoint ), 'g' );
1377
		}
1378
		return typeof num === 'string' && decimalPoint !== '.' ?
1379
			num.replace( /\./g, '' ).replace( _re_dic[ decimalPoint ], '.' ) :
1380
			num;
1381
	};
1382
	
1383
	
1384
	var _isNumber = function ( d, decimalPoint, formatted ) {
1385
		var strType = typeof d === 'string';
1386
	
1387
		// If empty return immediately so there must be a number if it is a
1388
		// formatted string (this stops the string "k", or "kr", etc being detected
1389
		// as a formatted number for currency
1390
		if ( _empty( d ) ) {
1391
			return true;
1392
		}
1393
	
1394
		if ( decimalPoint && strType ) {
1395
			d = _numToDecimal( d, decimalPoint );
1396
		}
1397
	
1398
		if ( formatted && strType ) {
1399
			d = d.replace( _re_formatted_numeric, '' );
1400
		}
1401
	
1402
		return !isNaN( parseFloat(d) ) && isFinite( d );
1403
	};
1404
	
1405
	
1406
	// A string without HTML in it can be considered to be HTML still
1407
	var _isHtml = function ( d ) {
1408
		return _empty( d ) || typeof d === 'string';
1409
	};
1410
	
1411
	
1412
	var _htmlNumeric = function ( d, decimalPoint, formatted ) {
1413
		if ( _empty( d ) ) {
1414
			return true;
1415
		}
1416
	
1417
		var html = _isHtml( d );
1418
		return ! html ?
1419
			null :
1420
			_isNumber( _stripHtml( d ), decimalPoint, formatted ) ?
1421
				true :
1422
				null;
1423
	};
1424
	
1425
	
1426
	var _pluck = function ( a, prop, prop2 ) {
1427
		var out = [];
1428
		var i=0, ien=a.length;
1429
	
1430
		// Could have the test in the loop for slightly smaller code, but speed
1431
		// is essential here
1432
		if ( prop2 !== undefined ) {
1433
			for ( ; i<ien ; i++ ) {
1434
				if ( a[i] && a[i][ prop ] ) {
1435
					out.push( a[i][ prop ][ prop2 ] );
1436
				}
1437
			}
1438
		}
1439
		else {
1440
			for ( ; i<ien ; i++ ) {
1441
				if ( a[i] ) {
1442
					out.push( a[i][ prop ] );
1443
				}
1444
			}
1445
		}
1446
	
1447
		return out;
1448
	};
1449
	
1450
	
1451
	// Basically the same as _pluck, but rather than looping over `a` we use `order`
1452
	// as the indexes to pick from `a`
1453
	var _pluck_order = function ( a, order, prop, prop2 )
1454
	{
1455
		var out = [];
1456
		var i=0, ien=order.length;
1457
	
1458
		// Could have the test in the loop for slightly smaller code, but speed
1459
		// is essential here
1460
		if ( prop2 !== undefined ) {
1461
			for ( ; i<ien ; i++ ) {
1462
				if ( a[ order[i] ][ prop ] ) {
1463
					out.push( a[ order[i] ][ prop ][ prop2 ] );
1464
				}
1465
			}
1466
		}
1467
		else {
1468
			for ( ; i<ien ; i++ ) {
1469
				out.push( a[ order[i] ][ prop ] );
1470
			}
1471
		}
1472
	
1473
		return out;
1474
	};
1475
	
1476
	
1477
	var _range = function ( len, start )
1478
	{
1479
		var out = [];
1480
		var end;
1481
	
1482
		if ( start === undefined ) {
1483
			start = 0;
1484
			end = len;
1485
		}
1486
		else {
1487
			end = start;
1488
			start = len;
1489
		}
1490
	
1491
		for ( var i=start ; i<end ; i++ ) {
1492
			out.push( i );
1493
		}
1494
	
1495
		return out;
1496
	};
1497
	
1498
	
1499
	var _removeEmpty = function ( a )
1500
	{
1501
		var out = [];
1502
	
1503
		for ( var i=0, ien=a.length ; i<ien ; i++ ) {
1504
			if ( a[i] ) { // careful - will remove all falsy values!
1505
				out.push( a[i] );
1506
			}
1507
		}
1508
	
1509
		return out;
1510
	};
1511
	
1512
	
1513
	var _stripHtml = function ( d ) {
1514
		return d.replace( _re_html, '' );
1515
	};
1516
	
1517
	
1518
	/**
1519
	 * Determine if all values in the array are unique. This means we can short
1520
	 * cut the _unique method at the cost of a single loop. A sorted array is used
1521
	 * to easily check the values.
1522
	 *
1523
	 * @param  {array} src Source array
1524
	 * @return {boolean} true if all unique, false otherwise
1525
	 * @ignore
1526
	 */
1527
	var _areAllUnique = function ( src ) {
1528
		if ( src.length < 2 ) {
1529
			return true;
1530
		}
1531
	
1532
		var sorted = src.slice().sort();
1533
		var last = sorted[0];
1534
	
1535
		for ( var i=1, ien=sorted.length ; i<ien ; i++ ) {
1536
			if ( sorted[i] === last ) {
1537
				return false;
1538
			}
1539
	
1540
			last = sorted[i];
1541
		}
1542
	
1543
		return true;
1544
	};
1545
	
1546
	
1547
	/**
1548
	 * Find the unique elements in a source array.
1549
	 *
1550
	 * @param  {array} src Source array
1551
	 * @return {array} Array of unique items
1552
	 * @ignore
1553
	 */
1554
	var _unique = function ( src )
1555
	{
1556
		if ( _areAllUnique( src ) ) {
1557
			return src.slice();
1558
		}
1559
	
1560
		// A faster unique method is to use object keys to identify used values,
1561
		// but this doesn't work with arrays or objects, which we must also
1562
		// consider. See jsperf.com/compare-array-unique-versions/4 for more
1563
		// information.
1564
		var
1565
			out = [],
1566
			val,
1567
			i, ien=src.length,
1568
			j, k=0;
1569
	
1570
		again: for ( i=0 ; i<ien ; i++ ) {
1571
			val = src[i];
1572
	
1573
			for ( j=0 ; j<k ; j++ ) {
1574
				if ( out[j] === val ) {
1575
					continue again;
1576
				}
1577
			}
1578
	
1579
			out.push( val );
1580
			k++;
1581
		}
1582
	
1583
		return out;
1584
	};
1585
	
1586
	
1587
	/**
1588
	 * DataTables utility methods
1589
	 * 
1590
	 * This namespace provides helper methods that DataTables uses internally to
1591
	 * create a DataTable, but which are not exclusively used only for DataTables.
1592
	 * These methods can be used by extension authors to save the duplication of
1593
	 * code.
1594
	 *
1595
	 *  @namespace
1596
	 */
1597
	DataTable.util = {
1598
		/**
1599
		 * Throttle the calls to a function. Arguments and context are maintained
1600
		 * for the throttled function.
1601
		 *
1602
		 * @param {function} fn Function to be called
1603
		 * @param {integer} freq Call frequency in mS
1604
		 * @return {function} Wrapped function
1605
		 */
1606
		throttle: function ( fn, freq ) {
1607
			var
1608
				frequency = freq !== undefined ? freq : 200,
1609
				last,
1610
				timer;
1611
	
1612
			return function () {
1613
				var
1614
					that = this,
1615
					now  = +new Date(),
1616
					args = arguments;
1617
	
1618
				if ( last && now < last + frequency ) {
1619
					clearTimeout( timer );
1620
	
1621
					timer = setTimeout( function () {
1622
						last = undefined;
1623
						fn.apply( that, args );
1624
					}, frequency );
1625
				}
1626
				else {
1627
					last = now;
1628
					fn.apply( that, args );
1629
				}
1630
			};
1631
		},
1632
	
1633
	
1634
		/**
1635
		 * Escape a string such that it can be used in a regular expression
1636
		 *
1637
		 *  @param {string} val string to escape
1638
		 *  @returns {string} escaped string
1639
		 */
1640
		escapeRegex: function ( val ) {
1641
			return val.replace( _re_escape_regex, '\\$1' );
1642
		}
1643
	};
1644
	
1645
	
1646
	
1647
	/**
1648
	 * Create a mapping object that allows camel case parameters to be looked up
1649
	 * for their Hungarian counterparts. The mapping is stored in a private
1650
	 * parameter called `_hungarianMap` which can be accessed on the source object.
1651
	 *  @param {object} o
1652
	 *  @memberof DataTable#oApi
1653
	 */
1654
	function _fnHungarianMap ( o )
1655
	{
1656
		var
1657
			hungarian = 'a aa ai ao as b fn i m o s ',
1658
			match,
1659
			newKey,
1660
			map = {};
1661
	
1662
		$.each( o, function (key, val) {
0 ignored issues
show
Unused Code introduced by
The parameter val is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
1663
			match = key.match(/^([^A-Z]+?)([A-Z])/);
1664
	
1665
			if ( match && hungarian.indexOf(match[1]+' ') !== -1 )
1666
			{
1667
				newKey = key.replace( match[0], match[2].toLowerCase() );
1668
				map[ newKey ] = key;
1669
	
1670
				if ( match[1] === 'o' )
1671
				{
1672
					_fnHungarianMap( o[key] );
1673
				}
1674
			}
1675
		} );
1676
	
1677
		o._hungarianMap = map;
1678
	}
1679
	
1680
	
1681
	/**
1682
	 * Convert from camel case parameters to Hungarian, based on a Hungarian map
1683
	 * created by _fnHungarianMap.
1684
	 *  @param {object} src The model object which holds all parameters that can be
1685
	 *    mapped.
1686
	 *  @param {object} user The object to convert from camel case to Hungarian.
1687
	 *  @param {boolean} force When set to `true`, properties which already have a
1688
	 *    Hungarian value in the `user` object will be overwritten. Otherwise they
1689
	 *    won't be.
1690
	 *  @memberof DataTable#oApi
1691
	 */
1692
	function _fnCamelToHungarian ( src, user, force )
1693
	{
1694
		if ( ! src._hungarianMap ) {
1695
			_fnHungarianMap( src );
1696
		}
1697
	
1698
		var hungarianKey;
1699
	
1700
		$.each( user, function (key, val) {
0 ignored issues
show
Unused Code introduced by
The parameter val is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
1701
			hungarianKey = src._hungarianMap[ key ];
1702
	
1703
			if ( hungarianKey !== undefined && (force || user[hungarianKey] === undefined) )
1704
			{
1705
				// For objects, we need to buzz down into the object to copy parameters
1706
				if ( hungarianKey.charAt(0) === 'o' )
1707
				{
1708
					// Copy the camelCase options over to the hungarian
1709
					if ( ! user[ hungarianKey ] ) {
1710
						user[ hungarianKey ] = {};
1711
					}
1712
					$.extend( true, user[hungarianKey], user[key] );
1713
	
1714
					_fnCamelToHungarian( src[hungarianKey], user[hungarianKey], force );
1715
				}
1716
				else {
1717
					user[hungarianKey] = user[ key ];
1718
				}
1719
			}
1720
		} );
1721
	}
1722
	
1723
	
1724
	/**
1725
	 * Language compatibility - when certain options are given, and others aren't, we
1726
	 * need to duplicate the values over, in order to provide backwards compatibility
1727
	 * with older language files.
1728
	 *  @param {object} oSettings dataTables settings object
1729
	 *  @memberof DataTable#oApi
1730
	 */
1731
	function _fnLanguageCompat( lang )
1732
	{
1733
		var defaults = DataTable.defaults.oLanguage;
1734
		var zeroRecords = lang.sZeroRecords;
1735
	
1736
		/* Backwards compatibility - if there is no sEmptyTable given, then use the same as
1737
		 * sZeroRecords - assuming that is given.
1738
		 */
1739
		if ( ! lang.sEmptyTable && zeroRecords &&
1740
			defaults.sEmptyTable === "No data available in table" )
1741
		{
1742
			_fnMap( lang, lang, 'sZeroRecords', 'sEmptyTable' );
1743
		}
1744
	
1745
		/* Likewise with loading records */
1746
		if ( ! lang.sLoadingRecords && zeroRecords &&
1747
			defaults.sLoadingRecords === "Loading..." )
1748
		{
1749
			_fnMap( lang, lang, 'sZeroRecords', 'sLoadingRecords' );
1750
		}
1751
	
1752
		// Old parameter name of the thousands separator mapped onto the new
1753
		if ( lang.sInfoThousands ) {
1754
			lang.sThousands = lang.sInfoThousands;
1755
		}
1756
	
1757
		var decimal = lang.sDecimal;
1758
		if ( decimal ) {
1759
			_addNumericSort( decimal );
1760
		}
1761
	}
1762
	
1763
	
1764
	/**
1765
	 * Map one parameter onto another
1766
	 *  @param {object} o Object to map
1767
	 *  @param {*} knew The new parameter name
1768
	 *  @param {*} old The old parameter name
1769
	 */
1770
	var _fnCompatMap = function ( o, knew, old ) {
1771
		if ( o[ knew ] !== undefined ) {
1772
			o[ old ] = o[ knew ];
1773
		}
1774
	};
1775
	
1776
	
1777
	/**
1778
	 * Provide backwards compatibility for the main DT options. Note that the new
1779
	 * options are mapped onto the old parameters, so this is an external interface
1780
	 * change only.
1781
	 *  @param {object} init Object to map
1782
	 */
1783
	function _fnCompatOpts ( init )
1784
	{
1785
		_fnCompatMap( init, 'ordering',      'bSort' );
1786
		_fnCompatMap( init, 'orderMulti',    'bSortMulti' );
1787
		_fnCompatMap( init, 'orderClasses',  'bSortClasses' );
1788
		_fnCompatMap( init, 'orderCellsTop', 'bSortCellsTop' );
1789
		_fnCompatMap( init, 'order',         'aaSorting' );
1790
		_fnCompatMap( init, 'orderFixed',    'aaSortingFixed' );
1791
		_fnCompatMap( init, 'paging',        'bPaginate' );
1792
		_fnCompatMap( init, 'pagingType',    'sPaginationType' );
1793
		_fnCompatMap( init, 'pageLength',    'iDisplayLength' );
1794
		_fnCompatMap( init, 'searching',     'bFilter' );
1795
	
1796
		// Boolean initialisation of x-scrolling
1797
		if ( typeof init.sScrollX === 'boolean' ) {
1798
			init.sScrollX = init.sScrollX ? '100%' : '';
1799
		}
1800
		if ( typeof init.scrollX === 'boolean' ) {
1801
			init.scrollX = init.scrollX ? '100%' : '';
1802
		}
1803
	
1804
		// Column search objects are in an array, so it needs to be converted
1805
		// element by element
1806
		var searchCols = init.aoSearchCols;
1807
	
1808
		if ( searchCols ) {
1809
			for ( var i=0, ien=searchCols.length ; i<ien ; i++ ) {
1810
				if ( searchCols[i] ) {
1811
					_fnCamelToHungarian( DataTable.models.oSearch, searchCols[i] );
1812
				}
1813
			}
1814
		}
1815
	}
1816
	
1817
	
1818
	/**
1819
	 * Provide backwards compatibility for column options. Note that the new options
1820
	 * are mapped onto the old parameters, so this is an external interface change
1821
	 * only.
1822
	 *  @param {object} init Object to map
1823
	 */
1824
	function _fnCompatCols ( init )
1825
	{
1826
		_fnCompatMap( init, 'orderable',     'bSortable' );
1827
		_fnCompatMap( init, 'orderData',     'aDataSort' );
1828
		_fnCompatMap( init, 'orderSequence', 'asSorting' );
1829
		_fnCompatMap( init, 'orderDataType', 'sortDataType' );
1830
	
1831
		// orderData can be given as an integer
1832
		var dataSort = init.aDataSort;
1833
		if ( typeof dataSort === 'number' && ! $.isArray( dataSort ) ) {
1834
			init.aDataSort = [ dataSort ];
1835
		}
1836
	}
1837
	
1838
	
1839
	/**
1840
	 * Browser feature detection for capabilities, quirks
1841
	 *  @param {object} settings dataTables settings object
1842
	 *  @memberof DataTable#oApi
1843
	 */
1844
	function _fnBrowserDetect( settings )
1845
	{
1846
		// We don't need to do this every time DataTables is constructed, the values
1847
		// calculated are specific to the browser and OS configuration which we
1848
		// don't expect to change between initialisations
1849
		if ( ! DataTable.__browser ) {
1850
			var browser = {};
1851
			DataTable.__browser = browser;
1852
	
1853
			// Scrolling feature / quirks detection
1854
			var n = $('<div/>')
1855
				.css( {
1856
					position: 'fixed',
1857
					top: 0,
1858
					left: $(window).scrollLeft()*-1, // allow for scrolling
1859
					height: 1,
1860
					width: 1,
1861
					overflow: 'hidden'
1862
				} )
1863
				.append(
1864
					$('<div/>')
1865
						.css( {
1866
							position: 'absolute',
1867
							top: 1,
1868
							left: 1,
1869
							width: 100,
1870
							overflow: 'scroll'
1871
						} )
1872
						.append(
1873
							$('<div/>')
1874
								.css( {
1875
									width: '100%',
1876
									height: 10
1877
								} )
1878
						)
1879
				)
1880
				.appendTo( 'body' );
1881
	
1882
			var outer = n.children();
1883
			var inner = outer.children();
1884
	
1885
			// Numbers below, in order, are:
1886
			// inner.offsetWidth, inner.clientWidth, outer.offsetWidth, outer.clientWidth
1887
			//
1888
			// IE6 XP:                           100 100 100  83
1889
			// IE7 Vista:                        100 100 100  83
1890
			// IE 8+ Windows:                     83  83 100  83
1891
			// Evergreen Windows:                 83  83 100  83
1892
			// Evergreen Mac with scrollbars:     85  85 100  85
1893
			// Evergreen Mac without scrollbars: 100 100 100 100
1894
	
1895
			// Get scrollbar width
1896
			browser.barWidth = outer[0].offsetWidth - outer[0].clientWidth;
1897
	
1898
			// IE6/7 will oversize a width 100% element inside a scrolling element, to
1899
			// include the width of the scrollbar, while other browsers ensure the inner
1900
			// element is contained without forcing scrolling
1901
			browser.bScrollOversize = inner[0].offsetWidth === 100 && outer[0].clientWidth !== 100;
1902
	
1903
			// In rtl text layout, some browsers (most, but not all) will place the
1904
			// scrollbar on the left, rather than the right.
1905
			browser.bScrollbarLeft = Math.round( inner.offset().left ) !== 1;
1906
	
1907
			// IE8- don't provide height and width for getBoundingClientRect
1908
			browser.bBounding = n[0].getBoundingClientRect().width ? true : false;
1909
	
1910
			n.remove();
1911
		}
1912
	
1913
		$.extend( settings.oBrowser, DataTable.__browser );
1914
		settings.oScroll.iBarWidth = DataTable.__browser.barWidth;
1915
	}
1916
	
1917
	
1918
	/**
1919
	 * Array.prototype reduce[Right] method, used for browsers which don't support
1920
	 * JS 1.6. Done this way to reduce code size, since we iterate either way
1921
	 *  @param {object} settings dataTables settings object
1922
	 *  @memberof DataTable#oApi
1923
	 */
1924
	function _fnReduce ( that, fn, init, start, end, inc )
1925
	{
1926
		var
1927
			i = start,
1928
			value,
1929
			isSet = false;
1930
	
1931
		if ( init !== undefined ) {
1932
			value = init;
1933
			isSet = true;
1934
		}
1935
	
1936
		while ( i !== end ) {
1937
			if ( ! that.hasOwnProperty(i) ) {
1938
				continue;
1939
			}
1940
	
1941
			value = isSet ?
1942
				fn( value, that[i], i, that ) :
0 ignored issues
show
Bug introduced by
The variable value does not seem to be initialized in case init !== undefined on line 1931 is false. Are you sure the function fn handles undefined variables?
Loading history...
1943
				that[i];
1944
	
1945
			isSet = true;
1946
			i += inc;
1947
		}
1948
	
1949
		return value;
1950
	}
1951
	
1952
	/**
1953
	 * Add a column to the list used for the table with default values
1954
	 *  @param {object} oSettings dataTables settings object
1955
	 *  @param {node} nTh The th element for this column
1956
	 *  @memberof DataTable#oApi
1957
	 */
1958
	function _fnAddColumn( oSettings, nTh )
1959
	{
1960
		// Add column to aoColumns array
1961
		var oDefaults = DataTable.defaults.column;
1962
		var iCol = oSettings.aoColumns.length;
1963
		var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {
1964
			"nTh": nTh ? nTh : document.createElement('th'),
1965
			"sTitle":    oDefaults.sTitle    ? oDefaults.sTitle    : nTh ? nTh.innerHTML : '',
1966
			"aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],
1967
			"mData": oDefaults.mData ? oDefaults.mData : iCol,
1968
			idx: iCol
1969
		} );
1970
		oSettings.aoColumns.push( oCol );
1971
	
1972
		// Add search object for column specific search. Note that the `searchCols[ iCol ]`
1973
		// passed into extend can be undefined. This allows the user to give a default
1974
		// with only some of the parameters defined, and also not give a default
1975
		var searchCols = oSettings.aoPreSearchCols;
1976
		searchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] );
1977
	
1978
		// Use the default column options function to initialise classes etc
1979
		_fnColumnOptions( oSettings, iCol, $(nTh).data() );
1980
	}
1981
	
1982
	
1983
	/**
1984
	 * Apply options for a column
1985
	 *  @param {object} oSettings dataTables settings object
1986
	 *  @param {int} iCol column index to consider
1987
	 *  @param {object} oOptions object with sType, bVisible and bSearchable etc
1988
	 *  @memberof DataTable#oApi
1989
	 */
1990
	function _fnColumnOptions( oSettings, iCol, oOptions )
1991
	{
1992
		var oCol = oSettings.aoColumns[ iCol ];
1993
		var oClasses = oSettings.oClasses;
1994
		var th = $(oCol.nTh);
1995
	
1996
		// Try to get width information from the DOM. We can't get it from CSS
1997
		// as we'd need to parse the CSS stylesheet. `width` option can override
1998
		if ( ! oCol.sWidthOrig ) {
1999
			// Width attribute
2000
			oCol.sWidthOrig = th.attr('width') || null;
2001
	
2002
			// Style attribute
2003
			var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/);
2004
			if ( t ) {
2005
				oCol.sWidthOrig = t[1];
2006
			}
2007
		}
2008
	
2009
		/* User specified column options */
2010
		if ( oOptions !== undefined && oOptions !== null )
2011
		{
2012
			// Backwards compatibility
2013
			_fnCompatCols( oOptions );
2014
	
2015
			// Map camel case parameters to their Hungarian counterparts
2016
			_fnCamelToHungarian( DataTable.defaults.column, oOptions );
2017
	
2018
			/* Backwards compatibility for mDataProp */
2019
			if ( oOptions.mDataProp !== undefined && !oOptions.mData )
2020
			{
2021
				oOptions.mData = oOptions.mDataProp;
2022
			}
2023
	
2024
			if ( oOptions.sType )
2025
			{
2026
				oCol._sManualType = oOptions.sType;
2027
			}
2028
	
2029
			// `class` is a reserved word in Javascript, so we need to provide
2030
			// the ability to use a valid name for the camel case input
2031
			if ( oOptions.className && ! oOptions.sClass )
2032
			{
2033
				oOptions.sClass = oOptions.className;
2034
			}
2035
			if ( oOptions.sClass ) {
2036
				th.addClass( oOptions.sClass );
2037
			}
2038
	
2039
			$.extend( oCol, oOptions );
2040
			_fnMap( oCol, oOptions, "sWidth", "sWidthOrig" );
2041
	
2042
			/* iDataSort to be applied (backwards compatibility), but aDataSort will take
2043
			 * priority if defined
2044
			 */
2045
			if ( oOptions.iDataSort !== undefined )
2046
			{
2047
				oCol.aDataSort = [ oOptions.iDataSort ];
2048
			}
2049
			_fnMap( oCol, oOptions, "aDataSort" );
2050
		}
2051
	
2052
		/* Cache the data get and set functions for speed */
2053
		var mDataSrc = oCol.mData;
2054
		var mData = _fnGetObjectDataFn( mDataSrc );
2055
		var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null;
2056
	
2057
		var attrTest = function( src ) {
2058
			return typeof src === 'string' && src.indexOf('@') !== -1;
2059
		};
2060
		oCol._bAttrSrc = $.isPlainObject( mDataSrc ) && (
2061
			attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter)
2062
		);
2063
		oCol._setter = null;
2064
	
2065
		oCol.fnGetData = function (rowData, type, meta) {
2066
			var innerData = mData( rowData, type, undefined, meta );
2067
	
2068
			return mRender && type ?
2069
				mRender( innerData, type, rowData, meta ) :
2070
				innerData;
2071
		};
2072
		oCol.fnSetData = function ( rowData, val, meta ) {
2073
			return _fnSetObjectDataFn( mDataSrc )( rowData, val, meta );
2074
		};
2075
	
2076
		// Indicate if DataTables should read DOM data as an object or array
2077
		// Used in _fnGetRowElements
2078
		if ( typeof mDataSrc !== 'number' ) {
2079
			oSettings._rowReadObject = true;
2080
		}
2081
	
2082
		/* Feature sorting overrides column specific when off */
2083
		if ( !oSettings.oFeatures.bSort )
2084
		{
2085
			oCol.bSortable = false;
2086
			th.addClass( oClasses.sSortableNone ); // Have to add class here as order event isn't called
2087
		}
2088
	
2089
		/* Check that the class assignment is correct for sorting */
2090
		var bAsc = $.inArray('asc', oCol.asSorting) !== -1;
2091
		var bDesc = $.inArray('desc', oCol.asSorting) !== -1;
2092
		if ( !oCol.bSortable || (!bAsc && !bDesc) )
2093
		{
2094
			oCol.sSortingClass = oClasses.sSortableNone;
2095
			oCol.sSortingClassJUI = "";
2096
		}
2097
		else if ( bAsc && !bDesc )
2098
		{
2099
			oCol.sSortingClass = oClasses.sSortableAsc;
2100
			oCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed;
2101
		}
2102
		else if ( !bAsc && bDesc )
2103
		{
2104
			oCol.sSortingClass = oClasses.sSortableDesc;
2105
			oCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed;
2106
		}
2107
		else
2108
		{
2109
			oCol.sSortingClass = oClasses.sSortable;
2110
			oCol.sSortingClassJUI = oClasses.sSortJUI;
2111
		}
2112
	}
2113
	
2114
	
2115
	/**
2116
	 * Adjust the table column widths for new data. Note: you would probably want to
2117
	 * do a redraw after calling this function!
2118
	 *  @param {object} settings dataTables settings object
2119
	 *  @memberof DataTable#oApi
2120
	 */
2121
	function _fnAdjustColumnSizing ( settings )
2122
	{
2123
		/* Not interested in doing column width calculation if auto-width is disabled */
2124
		if ( settings.oFeatures.bAutoWidth !== false )
2125
		{
2126
			var columns = settings.aoColumns;
2127
	
2128
			_fnCalculateColumnWidths( settings );
2129
			for ( var i=0 , iLen=columns.length ; i<iLen ; i++ )
2130
			{
2131
				columns[i].nTh.style.width = columns[i].sWidth;
2132
			}
2133
		}
2134
	
2135
		var scroll = settings.oScroll;
2136
		if ( scroll.sY !== '' || scroll.sX !== '')
2137
		{
2138
			_fnScrollDraw( settings );
2139
		}
2140
	
2141
		_fnCallbackFire( settings, null, 'column-sizing', [settings] );
2142
	}
2143
	
2144
	
2145
	/**
2146
	 * Covert the index of a visible column to the index in the data array (take account
2147
	 * of hidden columns)
2148
	 *  @param {object} oSettings dataTables settings object
2149
	 *  @param {int} iMatch Visible column index to lookup
2150
	 *  @returns {int} i the data index
2151
	 *  @memberof DataTable#oApi
2152
	 */
2153
	function _fnVisibleToColumnIndex( oSettings, iMatch )
2154
	{
2155
		var aiVis = _fnGetColumns( oSettings, 'bVisible' );
2156
	
2157
		return typeof aiVis[iMatch] === 'number' ?
2158
			aiVis[iMatch] :
2159
			null;
2160
	}
2161
	
2162
	
2163
	/**
2164
	 * Covert the index of an index in the data array and convert it to the visible
2165
	 *   column index (take account of hidden columns)
2166
	 *  @param {int} iMatch Column index to lookup
2167
	 *  @param {object} oSettings dataTables settings object
2168
	 *  @returns {int} i the data index
2169
	 *  @memberof DataTable#oApi
2170
	 */
2171
	function _fnColumnIndexToVisible( oSettings, iMatch )
2172
	{
2173
		var aiVis = _fnGetColumns( oSettings, 'bVisible' );
2174
		var iPos = $.inArray( iMatch, aiVis );
2175
	
2176
		return iPos !== -1 ? iPos : null;
2177
	}
2178
	
2179
	
2180
	/**
2181
	 * Get the number of visible columns
2182
	 *  @param {object} oSettings dataTables settings object
2183
	 *  @returns {int} i the number of visible columns
2184
	 *  @memberof DataTable#oApi
2185
	 */
2186
	function _fnVisbleColumns( oSettings )
2187
	{
2188
		var vis = 0;
2189
	
2190
		// No reduce in IE8, use a loop for now
2191
		$.each( oSettings.aoColumns, function ( i, col ) {
2192
			if ( col.bVisible && $(col.nTh).css('display') !== 'none' ) {
2193
				vis++;
2194
			}
2195
		} );
2196
	
2197
		return vis;
2198
	}
2199
	
2200
	
2201
	/**
2202
	 * Get an array of column indexes that match a given property
2203
	 *  @param {object} oSettings dataTables settings object
2204
	 *  @param {string} sParam Parameter in aoColumns to look for - typically
2205
	 *    bVisible or bSearchable
2206
	 *  @returns {array} Array of indexes with matched properties
2207
	 *  @memberof DataTable#oApi
2208
	 */
2209
	function _fnGetColumns( oSettings, sParam )
2210
	{
2211
		var a = [];
2212
	
2213
		$.map( oSettings.aoColumns, function(val, i) {
2214
			if ( val[sParam] ) {
2215
				a.push( i );
2216
			}
2217
		} );
2218
	
2219
		return a;
2220
	}
2221
	
2222
	
2223
	/**
2224
	 * Calculate the 'type' of a column
2225
	 *  @param {object} settings dataTables settings object
2226
	 *  @memberof DataTable#oApi
2227
	 */
2228
	function _fnColumnTypes ( settings )
2229
	{
2230
		var columns = settings.aoColumns;
2231
		var data = settings.aoData;
2232
		var types = DataTable.ext.type.detect;
2233
		var i, ien, j, jen, k, ken;
2234
		var col, cell, detectedType, cache;
0 ignored issues
show
Unused Code introduced by
The variable cell seems to be never used. Consider removing it.
Loading history...
2235
	
2236
		// For each column, spin over the 
2237
		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
2238
			col = columns[i];
2239
			cache = [];
2240
	
2241
			if ( ! col.sType && col._sManualType ) {
2242
				col.sType = col._sManualType;
2243
			}
2244
			else if ( ! col.sType ) {
2245
				for ( j=0, jen=types.length ; j<jen ; j++ ) {
2246
					for ( k=0, ken=data.length ; k<ken ; k++ ) {
2247
						// Use a cache array so we only need to get the type data
2248
						// from the formatter once (when using multiple detectors)
2249
						if ( cache[k] === undefined ) {
2250
							cache[k] = _fnGetCellData( settings, k, i, 'type' );
2251
						}
2252
	
2253
						detectedType = types[j]( cache[k], settings );
2254
	
2255
						// If null, then this type can't apply to this column, so
2256
						// rather than testing all cells, break out. There is an
2257
						// exception for the last type which is `html`. We need to
2258
						// scan all rows since it is possible to mix string and HTML
2259
						// types
2260
						if ( ! detectedType && j !== types.length-1 ) {
2261
							break;
2262
						}
2263
	
2264
						// Only a single match is needed for html type since it is
2265
						// bottom of the pile and very similar to string
2266
						if ( detectedType === 'html' ) {
2267
							break;
2268
						}
2269
					}
2270
	
2271
					// Type is valid for all data points in the column - use this
2272
					// type
2273
					if ( detectedType ) {
2274
						col.sType = detectedType;
2275
						break;
2276
					}
2277
				}
2278
	
2279
				// Fall back - if no type was detected, always use string
2280
				if ( ! col.sType ) {
2281
					col.sType = 'string';
2282
				}
2283
			}
2284
		}
2285
	}
2286
	
2287
	
2288
	/**
2289
	 * Take the column definitions and static columns arrays and calculate how
2290
	 * they relate to column indexes. The callback function will then apply the
2291
	 * definition found for a column to a suitable configuration object.
2292
	 *  @param {object} oSettings dataTables settings object
2293
	 *  @param {array} aoColDefs The aoColumnDefs array that is to be applied
2294
	 *  @param {array} aoCols The aoColumns array that defines columns individually
2295
	 *  @param {function} fn Callback function - takes two parameters, the calculated
2296
	 *    column index and the definition for that column.
2297
	 *  @memberof DataTable#oApi
2298
	 */
2299
	function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )
2300
	{
2301
		var i, iLen, j, jLen, k, kLen, def;
2302
		var columns = oSettings.aoColumns;
2303
	
2304
		// Column definitions with aTargets
2305
		if ( aoColDefs )
2306
		{
2307
			/* Loop over the definitions array - loop in reverse so first instance has priority */
2308
			for ( i=aoColDefs.length-1 ; i>=0 ; i-- )
2309
			{
2310
				def = aoColDefs[i];
2311
	
2312
				/* Each definition can target multiple columns, as it is an array */
2313
				var aTargets = def.targets !== undefined ?
2314
					def.targets :
2315
					def.aTargets;
2316
	
2317
				if ( ! $.isArray( aTargets ) )
2318
				{
2319
					aTargets = [ aTargets ];
2320
				}
2321
	
2322
				for ( j=0, jLen=aTargets.length ; j<jLen ; j++ )
2323
				{
2324
					if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 )
2325
					{
2326
						/* Add columns that we don't yet know about */
2327
						while( columns.length <= aTargets[j] )
2328
						{
2329
							_fnAddColumn( oSettings );
2330
						}
2331
	
2332
						/* Integer, basic index */
2333
						fn( aTargets[j], def );
2334
					}
2335
					else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 )
2336
					{
2337
						/* Negative integer, right to left column counting */
2338
						fn( columns.length+aTargets[j], def );
2339
					}
2340
					else if ( typeof aTargets[j] === 'string' )
2341
					{
2342
						/* Class name matching on TH element */
2343
						for ( k=0, kLen=columns.length ; k<kLen ; k++ )
2344
						{
2345
							if ( aTargets[j] == "_all" ||
2346
							     $(columns[k].nTh).hasClass( aTargets[j] ) )
2347
							{
2348
								fn( k, def );
2349
							}
2350
						}
2351
					}
2352
				}
2353
			}
2354
		}
2355
	
2356
		// Statically defined columns array
2357
		if ( aoCols )
2358
		{
2359
			for ( i=0, iLen=aoCols.length ; i<iLen ; i++ )
2360
			{
2361
				fn( i, aoCols[i] );
2362
			}
2363
		}
2364
	}
2365
	
2366
	/**
2367
	 * Add a data array to the table, creating DOM node etc. This is the parallel to
2368
	 * _fnGatherData, but for adding rows from a Javascript source, rather than a
2369
	 * DOM source.
2370
	 *  @param {object} oSettings dataTables settings object
2371
	 *  @param {array} aData data array to be added
2372
	 *  @param {node} [nTr] TR element to add to the table - optional. If not given,
2373
	 *    DataTables will create a row automatically
2374
	 *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
2375
	 *    if nTr is.
2376
	 *  @returns {int} >=0 if successful (index of new aoData entry), -1 if failed
2377
	 *  @memberof DataTable#oApi
2378
	 */
2379
	function _fnAddData ( oSettings, aDataIn, nTr, anTds )
2380
	{
2381
		/* Create the object for storing information about this new row */
2382
		var iRow = oSettings.aoData.length;
2383
		var oData = $.extend( true, {}, DataTable.models.oRow, {
2384
			src: nTr ? 'dom' : 'data',
2385
			idx: iRow
2386
		} );
2387
	
2388
		oData._aData = aDataIn;
2389
		oSettings.aoData.push( oData );
2390
	
2391
		/* Create the cells */
2392
		var nTd, sThisType;
0 ignored issues
show
Unused Code introduced by
The variable sThisType seems to be never used. Consider removing it.
Loading history...
Unused Code introduced by
The variable nTd seems to be never used. Consider removing it.
Loading history...
2393
		var columns = oSettings.aoColumns;
2394
	
2395
		// Invalidate the column types as the new data needs to be revalidated
2396
		for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
2397
		{
2398
			columns[i].sType = null;
2399
		}
2400
	
2401
		/* Add to the display array */
2402
		oSettings.aiDisplayMaster.push( iRow );
2403
	
2404
		var id = oSettings.rowIdFn( aDataIn );
2405
		if ( id !== undefined ) {
2406
			oSettings.aIds[ id ] = oData;
2407
		}
2408
	
2409
		/* Create the DOM information, or register it if already present */
2410
		if ( nTr || ! oSettings.oFeatures.bDeferRender )
2411
		{
2412
			_fnCreateTr( oSettings, iRow, nTr, anTds );
2413
		}
2414
	
2415
		return iRow;
2416
	}
2417
	
2418
	
2419
	/**
2420
	 * Add one or more TR elements to the table. Generally we'd expect to
2421
	 * use this for reading data from a DOM sourced table, but it could be
2422
	 * used for an TR element. Note that if a TR is given, it is used (i.e.
2423
	 * it is not cloned).
2424
	 *  @param {object} settings dataTables settings object
2425
	 *  @param {array|node|jQuery} trs The TR element(s) to add to the table
2426
	 *  @returns {array} Array of indexes for the added rows
2427
	 *  @memberof DataTable#oApi
2428
	 */
2429
	function _fnAddTr( settings, trs )
2430
	{
2431
		var row;
2432
	
2433
		// Allow an individual node to be passed in
2434
		if ( ! (trs instanceof $) ) {
2435
			trs = $(trs);
2436
		}
2437
	
2438
		return trs.map( function (i, el) {
2439
			row = _fnGetRowElements( settings, el );
2440
			return _fnAddData( settings, row.data, el, row.cells );
2441
		} );
2442
	}
2443
	
2444
	
2445
	/**
2446
	 * Take a TR element and convert it to an index in aoData
2447
	 *  @param {object} oSettings dataTables settings object
2448
	 *  @param {node} n the TR element to find
2449
	 *  @returns {int} index if the node is found, null if not
2450
	 *  @memberof DataTable#oApi
2451
	 */
2452
	function _fnNodeToDataIndex( oSettings, n )
2453
	{
2454
		return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null;
2455
	}
2456
	
2457
	
2458
	/**
2459
	 * Take a TD element and convert it into a column data index (not the visible index)
2460
	 *  @param {object} oSettings dataTables settings object
2461
	 *  @param {int} iRow The row number the TD/TH can be found in
2462
	 *  @param {node} n The TD/TH element to find
2463
	 *  @returns {int} index if the node is found, -1 if not
2464
	 *  @memberof DataTable#oApi
2465
	 */
2466
	function _fnNodeToColumnIndex( oSettings, iRow, n )
2467
	{
2468
		return $.inArray( n, oSettings.aoData[ iRow ].anCells );
2469
	}
2470
	
2471
	
2472
	/**
2473
	 * Get the data for a given cell from the internal cache, taking into account data mapping
2474
	 *  @param {object} settings dataTables settings object
2475
	 *  @param {int} rowIdx aoData row id
2476
	 *  @param {int} colIdx Column index
2477
	 *  @param {string} type data get type ('display', 'type' 'filter' 'sort')
2478
	 *  @returns {*} Cell data
2479
	 *  @memberof DataTable#oApi
2480
	 */
2481
	function _fnGetCellData( settings, rowIdx, colIdx, type )
2482
	{
2483
		var draw           = settings.iDraw;
2484
		var col            = settings.aoColumns[colIdx];
2485
		var rowData        = settings.aoData[rowIdx]._aData;
2486
		var defaultContent = col.sDefaultContent;
2487
		var cellData       = col.fnGetData( rowData, type, {
2488
			settings: settings,
2489
			row:      rowIdx,
2490
			col:      colIdx
2491
		} );
2492
	
2493
		if ( cellData === undefined ) {
2494
			if ( settings.iDrawError != draw && defaultContent === null ) {
2495
				_fnLog( settings, 0, "Requested unknown parameter "+
2496
					(typeof col.mData=='function' ? '{function}' : "'"+col.mData+"'")+
2497
					" for row "+rowIdx+", column "+colIdx, 4 );
2498
				settings.iDrawError = draw;
2499
			}
2500
			return defaultContent;
2501
		}
2502
	
2503
		// When the data source is null and a specific data type is requested (i.e.
2504
		// not the original data), we can use default column data
2505
		if ( (cellData === rowData || cellData === null) && defaultContent !== null && type !== undefined ) {
2506
			cellData = defaultContent;
2507
		}
2508
		else if ( typeof cellData === 'function' ) {
2509
			// If the data source is a function, then we run it and use the return,
2510
			// executing in the scope of the data object (for instances)
2511
			return cellData.call( rowData );
2512
		}
2513
	
2514
		if ( cellData === null && type == 'display' ) {
2515
			return '';
2516
		}
2517
		return cellData;
2518
	}
2519
	
2520
	
2521
	/**
2522
	 * Set the value for a specific cell, into the internal data cache
2523
	 *  @param {object} settings dataTables settings object
2524
	 *  @param {int} rowIdx aoData row id
2525
	 *  @param {int} colIdx Column index
2526
	 *  @param {*} val Value to set
2527
	 *  @memberof DataTable#oApi
2528
	 */
2529
	function _fnSetCellData( settings, rowIdx, colIdx, val )
2530
	{
2531
		var col     = settings.aoColumns[colIdx];
2532
		var rowData = settings.aoData[rowIdx]._aData;
2533
	
2534
		col.fnSetData( rowData, val, {
2535
			settings: settings,
2536
			row:      rowIdx,
2537
			col:      colIdx
2538
		}  );
2539
	}
2540
	
2541
	
2542
	// Private variable that is used to match action syntax in the data property object
2543
	var __reArray = /\[.*?\]$/;
2544
	var __reFn = /\(\)$/;
2545
	
2546
	/**
2547
	 * Split string on periods, taking into account escaped periods
2548
	 * @param  {string} str String to split
2549
	 * @return {array} Split string
2550
	 */
2551
	function _fnSplitObjNotation( str )
2552
	{
2553
		return $.map( str.match(/(\\.|[^\.])+/g) || [''], function ( s ) {
2554
			return s.replace(/\\\./g, '.');
2555
		} );
2556
	}
2557
	
2558
	
2559
	/**
2560
	 * Return a function that can be used to get data from a source object, taking
2561
	 * into account the ability to use nested objects as a source
2562
	 *  @param {string|int|function} mSource The data source for the object
2563
	 *  @returns {function} Data get function
2564
	 *  @memberof DataTable#oApi
2565
	 */
2566
	function _fnGetObjectDataFn( mSource )
2567
	{
2568
		if ( $.isPlainObject( mSource ) )
2569
		{
2570
			/* Build an object of get functions, and wrap them in a single call */
2571
			var o = {};
2572
			$.each( mSource, function (key, val) {
2573
				if ( val ) {
2574
					o[key] = _fnGetObjectDataFn( val );
2575
				}
2576
			} );
2577
	
2578
			return function (data, type, row, meta) {
2579
				var t = o[type] || o._;
2580
				return t !== undefined ?
2581
					t(data, type, row, meta) :
2582
					data;
2583
			};
2584
		}
2585 View Code Duplication
		else if ( mSource === null )
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
2586
		{
2587
			/* Give an empty string for rendering / sorting etc */
2588
			return function (data) { // type, row and meta also passed, but not used
2589
				return data;
2590
			};
2591
		}
2592
		else if ( typeof mSource === 'function' )
2593
		{
2594
			return function (data, type, row, meta) {
2595
				return mSource( data, type, row, meta );
2596
			};
2597
		}
2598
		else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
2599
			      mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
2600
		{
2601
			/* If there is a . in the source string then the data source is in a
2602
			 * nested object so we loop over the data for each level to get the next
2603
			 * level down. On each loop we test for undefined, and if found immediately
2604
			 * return. This allows entire objects to be missing and sDefaultContent to
2605
			 * be used if defined, rather than throwing an error
2606
			 */
2607
			var fetchData = function (data, type, src) {
2608
				var arrayNotation, funcNotation, out, innerSrc;
2609
	
2610
				if ( src !== "" )
2611
				{
2612
					var a = _fnSplitObjNotation( src );
2613
	
2614
					for ( var i=0, iLen=a.length ; i<iLen ; i++ )
2615
					{
2616
						// Check if we are dealing with special notation
2617
						arrayNotation = a[i].match(__reArray);
2618
						funcNotation = a[i].match(__reFn);
2619
	
2620
						if ( arrayNotation )
2621
						{
2622
							// Array notation
2623
							a[i] = a[i].replace(__reArray, '');
2624
	
2625
							// Condition allows simply [] to be passed in
2626
							if ( a[i] !== "" ) {
2627
								data = data[ a[i] ];
2628
							}
2629
							out = [];
2630
	
2631
							// Get the remainder of the nested object to get
2632
							a.splice( 0, i+1 );
2633
							innerSrc = a.join('.');
2634
	
2635
							// Traverse each entry in the array getting the properties requested
2636
							if ( $.isArray( data ) ) {
2637
								for ( var j=0, jLen=data.length ; j<jLen ; j++ ) {
2638
									out.push( fetchData( data[j], type, innerSrc ) );
2639
								}
2640
							}
2641
	
2642
							// If a string is given in between the array notation indicators, that
2643
							// is used to join the strings together, otherwise an array is returned
2644
							var join = arrayNotation[0].substring(1, arrayNotation[0].length-1);
2645
							data = (join==="") ? out : out.join(join);
2646
	
2647
							// The inner call to fetchData has already traversed through the remainder
2648
							// of the source requested, so we exit from the loop
2649
							break;
2650
						}
2651
						else if ( funcNotation )
2652
						{
2653
							// Function call
2654
							a[i] = a[i].replace(__reFn, '');
2655
							data = data[ a[i] ]();
2656
							continue;
2657
						}
2658
	
2659
						if ( data === null || data[ a[i] ] === undefined )
2660
						{
2661
							return undefined;
2662
						}
2663
						data = data[ a[i] ];
2664
					}
2665
				}
2666
	
2667
				return data;
2668
			};
2669
	
2670
			return function (data, type) { // row and meta also passed, but not used
2671
				return fetchData( data, type, mSource );
2672
			};
2673
		}
2674
		else
2675
		{
2676
			/* Array or flat object mapping */
2677
			return function (data, type) { // row and meta also passed, but not used
0 ignored issues
show
Unused Code introduced by
The parameter type is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
2678
				return data[mSource];
2679
			};
2680
		}
2681
	}
2682
	
2683
	
2684
	/**
2685
	 * Return a function that can be used to set data from a source object, taking
2686
	 * into account the ability to use nested objects as a source
2687
	 *  @param {string|int|function} mSource The data source for the object
2688
	 *  @returns {function} Data set function
2689
	 *  @memberof DataTable#oApi
2690
	 */
2691
	function _fnSetObjectDataFn( mSource )
2692
	{
2693 View Code Duplication
		if ( $.isPlainObject( mSource ) )
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
2694
		{
2695
			/* Unlike get, only the underscore (global) option is used for for
2696
			 * setting data since we don't know the type here. This is why an object
2697
			 * option is not documented for `mData` (which is read/write), but it is
2698
			 * for `mRender` which is read only.
2699
			 */
2700
			return _fnSetObjectDataFn( mSource._ );
2701
		}
2702
		else if ( mSource === null )
2703
		{
2704
			/* Nothing to do when the data source is null */
2705
			return function () {};
2706
		}
2707
		else if ( typeof mSource === 'function' )
2708
		{
2709
			return function (data, val, meta) {
2710
				mSource( data, 'set', val, meta );
2711
			};
2712
		}
2713
		else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
2714
			      mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
2715
		{
2716
			/* Like the get, we need to get data from a nested object */
2717
			var setData = function (data, val, src) {
2718
				var a = _fnSplitObjNotation( src ), b;
2719
				var aLast = a[a.length-1];
2720
				var arrayNotation, funcNotation, o, innerSrc;
2721
	
2722
				for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ )
2723
				{
2724
					// Check if we are dealing with an array notation request
2725
					arrayNotation = a[i].match(__reArray);
2726
					funcNotation = a[i].match(__reFn);
2727
	
2728
					if ( arrayNotation )
2729
					{
2730
						a[i] = a[i].replace(__reArray, '');
2731
						data[ a[i] ] = [];
2732
	
2733
						// Get the remainder of the nested object to set so we can recurse
2734
						b = a.slice();
2735
						b.splice( 0, i+1 );
2736
						innerSrc = b.join('.');
2737
	
2738
						// Traverse each entry in the array setting the properties requested
2739
						if ( $.isArray( val ) )
2740
						{
2741
							for ( var j=0, jLen=val.length ; j<jLen ; j++ )
2742
							{
2743
								o = {};
2744
								setData( o, val[j], innerSrc );
2745
								data[ a[i] ].push( o );
2746
							}
2747
						}
2748
						else
2749
						{
2750
							// We've been asked to save data to an array, but it
2751
							// isn't array data to be saved. Best that can be done
2752
							// is to just save the value.
2753
							data[ a[i] ] = val;
2754
						}
2755
	
2756
						// The inner call to setData has already traversed through the remainder
2757
						// of the source and has set the data, thus we can exit here
2758
						return;
2759
					}
2760
					else if ( funcNotation )
2761
					{
2762
						// Function call
2763
						a[i] = a[i].replace(__reFn, '');
2764
						data = data[ a[i] ]( val );
2765
					}
2766
	
2767
					// If the nested object doesn't currently exist - since we are
2768
					// trying to set the value - create it
2769
					if ( data[ a[i] ] === null || data[ a[i] ] === undefined )
2770
					{
2771
						data[ a[i] ] = {};
2772
					}
2773
					data = data[ a[i] ];
2774
				}
2775
	
2776
				// Last item in the input - i.e, the actual set
2777
				if ( aLast.match(__reFn ) )
2778
				{
2779
					// Function call
2780
					data = data[ aLast.replace(__reFn, '') ]( val );
0 ignored issues
show
Unused Code introduced by
The assignment to variable data seems to be never used. Consider removing it.
Loading history...
2781
				}
2782
				else
2783
				{
2784
					// If array notation is used, we just want to strip it and use the property name
2785
					// and assign the value. If it isn't used, then we get the result we want anyway
2786
					data[ aLast.replace(__reArray, '') ] = val;
2787
				}
2788
			};
2789
	
2790
			return function (data, val) { // meta is also passed in, but not used
2791
				return setData( data, val, mSource );
2792
			};
2793
		}
2794
		else
2795
		{
2796
			/* Array or flat object mapping */
2797
			return function (data, val) { // meta is also passed in, but not used
2798
				data[mSource] = val;
2799
			};
2800
		}
2801
	}
2802
	
2803
	
2804
	/**
2805
	 * Return an array with the full table data
2806
	 *  @param {object} oSettings dataTables settings object
2807
	 *  @returns array {array} aData Master data array
2808
	 *  @memberof DataTable#oApi
2809
	 */
2810
	function _fnGetDataMaster ( settings )
2811
	{
2812
		return _pluck( settings.aoData, '_aData' );
2813
	}
2814
	
2815
	
2816
	/**
2817
	 * Nuke the table
2818
	 *  @param {object} oSettings dataTables settings object
2819
	 *  @memberof DataTable#oApi
2820
	 */
2821
	function _fnClearTable( settings )
2822
	{
2823
		settings.aoData.length = 0;
2824
		settings.aiDisplayMaster.length = 0;
2825
		settings.aiDisplay.length = 0;
2826
		settings.aIds = {};
2827
	}
2828
	
2829
	
2830
	 /**
2831
	 * Take an array of integers (index array) and remove a target integer (value - not
2832
	 * the key!)
2833
	 *  @param {array} a Index array to target
2834
	 *  @param {int} iTarget value to find
2835
	 *  @memberof DataTable#oApi
2836
	 */
2837
	function _fnDeleteIndex( a, iTarget, splice )
2838
	{
2839
		var iTargetIndex = -1;
2840
	
2841
		for ( var i=0, iLen=a.length ; i<iLen ; i++ )
2842
		{
2843
			if ( a[i] == iTarget )
2844
			{
2845
				iTargetIndex = i;
2846
			}
2847
			else if ( a[i] > iTarget )
2848
			{
2849
				a[i]--;
2850
			}
2851
		}
2852
	
2853
		if ( iTargetIndex != -1 && splice === undefined )
2854
		{
2855
			a.splice( iTargetIndex, 1 );
2856
		}
2857
	}
2858
	
2859
	
2860
	/**
2861
	 * Mark cached data as invalid such that a re-read of the data will occur when
2862
	 * the cached data is next requested. Also update from the data source object.
2863
	 *
2864
	 * @param {object} settings DataTables settings object
2865
	 * @param {int}    rowIdx   Row index to invalidate
2866
	 * @param {string} [src]    Source to invalidate from: undefined, 'auto', 'dom'
2867
	 *     or 'data'
2868
	 * @param {int}    [colIdx] Column index to invalidate. If undefined the whole
2869
	 *     row will be invalidated
2870
	 * @memberof DataTable#oApi
2871
	 *
2872
	 * @todo For the modularisation of v1.11 this will need to become a callback, so
2873
	 *   the sort and filter methods can subscribe to it. That will required
2874
	 *   initialisation options for sorting, which is why it is not already baked in
2875
	 */
2876
	function _fnInvalidate( settings, rowIdx, src, colIdx )
2877
	{
2878
		var row = settings.aoData[ rowIdx ];
2879
		var i, ien;
2880
		var cellWrite = function ( cell, col ) {
2881
			// This is very frustrating, but in IE if you just write directly
2882
			// to innerHTML, and elements that are overwritten are GC'ed,
2883
			// even if there is a reference to them elsewhere
2884
			while ( cell.childNodes.length ) {
2885
				cell.removeChild( cell.firstChild );
2886
			}
2887
	
2888
			cell.innerHTML = _fnGetCellData( settings, rowIdx, col, 'display' );
2889
		};
2890
	
2891
		// Are we reading last data from DOM or the data object?
2892
		if ( src === 'dom' || ((! src || src === 'auto') && row.src === 'dom') ) {
2893
			// Read the data from the DOM
2894
			row._aData = _fnGetRowElements(
2895
					settings, row, colIdx, colIdx === undefined ? undefined : row._aData
2896
				)
2897
				.data;
2898
		}
2899
		else {
2900
			// Reading from data object, update the DOM
2901
			var cells = row.anCells;
2902
	
2903
			if ( cells ) {
2904
				if ( colIdx !== undefined ) {
2905
					cellWrite( cells[colIdx], colIdx );
2906
				}
2907
				else {
2908
					for ( i=0, ien=cells.length ; i<ien ; i++ ) {
2909
						cellWrite( cells[i], i );
2910
					}
2911
				}
2912
			}
2913
		}
2914
	
2915
		// For both row and cell invalidation, the cached data for sorting and
2916
		// filtering is nulled out
2917
		row._aSortData = null;
2918
		row._aFilterData = null;
2919
	
2920
		// Invalidate the type for a specific column (if given) or all columns since
2921
		// the data might have changed
2922
		var cols = settings.aoColumns;
2923
		if ( colIdx !== undefined ) {
2924
			cols[ colIdx ].sType = null;
2925
		}
2926
		else {
2927
			for ( i=0, ien=cols.length ; i<ien ; i++ ) {
2928
				cols[i].sType = null;
2929
			}
2930
	
2931
			// Update DataTables special `DT_*` attributes for the row
2932
			_fnRowAttributes( settings, row );
2933
		}
2934
	}
2935
	
2936
	
2937
	/**
2938
	 * Build a data source object from an HTML row, reading the contents of the
2939
	 * cells that are in the row.
2940
	 *
2941
	 * @param {object} settings DataTables settings object
2942
	 * @param {node|object} TR element from which to read data or existing row
2943
	 *   object from which to re-read the data from the cells
2944
	 * @param {int} [colIdx] Optional column index
2945
	 * @param {array|object} [d] Data source object. If `colIdx` is given then this
2946
	 *   parameter should also be given and will be used to write the data into.
2947
	 *   Only the column in question will be written
2948
	 * @returns {object} Object with two parameters: `data` the data read, in
2949
	 *   document order, and `cells` and array of nodes (they can be useful to the
2950
	 *   caller, so rather than needing a second traversal to get them, just return
2951
	 *   them from here).
2952
	 * @memberof DataTable#oApi
2953
	 */
2954
	function _fnGetRowElements( settings, row, colIdx, d )
2955
	{
2956
		var
2957
			tds = [],
2958
			td = row.firstChild,
2959
			name, col, o, i=0, contents,
0 ignored issues
show
Unused Code introduced by
The variable o seems to be never used. Consider removing it.
Loading history...
2960
			columns = settings.aoColumns,
2961
			objectRead = settings._rowReadObject;
2962
	
2963
		// Allow the data object to be passed in, or construct
2964
		d = d !== undefined ?
2965
			d :
2966
			objectRead ?
2967
				{} :
2968
				[];
2969
	
2970
		var attr = function ( str, td  ) {
2971
			if ( typeof str === 'string' ) {
2972
				var idx = str.indexOf('@');
2973
	
2974
				if ( idx !== -1 ) {
2975
					var attr = str.substring( idx+1 );
2976
					var setter = _fnSetObjectDataFn( str );
2977
					setter( d, td.getAttribute( attr ) );
2978
				}
2979
			}
2980
		};
2981
	
2982
		// Read data from a cell and store into the data object
2983
		var cellProcess = function ( cell ) {
2984
			if ( colIdx === undefined || colIdx === i ) {
2985
				col = columns[i];
2986
				contents = $.trim(cell.innerHTML);
2987
	
2988
				if ( col && col._bAttrSrc ) {
2989
					var setter = _fnSetObjectDataFn( col.mData._ );
2990
					setter( d, contents );
2991
	
2992
					attr( col.mData.sort, cell );
2993
					attr( col.mData.type, cell );
2994
					attr( col.mData.filter, cell );
2995
				}
2996
				else {
2997
					// Depending on the `data` option for the columns the data can
2998
					// be read to either an object or an array.
2999
					if ( objectRead ) {
3000
						if ( ! col._setter ) {
3001
							// Cache the setter function
3002
							col._setter = _fnSetObjectDataFn( col.mData );
3003
						}
3004
						col._setter( d, contents );
3005
					}
3006
					else {
3007
						d[i] = contents;
3008
					}
3009
				}
3010
			}
3011
	
3012
			i++;
3013
		};
3014
	
3015
		if ( td ) {
3016
			// `tr` element was passed in
3017
			while ( td ) {
3018
				name = td.nodeName.toUpperCase();
3019
	
3020
				if ( name == "TD" || name == "TH" ) {
3021
					cellProcess( td );
3022
					tds.push( td );
3023
				}
3024
	
3025
				td = td.nextSibling;
3026
			}
3027
		}
3028
		else {
3029
			// Existing row object passed in
3030
			tds = row.anCells;
3031
	
3032
			for ( var j=0, jen=tds.length ; j<jen ; j++ ) {
3033
				cellProcess( tds[j] );
3034
			}
3035
		}
3036
	
3037
		// Read the ID from the DOM if present
3038
		var rowNode = row.firstChild ? row : row.nTr;
3039
	
3040
		if ( rowNode ) {
3041
			var id = rowNode.getAttribute( 'id' );
3042
	
3043
			if ( id ) {
3044
				_fnSetObjectDataFn( settings.rowId )( d, id );
3045
			}
3046
		}
3047
	
3048
		return {
3049
			data: d,
3050
			cells: tds
3051
		};
3052
	}
3053
	/**
3054
	 * Create a new TR element (and it's TD children) for a row
3055
	 *  @param {object} oSettings dataTables settings object
3056
	 *  @param {int} iRow Row to consider
3057
	 *  @param {node} [nTrIn] TR element to add to the table - optional. If not given,
3058
	 *    DataTables will create a row automatically
3059
	 *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
3060
	 *    if nTr is.
3061
	 *  @memberof DataTable#oApi
3062
	 */
3063
	function _fnCreateTr ( oSettings, iRow, nTrIn, anTds )
3064
	{
3065
		var
3066
			row = oSettings.aoData[iRow],
3067
			rowData = row._aData,
3068
			cells = [],
3069
			nTr, nTd, oCol,
3070
			i, iLen;
3071
	
3072
		if ( row.nTr === null )
3073
		{
3074
			nTr = nTrIn || document.createElement('tr');
3075
	
3076
			row.nTr = nTr;
3077
			row.anCells = cells;
3078
	
3079
			/* Use a private property on the node to allow reserve mapping from the node
3080
			 * to the aoData array for fast look up
3081
			 */
3082
			nTr._DT_RowIndex = iRow;
3083
	
3084
			/* Special parameters can be given by the data source to be used on the row */
3085
			_fnRowAttributes( oSettings, row );
3086
	
3087
			/* Process each column */
3088
			for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
3089
			{
3090
				oCol = oSettings.aoColumns[i];
3091
	
3092
				nTd = nTrIn ? anTds[i] : document.createElement( oCol.sCellType );
3093
				nTd._DT_CellIndex = {
3094
					row: iRow,
3095
					column: i
3096
				};
3097
				
3098
				cells.push( nTd );
3099
	
3100
				// Need to create the HTML if new, or if a rendering function is defined
3101
				if ( (!nTrIn || oCol.mRender || oCol.mData !== i) &&
3102
					 (!$.isPlainObject(oCol.mData) || oCol.mData._ !== i+'.display')
3103
				) {
3104
					nTd.innerHTML = _fnGetCellData( oSettings, iRow, i, 'display' );
3105
				}
3106
	
3107
				/* Add user defined class */
3108
				if ( oCol.sClass )
3109
				{
3110
					nTd.className += ' '+oCol.sClass;
3111
				}
3112
	
3113
				// Visibility - add or remove as required
3114
				if ( oCol.bVisible && ! nTrIn )
3115
				{
3116
					nTr.appendChild( nTd );
3117
				}
3118
				else if ( ! oCol.bVisible && nTrIn )
3119
				{
3120
					nTd.parentNode.removeChild( nTd );
3121
				}
3122
	
3123
				if ( oCol.fnCreatedCell )
3124
				{
3125
					oCol.fnCreatedCell.call( oSettings.oInstance,
3126
						nTd, _fnGetCellData( oSettings, iRow, i ), rowData, iRow, i
3127
					);
3128
				}
3129
			}
3130
	
3131
			_fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow] );
3132
		}
3133
	
3134
		// Remove once webkit bug 131819 and Chromium bug 365619 have been resolved
3135
		// and deployed
3136
		row.nTr.setAttribute( 'role', 'row' );
3137
	}
3138
	
3139
	
3140
	/**
3141
	 * Add attributes to a row based on the special `DT_*` parameters in a data
3142
	 * source object.
3143
	 *  @param {object} settings DataTables settings object
3144
	 *  @param {object} DataTables row object for the row to be modified
3145
	 *  @memberof DataTable#oApi
3146
	 */
3147
	function _fnRowAttributes( settings, row )
3148
	{
3149
		var tr = row.nTr;
3150
		var data = row._aData;
3151
	
3152
		if ( tr ) {
3153
			var id = settings.rowIdFn( data );
3154
	
3155
			if ( id ) {
3156
				tr.id = id;
3157
			}
3158
	
3159
			if ( data.DT_RowClass ) {
3160
				// Remove any classes added by DT_RowClass before
3161
				var a = data.DT_RowClass.split(' ');
3162
				row.__rowc = row.__rowc ?
3163
					_unique( row.__rowc.concat( a ) ) :
3164
					a;
3165
	
3166
				$(tr)
3167
					.removeClass( row.__rowc.join(' ') )
3168
					.addClass( data.DT_RowClass );
3169
			}
3170
	
3171
			if ( data.DT_RowAttr ) {
3172
				$(tr).attr( data.DT_RowAttr );
3173
			}
3174
	
3175
			if ( data.DT_RowData ) {
3176
				$(tr).data( data.DT_RowData );
3177
			}
3178
		}
3179
	}
3180
	
3181
	
3182
	/**
3183
	 * Create the HTML header for the table
3184
	 *  @param {object} oSettings dataTables settings object
3185
	 *  @memberof DataTable#oApi
3186
	 */
3187
	function _fnBuildHead( oSettings )
3188
	{
3189
		var i, ien, cell, row, column;
3190
		var thead = oSettings.nTHead;
3191
		var tfoot = oSettings.nTFoot;
3192
		var createHeader = $('th, td', thead).length === 0;
3193
		var classes = oSettings.oClasses;
3194
		var columns = oSettings.aoColumns;
3195
	
3196
		if ( createHeader ) {
3197
			row = $('<tr/>').appendTo( thead );
3198
		}
3199
	
3200
		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
3201
			column = columns[i];
3202
			cell = $( column.nTh ).addClass( column.sClass );
3203
	
3204
			if ( createHeader ) {
3205
				cell.appendTo( row );
0 ignored issues
show
Bug introduced by
The variable row does not seem to be initialized in case createHeader on line 3196 is false. Are you sure the function appendTo handles undefined variables?
Loading history...
3206
			}
3207
	
3208
			// 1.11 move into sorting
3209
			if ( oSettings.oFeatures.bSort ) {
3210
				cell.addClass( column.sSortingClass );
3211
	
3212
				if ( column.bSortable !== false ) {
3213
					cell
3214
						.attr( 'tabindex', oSettings.iTabIndex )
3215
						.attr( 'aria-controls', oSettings.sTableId );
3216
	
3217
					_fnSortAttachListener( oSettings, column.nTh, i );
3218
				}
3219
			}
3220
	
3221
			if ( column.sTitle != cell[0].innerHTML ) {
3222
				cell.html( column.sTitle );
3223
			}
3224
	
3225
			_fnRenderer( oSettings, 'header' )(
3226
				oSettings, cell, column, classes
3227
			);
3228
		}
3229
	
3230
		if ( createHeader ) {
3231
			_fnDetectHeader( oSettings.aoHeader, thead );
3232
		}
3233
		
3234
		/* ARIA role for the rows */
3235
	 	$(thead).find('>tr').attr('role', 'row');
3236
	
3237
		/* Deal with the footer - add classes if required */
3238
		$(thead).find('>tr>th, >tr>td').addClass( classes.sHeaderTH );
3239
		$(tfoot).find('>tr>th, >tr>td').addClass( classes.sFooterTH );
3240
	
3241
		// Cache the footer cells. Note that we only take the cells from the first
3242
		// row in the footer. If there is more than one row the user wants to
3243
		// interact with, they need to use the table().foot() method. Note also this
3244
		// allows cells to be used for multiple columns using colspan
3245
		if ( tfoot !== null ) {
3246
			var cells = oSettings.aoFooter[0];
3247
	
3248
			for ( i=0, ien=cells.length ; i<ien ; i++ ) {
3249
				column = columns[i];
3250
				column.nTf = cells[i].cell;
3251
	
3252
				if ( column.sClass ) {
3253
					$(column.nTf).addClass( column.sClass );
3254
				}
3255
			}
3256
		}
3257
	}
3258
	
3259
	
3260
	/**
3261
	 * Draw the header (or footer) element based on the column visibility states. The
3262
	 * methodology here is to use the layout array from _fnDetectHeader, modified for
3263
	 * the instantaneous column visibility, to construct the new layout. The grid is
3264
	 * traversed over cell at a time in a rows x columns grid fashion, although each
3265
	 * cell insert can cover multiple elements in the grid - which is tracks using the
3266
	 * aApplied array. Cell inserts in the grid will only occur where there isn't
3267
	 * already a cell in that position.
3268
	 *  @param {object} oSettings dataTables settings object
3269
	 *  @param array {objects} aoSource Layout array from _fnDetectHeader
3270
	 *  @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,
3271
	 *  @memberof DataTable#oApi
3272
	 */
3273
	function _fnDrawHead( oSettings, aoSource, bIncludeHidden )
3274
	{
3275
		var i, iLen, j, jLen, k, kLen, n, nLocalTr;
0 ignored issues
show
Unused Code introduced by
The variable kLen seems to be never used. Consider removing it.
Loading history...
3276
		var aoLocal = [];
3277
		var aApplied = [];
3278
		var iColumns = oSettings.aoColumns.length;
3279
		var iRowspan, iColspan;
3280
	
3281
		if ( ! aoSource )
3282
		{
3283
			return;
3284
		}
3285
	
3286
		if (  bIncludeHidden === undefined )
3287
		{
3288
			bIncludeHidden = false;
3289
		}
3290
	
3291
		/* Make a copy of the master layout array, but without the visible columns in it */
3292
		for ( i=0, iLen=aoSource.length ; i<iLen ; i++ )
3293
		{
3294
			aoLocal[i] = aoSource[i].slice();
3295
			aoLocal[i].nTr = aoSource[i].nTr;
3296
	
3297
			/* Remove any columns which are currently hidden */
3298
			for ( j=iColumns-1 ; j>=0 ; j-- )
3299
			{
3300
				if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden )
3301
				{
3302
					aoLocal[i].splice( j, 1 );
3303
				}
3304
			}
3305
	
3306
			/* Prep the applied array - it needs an element for each row */
3307
			aApplied.push( [] );
3308
		}
3309
	
3310
		for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ )
3311
		{
3312
			nLocalTr = aoLocal[i].nTr;
3313
	
3314
			/* All cells are going to be replaced, so empty out the row */
3315
			if ( nLocalTr )
3316
			{
3317
				while( (n = nLocalTr.firstChild) )
3318
				{
3319
					nLocalTr.removeChild( n );
3320
				}
3321
			}
3322
	
3323
			for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ )
3324
			{
3325
				iRowspan = 1;
3326
				iColspan = 1;
3327
	
3328
				/* Check to see if there is already a cell (row/colspan) covering our target
3329
				 * insert point. If there is, then there is nothing to do.
3330
				 */
3331
				if ( aApplied[i][j] === undefined )
3332
				{
3333
					nLocalTr.appendChild( aoLocal[i][j].cell );
3334
					aApplied[i][j] = 1;
3335
	
3336
					/* Expand the cell to cover as many rows as needed */
3337
					while ( aoLocal[i+iRowspan] !== undefined &&
3338
					        aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell )
3339
					{
3340
						aApplied[i+iRowspan][j] = 1;
3341
						iRowspan++;
3342
					}
3343
	
3344
					/* Expand the cell to cover as many columns as needed */
3345
					while ( aoLocal[i][j+iColspan] !== undefined &&
3346
					        aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell )
3347
					{
3348
						/* Must update the applied array over the rows for the columns */
3349
						for ( k=0 ; k<iRowspan ; k++ )
3350
						{
3351
							aApplied[i+k][j+iColspan] = 1;
3352
						}
3353
						iColspan++;
3354
					}
3355
	
3356
					/* Do the actual expansion in the DOM */
3357
					$(aoLocal[i][j].cell)
3358
						.attr('rowspan', iRowspan)
3359
						.attr('colspan', iColspan);
3360
				}
3361
			}
3362
		}
3363
	}
3364
	
3365
	
3366
	/**
3367
	 * Insert the required TR nodes into the table for display
3368
	 *  @param {object} oSettings dataTables settings object
3369
	 *  @memberof DataTable#oApi
3370
	 */
3371
	function _fnDraw( oSettings )
3372
	{
3373
		/* Provide a pre-callback function which can be used to cancel the draw is false is returned */
3374
		var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] );
3375
		if ( $.inArray( false, aPreDraw ) !== -1 )
3376
		{
3377
			_fnProcessingDisplay( oSettings, false );
3378
			return;
3379
		}
3380
	
3381
		var i, iLen, n;
0 ignored issues
show
Unused Code introduced by
The variable iLen seems to be never used. Consider removing it.
Loading history...
Unused Code introduced by
The variable n seems to be never used. Consider removing it.
Loading history...
Unused Code introduced by
The variable i seems to be never used. Consider removing it.
Loading history...
3382
		var anRows = [];
3383
		var iRowCount = 0;
3384
		var asStripeClasses = oSettings.asStripeClasses;
3385
		var iStripes = asStripeClasses.length;
3386
		var iOpenRows = oSettings.aoOpenRows.length;
0 ignored issues
show
Unused Code introduced by
The variable iOpenRows seems to be never used. Consider removing it.
Loading history...
3387
		var oLang = oSettings.oLanguage;
3388
		var iInitDisplayStart = oSettings.iInitDisplayStart;
3389
		var bServerSide = _fnDataSource( oSettings ) == 'ssp';
3390
		var aiDisplay = oSettings.aiDisplay;
3391
	
3392
		oSettings.bDrawing = true;
3393
	
3394
		/* Check and see if we have an initial draw position from state saving */
3395
		if ( iInitDisplayStart !== undefined && iInitDisplayStart !== -1 )
3396
		{
3397
			oSettings._iDisplayStart = bServerSide ?
3398
				iInitDisplayStart :
3399
				iInitDisplayStart >= oSettings.fnRecordsDisplay() ?
3400
					0 :
3401
					iInitDisplayStart;
3402
	
3403
			oSettings.iInitDisplayStart = -1;
3404
		}
3405
	
3406
		var iDisplayStart = oSettings._iDisplayStart;
3407
		var iDisplayEnd = oSettings.fnDisplayEnd();
3408
	
3409
		/* Server-side processing draw intercept */
3410
		if ( oSettings.bDeferLoading )
3411
		{
3412
			oSettings.bDeferLoading = false;
3413
			oSettings.iDraw++;
3414
			_fnProcessingDisplay( oSettings, false );
3415
		}
3416
		else if ( !bServerSide )
3417
		{
3418
			oSettings.iDraw++;
3419
		}
3420
		else if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) )
3421
		{
3422
			return;
3423
		}
3424
	
3425
		if ( aiDisplay.length !== 0 )
3426
		{
3427
			var iStart = bServerSide ? 0 : iDisplayStart;
3428
			var iEnd = bServerSide ? oSettings.aoData.length : iDisplayEnd;
3429
	
3430
			for ( var j=iStart ; j<iEnd ; j++ )
3431
			{
3432
				var iDataIndex = aiDisplay[j];
3433
				var aoData = oSettings.aoData[ iDataIndex ];
3434
				if ( aoData.nTr === null )
3435
				{
3436
					_fnCreateTr( oSettings, iDataIndex );
3437
				}
3438
	
3439
				var nRow = aoData.nTr;
3440
	
3441
				/* Remove the old striping classes and then add the new one */
3442
				if ( iStripes !== 0 )
3443
				{
3444
					var sStripe = asStripeClasses[ iRowCount % iStripes ];
3445
					if ( aoData._sRowStripe != sStripe )
3446
					{
3447
						$(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe );
3448
						aoData._sRowStripe = sStripe;
3449
					}
3450
				}
3451
	
3452
				// Row callback functions - might want to manipulate the row
3453
				// iRowCount and j are not currently documented. Are they at all
3454
				// useful?
3455
				_fnCallbackFire( oSettings, 'aoRowCallback', null,
3456
					[nRow, aoData._aData, iRowCount, j] );
3457
	
3458
				anRows.push( nRow );
3459
				iRowCount++;
3460
			}
3461
		}
3462
		else
3463
		{
3464
			/* Table is empty - create a row with an empty message in it */
3465
			var sZero = oLang.sZeroRecords;
3466
			if ( oSettings.iDraw == 1 &&  _fnDataSource( oSettings ) == 'ajax' )
3467
			{
3468
				sZero = oLang.sLoadingRecords;
3469
			}
3470
			else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 )
3471
			{
3472
				sZero = oLang.sEmptyTable;
3473
			}
3474
	
3475
			anRows[ 0 ] = $( '<tr/>', { 'class': iStripes ? asStripeClasses[0] : '' } )
3476
				.append( $('<td />', {
3477
					'valign':  'top',
3478
					'colSpan': _fnVisbleColumns( oSettings ),
3479
					'class':   oSettings.oClasses.sRowEmpty
3480
				} ).html( sZero ) )[0];
3481
		}
3482
	
3483
		/* Header and footer callbacks */
3484
		_fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0],
3485
			_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
3486
	
3487
		_fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0],
3488
			_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
3489
	
3490
		var body = $(oSettings.nTBody);
3491
	
3492
		body.children().detach();
3493
		body.append( $(anRows) );
3494
	
3495
		/* Call all required callback functions for the end of a draw */
3496
		_fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] );
3497
	
3498
		/* Draw is complete, sorting and filtering must be as well */
3499
		oSettings.bSorted = false;
3500
		oSettings.bFiltered = false;
3501
		oSettings.bDrawing = false;
3502
	}
3503
	
3504
	
3505
	/**
3506
	 * Redraw the table - taking account of the various features which are enabled
3507
	 *  @param {object} oSettings dataTables settings object
3508
	 *  @param {boolean} [holdPosition] Keep the current paging position. By default
3509
	 *    the paging is reset to the first page
3510
	 *  @memberof DataTable#oApi
3511
	 */
3512
	function _fnReDraw( settings, holdPosition )
3513
	{
3514
		var
3515
			features = settings.oFeatures,
3516
			sort     = features.bSort,
3517
			filter   = features.bFilter;
3518
	
3519
		if ( sort ) {
3520
			_fnSort( settings );
3521
		}
3522
	
3523
		if ( filter ) {
3524
			_fnFilterComplete( settings, settings.oPreviousSearch );
3525
		}
3526
		else {
3527
			// No filtering, so we want to just use the display master
3528
			settings.aiDisplay = settings.aiDisplayMaster.slice();
3529
		}
3530
	
3531
		if ( holdPosition !== true ) {
3532
			settings._iDisplayStart = 0;
3533
		}
3534
	
3535
		// Let any modules know about the draw hold position state (used by
3536
		// scrolling internally)
3537
		settings._drawHold = holdPosition;
3538
	
3539
		_fnDraw( settings );
3540
	
3541
		settings._drawHold = false;
3542
	}
3543
	
3544
	
3545
	/**
3546
	 * Add the options to the page HTML for the table
3547
	 *  @param {object} oSettings dataTables settings object
3548
	 *  @memberof DataTable#oApi
3549
	 */
3550
	function _fnAddOptionsHtml ( oSettings )
3551
	{
3552
		var classes = oSettings.oClasses;
3553
		var table = $(oSettings.nTable);
3554
		var holding = $('<div/>').insertBefore( table ); // Holding element for speed
3555
		var features = oSettings.oFeatures;
3556
	
3557
		// All DataTables are wrapped in a div
3558
		var insert = $('<div/>', {
3559
			id:      oSettings.sTableId+'_wrapper',
3560
			'class': classes.sWrapper + (oSettings.nTFoot ? '' : ' '+classes.sNoFooter)
3561
		} );
3562
	
3563
		oSettings.nHolding = holding[0];
3564
		oSettings.nTableWrapper = insert[0];
3565
		oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;
3566
	
3567
		/* Loop over the user set positioning and place the elements as needed */
3568
		var aDom = oSettings.sDom.split('');
3569
		var featureNode, cOption, nNewNode, cNext, sAttr, j;
3570
		for ( var i=0 ; i<aDom.length ; i++ )
3571
		{
3572
			featureNode = null;
3573
			cOption = aDom[i];
3574
	
3575
			if ( cOption == '<' )
3576
			{
3577
				/* New container div */
3578
				nNewNode = $('<div/>')[0];
3579
	
3580
				/* Check to see if we should append an id and/or a class name to the container */
3581
				cNext = aDom[i+1];
3582
				if ( cNext == "'" || cNext == '"' )
3583
				{
3584
					sAttr = "";
3585
					j = 2;
3586
					while ( aDom[i+j] != cNext )
3587
					{
3588
						sAttr += aDom[i+j];
3589
						j++;
3590
					}
3591
	
3592
					/* Replace jQuery UI constants @todo depreciated */
3593
					if ( sAttr == "H" )
3594
					{
3595
						sAttr = classes.sJUIHeader;
3596
					}
3597
					else if ( sAttr == "F" )
3598
					{
3599
						sAttr = classes.sJUIFooter;
3600
					}
3601
	
3602
					/* The attribute can be in the format of "#id.class", "#id" or "class" This logic
3603
					 * breaks the string into parts and applies them as needed
3604
					 */
3605
					if ( sAttr.indexOf('.') != -1 )
3606
					{
3607
						var aSplit = sAttr.split('.');
3608
						nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);
3609
						nNewNode.className = aSplit[1];
3610
					}
3611
					else if ( sAttr.charAt(0) == "#" )
3612
					{
3613
						nNewNode.id = sAttr.substr(1, sAttr.length-1);
3614
					}
3615
					else
3616
					{
3617
						nNewNode.className = sAttr;
3618
					}
3619
	
3620
					i += j; /* Move along the position array */
3621
				}
3622
	
3623
				insert.append( nNewNode );
3624
				insert = $(nNewNode);
3625
			}
3626
			else if ( cOption == '>' )
3627
			{
3628
				/* End container div */
3629
				insert = insert.parent();
3630
			}
3631
			// @todo Move options into their own plugins?
3632
			else if ( cOption == 'l' && features.bPaginate && features.bLengthChange )
3633
			{
3634
				/* Length */
3635
				featureNode = _fnFeatureHtmlLength( oSettings );
3636
			}
3637
			else if ( cOption == 'f' && features.bFilter )
3638
			{
3639
				/* Filter */
3640
				featureNode = _fnFeatureHtmlFilter( oSettings );
3641
			}
3642
			else if ( cOption == 'r' && features.bProcessing )
3643
			{
3644
				/* pRocessing */
3645
				featureNode = _fnFeatureHtmlProcessing( oSettings );
3646
			}
3647
			else if ( cOption == 't' )
3648
			{
3649
				/* Table */
3650
				featureNode = _fnFeatureHtmlTable( oSettings );
3651
			}
3652
			else if ( cOption ==  'i' && features.bInfo )
3653
			{
3654
				/* Info */
3655
				featureNode = _fnFeatureHtmlInfo( oSettings );
3656
			}
3657
			else if ( cOption == 'p' && features.bPaginate )
3658
			{
3659
				/* Pagination */
3660
				featureNode = _fnFeatureHtmlPaginate( oSettings );
3661
			}
3662
			else if ( DataTable.ext.feature.length !== 0 )
3663
			{
3664
				/* Plug-in features */
3665
				var aoFeatures = DataTable.ext.feature;
3666
				for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )
3667
				{
3668
					if ( cOption == aoFeatures[k].cFeature )
3669
					{
3670
						featureNode = aoFeatures[k].fnInit( oSettings );
3671
						break;
3672
					}
3673
				}
3674
			}
3675
	
3676
			/* Add to the 2D features array */
3677
			if ( featureNode )
3678
			{
3679
				var aanFeatures = oSettings.aanFeatures;
3680
	
3681
				if ( ! aanFeatures[cOption] )
3682
				{
3683
					aanFeatures[cOption] = [];
3684
				}
3685
	
3686
				aanFeatures[cOption].push( featureNode );
3687
				insert.append( featureNode );
3688
			}
3689
		}
3690
	
3691
		/* Built our DOM structure - replace the holding div with what we want */
3692
		holding.replaceWith( insert );
3693
		oSettings.nHolding = null;
3694
	}
3695
	
3696
	
3697
	/**
3698
	 * Use the DOM source to create up an array of header cells. The idea here is to
3699
	 * create a layout grid (array) of rows x columns, which contains a reference
3700
	 * to the cell that that point in the grid (regardless of col/rowspan), such that
3701
	 * any column / row could be removed and the new grid constructed
3702
	 *  @param array {object} aLayout Array to store the calculated layout in
3703
	 *  @param {node} nThead The header/footer element for the table
3704
	 *  @memberof DataTable#oApi
3705
	 */
3706
	function _fnDetectHeader ( aLayout, nThead )
3707
	{
3708
		var nTrs = $(nThead).children('tr');
3709
		var nTr, nCell;
3710
		var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan;
0 ignored issues
show
Unused Code introduced by
The variable jLen seems to be never used. Consider removing it.
Loading history...
3711
		var bUnique;
3712
		var fnShiftCol = function ( a, i, j ) {
3713
			var k = a[i];
3714
	                while ( k[j] ) {
3715
				j++;
3716
			}
3717
			return j;
3718
		};
3719
	
3720
		aLayout.splice( 0, aLayout.length );
3721
	
3722
		/* We know how many rows there are in the layout - so prep it */
3723
		for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
3724
		{
3725
			aLayout.push( [] );
3726
		}
3727
	
3728
		/* Calculate a layout array */
3729
		for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
3730
		{
3731
			nTr = nTrs[i];
3732
			iColumn = 0;
3733
	
3734
			/* For every cell in the row... */
3735
			nCell = nTr.firstChild;
3736
			while ( nCell ) {
3737
				if ( nCell.nodeName.toUpperCase() == "TD" ||
3738
				     nCell.nodeName.toUpperCase() == "TH" )
3739
				{
3740
					/* Get the col and rowspan attributes from the DOM and sanitise them */
3741
					iColspan = nCell.getAttribute('colspan') * 1;
3742
					iRowspan = nCell.getAttribute('rowspan') * 1;
3743
					iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan;
3744
					iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan;
3745
	
3746
					/* There might be colspan cells already in this row, so shift our target
3747
					 * accordingly
3748
					 */
3749
					iColShifted = fnShiftCol( aLayout, i, iColumn );
3750
	
3751
					/* Cache calculation for unique columns */
3752
					bUnique = iColspan === 1 ? true : false;
3753
	
3754
					/* If there is col / rowspan, copy the information into the layout grid */
3755
					for ( l=0 ; l<iColspan ; l++ )
3756
					{
3757
						for ( k=0 ; k<iRowspan ; k++ )
3758
						{
3759
							aLayout[i+k][iColShifted+l] = {
3760
								"cell": nCell,
3761
								"unique": bUnique
3762
							};
3763
							aLayout[i+k].nTr = nTr;
3764
						}
3765
					}
3766
				}
3767
				nCell = nCell.nextSibling;
3768
			}
3769
		}
3770
	}
3771
	
3772
	
3773
	/**
3774
	 * Get an array of unique th elements, one for each column
3775
	 *  @param {object} oSettings dataTables settings object
3776
	 *  @param {node} nHeader automatically detect the layout from this node - optional
3777
	 *  @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional
3778
	 *  @returns array {node} aReturn list of unique th's
3779
	 *  @memberof DataTable#oApi
3780
	 */
3781
	function _fnGetUniqueThs ( oSettings, nHeader, aLayout )
3782
	{
3783
		var aReturn = [];
3784
		if ( !aLayout )
3785
		{
3786
			aLayout = oSettings.aoHeader;
3787
			if ( nHeader )
3788
			{
3789
				aLayout = [];
3790
				_fnDetectHeader( aLayout, nHeader );
3791
			}
3792
		}
3793
	
3794
		for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ )
3795
		{
3796
			for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ )
3797
			{
3798
				if ( aLayout[i][j].unique &&
3799
					 (!aReturn[j] || !oSettings.bSortCellsTop) )
3800
				{
3801
					aReturn[j] = aLayout[i][j].cell;
3802
				}
3803
			}
3804
		}
3805
	
3806
		return aReturn;
3807
	}
3808
	
3809
	/**
3810
	 * Create an Ajax call based on the table's settings, taking into account that
3811
	 * parameters can have multiple forms, and backwards compatibility.
3812
	 *
3813
	 * @param {object} oSettings dataTables settings object
3814
	 * @param {array} data Data to send to the server, required by
3815
	 *     DataTables - may be augmented by developer callbacks
3816
	 * @param {function} fn Callback function to run when data is obtained
3817
	 */
3818
	function _fnBuildAjax( oSettings, data, fn )
3819
	{
3820
		// Compatibility with 1.9-, allow fnServerData and event to manipulate
3821
		_fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [data] );
3822
	
3823
		// Convert to object based for 1.10+ if using the old array scheme which can
3824
		// come from server-side processing or serverParams
3825
		if ( data && $.isArray(data) ) {
3826
			var tmp = {};
3827
			var rbracket = /(.*?)\[\]$/;
3828
	
3829
			$.each( data, function (key, val) {
3830
				var match = val.name.match(rbracket);
3831
	
3832
				if ( match ) {
3833
					// Support for arrays
3834
					var name = match[0];
3835
	
3836
					if ( ! tmp[ name ] ) {
3837
						tmp[ name ] = [];
3838
					}
3839
					tmp[ name ].push( val.value );
3840
				}
3841
				else {
3842
					tmp[val.name] = val.value;
3843
				}
3844
			} );
3845
			data = tmp;
3846
		}
3847
	
3848
		var ajaxData;
3849
		var ajax = oSettings.ajax;
3850
		var instance = oSettings.oInstance;
3851
		var callback = function ( json ) {
3852
			_fnCallbackFire( oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR] );
3853
			fn( json );
3854
		};
3855
	
3856
		if ( $.isPlainObject( ajax ) && ajax.data )
3857
		{
3858
			ajaxData = ajax.data;
3859
	
3860
			var newData = $.isFunction( ajaxData ) ?
3861
				ajaxData( data, oSettings ) :  // fn can manipulate data or return
3862
				ajaxData;                      // an object object or array to merge
3863
	
3864
			// If the function returned something, use that alone
3865
			data = $.isFunction( ajaxData ) && newData ?
3866
				newData :
3867
				$.extend( true, data, newData );
3868
	
3869
			// Remove the data property as we've resolved it already and don't want
3870
			// jQuery to do it again (it is restored at the end of the function)
3871
			delete ajax.data;
3872
		}
3873
	
3874
		var baseAjax = {
3875
			"data": data,
3876
			"success": function (json) {
3877
				var error = json.error || json.sError;
3878
				if ( error ) {
3879
					_fnLog( oSettings, 0, error );
3880
				}
3881
	
3882
				oSettings.json = json;
3883
				callback( json );
3884
			},
3885
			"dataType": "json",
3886
			"cache": false,
3887
			"type": oSettings.sServerMethod,
3888
			"error": function (xhr, error, thrown) {
0 ignored issues
show
Unused Code introduced by
The parameter thrown is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
3889
				var ret = _fnCallbackFire( oSettings, null, 'xhr', [oSettings, null, oSettings.jqXHR] );
3890
	
3891
				if ( $.inArray( true, ret ) === -1 ) {
3892
					if ( error == "parsererror" ) {
3893
						_fnLog( oSettings, 0, 'Invalid JSON response', 1 );
3894
					}
3895
					else if ( xhr.readyState === 4 ) {
3896
						_fnLog( oSettings, 0, 'Ajax error', 7 );
3897
					}
3898
				}
3899
	
3900
				_fnProcessingDisplay( oSettings, false );
3901
			}
3902
		};
3903
	
3904
		// Store the data submitted for the API
3905
		oSettings.oAjaxData = data;
3906
	
3907
		// Allow plug-ins and external processes to modify the data
3908
		_fnCallbackFire( oSettings, null, 'preXhr', [oSettings, data] );
3909
	
3910
		if ( oSettings.fnServerData )
3911
		{
3912
			// DataTables 1.9- compatibility
3913
			oSettings.fnServerData.call( instance,
3914
				oSettings.sAjaxSource,
3915
				$.map( data, function (val, key) { // Need to convert back to 1.9 trad format
3916
					return { name: key, value: val };
3917
				} ),
3918
				callback,
3919
				oSettings
3920
			);
3921
		}
3922
		else if ( oSettings.sAjaxSource || typeof ajax === 'string' )
3923
		{
3924
			// DataTables 1.9- compatibility
3925
			oSettings.jqXHR = $.ajax( $.extend( baseAjax, {
3926
				url: ajax || oSettings.sAjaxSource
3927
			} ) );
3928
		}
3929
		else if ( $.isFunction( ajax ) )
3930
		{
3931
			// Is a function - let the caller define what needs to be done
3932
			oSettings.jqXHR = ajax.call( instance, data, callback, oSettings );
3933
		}
3934
		else
3935
		{
3936
			// Object to extend the base settings
3937
			oSettings.jqXHR = $.ajax( $.extend( baseAjax, ajax ) );
3938
	
3939
			// Restore for next time around
3940
			ajax.data = ajaxData;
0 ignored issues
show
Bug introduced by
The variable ajaxData does not seem to be initialized in case $.isPlainObject(ajax) && ajax.data on line 3856 is false. Are you sure this can never be the case?
Loading history...
3941
		}
3942
	}
3943
	
3944
	
3945
	/**
3946
	 * Update the table using an Ajax call
3947
	 *  @param {object} settings dataTables settings object
3948
	 *  @returns {boolean} Block the table drawing or not
3949
	 *  @memberof DataTable#oApi
3950
	 */
3951
	function _fnAjaxUpdate( settings )
3952
	{
3953
		if ( settings.bAjaxDataGet ) {
3954
			settings.iDraw++;
3955
			_fnProcessingDisplay( settings, true );
3956
	
3957
			_fnBuildAjax(
3958
				settings,
3959
				_fnAjaxParameters( settings ),
3960
				function(json) {
3961
					_fnAjaxUpdateDraw( settings, json );
3962
				}
3963
			);
3964
	
3965
			return false;
3966
		}
3967
		return true;
3968
	}
3969
	
3970
	
3971
	/**
3972
	 * Build up the parameters in an object needed for a server-side processing
3973
	 * request. Note that this is basically done twice, is different ways - a modern
3974
	 * method which is used by default in DataTables 1.10 which uses objects and
3975
	 * arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if
3976
	 * the sAjaxSource option is used in the initialisation, or the legacyAjax
3977
	 * option is set.
3978
	 *  @param {object} oSettings dataTables settings object
3979
	 *  @returns {bool} block the table drawing or not
3980
	 *  @memberof DataTable#oApi
3981
	 */
3982
	function _fnAjaxParameters( settings )
3983
	{
3984
		var
3985
			columns = settings.aoColumns,
3986
			columnCount = columns.length,
3987
			features = settings.oFeatures,
3988
			preSearch = settings.oPreviousSearch,
3989
			preColSearch = settings.aoPreSearchCols,
3990
			i, data = [], dataProp, column, columnSearch,
3991
			sort = _fnSortFlatten( settings ),
3992
			displayStart = settings._iDisplayStart,
3993
			displayLength = features.bPaginate !== false ?
3994
				settings._iDisplayLength :
3995
				-1;
3996
	
3997
		var param = function ( name, value ) {
3998
			data.push( { 'name': name, 'value': value } );
3999
		};
4000
	
4001
		// DataTables 1.9- compatible method
4002
		param( 'sEcho',          settings.iDraw );
4003
		param( 'iColumns',       columnCount );
4004
		param( 'sColumns',       _pluck( columns, 'sName' ).join(',') );
4005
		param( 'iDisplayStart',  displayStart );
4006
		param( 'iDisplayLength', displayLength );
4007
	
4008
		// DataTables 1.10+ method
4009
		var d = {
4010
			draw:    settings.iDraw,
4011
			columns: [],
4012
			order:   [],
4013
			start:   displayStart,
4014
			length:  displayLength,
4015
			search:  {
4016
				value: preSearch.sSearch,
4017
				regex: preSearch.bRegex
4018
			}
4019
		};
4020
	
4021
		for ( i=0 ; i<columnCount ; i++ ) {
4022
			column = columns[i];
4023
			columnSearch = preColSearch[i];
4024
			dataProp = typeof column.mData=="function" ? 'function' : column.mData ;
4025
	
4026
			d.columns.push( {
4027
				data:       dataProp,
4028
				name:       column.sName,
4029
				searchable: column.bSearchable,
4030
				orderable:  column.bSortable,
4031
				search:     {
4032
					value: columnSearch.sSearch,
4033
					regex: columnSearch.bRegex
4034
				}
4035
			} );
4036
	
4037
			param( "mDataProp_"+i, dataProp );
4038
	
4039
			if ( features.bFilter ) {
4040
				param( 'sSearch_'+i,     columnSearch.sSearch );
4041
				param( 'bRegex_'+i,      columnSearch.bRegex );
4042
				param( 'bSearchable_'+i, column.bSearchable );
4043
			}
4044
	
4045
			if ( features.bSort ) {
4046
				param( 'bSortable_'+i, column.bSortable );
4047
			}
4048
		}
4049
	
4050
		if ( features.bFilter ) {
4051
			param( 'sSearch', preSearch.sSearch );
4052
			param( 'bRegex', preSearch.bRegex );
4053
		}
4054
	
4055
		if ( features.bSort ) {
4056
			$.each( sort, function ( i, val ) {
4057
				d.order.push( { column: val.col, dir: val.dir } );
4058
	
4059
				param( 'iSortCol_'+i, val.col );
4060
				param( 'sSortDir_'+i, val.dir );
4061
			} );
4062
	
4063
			param( 'iSortingCols', sort.length );
4064
		}
4065
	
4066
		// If the legacy.ajax parameter is null, then we automatically decide which
4067
		// form to use, based on sAjaxSource
4068
		var legacy = DataTable.ext.legacy.ajax;
4069
		if ( legacy === null ) {
4070
			return settings.sAjaxSource ? data : d;
4071
		}
4072
	
4073
		// Otherwise, if legacy has been specified then we use that to decide on the
4074
		// form
4075
		return legacy ? data : d;
4076
	}
4077
	
4078
	
4079
	/**
4080
	 * Data the data from the server (nuking the old) and redraw the table
4081
	 *  @param {object} oSettings dataTables settings object
4082
	 *  @param {object} json json data return from the server.
4083
	 *  @param {string} json.sEcho Tracking flag for DataTables to match requests
4084
	 *  @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering
4085
	 *  @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering
4086
	 *  @param {array} json.aaData The data to display on this page
4087
	 *  @param {string} [json.sColumns] Column ordering (sName, comma separated)
4088
	 *  @memberof DataTable#oApi
4089
	 */
4090
	function _fnAjaxUpdateDraw ( settings, json )
4091
	{
4092
		// v1.10 uses camelCase variables, while 1.9 uses Hungarian notation.
4093
		// Support both
4094
		var compat = function ( old, modern ) {
4095
			return json[old] !== undefined ? json[old] : json[modern];
4096
		};
4097
	
4098
		var data = _fnAjaxDataSrc( settings, json );
4099
		var draw            = compat( 'sEcho',                'draw' );
4100
		var recordsTotal    = compat( 'iTotalRecords',        'recordsTotal' );
4101
		var recordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' );
4102
	
4103
		if ( draw ) {
4104
			// Protect against out of sequence returns
4105
			if ( draw*1 < settings.iDraw ) {
4106
				return;
4107
			}
4108
			settings.iDraw = draw * 1;
4109
		}
4110
	
4111
		_fnClearTable( settings );
4112
		settings._iRecordsTotal   = parseInt(recordsTotal, 10);
4113
		settings._iRecordsDisplay = parseInt(recordsFiltered, 10);
4114
	
4115
		for ( var i=0, ien=data.length ; i<ien ; i++ ) {
4116
			_fnAddData( settings, data[i] );
4117
		}
4118
		settings.aiDisplay = settings.aiDisplayMaster.slice();
4119
	
4120
		settings.bAjaxDataGet = false;
4121
		_fnDraw( settings );
4122
	
4123
		if ( ! settings._bInitComplete ) {
4124
			_fnInitComplete( settings, json );
4125
		}
4126
	
4127
		settings.bAjaxDataGet = true;
4128
		_fnProcessingDisplay( settings, false );
4129
	}
4130
	
4131
	
4132
	/**
4133
	 * Get the data from the JSON data source to use for drawing a table. Using
4134
	 * `_fnGetObjectDataFn` allows the data to be sourced from a property of the
4135
	 * source object, or from a processing function.
4136
	 *  @param {object} oSettings dataTables settings object
4137
	 *  @param  {object} json Data source object / array from the server
4138
	 *  @return {array} Array of data to use
4139
	 */
4140
	function _fnAjaxDataSrc ( oSettings, json )
4141
	{
4142
		var dataSrc = $.isPlainObject( oSettings.ajax ) && oSettings.ajax.dataSrc !== undefined ?
4143
			oSettings.ajax.dataSrc :
4144
			oSettings.sAjaxDataProp; // Compatibility with 1.9-.
4145
	
4146
		// Compatibility with 1.9-. In order to read from aaData, check if the
4147
		// default has been changed, if not, check for aaData
4148
		if ( dataSrc === 'data' ) {
4149
			return json.aaData || json[dataSrc];
4150
		}
4151
	
4152
		return dataSrc !== "" ?
4153
			_fnGetObjectDataFn( dataSrc )( json ) :
4154
			json;
4155
	}
4156
	
4157
	/**
4158
	 * Generate the node required for filtering text
4159
	 *  @returns {node} Filter control element
4160
	 *  @param {object} oSettings dataTables settings object
4161
	 *  @memberof DataTable#oApi
4162
	 */
4163
	function _fnFeatureHtmlFilter ( settings )
4164
	{
4165
		var classes = settings.oClasses;
4166
		var tableId = settings.sTableId;
4167
		var language = settings.oLanguage;
4168
		var previousSearch = settings.oPreviousSearch;
4169
		var features = settings.aanFeatures;
4170
		var input = '<input type="search" class="'+classes.sFilterInput+'"/>';
4171
	
4172
		var str = language.sSearch;
4173
		str = str.match(/_INPUT_/) ?
4174
			str.replace('_INPUT_', input) :
4175
			str+input;
4176
	
4177
		var filter = $('<div/>', {
4178
				'id': ! features.f ? tableId+'_filter' : null,
4179
				'class': classes.sFilter
4180
			} )
4181
			.append( $('<label/>' ).append( str ) );
4182
	
4183
		var searchFn = function() {
4184
			/* Update all other filter input elements for the new display */
4185
			var n = features.f;
0 ignored issues
show
Unused Code introduced by
The variable n seems to be never used. Consider removing it.
Loading history...
4186
			var val = !this.value ? "" : this.value; // mental IE8 fix :-(
4187
	
4188
			/* Now do the filter */
4189
			if ( val != previousSearch.sSearch ) {
4190
				_fnFilterComplete( settings, {
4191
					"sSearch": val,
4192
					"bRegex": previousSearch.bRegex,
4193
					"bSmart": previousSearch.bSmart ,
4194
					"bCaseInsensitive": previousSearch.bCaseInsensitive
4195
				} );
4196
	
4197
				// Need to redraw, without resorting
4198
				settings._iDisplayStart = 0;
4199
				_fnDraw( settings );
4200
			}
4201
		};
4202
	
4203
		var searchDelay = settings.searchDelay !== null ?
4204
			settings.searchDelay :
4205
			_fnDataSource( settings ) === 'ssp' ?
4206
				400 :
4207
				0;
4208
	
4209
		var jqFilter = $('input', filter)
4210
			.val( previousSearch.sSearch )
4211
			.attr( 'placeholder', language.sSearchPlaceholder )
4212
			.on(
4213
				'keyup.DT search.DT input.DT paste.DT cut.DT',
4214
				searchDelay ?
4215
					_fnThrottle( searchFn, searchDelay ) :
4216
					searchFn
4217
			)
4218
			.on( 'keypress.DT', function(e) {
4219
				/* Prevent form submission */
4220
				if ( e.keyCode == 13 ) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if e.keyCode == 13 is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
4221
					return false;
4222
				}
4223
			} )
4224
			.attr('aria-controls', tableId);
4225
	
4226
		// Update the input elements whenever the table is filtered
4227
		$(settings.nTable).on( 'search.dt.DT', function ( ev, s ) {
4228
			if ( settings === s ) {
4229
				// IE9 throws an 'unknown error' if document.activeElement is used
4230
				// inside an iframe or frame...
4231
				try {
4232
					if ( jqFilter[0] !== document.activeElement ) {
4233
						jqFilter.val( previousSearch.sSearch );
4234
					}
4235
				}
4236
				catch ( e ) {}
0 ignored issues
show
Coding Style Comprehensibility Best Practice introduced by
Empty catch clauses should be used with caution; consider adding a comment why this is needed.
Loading history...
4237
			}
4238
		} );
4239
	
4240
		return filter[0];
4241
	}
4242
	
4243
	
4244
	/**
4245
	 * Filter the table using both the global filter and column based filtering
4246
	 *  @param {object} oSettings dataTables settings object
4247
	 *  @param {object} oSearch search information
4248
	 *  @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)
4249
	 *  @memberof DataTable#oApi
4250
	 */
4251
	function _fnFilterComplete ( oSettings, oInput, iForce )
4252
	{
4253
		var oPrevSearch = oSettings.oPreviousSearch;
4254
		var aoPrevSearch = oSettings.aoPreSearchCols;
4255
		var fnSaveFilter = function ( oFilter ) {
4256
			/* Save the filtering values */
4257
			oPrevSearch.sSearch = oFilter.sSearch;
4258
			oPrevSearch.bRegex = oFilter.bRegex;
4259
			oPrevSearch.bSmart = oFilter.bSmart;
4260
			oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive;
4261
		};
4262
		var fnRegex = function ( o ) {
4263
			// Backwards compatibility with the bEscapeRegex option
4264
			return o.bEscapeRegex !== undefined ? !o.bEscapeRegex : o.bRegex;
4265
		};
4266
	
4267
		// Resolve any column types that are unknown due to addition or invalidation
4268
		// @todo As per sort - can this be moved into an event handler?
4269
		_fnColumnTypes( oSettings );
4270
	
4271
		/* In server-side processing all filtering is done by the server, so no point hanging around here */
4272
		if ( _fnDataSource( oSettings ) != 'ssp' )
4273
		{
4274
			/* Global filter */
4275
			_fnFilter( oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive );
4276
			fnSaveFilter( oInput );
4277
	
4278
			/* Now do the individual column filter */
4279
			for ( var i=0 ; i<aoPrevSearch.length ; i++ )
4280
			{
4281
				_fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, fnRegex(aoPrevSearch[i]),
4282
					aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive );
4283
			}
4284
	
4285
			/* Custom filtering */
4286
			_fnFilterCustom( oSettings );
4287
		}
4288
		else
4289
		{
4290
			fnSaveFilter( oInput );
4291
		}
4292
	
4293
		/* Tell the draw function we have been filtering */
4294
		oSettings.bFiltered = true;
4295
		_fnCallbackFire( oSettings, null, 'search', [oSettings] );
4296
	}
4297
	
4298
	
4299
	/**
4300
	 * Apply custom filtering functions
4301
	 *  @param {object} oSettings dataTables settings object
4302
	 *  @memberof DataTable#oApi
4303
	 */
4304
	function _fnFilterCustom( settings )
4305
	{
4306
		var filters = DataTable.ext.search;
4307
		var displayRows = settings.aiDisplay;
4308
		var row, rowIdx;
4309
	
4310
		for ( var i=0, ien=filters.length ; i<ien ; i++ ) {
4311
			var rows = [];
4312
	
4313
			// Loop over each row and see if it should be included
4314
			for ( var j=0, jen=displayRows.length ; j<jen ; j++ ) {
4315
				rowIdx = displayRows[ j ];
4316
				row = settings.aoData[ rowIdx ];
4317
	
4318
				if ( filters[i]( settings, row._aFilterData, rowIdx, row._aData, j ) ) {
4319
					rows.push( rowIdx );
4320
				}
4321
			}
4322
	
4323
			// So the array reference doesn't break set the results into the
4324
			// existing array
4325
			displayRows.length = 0;
4326
			$.merge( displayRows, rows );
4327
		}
4328
	}
4329
	
4330
	
4331
	/**
4332
	 * Filter the table on a per-column basis
4333
	 *  @param {object} oSettings dataTables settings object
4334
	 *  @param {string} sInput string to filter on
4335
	 *  @param {int} iColumn column to filter
4336
	 *  @param {bool} bRegex treat search string as a regular expression or not
4337
	 *  @param {bool} bSmart use smart filtering or not
4338
	 *  @param {bool} bCaseInsensitive Do case insenstive matching or not
4339
	 *  @memberof DataTable#oApi
4340
	 */
4341
	function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, caseInsensitive )
4342
	{
4343
		if ( searchStr === '' ) {
4344
			return;
4345
		}
4346
	
4347
		var data;
4348
		var out = [];
4349
		var display = settings.aiDisplay;
4350
		var rpSearch = _fnFilterCreateSearch( searchStr, regex, smart, caseInsensitive );
4351
	
4352
		for ( var i=0 ; i<display.length ; i++ ) {
4353
			data = settings.aoData[ display[i] ]._aFilterData[ colIdx ];
4354
	
4355
			if ( rpSearch.test( data ) ) {
4356
				out.push( display[i] );
4357
			}
4358
		}
4359
	
4360
		settings.aiDisplay = out;
4361
	}
4362
	
4363
	
4364
	/**
4365
	 * Filter the data table based on user input and draw the table
4366
	 *  @param {object} settings dataTables settings object
4367
	 *  @param {string} input string to filter on
4368
	 *  @param {int} force optional - force a research of the master array (1) or not (undefined or 0)
4369
	 *  @param {bool} regex treat as a regular expression or not
4370
	 *  @param {bool} smart perform smart filtering or not
4371
	 *  @param {bool} caseInsensitive Do case insenstive matching or not
4372
	 *  @memberof DataTable#oApi
4373
	 */
4374
	function _fnFilter( settings, input, force, regex, smart, caseInsensitive )
4375
	{
4376
		var rpSearch = _fnFilterCreateSearch( input, regex, smart, caseInsensitive );
4377
		var prevSearch = settings.oPreviousSearch.sSearch;
4378
		var displayMaster = settings.aiDisplayMaster;
4379
		var display, invalidated, i;
4380
		var filtered = [];
4381
	
4382
		// Need to take account of custom filtering functions - always filter
4383
		if ( DataTable.ext.search.length !== 0 ) {
4384
			force = true;
4385
		}
4386
	
4387
		// Check if any of the rows were invalidated
4388
		invalidated = _fnFilterData( settings );
4389
	
4390
		// If the input is blank - we just want the full data set
4391
		if ( input.length <= 0 ) {
4392
			settings.aiDisplay = displayMaster.slice();
4393
		}
4394
		else {
4395
			// New search - start from the master array
4396
			if ( invalidated ||
4397
				 force ||
4398
				 prevSearch.length > input.length ||
4399
				 input.indexOf(prevSearch) !== 0 ||
4400
				 settings.bSorted // On resort, the display master needs to be
4401
				                  // re-filtered since indexes will have changed
4402
			) {
4403
				settings.aiDisplay = displayMaster.slice();
4404
			}
4405
	
4406
			// Search the display array
4407
			display = settings.aiDisplay;
4408
	
4409
			for ( i=0 ; i<display.length ; i++ ) {
4410
				if ( rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) {
4411
					filtered.push( display[i] );
4412
				}
4413
			}
4414
	
4415
			settings.aiDisplay = filtered;
4416
		}
4417
	}
4418
	
4419
	
4420
	/**
4421
	 * Build a regular expression object suitable for searching a table
4422
	 *  @param {string} sSearch string to search for
4423
	 *  @param {bool} bRegex treat as a regular expression or not
4424
	 *  @param {bool} bSmart perform smart filtering or not
4425
	 *  @param {bool} bCaseInsensitive Do case insensitive matching or not
4426
	 *  @returns {RegExp} constructed object
4427
	 *  @memberof DataTable#oApi
4428
	 */
4429
	function _fnFilterCreateSearch( search, regex, smart, caseInsensitive )
4430
	{
4431
		search = regex ?
4432
			search :
4433
			_fnEscapeRegex( search );
4434
		
4435
		if ( smart ) {
4436
			/* For smart filtering we want to allow the search to work regardless of
4437
			 * word order. We also want double quoted text to be preserved, so word
4438
			 * order is important - a la google. So this is what we want to
4439
			 * generate:
4440
			 * 
4441
			 * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$
4442
			 */
4443
			var a = $.map( search.match( /"[^"]+"|[^ ]+/g ) || [''], function ( word ) {
4444
				if ( word.charAt(0) === '"' ) {
4445
					var m = word.match( /^"(.*)"$/ );
4446
					word = m ? m[1] : word;
4447
				}
4448
	
4449
				return word.replace('"', '');
4450
			} );
4451
	
4452
			search = '^(?=.*?'+a.join( ')(?=.*?' )+').*$';
4453
		}
4454
	
4455
		return new RegExp( search, caseInsensitive ? 'i' : '' );
4456
	}
4457
	
4458
	
4459
	/**
4460
	 * Escape a string such that it can be used in a regular expression
4461
	 *  @param {string} sVal string to escape
4462
	 *  @returns {string} escaped string
4463
	 *  @memberof DataTable#oApi
4464
	 */
4465
	var _fnEscapeRegex = DataTable.util.escapeRegex;
4466
	
4467
	var __filter_div = $('<div>')[0];
4468
	var __filter_div_textContent = __filter_div.textContent !== undefined;
4469
	
4470
	// Update the filtering data for each row if needed (by invalidation or first run)
4471
	function _fnFilterData ( settings )
4472
	{
4473
		var columns = settings.aoColumns;
4474
		var column;
4475
		var i, j, ien, jen, filterData, cellData, row;
4476
		var fomatters = DataTable.ext.type.search;
4477
		var wasInvalidated = false;
4478
	
4479
		for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
4480
			row = settings.aoData[i];
4481
	
4482
			if ( ! row._aFilterData ) {
4483
				filterData = [];
4484
	
4485
				for ( j=0, jen=columns.length ; j<jen ; j++ ) {
4486
					column = columns[j];
4487
	
4488
					if ( column.bSearchable ) {
4489
						cellData = _fnGetCellData( settings, i, j, 'filter' );
4490
	
4491
						if ( fomatters[ column.sType ] ) {
4492
							cellData = fomatters[ column.sType ]( cellData );
4493
						}
4494
	
4495
						// Search in DataTables 1.10 is string based. In 1.11 this
4496
						// should be altered to also allow strict type checking.
4497
						if ( cellData === null ) {
4498
							cellData = '';
4499
						}
4500
	
4501
						if ( typeof cellData !== 'string' && cellData.toString ) {
4502
							cellData = cellData.toString();
4503
						}
4504
					}
4505
					else {
4506
						cellData = '';
4507
					}
4508
	
4509
					// If it looks like there is an HTML entity in the string,
4510
					// attempt to decode it so sorting works as expected. Note that
4511
					// we could use a single line of jQuery to do this, but the DOM
4512
					// method used here is much faster http://jsperf.com/html-decode
4513
					if ( cellData.indexOf && cellData.indexOf('&') !== -1 ) {
4514
						__filter_div.innerHTML = cellData;
4515
						cellData = __filter_div_textContent ?
4516
							__filter_div.textContent :
4517
							__filter_div.innerText;
4518
					}
4519
	
4520
					if ( cellData.replace ) {
4521
						cellData = cellData.replace(/[\r\n]/g, '');
4522
					}
4523
	
4524
					filterData.push( cellData );
4525
				}
4526
	
4527
				row._aFilterData = filterData;
4528
				row._sFilterRow = filterData.join('  ');
4529
				wasInvalidated = true;
4530
			}
4531
		}
4532
	
4533
		return wasInvalidated;
4534
	}
4535
	
4536
	
4537
	/**
4538
	 * Convert from the internal Hungarian notation to camelCase for external
4539
	 * interaction
4540
	 *  @param {object} obj Object to convert
4541
	 *  @returns {object} Inverted object
4542
	 *  @memberof DataTable#oApi
4543
	 */
4544
	function _fnSearchToCamel ( obj )
4545
	{
4546
		return {
4547
			search:          obj.sSearch,
4548
			smart:           obj.bSmart,
4549
			regex:           obj.bRegex,
4550
			caseInsensitive: obj.bCaseInsensitive
4551
		};
4552
	}
4553
	
4554
	
4555
	
4556
	/**
4557
	 * Convert from camelCase notation to the internal Hungarian. We could use the
4558
	 * Hungarian convert function here, but this is cleaner
4559
	 *  @param {object} obj Object to convert
4560
	 *  @returns {object} Inverted object
4561
	 *  @memberof DataTable#oApi
4562
	 */
4563
	function _fnSearchToHung ( obj )
4564
	{
4565
		return {
4566
			sSearch:          obj.search,
4567
			bSmart:           obj.smart,
4568
			bRegex:           obj.regex,
4569
			bCaseInsensitive: obj.caseInsensitive
4570
		};
4571
	}
4572
	
4573
	/**
4574
	 * Generate the node required for the info display
4575
	 *  @param {object} oSettings dataTables settings object
4576
	 *  @returns {node} Information element
4577
	 *  @memberof DataTable#oApi
4578
	 */
4579
	function _fnFeatureHtmlInfo ( settings )
4580
	{
4581
		var
4582
			tid = settings.sTableId,
4583
			nodes = settings.aanFeatures.i,
4584
			n = $('<div/>', {
4585
				'class': settings.oClasses.sInfo,
4586
				'id': ! nodes ? tid+'_info' : null
4587
			} );
4588
	
4589
		if ( ! nodes ) {
4590
			// Update display on each draw
4591
			settings.aoDrawCallback.push( {
4592
				"fn": _fnUpdateInfo,
4593
				"sName": "information"
4594
			} );
4595
	
4596
			n
4597
				.attr( 'role', 'status' )
4598
				.attr( 'aria-live', 'polite' );
4599
	
4600
			// Table is described by our info div
4601
			$(settings.nTable).attr( 'aria-describedby', tid+'_info' );
4602
		}
4603
	
4604
		return n[0];
4605
	}
4606
	
4607
	
4608
	/**
4609
	 * Update the information elements in the display
4610
	 *  @param {object} settings dataTables settings object
4611
	 *  @memberof DataTable#oApi
4612
	 */
4613
	function _fnUpdateInfo ( settings )
4614
	{
4615
		/* Show information about the table */
4616
		var nodes = settings.aanFeatures.i;
4617
		if ( nodes.length === 0 ) {
4618
			return;
4619
		}
4620
	
4621
		var
4622
			lang  = settings.oLanguage,
4623
			start = settings._iDisplayStart+1,
4624
			end   = settings.fnDisplayEnd(),
4625
			max   = settings.fnRecordsTotal(),
4626
			total = settings.fnRecordsDisplay(),
4627
			out   = total ?
4628
				lang.sInfo :
4629
				lang.sInfoEmpty;
4630
	
4631
		if ( total !== max ) {
4632
			/* Record set after filtering */
4633
			out += ' ' + lang.sInfoFiltered;
4634
		}
4635
	
4636
		// Convert the macros
4637
		out += lang.sInfoPostFix;
4638
		out = _fnInfoMacros( settings, out );
4639
	
4640
		var callback = lang.fnInfoCallback;
4641
		if ( callback !== null ) {
4642
			out = callback.call( settings.oInstance,
4643
				settings, start, end, max, total, out
4644
			);
4645
		}
4646
	
4647
		$(nodes).html( out );
4648
	}
4649
	
4650
	
4651
	function _fnInfoMacros ( settings, str )
4652
	{
4653
		// When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
4654
		// internally
4655
		var
4656
			formatter  = settings.fnFormatNumber,
4657
			start      = settings._iDisplayStart+1,
4658
			len        = settings._iDisplayLength,
4659
			vis        = settings.fnRecordsDisplay(),
4660
			all        = len === -1;
4661
	
4662
		return str.
4663
			replace(/_START_/g, formatter.call( settings, start ) ).
4664
			replace(/_END_/g,   formatter.call( settings, settings.fnDisplayEnd() ) ).
4665
			replace(/_MAX_/g,   formatter.call( settings, settings.fnRecordsTotal() ) ).
4666
			replace(/_TOTAL_/g, formatter.call( settings, vis ) ).
4667
			replace(/_PAGE_/g,  formatter.call( settings, all ? 1 : Math.ceil( start / len ) ) ).
4668
			replace(/_PAGES_/g, formatter.call( settings, all ? 1 : Math.ceil( vis / len ) ) );
4669
	}
4670
	
4671
	
4672
	
4673
	/**
4674
	 * Draw the table for the first time, adding all required features
4675
	 *  @param {object} settings dataTables settings object
4676
	 *  @memberof DataTable#oApi
4677
	 */
4678
	function _fnInitialise ( settings )
4679
	{
4680
		var i, iLen, iAjaxStart=settings.iInitDisplayStart;
4681
		var columns = settings.aoColumns, column;
4682
		var features = settings.oFeatures;
4683
		var deferLoading = settings.bDeferLoading; // value modified by the draw
4684
	
4685
		/* Ensure that the table data is fully initialised */
4686
		if ( ! settings.bInitialised ) {
4687
			setTimeout( function(){ _fnInitialise( settings ); }, 200 );
4688
			return;
4689
		}
4690
	
4691
		/* Show the display HTML options */
4692
		_fnAddOptionsHtml( settings );
4693
	
4694
		/* Build and draw the header / footer for the table */
4695
		_fnBuildHead( settings );
4696
		_fnDrawHead( settings, settings.aoHeader );
4697
		_fnDrawHead( settings, settings.aoFooter );
4698
	
4699
		/* Okay to show that something is going on now */
4700
		_fnProcessingDisplay( settings, true );
4701
	
4702
		/* Calculate sizes for columns */
4703
		if ( features.bAutoWidth ) {
4704
			_fnCalculateColumnWidths( settings );
4705
		}
4706
	
4707
		for ( i=0, iLen=columns.length ; i<iLen ; i++ ) {
4708
			column = columns[i];
4709
	
4710
			if ( column.sWidth ) {
4711
				column.nTh.style.width = _fnStringToCss( column.sWidth );
4712
			}
4713
		}
4714
	
4715
		_fnCallbackFire( settings, null, 'preInit', [settings] );
4716
	
4717
		// If there is default sorting required - let's do it. The sort function
4718
		// will do the drawing for us. Otherwise we draw the table regardless of the
4719
		// Ajax source - this allows the table to look initialised for Ajax sourcing
4720
		// data (show 'loading' message possibly)
4721
		_fnReDraw( settings );
4722
	
4723
		// Server-side processing init complete is done by _fnAjaxUpdateDraw
4724
		var dataSrc = _fnDataSource( settings );
4725
		if ( dataSrc != 'ssp' || deferLoading ) {
4726
			// if there is an ajax source load the data
4727
			if ( dataSrc == 'ajax' ) {
4728
				_fnBuildAjax( settings, [], function(json) {
0 ignored issues
show
Bug introduced by
The call to _fnBuildAjax seems to have too many arguments starting with settings.
Loading history...
4729
					var aData = _fnAjaxDataSrc( settings, json );
4730
	
4731
					// Got the data - add it to the table
4732
					for ( i=0 ; i<aData.length ; i++ ) {
0 ignored issues
show
Bug introduced by
The variable i is changed as part of the for loop for example by i++ on line 4732. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
4733
						_fnAddData( settings, aData[i] );
4734
					}
4735
	
4736
					// Reset the init display for cookie saving. We've already done
4737
					// a filter, and therefore cleared it before. So we need to make
4738
					// it appear 'fresh'
4739
					settings.iInitDisplayStart = iAjaxStart;
4740
	
4741
					_fnReDraw( settings );
4742
	
4743
					_fnProcessingDisplay( settings, false );
4744
					_fnInitComplete( settings, json );
4745
				}, settings );
4746
			}
4747
			else {
4748
				_fnProcessingDisplay( settings, false );
4749
				_fnInitComplete( settings );
4750
			}
4751
		}
4752
	}
4753
	
4754
	
4755
	/**
4756
	 * Draw the table for the first time, adding all required features
4757
	 *  @param {object} oSettings dataTables settings object
4758
	 *  @param {object} [json] JSON from the server that completed the table, if using Ajax source
4759
	 *    with client-side processing (optional)
4760
	 *  @memberof DataTable#oApi
4761
	 */
4762
	function _fnInitComplete ( settings, json )
4763
	{
4764
		settings._bInitComplete = true;
4765
	
4766
		// When data was added after the initialisation (data or Ajax) we need to
4767
		// calculate the column sizing
4768
		if ( json || settings.oInit.aaData ) {
4769
			_fnAdjustColumnSizing( settings );
4770
		}
4771
	
4772
		_fnCallbackFire( settings, null, 'plugin-init', [settings, json] );
4773
		_fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] );
4774
	}
4775
	
4776
	
4777
	function _fnLengthChange ( settings, val )
4778
	{
4779
		var len = parseInt( val, 10 );
4780
		settings._iDisplayLength = len;
4781
	
4782
		_fnLengthOverflow( settings );
4783
	
4784
		// Fire length change event
4785
		_fnCallbackFire( settings, null, 'length', [settings, len] );
4786
	}
4787
	
4788
	
4789
	/**
4790
	 * Generate the node required for user display length changing
4791
	 *  @param {object} settings dataTables settings object
4792
	 *  @returns {node} Display length feature node
4793
	 *  @memberof DataTable#oApi
4794
	 */
4795
	function _fnFeatureHtmlLength ( settings )
4796
	{
4797
		var
4798
			classes  = settings.oClasses,
4799
			tableId  = settings.sTableId,
4800
			menu     = settings.aLengthMenu,
4801
			d2       = $.isArray( menu[0] ),
4802
			lengths  = d2 ? menu[0] : menu,
4803
			language = d2 ? menu[1] : menu;
4804
	
4805
		var select = $('<select/>', {
4806
			'name':          tableId+'_length',
4807
			'aria-controls': tableId,
4808
			'class':         classes.sLengthSelect
4809
		} );
4810
	
4811
		for ( var i=0, ien=lengths.length ; i<ien ; i++ ) {
4812
			select[0][ i ] = new Option(
0 ignored issues
show
Bug introduced by
The variable Option seems to be never declared. If this is a global, consider adding a /** global: Option */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
4813
				typeof language[i] === 'number' ?
4814
					settings.fnFormatNumber( language[i] ) :
4815
					language[i],
4816
				lengths[i]
4817
			);
4818
		}
4819
	
4820
		var div = $('<div><label/></div>').addClass( classes.sLength );
4821
		if ( ! settings.aanFeatures.l ) {
4822
			div[0].id = tableId+'_length';
4823
		}
4824
	
4825
		div.children().append(
4826
			settings.oLanguage.sLengthMenu.replace( '_MENU_', select[0].outerHTML )
4827
		);
4828
	
4829
		// Can't use `select` variable as user might provide their own and the
4830
		// reference is broken by the use of outerHTML
4831
		$('select', div)
4832
			.val( settings._iDisplayLength )
4833
			.on( 'change.DT', function(e) {
0 ignored issues
show
Unused Code introduced by
The parameter e is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
4834
				_fnLengthChange( settings, $(this).val() );
4835
				_fnDraw( settings );
4836
			} );
4837
	
4838
		// Update node value whenever anything changes the table's length
4839
		$(settings.nTable).on( 'length.dt.DT', function (e, s, len) {
4840
			if ( settings === s ) {
4841
				$('select', div).val( len );
4842
			}
4843
		} );
4844
	
4845
		return div[0];
4846
	}
4847
	
4848
	
4849
	
4850
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
4851
	 * Note that most of the paging logic is done in
4852
	 * DataTable.ext.pager
4853
	 */
4854
	
4855
	/**
4856
	 * Generate the node required for default pagination
4857
	 *  @param {object} oSettings dataTables settings object
4858
	 *  @returns {node} Pagination feature node
4859
	 *  @memberof DataTable#oApi
4860
	 */
4861
	function _fnFeatureHtmlPaginate ( settings )
4862
	{
4863
		var
4864
			type   = settings.sPaginationType,
4865
			plugin = DataTable.ext.pager[ type ],
4866
			modern = typeof plugin === 'function',
4867
			redraw = function( settings ) {
4868
				_fnDraw( settings );
4869
			},
4870
			node = $('<div/>').addClass( settings.oClasses.sPaging + type )[0],
4871
			features = settings.aanFeatures;
4872
	
4873
		if ( ! modern ) {
4874
			plugin.fnInit( settings, node, redraw );
4875
		}
4876
	
4877
		/* Add a draw callback for the pagination on first instance, to update the paging display */
4878
		if ( ! features.p )
4879
		{
4880
			node.id = settings.sTableId+'_paginate';
4881
	
4882
			settings.aoDrawCallback.push( {
4883
				"fn": function( settings ) {
4884
					if ( modern ) {
4885
						var
4886
							start      = settings._iDisplayStart,
4887
							len        = settings._iDisplayLength,
4888
							visRecords = settings.fnRecordsDisplay(),
4889
							all        = len === -1,
4890
							page = all ? 0 : Math.ceil( start / len ),
4891
							pages = all ? 1 : Math.ceil( visRecords / len ),
4892
							buttons = plugin(page, pages),
4893
							i, ien;
4894
	
4895
						for ( i=0, ien=features.p.length ; i<ien ; i++ ) {
4896
							_fnRenderer( settings, 'pageButton' )(
4897
								settings, features.p[i], i, buttons, page, pages
4898
							);
4899
						}
4900
					}
4901
					else {
4902
						plugin.fnUpdate( settings, redraw );
4903
					}
4904
				},
4905
				"sName": "pagination"
4906
			} );
4907
		}
4908
	
4909
		return node;
4910
	}
4911
	
4912
	
4913
	/**
4914
	 * Alter the display settings to change the page
4915
	 *  @param {object} settings DataTables settings object
4916
	 *  @param {string|int} action Paging action to take: "first", "previous",
4917
	 *    "next" or "last" or page number to jump to (integer)
4918
	 *  @param [bool] redraw Automatically draw the update or not
4919
	 *  @returns {bool} true page has changed, false - no change
4920
	 *  @memberof DataTable#oApi
4921
	 */
4922
	function _fnPageChange ( settings, action, redraw )
4923
	{
4924
		var
4925
			start     = settings._iDisplayStart,
4926
			len       = settings._iDisplayLength,
4927
			records   = settings.fnRecordsDisplay();
4928
	
4929
		if ( records === 0 || len === -1 )
4930
		{
4931
			start = 0;
4932
		}
4933
		else if ( typeof action === "number" )
4934
		{
4935
			start = action * len;
4936
	
4937
			if ( start > records )
4938
			{
4939
				start = 0;
4940
			}
4941
		}
4942
		else if ( action == "first" )
4943
		{
4944
			start = 0;
4945
		}
4946
		else if ( action == "previous" )
4947
		{
4948
			start = len >= 0 ?
4949
				start - len :
4950
				0;
4951
	
4952
			if ( start < 0 )
4953
			{
4954
			  start = 0;
4955
			}
4956
		}
4957
		else if ( action == "next" )
4958
		{
4959
			if ( start + len < records )
4960
			{
4961
				start += len;
4962
			}
4963
		}
4964
		else if ( action == "last" )
4965
		{
4966
			start = Math.floor( (records-1) / len) * len;
4967
		}
4968
		else
4969
		{
4970
			_fnLog( settings, 0, "Unknown paging action: "+action, 5 );
4971
		}
4972
	
4973
		var changed = settings._iDisplayStart !== start;
4974
		settings._iDisplayStart = start;
4975
	
4976
		if ( changed ) {
4977
			_fnCallbackFire( settings, null, 'page', [settings] );
4978
	
4979
			if ( redraw ) {
4980
				_fnDraw( settings );
4981
			}
4982
		}
4983
	
4984
		return changed;
4985
	}
4986
	
4987
	
4988
	
4989
	/**
4990
	 * Generate the node required for the processing node
4991
	 *  @param {object} settings dataTables settings object
4992
	 *  @returns {node} Processing element
4993
	 *  @memberof DataTable#oApi
4994
	 */
4995
	function _fnFeatureHtmlProcessing ( settings )
4996
	{
4997
		return $('<div/>', {
4998
				'id': ! settings.aanFeatures.r ? settings.sTableId+'_processing' : null,
4999
				'class': settings.oClasses.sProcessing
5000
			} )
5001
			.html( settings.oLanguage.sProcessing )
5002
			.insertBefore( settings.nTable )[0];
5003
	}
5004
	
5005
	
5006
	/**
5007
	 * Display or hide the processing indicator
5008
	 *  @param {object} settings dataTables settings object
5009
	 *  @param {bool} show Show the processing indicator (true) or not (false)
5010
	 *  @memberof DataTable#oApi
5011
	 */
5012
	function _fnProcessingDisplay ( settings, show )
5013
	{
5014
		if ( settings.oFeatures.bProcessing ) {
5015
			$(settings.aanFeatures.r).css( 'display', show ? 'block' : 'none' );
5016
		}
5017
	
5018
		_fnCallbackFire( settings, null, 'processing', [settings, show] );
5019
	}
5020
	
5021
	/**
5022
	 * Add any control elements for the table - specifically scrolling
5023
	 *  @param {object} settings dataTables settings object
5024
	 *  @returns {node} Node to add to the DOM
5025
	 *  @memberof DataTable#oApi
5026
	 */
5027
	function _fnFeatureHtmlTable ( settings )
5028
	{
5029
		var table = $(settings.nTable);
5030
	
5031
		// Add the ARIA grid role to the table
5032
		table.attr( 'role', 'grid' );
5033
	
5034
		// Scrolling from here on in
5035
		var scroll = settings.oScroll;
5036
	
5037
		if ( scroll.sX === '' && scroll.sY === '' ) {
5038
			return settings.nTable;
5039
		}
5040
	
5041
		var scrollX = scroll.sX;
5042
		var scrollY = scroll.sY;
5043
		var classes = settings.oClasses;
5044
		var caption = table.children('caption');
5045
		var captionSide = caption.length ? caption[0]._captionSide : null;
5046
		var headerClone = $( table[0].cloneNode(false) );
5047
		var footerClone = $( table[0].cloneNode(false) );
5048
		var footer = table.children('tfoot');
5049
		var _div = '<div/>';
5050
		var size = function ( s ) {
5051
			return !s ? null : _fnStringToCss( s );
5052
		};
5053
	
5054
		if ( ! footer.length ) {
5055
			footer = null;
5056
		}
5057
	
5058
		/*
5059
		 * The HTML structure that we want to generate in this function is:
5060
		 *  div - scroller
5061
		 *    div - scroll head
5062
		 *      div - scroll head inner
5063
		 *        table - scroll head table
5064
		 *          thead - thead
5065
		 *    div - scroll body
5066
		 *      table - table (master table)
5067
		 *        thead - thead clone for sizing
5068
		 *        tbody - tbody
5069
		 *    div - scroll foot
5070
		 *      div - scroll foot inner
5071
		 *        table - scroll foot table
5072
		 *          tfoot - tfoot
5073
		 */
5074
		var scroller = $( _div, { 'class': classes.sScrollWrapper } )
5075
			.append(
5076
				$(_div, { 'class': classes.sScrollHead } )
5077
					.css( {
5078
						overflow: 'hidden',
5079
						position: 'relative',
5080
						border: 0,
5081
						width: scrollX ? size(scrollX) : '100%'
5082
					} )
5083
					.append(
5084
						$(_div, { 'class': classes.sScrollHeadInner } )
5085
							.css( {
5086
								'box-sizing': 'content-box',
5087
								width: scroll.sXInner || '100%'
5088
							} )
5089
							.append(
5090
								headerClone
5091
									.removeAttr('id')
5092
									.css( 'margin-left', 0 )
5093
									.append( captionSide === 'top' ? caption : null )
5094
									.append(
5095
										table.children('thead')
5096
									)
5097
							)
5098
					)
5099
			)
5100
			.append(
5101
				$(_div, { 'class': classes.sScrollBody } )
5102
					.css( {
5103
						position: 'relative',
5104
						overflow: 'auto',
5105
						width: size( scrollX )
5106
					} )
5107
					.append( table )
5108
			);
5109
	
5110
		if ( footer ) {
5111
			scroller.append(
5112
				$(_div, { 'class': classes.sScrollFoot } )
5113
					.css( {
5114
						overflow: 'hidden',
5115
						border: 0,
5116
						width: scrollX ? size(scrollX) : '100%'
5117
					} )
5118
					.append(
5119
						$(_div, { 'class': classes.sScrollFootInner } )
5120
							.append(
5121
								footerClone
5122
									.removeAttr('id')
5123
									.css( 'margin-left', 0 )
5124
									.append( captionSide === 'bottom' ? caption : null )
5125
									.append(
5126
										table.children('tfoot')
5127
									)
5128
							)
5129
					)
5130
			);
5131
		}
5132
	
5133
		var children = scroller.children();
5134
		var scrollHead = children[0];
5135
		var scrollBody = children[1];
5136
		var scrollFoot = footer ? children[2] : null;
5137
	
5138
		// When the body is scrolled, then we also want to scroll the headers
5139
		if ( scrollX ) {
5140
			$(scrollBody).on( 'scroll.DT', function (e) {
0 ignored issues
show
Unused Code introduced by
The parameter e is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
5141
				var scrollLeft = this.scrollLeft;
5142
	
5143
				scrollHead.scrollLeft = scrollLeft;
5144
	
5145
				if ( footer ) {
5146
					scrollFoot.scrollLeft = scrollLeft;
5147
				}
5148
			} );
5149
		}
5150
	
5151
		$(scrollBody).css(
5152
			scrollY && scroll.bCollapse ? 'max-height' : 'height', 
5153
			scrollY
5154
		);
5155
	
5156
		settings.nScrollHead = scrollHead;
5157
		settings.nScrollBody = scrollBody;
5158
		settings.nScrollFoot = scrollFoot;
5159
	
5160
		// On redraw - align columns
5161
		settings.aoDrawCallback.push( {
5162
			"fn": _fnScrollDraw,
5163
			"sName": "scrolling"
5164
		} );
5165
	
5166
		return scroller[0];
5167
	}
5168
	
5169
	
5170
	
5171
	/**
5172
	 * Update the header, footer and body tables for resizing - i.e. column
5173
	 * alignment.
5174
	 *
5175
	 * Welcome to the most horrible function DataTables. The process that this
5176
	 * function follows is basically:
5177
	 *   1. Re-create the table inside the scrolling div
5178
	 *   2. Take live measurements from the DOM
5179
	 *   3. Apply the measurements to align the columns
5180
	 *   4. Clean up
5181
	 *
5182
	 *  @param {object} settings dataTables settings object
5183
	 *  @memberof DataTable#oApi
5184
	 */
5185
	function _fnScrollDraw ( settings )
5186
	{
5187
		// Given that this is such a monster function, a lot of variables are use
5188
		// to try and keep the minimised size as small as possible
5189
		var
5190
			scroll         = settings.oScroll,
5191
			scrollX        = scroll.sX,
5192
			scrollXInner   = scroll.sXInner,
5193
			scrollY        = scroll.sY,
5194
			barWidth       = scroll.iBarWidth,
5195
			divHeader      = $(settings.nScrollHead),
5196
			divHeaderStyle = divHeader[0].style,
5197
			divHeaderInner = divHeader.children('div'),
5198
			divHeaderInnerStyle = divHeaderInner[0].style,
5199
			divHeaderTable = divHeaderInner.children('table'),
5200
			divBodyEl      = settings.nScrollBody,
5201
			divBody        = $(divBodyEl),
5202
			divBodyStyle   = divBodyEl.style,
5203
			divFooter      = $(settings.nScrollFoot),
5204
			divFooterInner = divFooter.children('div'),
5205
			divFooterTable = divFooterInner.children('table'),
5206
			header         = $(settings.nTHead),
5207
			table          = $(settings.nTable),
5208
			tableEl        = table[0],
5209
			tableStyle     = tableEl.style,
5210
			footer         = settings.nTFoot ? $(settings.nTFoot) : null,
5211
			browser        = settings.oBrowser,
5212
			ie67           = browser.bScrollOversize,
5213
			dtHeaderCells  = _pluck( settings.aoColumns, 'nTh' ),
5214
			headerTrgEls, footerTrgEls,
5215
			headerSrcEls, footerSrcEls,
5216
			headerCopy, footerCopy,
5217
			headerWidths=[], footerWidths=[],
5218
			headerContent=[], footerContent=[],
5219
			idx, correction, sanityWidth,
5220
			zeroOut = function(nSizer) {
5221
				var style = nSizer.style;
5222
				style.paddingTop = "0";
5223
				style.paddingBottom = "0";
5224
				style.borderTopWidth = "0";
5225
				style.borderBottomWidth = "0";
5226
				style.height = 0;
5227
			};
5228
	
5229
		// If the scrollbar visibility has changed from the last draw, we need to
5230
		// adjust the column sizes as the table width will have changed to account
5231
		// for the scrollbar
5232
		var scrollBarVis = divBodyEl.scrollHeight > divBodyEl.clientHeight;
5233
		
5234
		if ( settings.scrollBarVis !== scrollBarVis && settings.scrollBarVis !== undefined ) {
5235
			settings.scrollBarVis = scrollBarVis;
5236
			_fnAdjustColumnSizing( settings );
5237
			return; // adjust column sizing will call this function again
5238
		}
5239
		else {
5240
			settings.scrollBarVis = scrollBarVis;
5241
		}
5242
	
5243
		/*
5244
		 * 1. Re-create the table inside the scrolling div
5245
		 */
5246
	
5247
		// Remove the old minimised thead and tfoot elements in the inner table
5248
		table.children('thead, tfoot').remove();
5249
	
5250
		if ( footer ) {
5251
			footerCopy = footer.clone().prependTo( table );
5252
			footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized
5253
			footerSrcEls = footerCopy.find('tr');
5254
		}
5255
	
5256
		// Clone the current header and footer elements and then place it into the inner table
5257
		headerCopy = header.clone().prependTo( table );
5258
		headerTrgEls = header.find('tr'); // original header is in its own table
5259
		headerSrcEls = headerCopy.find('tr');
5260
		headerCopy.find('th, td').removeAttr('tabindex');
5261
	
5262
	
5263
		/*
5264
		 * 2. Take live measurements from the DOM - do not alter the DOM itself!
5265
		 */
5266
	
5267
		// Remove old sizing and apply the calculated column widths
5268
		// Get the unique column headers in the newly created (cloned) header. We want to apply the
5269
		// calculated sizes to this header
5270
		if ( ! scrollX )
5271
		{
5272
			divBodyStyle.width = '100%';
5273
			divHeader[0].style.width = '100%';
5274
		}
5275
	
5276
		$.each( _fnGetUniqueThs( settings, headerCopy ), function ( i, el ) {
5277
			idx = _fnVisibleToColumnIndex( settings, i );
5278
			el.style.width = settings.aoColumns[idx].sWidth;
5279
		} );
5280
	
5281
		if ( footer ) {
5282
			_fnApplyToChildren( function(n) {
5283
				n.style.width = "";
5284
			}, footerSrcEls );
0 ignored issues
show
Bug introduced by
The variable footerSrcEls does not seem to be initialized in case footer on line 5250 is false. Are you sure the function _fnApplyToChildren handles undefined variables?
Loading history...
5285
		}
5286
	
5287
		// Size the table as a whole
5288
		sanityWidth = table.outerWidth();
5289
		if ( scrollX === "" ) {
5290
			// No x scrolling
5291
			tableStyle.width = "100%";
5292
	
5293
			// IE7 will make the width of the table when 100% include the scrollbar
5294
			// - which is shouldn't. When there is a scrollbar we need to take this
5295
			// into account.
5296
			if ( ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight ||
5297
				divBody.css('overflow-y') == "scroll")
5298
			) {
5299
				tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth);
5300
			}
5301
	
5302
			// Recalculate the sanity width
5303
			sanityWidth = table.outerWidth();
5304
		}
5305
		else if ( scrollXInner !== "" ) {
5306
			// legacy x scroll inner has been given - use it
5307
			tableStyle.width = _fnStringToCss(scrollXInner);
5308
	
5309
			// Recalculate the sanity width
5310
			sanityWidth = table.outerWidth();
5311
		}
5312
	
5313
		// Hidden header should have zero height, so remove padding and borders. Then
5314
		// set the width based on the real headers
5315
	
5316
		// Apply all styles in one pass
5317
		_fnApplyToChildren( zeroOut, headerSrcEls );
5318
	
5319
		// Read all widths in next pass
5320
		_fnApplyToChildren( function(nSizer) {
5321
			headerContent.push( nSizer.innerHTML );
5322
			headerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
5323
		}, headerSrcEls );
5324
	
5325
		// Apply all widths in final pass
5326
		_fnApplyToChildren( function(nToSize, i) {
5327
			// Only apply widths to the DataTables detected header cells - this
5328
			// prevents complex headers from having contradictory sizes applied
5329
			if ( $.inArray( nToSize, dtHeaderCells ) !== -1 ) {
5330
				nToSize.style.width = headerWidths[i];
5331
			}
5332
		}, headerTrgEls );
5333
	
5334
		$(headerSrcEls).height(0);
5335
	
5336
		/* Same again with the footer if we have one */
5337
		if ( footer )
5338
		{
5339
			_fnApplyToChildren( zeroOut, footerSrcEls );
0 ignored issues
show
Bug introduced by
The variable footerSrcEls does not seem to be initialized in case footer on line 5250 is false. Are you sure the function _fnApplyToChildren handles undefined variables?
Loading history...
5340
	
5341
			_fnApplyToChildren( function(nSizer) {
5342
				footerContent.push( nSizer.innerHTML );
5343
				footerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
5344
			}, footerSrcEls );
0 ignored issues
show
Bug introduced by
The variable footerSrcEls does not seem to be initialized in case footer on line 5250 is false. Are you sure the function _fnApplyToChildren handles undefined variables?
Loading history...
5345
	
5346
			_fnApplyToChildren( function(nToSize, i) {
5347
				nToSize.style.width = footerWidths[i];
5348
			}, footerTrgEls );
0 ignored issues
show
Bug introduced by
The variable footerTrgEls does not seem to be initialized in case footer on line 5250 is false. Are you sure the function _fnApplyToChildren handles undefined variables?
Loading history...
5349
	
5350
			$(footerSrcEls).height(0);
0 ignored issues
show
Bug introduced by
The variable footerSrcEls does not seem to be initialized in case footer on line 5250 is false. Are you sure the function $ handles undefined variables?
Loading history...
5351
		}
5352
	
5353
	
5354
		/*
5355
		 * 3. Apply the measurements
5356
		 */
5357
	
5358
		// "Hide" the header and footer that we used for the sizing. We need to keep
5359
		// the content of the cell so that the width applied to the header and body
5360
		// both match, but we want to hide it completely. We want to also fix their
5361
		// width to what they currently are
5362
		_fnApplyToChildren( function(nSizer, i) {
5363
			nSizer.innerHTML = '<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+headerContent[i]+'</div>';
5364
			nSizer.style.width = headerWidths[i];
5365
		}, headerSrcEls );
5366
	
5367
		if ( footer )
5368
		{
5369
			_fnApplyToChildren( function(nSizer, i) {
5370
				nSizer.innerHTML = '<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+footerContent[i]+'</div>';
5371
				nSizer.style.width = footerWidths[i];
5372
			}, footerSrcEls );
0 ignored issues
show
Bug introduced by
The variable footerSrcEls does not seem to be initialized in case footer on line 5250 is false. Are you sure the function _fnApplyToChildren handles undefined variables?
Loading history...
5373
		}
5374
	
5375
		// Sanity check that the table is of a sensible width. If not then we are going to get
5376
		// misalignment - try to prevent this by not allowing the table to shrink below its min width
5377
		if ( table.outerWidth() < sanityWidth )
5378
		{
5379
			// The min width depends upon if we have a vertical scrollbar visible or not */
5380
			correction = ((divBodyEl.scrollHeight > divBodyEl.offsetHeight ||
5381
				divBody.css('overflow-y') == "scroll")) ?
5382
					sanityWidth+barWidth :
5383
					sanityWidth;
5384
	
5385
			// IE6/7 are a law unto themselves...
5386
			if ( ie67 && (divBodyEl.scrollHeight >
5387
				divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll")
5388
			) {
5389
				tableStyle.width = _fnStringToCss( correction-barWidth );
5390
			}
5391
	
5392
			// And give the user a warning that we've stopped the table getting too small
5393
			if ( scrollX === "" || scrollXInner !== "" ) {
5394
				_fnLog( settings, 1, 'Possible column misalignment', 6 );
5395
			}
5396
		}
5397
		else
5398
		{
5399
			correction = '100%';
5400
		}
5401
	
5402
		// Apply to the container elements
5403
		divBodyStyle.width = _fnStringToCss( correction );
5404
		divHeaderStyle.width = _fnStringToCss( correction );
5405
	
5406
		if ( footer ) {
5407
			settings.nScrollFoot.style.width = _fnStringToCss( correction );
5408
		}
5409
	
5410
	
5411
		/*
5412
		 * 4. Clean up
5413
		 */
5414
		if ( ! scrollY ) {
5415
			/* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
5416
			 * the scrollbar height from the visible display, rather than adding it on. We need to
5417
			 * set the height in order to sort this. Don't want to do it in any other browsers.
5418
			 */
5419
			if ( ie67 ) {
5420
				divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+barWidth );
5421
			}
5422
		}
5423
	
5424
		/* Finally set the width's of the header and footer tables */
5425
		var iOuterWidth = table.outerWidth();
5426
		divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth );
5427
		divHeaderInnerStyle.width = _fnStringToCss( iOuterWidth );
5428
	
5429
		// Figure out if there are scrollbar present - if so then we need a the header and footer to
5430
		// provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
5431
		var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll";
5432
		var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' );
5433
		divHeaderInnerStyle[ padding ] = bScrolling ? barWidth+"px" : "0px";
5434
	
5435
		if ( footer ) {
5436
			divFooterTable[0].style.width = _fnStringToCss( iOuterWidth );
5437
			divFooterInner[0].style.width = _fnStringToCss( iOuterWidth );
5438
			divFooterInner[0].style[padding] = bScrolling ? barWidth+"px" : "0px";
5439
		}
5440
	
5441
		// Correct DOM ordering for colgroup - comes before the thead
5442
		table.children('colgroup').insertBefore( table.children('thead') );
5443
	
5444
		/* Adjust the position of the header in case we loose the y-scrollbar */
5445
		divBody.scroll();
5446
	
5447
		// If sorting or filtering has occurred, jump the scrolling back to the top
5448
		// only if we aren't holding the position
5449
		if ( (settings.bSorted || settings.bFiltered) && ! settings._drawHold ) {
5450
			divBodyEl.scrollTop = 0;
5451
		}
5452
	}
5453
	
5454
	
5455
	
5456
	/**
5457
	 * Apply a given function to the display child nodes of an element array (typically
5458
	 * TD children of TR rows
5459
	 *  @param {function} fn Method to apply to the objects
5460
	 *  @param array {nodes} an1 List of elements to look through for display children
5461
	 *  @param array {nodes} an2 Another list (identical structure to the first) - optional
0 ignored issues
show
Documentation introduced by
The parameter array has already been documented on line 5460. The second definition is ignored.
Loading history...
5462
	 *  @memberof DataTable#oApi
5463
	 */
5464
	function _fnApplyToChildren( fn, an1, an2 )
5465
	{
5466
		var index=0, i=0, iLen=an1.length;
5467
		var nNode1, nNode2;
5468
	
5469
		while ( i < iLen ) {
5470
			nNode1 = an1[i].firstChild;
5471
			nNode2 = an2 ? an2[i].firstChild : null;
5472
	
5473
			while ( nNode1 ) {
5474
				if ( nNode1.nodeType === 1 ) {
5475
					if ( an2 ) {
5476
						fn( nNode1, nNode2, index );
5477
					}
5478
					else {
5479
						fn( nNode1, index );
5480
					}
5481
	
5482
					index++;
5483
				}
5484
	
5485
				nNode1 = nNode1.nextSibling;
5486
				nNode2 = an2 ? nNode2.nextSibling : null;
5487
			}
5488
	
5489
			i++;
5490
		}
5491
	}
5492
	
5493
	
5494
	
5495
	var __re_html_remove = /<.*?>/g;
5496
	
5497
	
5498
	/**
5499
	 * Calculate the width of columns for the table
5500
	 *  @param {object} oSettings dataTables settings object
5501
	 *  @memberof DataTable#oApi
5502
	 */
5503
	function _fnCalculateColumnWidths ( oSettings )
5504
	{
5505
		var
5506
			table = oSettings.nTable,
5507
			columns = oSettings.aoColumns,
5508
			scroll = oSettings.oScroll,
5509
			scrollY = scroll.sY,
5510
			scrollX = scroll.sX,
5511
			scrollXInner = scroll.sXInner,
5512
			columnCount = columns.length,
5513
			visibleColumns = _fnGetColumns( oSettings, 'bVisible' ),
5514
			headerCells = $('th', oSettings.nTHead),
5515
			tableWidthAttr = table.getAttribute('width'), // from DOM element
5516
			tableContainer = table.parentNode,
5517
			userInputs = false,
5518
			i, column, columnIdx, width, outerWidth,
5519
			browser = oSettings.oBrowser,
5520
			ie67 = browser.bScrollOversize;
5521
	
5522
		var styleWidth = table.style.width;
5523
		if ( styleWidth && styleWidth.indexOf('%') !== -1 ) {
5524
			tableWidthAttr = styleWidth;
5525
		}
5526
	
5527
		/* Convert any user input sizes into pixel sizes */
5528
		for ( i=0 ; i<visibleColumns.length ; i++ ) {
5529
			column = columns[ visibleColumns[i] ];
5530
	
5531
			if ( column.sWidth !== null ) {
5532
				column.sWidth = _fnConvertToWidth( column.sWidthOrig, tableContainer );
5533
	
5534
				userInputs = true;
5535
			}
5536
		}
5537
	
5538
		/* If the number of columns in the DOM equals the number that we have to
5539
		 * process in DataTables, then we can use the offsets that are created by
5540
		 * the web- browser. No custom sizes can be set in order for this to happen,
5541
		 * nor scrolling used
5542
		 */
5543
		if ( ie67 || ! userInputs && ! scrollX && ! scrollY &&
5544
		     columnCount == _fnVisbleColumns( oSettings ) &&
5545
		     columnCount == headerCells.length
5546
		) {
5547
			for ( i=0 ; i<columnCount ; i++ ) {
5548
				var colIdx = _fnVisibleToColumnIndex( oSettings, i );
5549
	
5550
				if ( colIdx !== null ) {
5551
					columns[ colIdx ].sWidth = _fnStringToCss( headerCells.eq(i).width() );
5552
				}
5553
			}
5554
		}
5555
		else
5556
		{
5557
			// Otherwise construct a single row, worst case, table with the widest
5558
			// node in the data, assign any user defined widths, then insert it into
5559
			// the DOM and allow the browser to do all the hard work of calculating
5560
			// table widths
5561
			var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table
5562
				.css( 'visibility', 'hidden' )
5563
				.removeAttr( 'id' );
5564
	
5565
			// Clean up the table body
5566
			tmpTable.find('tbody tr').remove();
5567
			var tr = $('<tr/>').appendTo( tmpTable.find('tbody') );
5568
	
5569
			// Clone the table header and footer - we can't use the header / footer
5570
			// from the cloned table, since if scrolling is active, the table's
5571
			// real header and footer are contained in different table tags
5572
			tmpTable.find('thead, tfoot').remove();
5573
			tmpTable
5574
				.append( $(oSettings.nTHead).clone() )
5575
				.append( $(oSettings.nTFoot).clone() );
5576
	
5577
			// Remove any assigned widths from the footer (from scrolling)
5578
			tmpTable.find('tfoot th, tfoot td').css('width', '');
5579
	
5580
			// Apply custom sizing to the cloned header
5581
			headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] );
5582
	
5583
			for ( i=0 ; i<visibleColumns.length ; i++ ) {
5584
				column = columns[ visibleColumns[i] ];
5585
	
5586
				headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ?
5587
					_fnStringToCss( column.sWidthOrig ) :
5588
					'';
5589
	
5590
				// For scrollX we need to force the column width otherwise the
5591
				// browser will collapse it. If this width is smaller than the
5592
				// width the column requires, then it will have no effect
5593
				if ( column.sWidthOrig && scrollX ) {
5594
					$( headerCells[i] ).append( $('<div/>').css( {
5595
						width: column.sWidthOrig,
5596
						margin: 0,
5597
						padding: 0,
5598
						border: 0,
5599
						height: 1
5600
					} ) );
5601
				}
5602
			}
5603
	
5604
			// Find the widest cell for each column and put it into the table
5605
			if ( oSettings.aoData.length ) {
5606
				for ( i=0 ; i<visibleColumns.length ; i++ ) {
5607
					columnIdx = visibleColumns[i];
5608
					column = columns[ columnIdx ];
5609
	
5610
					$( _fnGetWidestNode( oSettings, columnIdx ) )
5611
						.clone( false )
5612
						.append( column.sContentPadding )
5613
						.appendTo( tr );
5614
				}
5615
			}
5616
	
5617
			// Tidy the temporary table - remove name attributes so there aren't
5618
			// duplicated in the dom (radio elements for example)
5619
			$('[name]', tmpTable).removeAttr('name');
5620
	
5621
			// Table has been built, attach to the document so we can work with it.
5622
			// A holding element is used, positioned at the top of the container
5623
			// with minimal height, so it has no effect on if the container scrolls
5624
			// or not. Otherwise it might trigger scrolling when it actually isn't
5625
			// needed
5626
			var holder = $('<div/>').css( scrollX || scrollY ?
5627
					{
5628
						position: 'absolute',
5629
						top: 0,
5630
						left: 0,
5631
						height: 1,
5632
						right: 0,
5633
						overflow: 'hidden'
5634
					} :
5635
					{}
5636
				)
5637
				.append( tmpTable )
5638
				.appendTo( tableContainer );
5639
	
5640
			// When scrolling (X or Y) we want to set the width of the table as 
5641
			// appropriate. However, when not scrolling leave the table width as it
5642
			// is. This results in slightly different, but I think correct behaviour
5643
			if ( scrollX && scrollXInner ) {
5644
				tmpTable.width( scrollXInner );
5645
			}
5646
			else if ( scrollX ) {
5647
				tmpTable.css( 'width', 'auto' );
5648
				tmpTable.removeAttr('width');
5649
	
5650
				// If there is no width attribute or style, then allow the table to
5651
				// collapse
5652
				if ( tmpTable.width() < tableContainer.clientWidth && tableWidthAttr ) {
5653
					tmpTable.width( tableContainer.clientWidth );
5654
				}
5655
			}
5656
			else if ( scrollY ) {
5657
				tmpTable.width( tableContainer.clientWidth );
5658
			}
5659
			else if ( tableWidthAttr ) {
5660
				tmpTable.width( tableWidthAttr );
5661
			}
5662
	
5663
			// Get the width of each column in the constructed table - we need to
5664
			// know the inner width (so it can be assigned to the other table's
5665
			// cells) and the outer width so we can calculate the full width of the
5666
			// table. This is safe since DataTables requires a unique cell for each
5667
			// column, but if ever a header can span multiple columns, this will
5668
			// need to be modified.
5669
			var total = 0;
5670
			for ( i=0 ; i<visibleColumns.length ; i++ ) {
5671
				var cell = $(headerCells[i]);
5672
				var border = cell.outerWidth() - cell.width();
5673
	
5674
				// Use getBounding... where possible (not IE8-) because it can give
5675
				// sub-pixel accuracy, which we then want to round up!
5676
				var bounding = browser.bBounding ?
5677
					Math.ceil( headerCells[i].getBoundingClientRect().width ) :
5678
					cell.outerWidth();
5679
	
5680
				// Total is tracked to remove any sub-pixel errors as the outerWidth
5681
				// of the table might not equal the total given here (IE!).
5682
				total += bounding;
5683
	
5684
				// Width for each column to use
5685
				columns[ visibleColumns[i] ].sWidth = _fnStringToCss( bounding - border );
5686
			}
5687
	
5688
			table.style.width = _fnStringToCss( total );
5689
	
5690
			// Finished with the table - ditch it
5691
			holder.remove();
5692
		}
5693
	
5694
		// If there is a width attr, we want to attach an event listener which
5695
		// allows the table sizing to automatically adjust when the window is
5696
		// resized. Use the width attr rather than CSS, since we can't know if the
5697
		// CSS is a relative value or absolute - DOM read is always px.
5698
		if ( tableWidthAttr ) {
5699
			table.style.width = _fnStringToCss( tableWidthAttr );
5700
		}
5701
	
5702
		if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) {
5703
			var bindResize = function () {
5704
				$(window).on('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {
5705
					_fnAdjustColumnSizing( oSettings );
5706
				} ) );
5707
			};
5708
	
5709
			// IE6/7 will crash if we bind a resize event handler on page load.
5710
			// To be removed in 1.11 which drops IE6/7 support
5711
			if ( ie67 ) {
5712
				setTimeout( bindResize, 1000 );
5713
			}
5714
			else {
5715
				bindResize();
5716
			}
5717
	
5718
			oSettings._reszEvt = true;
5719
		}
5720
	}
5721
	
5722
	
5723
	/**
5724
	 * Throttle the calls to a function. Arguments and context are maintained for
5725
	 * the throttled function
5726
	 *  @param {function} fn Function to be called
5727
	 *  @param {int} [freq=200] call frequency in mS
5728
	 *  @returns {function} wrapped function
5729
	 *  @memberof DataTable#oApi
5730
	 */
5731
	var _fnThrottle = DataTable.util.throttle;
5732
	
5733
	
5734
	/**
5735
	 * Convert a CSS unit width to pixels (e.g. 2em)
5736
	 *  @param {string} width width to be converted
5737
	 *  @param {node} parent parent to get the with for (required for relative widths) - optional
5738
	 *  @returns {int} width in pixels
5739
	 *  @memberof DataTable#oApi
5740
	 */
5741
	function _fnConvertToWidth ( width, parent )
5742
	{
5743
		if ( ! width ) {
5744
			return 0;
5745
		}
5746
	
5747
		var n = $('<div/>')
5748
			.css( 'width', _fnStringToCss( width ) )
5749
			.appendTo( parent || document.body );
5750
	
5751
		var val = n[0].offsetWidth;
5752
		n.remove();
5753
	
5754
		return val;
5755
	}
5756
	
5757
	
5758
	/**
5759
	 * Get the widest node
5760
	 *  @param {object} settings dataTables settings object
5761
	 *  @param {int} colIdx column of interest
5762
	 *  @returns {node} widest table node
5763
	 *  @memberof DataTable#oApi
5764
	 */
5765
	function _fnGetWidestNode( settings, colIdx )
5766
	{
5767
		var idx = _fnGetMaxLenString( settings, colIdx );
5768
		if ( idx < 0 ) {
5769
			return null;
5770
		}
5771
	
5772
		var data = settings.aoData[ idx ];
5773
		return ! data.nTr ? // Might not have been created when deferred rendering
5774
			$('<td/>').html( _fnGetCellData( settings, idx, colIdx, 'display' ) )[0] :
5775
			data.anCells[ colIdx ];
5776
	}
5777
	
5778
	
5779
	/**
5780
	 * Get the maximum strlen for each data column
5781
	 *  @param {object} settings dataTables settings object
5782
	 *  @param {int} colIdx column of interest
5783
	 *  @returns {string} max string length for each column
5784
	 *  @memberof DataTable#oApi
5785
	 */
5786
	function _fnGetMaxLenString( settings, colIdx )
5787
	{
5788
		var s, max=-1, maxIdx = -1;
5789
	
5790
		for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
5791
			s = _fnGetCellData( settings, i, colIdx, 'display' )+'';
5792
			s = s.replace( __re_html_remove, '' );
5793
			s = s.replace( /&nbsp;/g, ' ' );
5794
	
5795
			if ( s.length > max ) {
5796
				max = s.length;
5797
				maxIdx = i;
5798
			}
5799
		}
5800
	
5801
		return maxIdx;
5802
	}
5803
	
5804
	
5805
	/**
5806
	 * Append a CSS unit (only if required) to a string
5807
	 *  @param {string} value to css-ify
5808
	 *  @returns {string} value with css unit
5809
	 *  @memberof DataTable#oApi
5810
	 */
5811
	function _fnStringToCss( s )
5812
	{
5813
		if ( s === null ) {
5814
			return '0px';
5815
		}
5816
	
5817
		if ( typeof s == 'number' ) {
5818
			return s < 0 ?
5819
				'0px' :
5820
				s+'px';
5821
		}
5822
	
5823
		// Check it has a unit character already
5824
		return s.match(/\d$/) ?
5825
			s+'px' :
5826
			s;
5827
	}
5828
	
5829
	
5830
	
5831
	function _fnSortFlatten ( settings )
5832
	{
5833
		var
5834
			i, iLen, k, kLen,
0 ignored issues
show
Unused Code introduced by
The variable iLen seems to be never used. Consider removing it.
Loading history...
5835
			aSort = [],
5836
			aiOrig = [],
0 ignored issues
show
Unused Code introduced by
The variable aiOrig seems to be never used. Consider removing it.
Loading history...
5837
			aoColumns = settings.aoColumns,
5838
			aDataSort, iCol, sType, srcCol,
5839
			fixed = settings.aaSortingFixed,
5840
			fixedObj = $.isPlainObject( fixed ),
5841
			nestedSort = [],
5842
			add = function ( a ) {
5843
				if ( a.length && ! $.isArray( a[0] ) ) {
5844
					// 1D array
5845
					nestedSort.push( a );
5846
				}
5847
				else {
5848
					// 2D array
5849
					$.merge( nestedSort, a );
5850
				}
5851
			};
5852
	
5853
		// Build the sort array, with pre-fix and post-fix options if they have been
5854
		// specified
5855
		if ( $.isArray( fixed ) ) {
5856
			add( fixed );
5857
		}
5858
	
5859
		if ( fixedObj && fixed.pre ) {
5860
			add( fixed.pre );
5861
		}
5862
	
5863
		add( settings.aaSorting );
5864
	
5865
		if (fixedObj && fixed.post ) {
5866
			add( fixed.post );
5867
		}
5868
	
5869
		for ( i=0 ; i<nestedSort.length ; i++ )
5870
		{
5871
			srcCol = nestedSort[i][0];
5872
			aDataSort = aoColumns[ srcCol ].aDataSort;
5873
	
5874
			for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ )
5875
			{
5876
				iCol = aDataSort[k];
5877
				sType = aoColumns[ iCol ].sType || 'string';
5878
	
5879
				if ( nestedSort[i]._idx === undefined ) {
5880
					nestedSort[i]._idx = $.inArray( nestedSort[i][1], aoColumns[iCol].asSorting );
5881
				}
5882
	
5883
				aSort.push( {
5884
					src:       srcCol,
5885
					col:       iCol,
5886
					dir:       nestedSort[i][1],
5887
					index:     nestedSort[i]._idx,
5888
					type:      sType,
5889
					formatter: DataTable.ext.type.order[ sType+"-pre" ]
5890
				} );
5891
			}
5892
		}
5893
	
5894
		return aSort;
5895
	}
5896
	
5897
	/**
5898
	 * Change the order of the table
5899
	 *  @param {object} oSettings dataTables settings object
5900
	 *  @memberof DataTable#oApi
5901
	 *  @todo This really needs split up!
5902
	 */
5903
	function _fnSort ( oSettings )
5904
	{
5905
		var
5906
			i, ien, iLen, j, jLen, k, kLen,
0 ignored issues
show
Unused Code introduced by
The variable kLen seems to be never used. Consider removing it.
Loading history...
Unused Code introduced by
The variable k seems to be never used. Consider removing it.
Loading history...
Unused Code introduced by
The variable j seems to be never used. Consider removing it.
Loading history...
Unused Code introduced by
The variable jLen seems to be never used. Consider removing it.
Loading history...
5907
			sDataType, nTh,
0 ignored issues
show
Unused Code introduced by
The variable nTh seems to be never used. Consider removing it.
Loading history...
Unused Code introduced by
The variable sDataType seems to be never used. Consider removing it.
Loading history...
5908
			aiOrig = [],
5909
			oExtSort = DataTable.ext.type.order,
5910
			aoData = oSettings.aoData,
5911
			aoColumns = oSettings.aoColumns,
0 ignored issues
show
Unused Code introduced by
The assignment to variable aoColumns seems to be never used. Consider removing it.
Loading history...
5912
			aDataSort, data, iCol, sType, oSort,
0 ignored issues
show
Unused Code introduced by
The variable oSort seems to be never used. Consider removing it.
Loading history...
Unused Code introduced by
The variable sType seems to be never used. Consider removing it.
Loading history...
Unused Code introduced by
The variable iCol seems to be never used. Consider removing it.
Loading history...
Unused Code introduced by
The variable data seems to be never used. Consider removing it.
Loading history...
Unused Code introduced by
The variable aDataSort seems to be never used. Consider removing it.
Loading history...
5913
			formatters = 0,
5914
			sortCol,
5915
			displayMaster = oSettings.aiDisplayMaster,
5916
			aSort;
5917
	
5918
		// Resolve any column types that are unknown due to addition or invalidation
5919
		// @todo Can this be moved into a 'data-ready' handler which is called when
5920
		//   data is going to be used in the table?
5921
		_fnColumnTypes( oSettings );
5922
	
5923
		aSort = _fnSortFlatten( oSettings );
5924
	
5925
		for ( i=0, ien=aSort.length ; i<ien ; i++ ) {
5926
			sortCol = aSort[i];
5927
	
5928
			// Track if we can use the fast sort algorithm
5929
			if ( sortCol.formatter ) {
5930
				formatters++;
5931
			}
5932
	
5933
			// Load the data needed for the sort, for each cell
5934
			_fnSortData( oSettings, sortCol.col );
5935
		}
5936
	
5937
		/* No sorting required if server-side or no sorting array */
5938
		if ( _fnDataSource( oSettings ) != 'ssp' && aSort.length !== 0 )
5939
		{
5940
			// Create a value - key array of the current row positions such that we can use their
5941
			// current position during the sort, if values match, in order to perform stable sorting
5942
			for ( i=0, iLen=displayMaster.length ; i<iLen ; i++ ) {
5943
				aiOrig[ displayMaster[i] ] = i;
5944
			}
5945
	
5946
			/* Do the sort - here we want multi-column sorting based on a given data source (column)
5947
			 * and sorting function (from oSort) in a certain direction. It's reasonably complex to
5948
			 * follow on it's own, but this is what we want (example two column sorting):
5949
			 *  fnLocalSorting = function(a,b){
5950
			 *    var iTest;
5951
			 *    iTest = oSort['string-asc']('data11', 'data12');
5952
			 *      if (iTest !== 0)
5953
			 *        return iTest;
5954
			 *    iTest = oSort['numeric-desc']('data21', 'data22');
5955
			 *    if (iTest !== 0)
5956
			 *      return iTest;
5957
			 *    return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
5958
			 *  }
5959
			 * Basically we have a test for each sorting column, if the data in that column is equal,
5960
			 * test the next column. If all columns match, then we use a numeric sort on the row
5961
			 * positions in the original data array to provide a stable sort.
5962
			 *
5963
			 * Note - I know it seems excessive to have two sorting methods, but the first is around
5964
			 * 15% faster, so the second is only maintained for backwards compatibility with sorting
5965
			 * methods which do not have a pre-sort formatting function.
5966
			 */
5967
			if ( formatters === aSort.length ) {
5968
				// All sort types have formatting functions
5969 View Code Duplication
				displayMaster.sort( function ( a, b ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
5970
					var
5971
						x, y, k, test, sort,
5972
						len=aSort.length,
5973
						dataA = aoData[a]._aSortData,
5974
						dataB = aoData[b]._aSortData;
5975
	
5976
					for ( k=0 ; k<len ; k++ ) {
5977
						sort = aSort[k];
5978
	
5979
						x = dataA[ sort.col ];
5980
						y = dataB[ sort.col ];
5981
	
5982
						test = x<y ? -1 : x>y ? 1 : 0;
5983
						if ( test !== 0 ) {
5984
							return sort.dir === 'asc' ? test : -test;
5985
						}
5986
					}
5987
	
5988
					x = aiOrig[a];
5989
					y = aiOrig[b];
5990
					return x<y ? -1 : x>y ? 1 : 0;
5991
				} );
5992
			}
5993
			else {
5994
				// Depreciated - remove in 1.11 (providing a plug-in option)
5995
				// Not all sort types have formatting methods, so we have to call their sorting
5996
				// methods.
5997 View Code Duplication
				displayMaster.sort( function ( a, b ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
5998
					var
5999
						x, y, k, l, test, sort, fn,
0 ignored issues
show
Unused Code introduced by
The variable l seems to be never used. Consider removing it.
Loading history...
6000
						len=aSort.length,
6001
						dataA = aoData[a]._aSortData,
6002
						dataB = aoData[b]._aSortData;
6003
	
6004
					for ( k=0 ; k<len ; k++ ) {
6005
						sort = aSort[k];
6006
	
6007
						x = dataA[ sort.col ];
6008
						y = dataB[ sort.col ];
6009
	
6010
						fn = oExtSort[ sort.type+"-"+sort.dir ] || oExtSort[ "string-"+sort.dir ];
6011
						test = fn( x, y );
6012
						if ( test !== 0 ) {
6013
							return test;
6014
						}
6015
					}
6016
	
6017
					x = aiOrig[a];
6018
					y = aiOrig[b];
6019
					return x<y ? -1 : x>y ? 1 : 0;
6020
				} );
6021
			}
6022
		}
6023
	
6024
		/* Tell the draw function that we have sorted the data */
6025
		oSettings.bSorted = true;
6026
	}
6027
	
6028
	
6029
	function _fnSortAria ( settings )
6030
	{
6031
		var label;
6032
		var nextSort;
6033
		var columns = settings.aoColumns;
6034
		var aSort = _fnSortFlatten( settings );
6035
		var oAria = settings.oLanguage.oAria;
6036
	
6037
		// ARIA attributes - need to loop all columns, to update all (removing old
6038
		// attributes as needed)
6039
		for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
6040
		{
6041
			var col = columns[i];
6042
			var asSorting = col.asSorting;
6043
			var sTitle = col.sTitle.replace( /<.*?>/g, "" );
6044
			var th = col.nTh;
6045
	
6046
			// IE7 is throwing an error when setting these properties with jQuery's
6047
			// attr() and removeAttr() methods...
6048
			th.removeAttribute('aria-sort');
6049
	
6050
			/* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
6051
			if ( col.bSortable ) {
6052
				if ( aSort.length > 0 && aSort[0].col == i ) {
6053
					th.setAttribute('aria-sort', aSort[0].dir=="asc" ? "ascending" : "descending" );
6054
					nextSort = asSorting[ aSort[0].index+1 ] || asSorting[0];
6055
				}
6056
				else {
6057
					nextSort = asSorting[0];
6058
				}
6059
	
6060
				label = sTitle + ( nextSort === "asc" ?
6061
					oAria.sSortAscending :
6062
					oAria.sSortDescending
6063
				);
6064
			}
6065
			else {
6066
				label = sTitle;
6067
			}
6068
	
6069
			th.setAttribute('aria-label', label);
6070
		}
6071
	}
6072
	
6073
	
6074
	/**
6075
	 * Function to run on user sort request
6076
	 *  @param {object} settings dataTables settings object
6077
	 *  @param {node} attachTo node to attach the handler to
6078
	 *  @param {int} colIdx column sorting index
6079
	 *  @param {boolean} [append=false] Append the requested sort to the existing
6080
	 *    sort if true (i.e. multi-column sort)
6081
	 *  @param {function} [callback] callback function
6082
	 *  @memberof DataTable#oApi
6083
	 */
6084
	function _fnSortListener ( settings, colIdx, append, callback )
6085
	{
6086
		var col = settings.aoColumns[ colIdx ];
6087
		var sorting = settings.aaSorting;
6088
		var asSorting = col.asSorting;
6089
		var nextSortIdx;
6090
		var next = function ( a, overflow ) {
6091
			var idx = a._idx;
6092
			if ( idx === undefined ) {
6093
				idx = $.inArray( a[1], asSorting );
6094
			}
6095
	
6096
			return idx+1 < asSorting.length ?
6097
				idx+1 :
6098
				overflow ?
6099
					null :
6100
					0;
6101
		};
6102
	
6103
		// Convert to 2D array if needed
6104
		if ( typeof sorting[0] === 'number' ) {
6105
			sorting = settings.aaSorting = [ sorting ];
6106
		}
6107
	
6108
		// If appending the sort then we are multi-column sorting
6109
		if ( append && settings.oFeatures.bSortMulti ) {
6110
			// Are we already doing some kind of sort on this column?
6111
			var sortIdx = $.inArray( colIdx, _pluck(sorting, '0') );
6112
	
6113
			if ( sortIdx !== -1 ) {
6114
				// Yes, modify the sort
6115
				nextSortIdx = next( sorting[sortIdx], true );
6116
	
6117
				if ( nextSortIdx === null && sorting.length === 1 ) {
6118
					nextSortIdx = 0; // can't remove sorting completely
6119
				}
6120
	
6121
				if ( nextSortIdx === null ) {
6122
					sorting.splice( sortIdx, 1 );
6123
				}
6124
				else {
6125
					sorting[sortIdx][1] = asSorting[ nextSortIdx ];
6126
					sorting[sortIdx]._idx = nextSortIdx;
6127
				}
6128
			}
6129
			else {
6130
				// No sort on this column yet
6131
				sorting.push( [ colIdx, asSorting[0], 0 ] );
6132
				sorting[sorting.length-1]._idx = 0;
6133
			}
6134
		}
6135
		else if ( sorting.length && sorting[0][0] == colIdx ) {
6136
			// Single column - already sorting on this column, modify the sort
6137
			nextSortIdx = next( sorting[0] );
6138
	
6139
			sorting.length = 1;
6140
			sorting[0][1] = asSorting[ nextSortIdx ];
6141
			sorting[0]._idx = nextSortIdx;
6142
		}
6143
		else {
6144
			// Single column - sort only on this column
6145
			sorting.length = 0;
6146
			sorting.push( [ colIdx, asSorting[0] ] );
6147
			sorting[0]._idx = 0;
6148
		}
6149
	
6150
		// Run the sort by calling a full redraw
6151
		_fnReDraw( settings );
6152
	
6153
		// callback used for async user interaction
6154
		if ( typeof callback == 'function' ) {
6155
			callback( settings );
6156
		}
6157
	}
6158
	
6159
	
6160
	/**
6161
	 * Attach a sort handler (click) to a node
6162
	 *  @param {object} settings dataTables settings object
6163
	 *  @param {node} attachTo node to attach the handler to
6164
	 *  @param {int} colIdx column sorting index
6165
	 *  @param {function} [callback] callback function
6166
	 *  @memberof DataTable#oApi
6167
	 */
6168
	function _fnSortAttachListener ( settings, attachTo, colIdx, callback )
6169
	{
6170
		var col = settings.aoColumns[ colIdx ];
6171
	
6172
		_fnBindAction( attachTo, {}, function (e) {
6173
			/* If the column is not sortable - don't to anything */
6174
			if ( col.bSortable === false ) {
6175
				return;
6176
			}
6177
	
6178
			// If processing is enabled use a timeout to allow the processing
6179
			// display to be shown - otherwise to it synchronously
6180
			if ( settings.oFeatures.bProcessing ) {
6181
				_fnProcessingDisplay( settings, true );
6182
	
6183
				setTimeout( function() {
6184
					_fnSortListener( settings, colIdx, e.shiftKey, callback );
6185
	
6186
					// In server-side processing, the draw callback will remove the
6187
					// processing display
6188
					if ( _fnDataSource( settings ) !== 'ssp' ) {
6189
						_fnProcessingDisplay( settings, false );
6190
					}
6191
				}, 0 );
6192
			}
6193
			else {
6194
				_fnSortListener( settings, colIdx, e.shiftKey, callback );
6195
			}
6196
		} );
6197
	}
6198
	
6199
	
6200
	/**
6201
	 * Set the sorting classes on table's body, Note: it is safe to call this function
6202
	 * when bSort and bSortClasses are false
6203
	 *  @param {object} oSettings dataTables settings object
6204
	 *  @memberof DataTable#oApi
6205
	 */
6206
	function _fnSortingClasses( settings )
6207
	{
6208
		var oldSort = settings.aLastSort;
6209
		var sortClass = settings.oClasses.sSortColumn;
6210
		var sort = _fnSortFlatten( settings );
6211
		var features = settings.oFeatures;
6212
		var i, ien, colIdx;
6213
	
6214
		if ( features.bSort && features.bSortClasses ) {
6215
			// Remove old sorting classes
6216
			for ( i=0, ien=oldSort.length ; i<ien ; i++ ) {
6217
				colIdx = oldSort[i].src;
6218
	
6219
				// Remove column sorting
6220
				$( _pluck( settings.aoData, 'anCells', colIdx ) )
6221
					.removeClass( sortClass + (i<2 ? i+1 : 3) );
6222
			}
6223
	
6224
			// Add new column sorting
6225
			for ( i=0, ien=sort.length ; i<ien ; i++ ) {
6226
				colIdx = sort[i].src;
6227
	
6228
				$( _pluck( settings.aoData, 'anCells', colIdx ) )
6229
					.addClass( sortClass + (i<2 ? i+1 : 3) );
6230
			}
6231
		}
6232
	
6233
		settings.aLastSort = sort;
6234
	}
6235
	
6236
	
6237
	// Get the data to sort a column, be it from cache, fresh (populating the
6238
	// cache), or from a sort formatter
6239
	function _fnSortData( settings, idx )
6240
	{
6241
		// Custom sorting function - provided by the sort data type
6242
		var column = settings.aoColumns[ idx ];
6243
		var customSort = DataTable.ext.order[ column.sSortDataType ];
6244
		var customData;
6245
	
6246
		if ( customSort ) {
6247
			customData = customSort.call( settings.oInstance, settings, idx,
6248
				_fnColumnIndexToVisible( settings, idx )
6249
			);
6250
		}
6251
	
6252
		// Use / populate cache
6253
		var row, cellData;
6254
		var formatter = DataTable.ext.type.order[ column.sType+"-pre" ];
6255
	
6256
		for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
6257
			row = settings.aoData[i];
6258
	
6259
			if ( ! row._aSortData ) {
6260
				row._aSortData = [];
6261
			}
6262
	
6263
			if ( ! row._aSortData[idx] || customSort ) {
6264
				cellData = customSort ?
6265
					customData[i] : // If there was a custom sort function, use data from there
0 ignored issues
show
Bug introduced by
The variable customData does not seem to be initialized in case customSort on line 6246 is false. Are you sure this can never be the case?
Loading history...
6266
					_fnGetCellData( settings, i, idx, 'sort' );
6267
	
6268
				row._aSortData[ idx ] = formatter ?
6269
					formatter( cellData ) :
6270
					cellData;
6271
			}
6272
		}
6273
	}
6274
	
6275
	
6276
	
6277
	/**
6278
	 * Save the state of a table
6279
	 *  @param {object} oSettings dataTables settings object
6280
	 *  @memberof DataTable#oApi
6281
	 */
6282
	function _fnSaveState ( settings )
6283
	{
6284
		if ( !settings.oFeatures.bStateSave || settings.bDestroying )
6285
		{
6286
			return;
6287
		}
6288
	
6289
		/* Store the interesting variables */
6290
		var state = {
6291
			time:    +new Date(),
6292
			start:   settings._iDisplayStart,
6293
			length:  settings._iDisplayLength,
6294
			order:   $.extend( true, [], settings.aaSorting ),
6295
			search:  _fnSearchToCamel( settings.oPreviousSearch ),
6296
			columns: $.map( settings.aoColumns, function ( col, i ) {
6297
				return {
6298
					visible: col.bVisible,
6299
					search: _fnSearchToCamel( settings.aoPreSearchCols[i] )
6300
				};
6301
			} )
6302
		};
6303
	
6304
		_fnCallbackFire( settings, "aoStateSaveParams", 'stateSaveParams', [settings, state] );
6305
	
6306
		settings.oSavedState = state;
6307
		settings.fnStateSaveCallback.call( settings.oInstance, settings, state );
6308
	}
6309
	
6310
	
6311
	/**
6312
	 * Attempt to load a saved table state
6313
	 *  @param {object} oSettings dataTables settings object
6314
	 *  @param {object} oInit DataTables init object so we can override settings
6315
	 *  @param {function} callback Callback to execute when the state has been loaded
6316
	 *  @memberof DataTable#oApi
6317
	 */
6318
	function _fnLoadState ( settings, oInit, callback )
6319
	{
6320
		var i, ien;
6321
		var columns = settings.aoColumns;
6322
		var loaded = function ( s ) {
6323
			if ( ! s || ! s.time ) {
6324
				callback();
6325
				return;
6326
			}
6327
	
6328
			// Allow custom and plug-in manipulation functions to alter the saved data set and
6329
			// cancelling of loading by returning false
6330
			var abStateLoad = _fnCallbackFire( settings, 'aoStateLoadParams', 'stateLoadParams', [settings, s] );
6331
			if ( $.inArray( false, abStateLoad ) !== -1 ) {
6332
				callback();
6333
				return;
6334
			}
6335
	
6336
			// Reject old data
6337
			var duration = settings.iStateDuration;
6338
			if ( duration > 0 && s.time < +new Date() - (duration*1000) ) {
6339
				callback();
6340
				return;
6341
			}
6342
	
6343
			// Number of columns have changed - all bets are off, no restore of settings
6344
			if ( s.columns && columns.length !== s.columns.length ) {
6345
				callback();
6346
				return;
6347
			}
6348
	
6349
			// Store the saved state so it might be accessed at any time
6350
			settings.oLoadedState = $.extend( true, {}, s );
6351
	
6352
			// Restore key features - todo - for 1.11 this needs to be done by
6353
			// subscribed events
6354
			if ( s.start !== undefined ) {
6355
				settings._iDisplayStart    = s.start;
6356
				settings.iInitDisplayStart = s.start;
6357
			}
6358
			if ( s.length !== undefined ) {
6359
				settings._iDisplayLength   = s.length;
6360
			}
6361
	
6362
			// Order
6363
			if ( s.order !== undefined ) {
6364
				settings.aaSorting = [];
6365
				$.each( s.order, function ( i, col ) {
6366
					settings.aaSorting.push( col[0] >= columns.length ?
6367
						[ 0, col[1] ] :
6368
						col
6369
					);
6370
				} );
6371
			}
6372
	
6373
			// Search
6374
			if ( s.search !== undefined ) {
6375
				$.extend( settings.oPreviousSearch, _fnSearchToHung( s.search ) );
6376
			}
6377
	
6378
			// Columns
6379
			//
6380
			if ( s.columns ) {
6381
				for ( i=0, ien=s.columns.length ; i<ien ; i++ ) {
0 ignored issues
show
Bug introduced by
The variable i is changed as part of the for loop for example by i++ on line 6381. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
6382
					var col = s.columns[i];
6383
	
6384
					// Visibility
6385
					if ( col.visible !== undefined ) {
6386
						columns[i].bVisible = col.visible;
6387
					}
6388
	
6389
					// Search
6390
					if ( col.search !== undefined ) {
6391
						$.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) );
6392
					}
6393
				}
6394
			}
6395
	
6396
			_fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, s] );
6397
			callback();
6398
		}
6399
	
6400
		if ( ! settings.oFeatures.bStateSave ) {
6401
			callback();
6402
			return;
6403
		}
6404
	
6405
		var state = settings.fnStateLoadCallback.call( settings.oInstance, settings, loaded );
6406
	
6407
		if ( state !== undefined ) {
6408
			loaded( state );
6409
		}
6410
		// otherwise, wait for the loaded callback to be executed
6411
	}
6412
	
6413
	
6414
	/**
6415
	 * Return the settings object for a particular table
6416
	 *  @param {node} table table we are using as a dataTable
6417
	 *  @returns {object} Settings object - or null if not found
6418
	 *  @memberof DataTable#oApi
6419
	 */
6420
	function _fnSettingsFromNode ( table )
6421
	{
6422
		var settings = DataTable.settings;
6423
		var idx = $.inArray( table, _pluck( settings, 'nTable' ) );
6424
	
6425
		return idx !== -1 ?
6426
			settings[ idx ] :
6427
			null;
6428
	}
6429
	
6430
	
6431
	/**
6432
	 * Log an error message
6433
	 *  @param {object} settings dataTables settings object
6434
	 *  @param {int} level log error messages, or display them to the user
6435
	 *  @param {string} msg error message
6436
	 *  @param {int} tn Technical note id to get more information about the error.
6437
	 *  @memberof DataTable#oApi
6438
	 */
6439
	function _fnLog( settings, level, msg, tn )
6440
	{
6441
		msg = 'DataTables warning: '+
6442
			(settings ? 'table id='+settings.sTableId+' - ' : '')+msg;
6443
	
6444
		if ( tn ) {
6445
			msg += '. For more information about this error, please see '+
6446
			'http://datatables.net/tn/'+tn;
6447
		}
6448
	
6449
		if ( ! level  ) {
6450
			// Backwards compatibility pre 1.10
6451
			var ext = DataTable.ext;
6452
			var type = ext.sErrMode || ext.errMode;
6453
	
6454
			if ( settings ) {
6455
				_fnCallbackFire( settings, null, 'error', [ settings, tn, msg ] );
6456
			}
6457
	
6458
			if ( type == 'alert' ) {
6459
				alert( msg );
6460
			}
6461
			else if ( type == 'throw' ) {
6462
				throw new Error(msg);
6463
			}
6464
			else if ( typeof type == 'function' ) {
6465
				type( settings, tn, msg );
6466
			}
6467
		}
6468
		else if ( window.console && console.log ) {
6469
			console.log( msg );
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
6470
		}
6471
	}
6472
	
6473
	
6474
	/**
6475
	 * See if a property is defined on one object, if so assign it to the other object
6476
	 *  @param {object} ret target object
6477
	 *  @param {object} src source object
6478
	 *  @param {string} name property
6479
	 *  @param {string} [mappedName] name to map too - optional, name used if not given
6480
	 *  @memberof DataTable#oApi
6481
	 */
6482
	function _fnMap( ret, src, name, mappedName )
6483
	{
6484
		if ( $.isArray( name ) ) {
6485
			$.each( name, function (i, val) {
6486
				if ( $.isArray( val ) ) {
6487
					_fnMap( ret, src, val[0], val[1] );
6488
				}
6489
				else {
6490
					_fnMap( ret, src, val );
6491
				}
6492
			} );
6493
	
6494
			return;
6495
		}
6496
	
6497
		if ( mappedName === undefined ) {
6498
			mappedName = name;
6499
		}
6500
	
6501
		if ( src[name] !== undefined ) {
6502
			ret[mappedName] = src[name];
6503
		}
6504
	}
6505
	
6506
	
6507
	/**
6508
	 * Extend objects - very similar to jQuery.extend, but deep copy objects, and
6509
	 * shallow copy arrays. The reason we need to do this, is that we don't want to
6510
	 * deep copy array init values (such as aaSorting) since the dev wouldn't be
6511
	 * able to override them, but we do want to deep copy arrays.
6512
	 *  @param {object} out Object to extend
6513
	 *  @param {object} extender Object from which the properties will be applied to
6514
	 *      out
6515
	 *  @param {boolean} breakRefs If true, then arrays will be sliced to take an
6516
	 *      independent copy with the exception of the `data` or `aaData` parameters
6517
	 *      if they are present. This is so you can pass in a collection to
6518
	 *      DataTables and have that used as your data source without breaking the
6519
	 *      references
6520
	 *  @returns {object} out Reference, just for convenience - out === the return.
6521
	 *  @memberof DataTable#oApi
6522
	 *  @todo This doesn't take account of arrays inside the deep copied objects.
6523
	 */
6524
	function _fnExtend( out, extender, breakRefs )
6525
	{
6526
		var val;
6527
	
6528
		for ( var prop in extender ) {
6529
			if ( extender.hasOwnProperty(prop) ) {
6530
				val = extender[prop];
6531
	
6532
				if ( $.isPlainObject( val ) ) {
6533
					if ( ! $.isPlainObject( out[prop] ) ) {
6534
						out[prop] = {};
6535
					}
6536
					$.extend( true, out[prop], val );
6537
				}
6538
				else if ( breakRefs && prop !== 'data' && prop !== 'aaData' && $.isArray(val) ) {
6539
					out[prop] = val.slice();
6540
				}
6541
				else {
6542
					out[prop] = val;
6543
				}
6544
			}
6545
		}
6546
	
6547
		return out;
6548
	}
6549
	
6550
	
6551
	/**
6552
	 * Bind an event handers to allow a click or return key to activate the callback.
6553
	 * This is good for accessibility since a return on the keyboard will have the
6554
	 * same effect as a click, if the element has focus.
6555
	 *  @param {element} n Element to bind the action to
6556
	 *  @param {object} oData Data object to pass to the triggered function
6557
	 *  @param {function} fn Callback function for when the event is triggered
6558
	 *  @memberof DataTable#oApi
6559
	 */
6560
	function _fnBindAction( n, oData, fn )
6561
	{
6562
		$(n)
6563
			.on( 'click.DT', oData, function (e) {
6564
					n.blur(); // Remove focus outline for mouse users
6565
					fn(e);
6566
				} )
6567
			.on( 'keypress.DT', oData, function (e){
6568
					if ( e.which === 13 ) {
6569
						e.preventDefault();
6570
						fn(e);
6571
					}
6572
				} )
6573
			.on( 'selectstart.DT', function () {
6574
					/* Take the brutal approach to cancelling text selection */
6575
					return false;
6576
				} );
6577
	}
6578
	
6579
	
6580
	/**
6581
	 * Register a callback function. Easily allows a callback function to be added to
6582
	 * an array store of callback functions that can then all be called together.
6583
	 *  @param {object} oSettings dataTables settings object
6584
	 *  @param {string} sStore Name of the array storage for the callbacks in oSettings
6585
	 *  @param {function} fn Function to be called back
6586
	 *  @param {string} sName Identifying name for the callback (i.e. a label)
6587
	 *  @memberof DataTable#oApi
6588
	 */
6589
	function _fnCallbackReg( oSettings, sStore, fn, sName )
6590
	{
6591
		if ( fn )
6592
		{
6593
			oSettings[sStore].push( {
6594
				"fn": fn,
6595
				"sName": sName
6596
			} );
6597
		}
6598
	}
6599
	
6600
	
6601
	/**
6602
	 * Fire callback functions and trigger events. Note that the loop over the
6603
	 * callback array store is done backwards! Further note that you do not want to
6604
	 * fire off triggers in time sensitive applications (for example cell creation)
6605
	 * as its slow.
6606
	 *  @param {object} settings dataTables settings object
6607
	 *  @param {string} callbackArr Name of the array storage for the callbacks in
6608
	 *      oSettings
6609
	 *  @param {string} eventName Name of the jQuery custom event to trigger. If
6610
	 *      null no trigger is fired
6611
	 *  @param {array} args Array of arguments to pass to the callback function /
6612
	 *      trigger
6613
	 *  @memberof DataTable#oApi
6614
	 */
6615
	function _fnCallbackFire( settings, callbackArr, eventName, args )
6616
	{
6617
		var ret = [];
6618
	
6619
		if ( callbackArr ) {
6620
			ret = $.map( settings[callbackArr].slice().reverse(), function (val, i) {
0 ignored issues
show
Unused Code introduced by
The parameter i is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
6621
				return val.fn.apply( settings.oInstance, args );
6622
			} );
6623
		}
6624
	
6625
		if ( eventName !== null ) {
6626
			var e = $.Event( eventName+'.dt' );
6627
	
6628
			$(settings.nTable).trigger( e, args );
6629
	
6630
			ret.push( e.result );
6631
		}
6632
	
6633
		return ret;
6634
	}
6635
	
6636
	
6637
	function _fnLengthOverflow ( settings )
6638
	{
6639
		var
6640
			start = settings._iDisplayStart,
6641
			end = settings.fnDisplayEnd(),
6642
			len = settings._iDisplayLength;
6643
	
6644
		/* If we have space to show extra rows (backing up from the end point - then do so */
6645
		if ( start >= end )
6646
		{
6647
			start = end - len;
6648
		}
6649
	
6650
		// Keep the start record on the current page
6651
		start -= (start % len);
6652
	
6653
		if ( len === -1 || start < 0 )
6654
		{
6655
			start = 0;
6656
		}
6657
	
6658
		settings._iDisplayStart = start;
6659
	}
6660
	
6661
	
6662
	function _fnRenderer( settings, type )
6663
	{
6664
		var renderer = settings.renderer;
6665
		var host = DataTable.ext.renderer[type];
6666
	
6667
		if ( $.isPlainObject( renderer ) && renderer[type] ) {
6668
			// Specific renderer for this type. If available use it, otherwise use
6669
			// the default.
6670
			return host[renderer[type]] || host._;
6671
		}
6672
		else if ( typeof renderer === 'string' ) {
6673
			// Common renderer - if there is one available for this type use it,
6674
			// otherwise use the default
6675
			return host[renderer] || host._;
6676
		}
6677
	
6678
		// Use the default
6679
		return host._;
6680
	}
6681
	
6682
	
6683
	/**
6684
	 * Detect the data source being used for the table. Used to simplify the code
6685
	 * a little (ajax) and to make it compress a little smaller.
6686
	 *
6687
	 *  @param {object} settings dataTables settings object
6688
	 *  @returns {string} Data source
6689
	 *  @memberof DataTable#oApi
6690
	 */
6691
	function _fnDataSource ( settings )
6692
	{
6693
		if ( settings.oFeatures.bServerSide ) {
6694
			return 'ssp';
6695
		}
6696
		else if ( settings.ajax || settings.sAjaxSource ) {
6697
			return 'ajax';
6698
		}
6699
		return 'dom';
6700
	}
6701
	
6702
6703
	
6704
	
6705
	/**
6706
	 * Computed structure of the DataTables API, defined by the options passed to
6707
	 * `DataTable.Api.register()` when building the API.
6708
	 *
6709
	 * The structure is built in order to speed creation and extension of the Api
6710
	 * objects since the extensions are effectively pre-parsed.
6711
	 *
6712
	 * The array is an array of objects with the following structure, where this
6713
	 * base array represents the Api prototype base:
6714
	 *
6715
	 *     [
6716
	 *       {
6717
	 *         name:      'data'                -- string   - Property name
6718
	 *         val:       function () {},       -- function - Api method (or undefined if just an object
6719
	 *         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
6720
	 *         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
6721
	 *       },
6722
	 *       {
6723
	 *         name:     'row'
6724
	 *         val:       {},
6725
	 *         methodExt: [ ... ],
6726
	 *         propExt:   [
6727
	 *           {
6728
	 *             name:      'data'
6729
	 *             val:       function () {},
6730
	 *             methodExt: [ ... ],
6731
	 *             propExt:   [ ... ]
6732
	 *           },
6733
	 *           ...
6734
	 *         ]
6735
	 *       }
6736
	 *     ]
6737
	 *
6738
	 * @type {Array}
6739
	 * @ignore
6740
	 */
6741
	var __apiStruct = [];
6742
	
6743
	
6744
	/**
6745
	 * `Array.prototype` reference.
6746
	 *
6747
	 * @type object
6748
	 * @ignore
6749
	 */
6750
	var __arrayProto = Array.prototype;
6751
	
6752
	
6753
	/**
6754
	 * Abstraction for `context` parameter of the `Api` constructor to allow it to
6755
	 * take several different forms for ease of use.
6756
	 *
6757
	 * Each of the input parameter types will be converted to a DataTables settings
6758
	 * object where possible.
6759
	 *
6760
	 * @param  {string|node|jQuery|object} mixed DataTable identifier. Can be one
6761
	 *   of:
6762
	 *
6763
	 *   * `string` - jQuery selector. Any DataTables' matching the given selector
6764
	 *     with be found and used.
6765
	 *   * `node` - `TABLE` node which has already been formed into a DataTable.
6766
	 *   * `jQuery` - A jQuery object of `TABLE` nodes.
6767
	 *   * `object` - DataTables settings object
6768
	 *   * `DataTables.Api` - API instance
6769
	 * @return {array|null} Matching DataTables settings objects. `null` or
6770
	 *   `undefined` is returned if no matching DataTable is found.
6771
	 * @ignore
6772
	 */
6773
	var _toSettings = function ( mixed )
6774
	{
6775
		var idx, jq;
6776
		var settings = DataTable.settings;
6777
		var tables = $.map( settings, function (el, i) {
0 ignored issues
show
Unused Code introduced by
The parameter i is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
6778
			return el.nTable;
6779
		} );
6780
	
6781
		if ( ! mixed ) {
6782
			return [];
6783
		}
6784
		else if ( mixed.nTable && mixed.oApi ) {
6785
			// DataTables settings object
6786
			return [ mixed ];
6787
		}
6788
		else if ( mixed.nodeName && mixed.nodeName.toLowerCase() === 'table' ) {
6789
			// Table node
6790
			idx = $.inArray( mixed, tables );
6791
			return idx !== -1 ? [ settings[idx] ] : null;
6792
		}
6793
		else if ( mixed && typeof mixed.settings === 'function' ) {
6794
			return mixed.settings().toArray();
6795
		}
6796
		else if ( typeof mixed === 'string' ) {
6797
			// jQuery selector
6798
			jq = $(mixed);
6799
		}
6800
		else if ( mixed instanceof $ ) {
6801
			// jQuery object (also DataTables instance)
6802
			jq = mixed;
6803
		}
6804
	
6805
		if ( jq ) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if jq is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
6806
			return jq.map( function(i) {
0 ignored issues
show
Unused Code introduced by
The parameter i is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
6807
				idx = $.inArray( this, tables );
6808
				return idx !== -1 ? settings[idx] : null;
6809
			} ).toArray();
6810
		}
6811
	};
6812
	
6813
	
6814
	/**
6815
	 * DataTables API class - used to control and interface with  one or more
6816
	 * DataTables enhanced tables.
6817
	 *
6818
	 * The API class is heavily based on jQuery, presenting a chainable interface
6819
	 * that you can use to interact with tables. Each instance of the API class has
6820
	 * a "context" - i.e. the tables that it will operate on. This could be a single
6821
	 * table, all tables on a page or a sub-set thereof.
6822
	 *
6823
	 * Additionally the API is designed to allow you to easily work with the data in
6824
	 * the tables, retrieving and manipulating it as required. This is done by
6825
	 * presenting the API class as an array like interface. The contents of the
6826
	 * array depend upon the actions requested by each method (for example
6827
	 * `rows().nodes()` will return an array of nodes, while `rows().data()` will
6828
	 * return an array of objects or arrays depending upon your table's
6829
	 * configuration). The API object has a number of array like methods (`push`,
6830
	 * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`,
6831
	 * `unique` etc) to assist your working with the data held in a table.
6832
	 *
6833
	 * Most methods (those which return an Api instance) are chainable, which means
6834
	 * the return from a method call also has all of the methods available that the
6835
	 * top level object had. For example, these two calls are equivalent:
6836
	 *
6837
	 *     // Not chained
6838
	 *     api.row.add( {...} );
6839
	 *     api.draw();
6840
	 *
6841
	 *     // Chained
6842
	 *     api.row.add( {...} ).draw();
6843
	 *
6844
	 * @class DataTable.Api
6845
	 * @param {array|object|string|jQuery} context DataTable identifier. This is
6846
	 *   used to define which DataTables enhanced tables this API will operate on.
6847
	 *   Can be one of:
6848
	 *
6849
	 *   * `string` - jQuery selector. Any DataTables' matching the given selector
6850
	 *     with be found and used.
6851
	 *   * `node` - `TABLE` node which has already been formed into a DataTable.
6852
	 *   * `jQuery` - A jQuery object of `TABLE` nodes.
6853
	 *   * `object` - DataTables settings object
6854
	 * @param {array} [data] Data to initialise the Api instance with.
6855
	 *
6856
	 * @example
6857
	 *   // Direct initialisation during DataTables construction
6858
	 *   var api = $('#example').DataTable();
6859
	 *
6860
	 * @example
6861
	 *   // Initialisation using a DataTables jQuery object
6862
	 *   var api = $('#example').dataTable().api();
6863
	 *
6864
	 * @example
6865
	 *   // Initialisation as a constructor
6866
	 *   var api = new $.fn.DataTable.Api( 'table.dataTable' );
6867
	 */
6868
	_Api = function ( context, data )
6869
	{
6870
		if ( ! (this instanceof _Api) ) {
6871
			return new _Api( context, data );
6872
		}
6873
	
6874
		var settings = [];
6875
		var ctxSettings = function ( o ) {
6876
			var a = _toSettings( o );
6877
			if ( a ) {
6878
				settings = settings.concat( a );
6879
			}
6880
		};
6881
	
6882
		if ( $.isArray( context ) ) {
6883
			for ( var i=0, ien=context.length ; i<ien ; i++ ) {
6884
				ctxSettings( context[i] );
6885
			}
6886
		}
6887
		else {
6888
			ctxSettings( context );
6889
		}
6890
	
6891
		// Remove duplicates
6892
		this.context = _unique( settings );
6893
	
6894
		// Initial data
6895
		if ( data ) {
6896
			$.merge( this, data );
6897
		}
6898
	
6899
		// selector
6900
		this.selector = {
6901
			rows: null,
6902
			cols: null,
6903
			opts: null
6904
		};
6905
	
6906
		_Api.extend( this, this, __apiStruct );
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
6907
	};
6908
	
6909
	DataTable.Api = _Api;
6910
	
6911
	// Don't destroy the existing prototype, just extend it. Required for jQuery 2's
6912
	// isPlainObject.
6913
	$.extend( _Api.prototype, {
6914
		any: function ()
6915
		{
6916
			return this.count() !== 0;
6917
		},
6918
	
6919
	
6920
		concat:  __arrayProto.concat,
6921
	
6922
	
6923
		context: [], // array of table settings objects
6924
	
6925
	
6926
		count: function ()
6927
		{
6928
			return this.flatten().length;
6929
		},
6930
	
6931
	
6932
		each: function ( fn )
6933
		{
6934
			for ( var i=0, ien=this.length ; i<ien; i++ ) {
6935
				fn.call( this, this[i], i, this );
6936
			}
6937
	
6938
			return this;
6939
		},
6940
	
6941
	
6942
		eq: function ( idx )
6943
		{
6944
			var ctx = this.context;
6945
	
6946
			return ctx.length > idx ?
6947
				new _Api( ctx[idx], this[idx] ) :
6948
				null;
6949
		},
6950
	
6951
	
6952
		filter: function ( fn )
6953
		{
6954
			var a = [];
6955
	
6956
			if ( __arrayProto.filter ) {
6957
				a = __arrayProto.filter.call( this, fn, this );
6958
			}
6959
			else {
6960
				// Compatibility for browsers without EMCA-252-5 (JS 1.6)
6961
				for ( var i=0, ien=this.length ; i<ien ; i++ ) {
6962
					if ( fn.call( this, this[i], i, this ) ) {
6963
						a.push( this[i] );
6964
					}
6965
				}
6966
			}
6967
	
6968
			return new _Api( this.context, a );
6969
		},
6970
	
6971
	
6972
		flatten: function ()
6973
		{
6974
			var a = [];
6975
			return new _Api( this.context, a.concat.apply( a, this.toArray() ) );
6976
		},
6977
	
6978
	
6979
		join:    __arrayProto.join,
6980
	
6981
	
6982
		indexOf: __arrayProto.indexOf || function (obj, start)
6983
		{
6984
			for ( var i=(start || 0), ien=this.length ; i<ien ; i++ ) {
6985
				if ( this[i] === obj ) {
6986
					return i;
6987
				}
6988
			}
6989
			return -1;
6990
		},
6991
	
6992
		iterator: function ( flatten, type, fn, alwaysNew ) {
6993
			var
6994
				a = [], ret,
6995
				i, ien, j, jen,
6996
				context = this.context,
6997
				rows, items, item,
6998
				selector = this.selector;
6999
	
7000
			// Argument shifting
7001
			if ( typeof flatten === 'string' ) {
7002
				alwaysNew = fn;
7003
				fn = type;
7004
				type = flatten;
7005
				flatten = false;
7006
			}
7007
	
7008
			for ( i=0, ien=context.length ; i<ien ; i++ ) {
7009
				var apiInst = new _Api( context[i] );
7010
	
7011
				if ( type === 'table' ) {
7012
					ret = fn.call( apiInst, context[i], i );
7013
	
7014
					if ( ret !== undefined ) {
7015
						a.push( ret );
7016
					}
7017
				}
7018
				else if ( type === 'columns' || type === 'rows' ) {
7019
					// this has same length as context - one entry for each table
7020
					ret = fn.call( apiInst, context[i], this[i], i );
7021
	
7022
					if ( ret !== undefined ) {
7023
						a.push( ret );
7024
					}
7025
				}
7026
				else if ( type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell' ) {
7027
					// columns and rows share the same structure.
7028
					// 'this' is an array of column indexes for each context
7029
					items = this[i];
7030
	
7031
					if ( type === 'column-rows' ) {
7032
						rows = _selector_row_indexes( context[i], selector.opts );
7033
					}
7034
	
7035
					for ( j=0, jen=items.length ; j<jen ; j++ ) {
7036
						item = items[j];
7037
	
7038
						if ( type === 'cell' ) {
7039
							ret = fn.call( apiInst, context[i], item.row, item.column, i, j );
7040
						}
7041
						else {
7042
							ret = fn.call( apiInst, context[i], item, i, j, rows );
0 ignored issues
show
Bug introduced by
The variable rows seems to not be initialized for all possible execution paths. Are you sure call handles undefined variables?
Loading history...
7043
						}
7044
	
7045
						if ( ret !== undefined ) {
7046
							a.push( ret );
7047
						}
7048
					}
7049
				}
7050
			}
7051
	
7052
			if ( a.length || alwaysNew ) {
7053
				var api = new _Api( context, flatten ? a.concat.apply( [], a ) : a );
7054
				var apiSelector = api.selector;
7055
				apiSelector.rows = selector.rows;
7056
				apiSelector.cols = selector.cols;
7057
				apiSelector.opts = selector.opts;
7058
				return api;
7059
			}
7060
			return this;
7061
		},
7062
	
7063
	
7064
		lastIndexOf: __arrayProto.lastIndexOf || function (obj, start)
0 ignored issues
show
Unused Code introduced by
The parameter obj is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter start is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
7065
		{
7066
			// Bit cheeky...
7067
			return this.indexOf.apply( this.toArray.reverse(), arguments );
7068
		},
7069
	
7070
	
7071
		length:  0,
7072
	
7073
	
7074
		map: function ( fn )
7075
		{
7076
			var a = [];
7077
	
7078
			if ( __arrayProto.map ) {
7079
				a = __arrayProto.map.call( this, fn, this );
7080
			}
7081
			else {
7082
				// Compatibility for browsers without EMCA-252-5 (JS 1.6)
7083
				for ( var i=0, ien=this.length ; i<ien ; i++ ) {
7084
					a.push( fn.call( this, this[i], i ) );
7085
				}
7086
			}
7087
	
7088
			return new _Api( this.context, a );
7089
		},
7090
	
7091
	
7092
		pluck: function ( prop )
7093
		{
7094
			return this.map( function ( el ) {
7095
				return el[ prop ];
7096
			} );
7097
		},
7098
	
7099
		pop:     __arrayProto.pop,
7100
	
7101
	
7102
		push:    __arrayProto.push,
7103
	
7104
	
7105
		// Does not return an API instance
7106
		reduce: __arrayProto.reduce || function ( fn, init )
7107
		{
7108
			return _fnReduce( this, fn, init, 0, this.length, 1 );
7109
		},
7110
	
7111
	
7112
		reduceRight: __arrayProto.reduceRight || function ( fn, init )
7113
		{
7114
			return _fnReduce( this, fn, init, this.length-1, -1, -1 );
7115
		},
7116
	
7117
	
7118
		reverse: __arrayProto.reverse,
7119
	
7120
	
7121
		// Object with rows, columns and opts
7122
		selector: null,
7123
	
7124
	
7125
		shift:   __arrayProto.shift,
7126
	
7127
	
7128
		slice: function () {
7129
			return new _Api( this.context, this );
7130
		},
7131
	
7132
	
7133
		sort:    __arrayProto.sort, // ? name - order?
7134
	
7135
	
7136
		splice:  __arrayProto.splice,
7137
	
7138
	
7139
		toArray: function ()
7140
		{
7141
			return __arrayProto.slice.call( this );
7142
		},
7143
	
7144
	
7145
		to$: function ()
7146
		{
7147
			return $( this );
7148
		},
7149
	
7150
	
7151
		toJQuery: function ()
7152
		{
7153
			return $( this );
7154
		},
7155
	
7156
	
7157
		unique: function ()
7158
		{
7159
			return new _Api( this.context, _unique(this) );
7160
		},
7161
	
7162
	
7163
		unshift: __arrayProto.unshift
7164
	} );
7165
	
7166
	
7167
	_Api.extend = function ( scope, obj, ext )
7168
	{
7169
		// Only extend API instances and static properties of the API
7170
		if ( ! ext.length || ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) {
7171
			return;
7172
		}
7173
	
7174
		var
7175
			i, ien,
7176
			j, jen,
0 ignored issues
show
Unused Code introduced by
The variable j seems to be never used. Consider removing it.
Loading history...
Unused Code introduced by
The variable jen seems to be never used. Consider removing it.
Loading history...
7177
			struct, inner,
0 ignored issues
show
Unused Code introduced by
The variable inner seems to be never used. Consider removing it.
Loading history...
7178
			methodScoping = function ( scope, fn, struc ) {
7179
				return function () {
7180
					var ret = fn.apply( scope, arguments );
7181
	
7182
					// Method extension
7183
					_Api.extend( ret, ret, struc.methodExt );
7184
					return ret;
7185
				};
7186
			};
7187
	
7188
		for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7189
			struct = ext[i];
7190
	
7191
			// Value
7192
			obj[ struct.name ] = typeof struct.val === 'function' ?
7193
				methodScoping( scope, struct.val, struct ) :
7194
				$.isPlainObject( struct.val ) ?
7195
					{} :
7196
					struct.val;
7197
	
7198
			obj[ struct.name ].__dt_wrapper = true;
7199
	
7200
			// Property extension
7201
			_Api.extend( scope, obj[ struct.name ], struct.propExt );
7202
		}
7203
	};
7204
	
7205
	
7206
	// @todo - Is there need for an augment function?
7207
	// _Api.augment = function ( inst, name )
7208
	// {
7209
	// 	// Find src object in the structure from the name
7210
	// 	var parts = name.split('.');
7211
	
7212
	// 	_Api.extend( inst, obj );
7213
	// };
7214
	
7215
	
7216
	//     [
7217
	//       {
7218
	//         name:      'data'                -- string   - Property name
7219
	//         val:       function () {},       -- function - Api method (or undefined if just an object
7220
	//         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
7221
	//         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
7222
	//       },
7223
	//       {
7224
	//         name:     'row'
7225
	//         val:       {},
7226
	//         methodExt: [ ... ],
7227
	//         propExt:   [
7228
	//           {
7229
	//             name:      'data'
7230
	//             val:       function () {},
7231
	//             methodExt: [ ... ],
7232
	//             propExt:   [ ... ]
7233
	//           },
7234
	//           ...
7235
	//         ]
7236
	//       }
7237
	//     ]
7238
	
7239
	_Api.register = _api_register = function ( name, val )
7240
	{
7241
		if ( $.isArray( name ) ) {
7242
			for ( var j=0, jen=name.length ; j<jen ; j++ ) {
7243
				_Api.register( name[j], val );
7244
			}
7245
			return;
7246
		}
7247
	
7248
		var
7249
			i, ien,
7250
			heir = name.split('.'),
7251
			struct = __apiStruct,
7252
			key, method;
7253
	
7254
		var find = function ( src, name ) {
7255
			for ( var i=0, ien=src.length ; i<ien ; i++ ) {
7256
				if ( src[i].name === name ) {
7257
					return src[i];
7258
				}
7259
			}
7260
			return null;
7261
		};
7262
	
7263
		for ( i=0, ien=heir.length ; i<ien ; i++ ) {
7264
			method = heir[i].indexOf('()') !== -1;
7265
			key = method ?
7266
				heir[i].replace('()', '') :
7267
				heir[i];
7268
	
7269
			var src = find( struct, key );
7270
			if ( ! src ) {
7271
				src = {
7272
					name:      key,
7273
					val:       {},
7274
					methodExt: [],
7275
					propExt:   []
7276
				};
7277
				struct.push( src );
7278
			}
7279
	
7280
			if ( i === ien-1 ) {
7281
				src.val = val;
7282
			}
7283
			else {
7284
				struct = method ?
7285
					src.methodExt :
7286
					src.propExt;
7287
			}
7288
		}
7289
	};
7290
	
7291
	
7292
	_Api.registerPlural = _api_registerPlural = function ( pluralName, singularName, val ) {
7293
		_Api.register( pluralName, val );
7294
	
7295
		_Api.register( singularName, function () {
7296
			var ret = val.apply( this, arguments );
7297
	
7298
			if ( ret === this ) {
7299
				// Returned item is the API instance that was passed in, return it
7300
				return this;
7301
			}
7302
			else if ( ret instanceof _Api ) {
7303
				// New API instance returned, want the value from the first item
7304
				// in the returned array for the singular result.
7305
				return ret.length ?
7306
					$.isArray( ret[0] ) ?
7307
						new _Api( ret.context, ret[0] ) : // Array results are 'enhanced'
7308
						ret[0] :
7309
					undefined;
7310
			}
7311
	
7312
			// Non-API return - just fire it back
7313
			return ret;
7314
		} );
7315
	};
7316
	
7317
	
7318
	/**
7319
	 * Selector for HTML tables. Apply the given selector to the give array of
7320
	 * DataTables settings objects.
7321
	 *
7322
	 * @param {string|integer} [selector] jQuery selector string or integer
7323
	 * @param  {array} Array of DataTables settings objects to be filtered
7324
	 * @return {array}
7325
	 * @ignore
7326
	 */
7327
	var __table_selector = function ( selector, a )
7328
	{
7329
		// Integer is used to pick out a table by index
7330
		if ( typeof selector === 'number' ) {
7331
			return [ a[ selector ] ];
7332
		}
7333
	
7334
		// Perform a jQuery selector on the table nodes
7335
		var nodes = $.map( a, function (el, i) {
0 ignored issues
show
Unused Code introduced by
The parameter i is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
7336
			return el.nTable;
7337
		} );
7338
	
7339
		return $(nodes)
7340
			.filter( selector )
7341
			.map( function (i) {
0 ignored issues
show
Unused Code introduced by
The parameter i is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
7342
				// Need to translate back from the table node to the settings
7343
				var idx = $.inArray( this, nodes );
7344
				return a[ idx ];
7345
			} )
7346
			.toArray();
7347
	};
7348
	
7349
	
7350
	
7351
	/**
7352
	 * Context selector for the API's context (i.e. the tables the API instance
7353
	 * refers to.
7354
	 *
7355
	 * @name    DataTable.Api#tables
7356
	 * @param {string|integer} [selector] Selector to pick which tables the iterator
7357
	 *   should operate on. If not given, all tables in the current context are
7358
	 *   used. This can be given as a jQuery selector (for example `':gt(0)'`) to
7359
	 *   select multiple tables or as an integer to select a single table.
7360
	 * @returns {DataTable.Api} Returns a new API instance if a selector is given.
7361
	 */
7362
	_api_register( 'tables()', function ( selector ) {
7363
		// A new instance is created if there was a selector specified
7364
		return selector ?
7365
			new _Api( __table_selector( selector, this.context ) ) :
7366
			this;
7367
	} );
7368
	
7369
	
7370
	_api_register( 'table()', function ( selector ) {
7371
		var tables = this.tables( selector );
7372
		var ctx = tables.context;
7373
	
7374
		// Truncate to the first matched table
7375
		return ctx.length ?
7376
			new _Api( ctx[0] ) :
7377
			tables;
7378
	} );
7379
	
7380
	
7381
	_api_registerPlural( 'tables().nodes()', 'table().node()' , function () {
7382
		return this.iterator( 'table', function ( ctx ) {
7383
			return ctx.nTable;
7384
		}, 1 );
7385
	} );
7386
	
7387
	
7388
	_api_registerPlural( 'tables().body()', 'table().body()' , function () {
7389
		return this.iterator( 'table', function ( ctx ) {
7390
			return ctx.nTBody;
7391
		}, 1 );
7392
	} );
7393
	
7394
	
7395
	_api_registerPlural( 'tables().header()', 'table().header()' , function () {
7396
		return this.iterator( 'table', function ( ctx ) {
7397
			return ctx.nTHead;
7398
		}, 1 );
7399
	} );
7400
	
7401
	
7402
	_api_registerPlural( 'tables().footer()', 'table().footer()' , function () {
7403
		return this.iterator( 'table', function ( ctx ) {
7404
			return ctx.nTFoot;
7405
		}, 1 );
7406
	} );
7407
	
7408
	
7409
	_api_registerPlural( 'tables().containers()', 'table().container()' , function () {
7410
		return this.iterator( 'table', function ( ctx ) {
7411
			return ctx.nTableWrapper;
7412
		}, 1 );
7413
	} );
7414
	
7415
	
7416
	
7417
	/**
7418
	 * Redraw the tables in the current context.
7419
	 */
7420
	_api_register( 'draw()', function ( paging ) {
7421
		return this.iterator( 'table', function ( settings ) {
7422
			if ( paging === 'page' ) {
7423
				_fnDraw( settings );
7424
			}
7425
			else {
7426
				if ( typeof paging === 'string' ) {
7427
					paging = paging === 'full-hold' ?
7428
						false :
7429
						true;
7430
				}
7431
	
7432
				_fnReDraw( settings, paging===false );
7433
			}
7434
		} );
7435
	} );
7436
	
7437
	
7438
	
7439
	/**
7440
	 * Get the current page index.
7441
	 *
7442
	 * @return {integer} Current page index (zero based)
7443
	 *//**
7444
	 * Set the current page.
7445
	 *
7446
	 * Note that if you attempt to show a page which does not exist, DataTables will
7447
	 * not throw an error, but rather reset the paging.
7448
	 *
7449
	 * @param {integer|string} action The paging action to take. This can be one of:
7450
	 *  * `integer` - The page index to jump to
7451
	 *  * `string` - An action to take:
7452
	 *    * `first` - Jump to first page.
7453
	 *    * `next` - Jump to the next page
7454
	 *    * `previous` - Jump to previous page
7455
	 *    * `last` - Jump to the last page.
7456
	 * @returns {DataTables.Api} this
7457
	 */
7458
	_api_register( 'page()', function ( action ) {
7459
		if ( action === undefined ) {
7460
			return this.page.info().page; // not an expensive call
7461
		}
7462
	
7463
		// else, have an action to take on all tables
7464
		return this.iterator( 'table', function ( settings ) {
7465
			_fnPageChange( settings, action );
7466
		} );
7467
	} );
7468
	
7469
	
7470
	/**
7471
	 * Paging information for the first table in the current context.
7472
	 *
7473
	 * If you require paging information for another table, use the `table()` method
7474
	 * with a suitable selector.
7475
	 *
7476
	 * @return {object} Object with the following properties set:
7477
	 *  * `page` - Current page index (zero based - i.e. the first page is `0`)
7478
	 *  * `pages` - Total number of pages
7479
	 *  * `start` - Display index for the first record shown on the current page
7480
	 *  * `end` - Display index for the last record shown on the current page
7481
	 *  * `length` - Display length (number of records). Note that generally `start
7482
	 *    + length = end`, but this is not always true, for example if there are
7483
	 *    only 2 records to show on the final page, with a length of 10.
7484
	 *  * `recordsTotal` - Full data set length
7485
	 *  * `recordsDisplay` - Data set length once the current filtering criterion
7486
	 *    are applied.
7487
	 */
7488
	_api_register( 'page.info()', function ( action ) {
0 ignored issues
show
Unused Code introduced by
The parameter action is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
7489
		if ( this.context.length === 0 ) {
7490
			return undefined;
7491
		}
7492
	
7493
		var
7494
			settings   = this.context[0],
7495
			start      = settings._iDisplayStart,
7496
			len        = settings.oFeatures.bPaginate ? settings._iDisplayLength : -1,
7497
			visRecords = settings.fnRecordsDisplay(),
7498
			all        = len === -1;
7499
	
7500
		return {
7501
			"page":           all ? 0 : Math.floor( start / len ),
7502
			"pages":          all ? 1 : Math.ceil( visRecords / len ),
7503
			"start":          start,
7504
			"end":            settings.fnDisplayEnd(),
7505
			"length":         len,
7506
			"recordsTotal":   settings.fnRecordsTotal(),
7507
			"recordsDisplay": visRecords,
7508
			"serverSide":     _fnDataSource( settings ) === 'ssp'
7509
		};
7510
	} );
7511
	
7512
	
7513
	/**
7514
	 * Get the current page length.
7515
	 *
7516
	 * @return {integer} Current page length. Note `-1` indicates that all records
7517
	 *   are to be shown.
7518
	 *//**
7519
	 * Set the current page length.
7520
	 *
7521
	 * @param {integer} Page length to set. Use `-1` to show all records.
7522
	 * @returns {DataTables.Api} this
7523
	 */
7524
	_api_register( 'page.len()', function ( len ) {
7525
		// Note that we can't call this function 'length()' because `length`
7526
		// is a Javascript property of functions which defines how many arguments
7527
		// the function expects.
7528
		if ( len === undefined ) {
7529
			return this.context.length !== 0 ?
7530
				this.context[0]._iDisplayLength :
7531
				undefined;
7532
		}
7533
	
7534
		// else, set the page length
7535
		return this.iterator( 'table', function ( settings ) {
7536
			_fnLengthChange( settings, len );
7537
		} );
7538
	} );
7539
	
7540
	
7541
	
7542
	var __reload = function ( settings, holdPosition, callback ) {
7543
		// Use the draw event to trigger a callback
7544
		if ( callback ) {
7545
			var api = new _Api( settings );
7546
	
7547
			api.one( 'draw', function () {
7548
				callback( api.ajax.json() );
7549
			} );
7550
		}
7551
	
7552
		if ( _fnDataSource( settings ) == 'ssp' ) {
7553
			_fnReDraw( settings, holdPosition );
7554
		}
7555
		else {
7556
			_fnProcessingDisplay( settings, true );
7557
	
7558
			// Cancel an existing request
7559
			var xhr = settings.jqXHR;
7560
			if ( xhr && xhr.readyState !== 4 ) {
7561
				xhr.abort();
7562
			}
7563
	
7564
			// Trigger xhr
7565
			_fnBuildAjax( settings, [], function( json ) {
7566
				_fnClearTable( settings );
7567
	
7568
				var data = _fnAjaxDataSrc( settings, json );
7569
				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7570
					_fnAddData( settings, data[i] );
7571
				}
7572
	
7573
				_fnReDraw( settings, holdPosition );
7574
				_fnProcessingDisplay( settings, false );
7575
			} );
7576
		}
7577
	};
7578
	
7579
	
7580
	/**
7581
	 * Get the JSON response from the last Ajax request that DataTables made to the
7582
	 * server. Note that this returns the JSON from the first table in the current
7583
	 * context.
7584
	 *
7585
	 * @return {object} JSON received from the server.
7586
	 */
7587
	_api_register( 'ajax.json()', function () {
7588
		var ctx = this.context;
7589
	
7590
		if ( ctx.length > 0 ) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if ctx.length > 0 is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
7591
			return ctx[0].json;
7592
		}
7593
	
7594
		// else return undefined;
7595
	} );
7596
	
7597
	
7598
	/**
7599
	 * Get the data submitted in the last Ajax request
7600
	 */
7601
	_api_register( 'ajax.params()', function () {
7602
		var ctx = this.context;
7603
	
7604
		if ( ctx.length > 0 ) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if ctx.length > 0 is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
7605
			return ctx[0].oAjaxData;
7606
		}
7607
	
7608
		// else return undefined;
7609
	} );
7610
	
7611
	
7612
	/**
7613
	 * Reload tables from the Ajax data source. Note that this function will
7614
	 * automatically re-draw the table when the remote data has been loaded.
7615
	 *
7616
	 * @param {boolean} [reset=true] Reset (default) or hold the current paging
7617
	 *   position. A full re-sort and re-filter is performed when this method is
7618
	 *   called, which is why the pagination reset is the default action.
7619
	 * @returns {DataTables.Api} this
7620
	 */
7621
	_api_register( 'ajax.reload()', function ( callback, resetPaging ) {
7622
		return this.iterator( 'table', function (settings) {
7623
			__reload( settings, resetPaging===false, callback );
7624
		} );
7625
	} );
7626
	
7627
	
7628
	/**
7629
	 * Get the current Ajax URL. Note that this returns the URL from the first
7630
	 * table in the current context.
7631
	 *
7632
	 * @return {string} Current Ajax source URL
7633
	 *//**
7634
	 * Set the Ajax URL. Note that this will set the URL for all tables in the
7635
	 * current context.
7636
	 *
7637
	 * @param {string} url URL to set.
7638
	 * @returns {DataTables.Api} this
7639
	 */
7640
	_api_register( 'ajax.url()', function ( url ) {
7641
		var ctx = this.context;
7642
	
7643
		if ( url === undefined ) {
7644
			// get
7645
			if ( ctx.length === 0 ) {
7646
				return undefined;
7647
			}
7648
			ctx = ctx[0];
7649
	
7650
			return ctx.ajax ?
7651
				$.isPlainObject( ctx.ajax ) ?
7652
					ctx.ajax.url :
7653
					ctx.ajax :
7654
				ctx.sAjaxSource;
7655
		}
7656
	
7657
		// set
7658
		return this.iterator( 'table', function ( settings ) {
7659
			if ( $.isPlainObject( settings.ajax ) ) {
7660
				settings.ajax.url = url;
7661
			}
7662
			else {
7663
				settings.ajax = url;
7664
			}
7665
			// No need to consider sAjaxSource here since DataTables gives priority
7666
			// to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any
7667
			// value of `sAjaxSource` redundant.
7668
		} );
7669
	} );
7670
	
7671
	
7672
	/**
7673
	 * Load data from the newly set Ajax URL. Note that this method is only
7674
	 * available when `ajax.url()` is used to set a URL. Additionally, this method
7675
	 * has the same effect as calling `ajax.reload()` but is provided for
7676
	 * convenience when setting a new URL. Like `ajax.reload()` it will
7677
	 * automatically redraw the table once the remote data has been loaded.
7678
	 *
7679
	 * @returns {DataTables.Api} this
7680
	 */
7681
	_api_register( 'ajax.url().load()', function ( callback, resetPaging ) {
7682
		// Same as a reload, but makes sense to present it for easy access after a
7683
		// url change
7684
		return this.iterator( 'table', function ( ctx ) {
7685
			__reload( ctx, resetPaging===false, callback );
7686
		} );
7687
	} );
7688
	
7689
	
7690
	
7691
	
7692
	var _selector_run = function ( type, selector, selectFn, settings, opts )
7693
	{
7694
		var
7695
			out = [], res,
7696
			a, i, ien, j, jen,
7697
			selectorType = typeof selector;
7698
	
7699
		// Can't just check for isArray here, as an API or jQuery instance might be
7700
		// given with their array like look
7701
		if ( ! selector || selectorType === 'string' || selectorType === 'function' || selector.length === undefined ) {
7702
			selector = [ selector ];
7703
		}
7704
	
7705
		for ( i=0, ien=selector.length ; i<ien ; i++ ) {
7706
			// Only split on simple strings - complex expressions will be jQuery selectors
7707
			a = selector[i] && selector[i].split && ! selector[i].match(/[\[\(:]/) ?
7708
				selector[i].split(',') :
7709
				[ selector[i] ];
7710
	
7711
			for ( j=0, jen=a.length ; j<jen ; j++ ) {
7712
				res = selectFn( typeof a[j] === 'string' ? $.trim(a[j]) : a[j] );
7713
	
7714
				if ( res && res.length ) {
7715
					out = out.concat( res );
7716
				}
7717
			}
7718
		}
7719
	
7720
		// selector extensions
7721
		var ext = _ext.selector[ type ];
7722
		if ( ext.length ) {
7723
			for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7724
				out = ext[i]( settings, opts, out );
7725
			}
7726
		}
7727
	
7728
		return _unique( out );
7729
	};
7730
	
7731
	
7732
	var _selector_opts = function ( opts )
7733
	{
7734
		if ( ! opts ) {
7735
			opts = {};
7736
		}
7737
	
7738
		// Backwards compatibility for 1.9- which used the terminology filter rather
7739
		// than search
7740
		if ( opts.filter && opts.search === undefined ) {
7741
			opts.search = opts.filter;
7742
		}
7743
	
7744
		return $.extend( {
7745
			search: 'none',
7746
			order: 'current',
7747
			page: 'all'
7748
		}, opts );
7749
	};
7750
	
7751
	
7752
	var _selector_first = function ( inst )
7753
	{
7754
		// Reduce the API instance to the first item found
7755
		for ( var i=0, ien=inst.length ; i<ien ; i++ ) {
7756
			if ( inst[i].length > 0 ) {
7757
				// Assign the first element to the first item in the instance
7758
				// and truncate the instance and context
7759
				inst[0] = inst[i];
7760
				inst[0].length = 1;
7761
				inst.length = 1;
7762
				inst.context = [ inst.context[i] ];
7763
	
7764
				return inst;
7765
			}
7766
		}
7767
	
7768
		// Not found - return an empty instance
7769
		inst.length = 0;
7770
		return inst;
7771
	};
7772
	
7773
	
7774
	var _selector_row_indexes = function ( settings, opts )
7775
	{
7776
		var
7777
			i, ien, tmp, a=[],
7778
			displayFiltered = settings.aiDisplay,
7779
			displayMaster = settings.aiDisplayMaster;
7780
	
7781
		var
7782
			search = opts.search,  // none, applied, removed
7783
			order  = opts.order,   // applied, current, index (original - compatibility with 1.9)
7784
			page   = opts.page;    // all, current
7785
	
7786
		if ( _fnDataSource( settings ) == 'ssp' ) {
7787
			// In server-side processing mode, most options are irrelevant since
7788
			// rows not shown don't exist and the index order is the applied order
7789
			// Removed is a special case - for consistency just return an empty
7790
			// array
7791
			return search === 'removed' ?
7792
				[] :
7793
				_range( 0, displayMaster.length );
7794
		}
7795
		else if ( page == 'current' ) {
7796
			// Current page implies that order=current and fitler=applied, since it is
7797
			// fairly senseless otherwise, regardless of what order and search actually
7798
			// are
7799
			for ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i<ien ; i++ ) {
7800
				a.push( displayFiltered[i] );
7801
			}
7802
		}
7803
		else if ( order == 'current' || order == 'applied' ) {
7804
			a = search == 'none' ?
7805
				displayMaster.slice() :                      // no search
7806
				search == 'applied' ?
7807
					displayFiltered.slice() :                // applied search
7808
					$.map( displayMaster, function (el, i) { // removed search
0 ignored issues
show
Unused Code introduced by
The parameter i is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
7809
						return $.inArray( el, displayFiltered ) === -1 ? el : null;
7810
					} );
7811
		}
7812
		else if ( order == 'index' || order == 'original' ) {
7813
			for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
7814
				if ( search == 'none' ) {
7815
					a.push( i );
7816
				}
7817
				else { // applied | removed
7818
					tmp = $.inArray( i, displayFiltered );
7819
	
7820
					if ((tmp === -1 && search == 'removed') ||
7821
						(tmp >= 0   && search == 'applied') )
7822
					{
7823
						a.push( i );
7824
					}
7825
				}
7826
			}
7827
		}
7828
	
7829
		return a;
7830
	};
7831
	
7832
	
7833
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
7834
	 * Rows
7835
	 *
7836
	 * {}          - no selector - use all available rows
7837
	 * {integer}   - row aoData index
7838
	 * {node}      - TR node
7839
	 * {string}    - jQuery selector to apply to the TR elements
7840
	 * {array}     - jQuery array of nodes, or simply an array of TR nodes
7841
	 *
7842
	 */
7843
	
7844
	
7845
	var __row_selector = function ( settings, selector, opts )
7846
	{
7847
		var rows;
7848
		var run = function ( sel ) {
7849
			var selInt = _intVal( sel );
7850
			var i, ien;
0 ignored issues
show
Unused Code introduced by
The variable i seems to be never used. Consider removing it.
Loading history...
Unused Code introduced by
The variable ien seems to be never used. Consider removing it.
Loading history...
7851
	
7852
			// Short cut - selector is a number and no options provided (default is
7853
			// all records, so no need to check if the index is in there, since it
7854
			// must be - dev error if the index doesn't exist).
7855
			if ( selInt !== null && ! opts ) {
7856
				return [ selInt ];
7857
			}
7858
	
7859
			if ( ! rows ) {
7860
				rows = _selector_row_indexes( settings, opts );
7861
			}
7862
	
7863
			if ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) {
7864
				// Selector - integer
7865
				return [ selInt ];
7866
			}
7867
			else if ( sel === null || sel === undefined || sel === '' ) {
7868
				// Selector - none
7869
				return rows;
7870
			}
7871
	
7872
			// Selector - function
7873
			if ( typeof sel === 'function' ) {
7874
				return $.map( rows, function (idx) {
7875
					var row = settings.aoData[ idx ];
7876
					return sel( idx, row._aData, row.nTr ) ? idx : null;
7877
				} );
7878
			}
7879
	
7880
			// Get nodes in the order from the `rows` array with null values removed
7881
			var nodes = _removeEmpty(
7882
				_pluck_order( settings.aoData, rows, 'nTr' )
7883
			);
7884
	
7885
			// Selector - node
7886
			if ( sel.nodeName ) {
7887
				if ( sel._DT_RowIndex !== undefined ) {
7888
					return [ sel._DT_RowIndex ]; // Property added by DT for fast lookup
7889
				}
7890
				else if ( sel._DT_CellIndex ) {
7891
					return [ sel._DT_CellIndex.row ];
7892
				}
7893
				else {
7894
					var host = $(sel).closest('*[data-dt-row]');
7895
					return host.length ?
7896
						[ host.data('dt-row') ] :
7897
						[];
7898
				}
7899
			}
7900
	
7901
			// ID selector. Want to always be able to select rows by id, regardless
7902
			// of if the tr element has been created or not, so can't rely upon
7903
			// jQuery here - hence a custom implementation. This does not match
7904
			// Sizzle's fast selector or HTML4 - in HTML5 the ID can be anything,
7905
			// but to select it using a CSS selector engine (like Sizzle or
7906
			// querySelect) it would need to need to be escaped for some characters.
7907
			// DataTables simplifies this for row selectors since you can select
7908
			// only a row. A # indicates an id any anything that follows is the id -
7909
			// unescaped.
7910
			if ( typeof sel === 'string' && sel.charAt(0) === '#' ) {
7911
				// get row index from id
7912
				var rowObj = settings.aIds[ sel.replace( /^#/, '' ) ];
7913
				if ( rowObj !== undefined ) {
7914
					return [ rowObj.idx ];
7915
				}
7916
	
7917
				// need to fall through to jQuery in case there is DOM id that
7918
				// matches
7919
			}
7920
	
7921
			// Selector - jQuery selector string, array of nodes or jQuery object/
7922
			// As jQuery's .filter() allows jQuery objects to be passed in filter,
7923
			// it also allows arrays, so this will cope with all three options
7924
			return $(nodes)
7925
				.filter( sel )
7926
				.map( function () {
7927
					return this._DT_RowIndex;
7928
				} )
7929
				.toArray();
7930
		};
7931
	
7932
		return _selector_run( 'row', selector, run, settings, opts );
7933
	};
7934
	
7935
	
7936
	_api_register( 'rows()', function ( selector, opts ) {
7937
		// argument shifting
7938
		if ( selector === undefined ) {
7939
			selector = '';
7940
		}
7941
		else if ( $.isPlainObject( selector ) ) {
7942
			opts = selector;
7943
			selector = '';
7944
		}
7945
	
7946
		opts = _selector_opts( opts );
7947
	
7948
		var inst = this.iterator( 'table', function ( settings ) {
7949
			return __row_selector( settings, selector, opts );
7950
		}, 1 );
7951
	
7952
		// Want argument shifting here and in __row_selector?
7953
		inst.selector.rows = selector;
7954
		inst.selector.opts = opts;
7955
	
7956
		return inst;
7957
	} );
7958
	
7959
	_api_register( 'rows().nodes()', function () {
7960
		return this.iterator( 'row', function ( settings, row ) {
7961
			return settings.aoData[ row ].nTr || undefined;
7962
		}, 1 );
7963
	} );
7964
	
7965
	_api_register( 'rows().data()', function () {
7966
		return this.iterator( true, 'rows', function ( settings, rows ) {
7967
			return _pluck_order( settings.aoData, rows, '_aData' );
7968
		}, 1 );
7969
	} );
7970
	
7971
	_api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) {
7972
		return this.iterator( 'row', function ( settings, row ) {
7973
			var r = settings.aoData[ row ];
7974
			return type === 'search' ? r._aFilterData : r._aSortData;
7975
		}, 1 );
7976
	} );
7977
	
7978
	_api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) {
7979
		return this.iterator( 'row', function ( settings, row ) {
7980
			_fnInvalidate( settings, row, src );
7981
		} );
7982
	} );
7983
	
7984
	_api_registerPlural( 'rows().indexes()', 'row().index()', function () {
7985
		return this.iterator( 'row', function ( settings, row ) {
7986
			return row;
7987
		}, 1 );
7988
	} );
7989
	
7990
	_api_registerPlural( 'rows().ids()', 'row().id()', function ( hash ) {
7991
		var a = [];
7992
		var context = this.context;
7993
	
7994
		// `iterator` will drop undefined values, but in this case we want them
7995
		for ( var i=0, ien=context.length ; i<ien ; i++ ) {
7996
			for ( var j=0, jen=this[i].length ; j<jen ; j++ ) {
7997
				var id = context[i].rowIdFn( context[i].aoData[ this[i][j] ]._aData );
7998
				a.push( (hash === true ? '#' : '' )+ id );
7999
			}
8000
		}
8001
	
8002
		return new _Api( context, a );
8003
	} );
8004
	
8005
	_api_registerPlural( 'rows().remove()', 'row().remove()', function () {
8006
		var that = this;
8007
	
8008
		this.iterator( 'row', function ( settings, row, thatIdx ) {
8009
			var data = settings.aoData;
8010
			var rowData = data[ row ];
8011
			var i, ien, j, jen;
8012
			var loopRow, loopCells;
8013
	
8014
			data.splice( row, 1 );
8015
	
8016
			// Update the cached indexes
8017
			for ( i=0, ien=data.length ; i<ien ; i++ ) {
8018
				loopRow = data[i];
8019
				loopCells = loopRow.anCells;
8020
	
8021
				// Rows
8022
				if ( loopRow.nTr !== null ) {
8023
					loopRow.nTr._DT_RowIndex = i;
8024
				}
8025
	
8026
				// Cells
8027
				if ( loopCells !== null ) {
8028
					for ( j=0, jen=loopCells.length ; j<jen ; j++ ) {
8029
						loopCells[j]._DT_CellIndex.row = i;
8030
					}
8031
				}
8032
			}
8033
	
8034
			// Delete from the display arrays
8035
			_fnDeleteIndex( settings.aiDisplayMaster, row );
8036
			_fnDeleteIndex( settings.aiDisplay, row );
8037
			_fnDeleteIndex( that[ thatIdx ], row, false ); // maintain local indexes
8038
	
8039
			// For server-side processing tables - subtract the deleted row from the count
8040
			if ( settings._iRecordsDisplay > 0 ) {
8041
				settings._iRecordsDisplay--;
8042
			}
8043
	
8044
			// Check for an 'overflow' they case for displaying the table
8045
			_fnLengthOverflow( settings );
8046
	
8047
			// Remove the row's ID reference if there is one
8048
			var id = settings.rowIdFn( rowData._aData );
8049
			if ( id !== undefined ) {
8050
				delete settings.aIds[ id ];
8051
			}
8052
		} );
8053
	
8054
		this.iterator( 'table', function ( settings ) {
8055
			for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
8056
				settings.aoData[i].idx = i;
8057
			}
8058
		} );
8059
	
8060
		return this;
8061
	} );
8062
	
8063
	
8064
	_api_register( 'rows.add()', function ( rows ) {
8065
		var newRows = this.iterator( 'table', function ( settings ) {
8066
				var row, i, ien;
8067
				var out = [];
8068
	
8069
				for ( i=0, ien=rows.length ; i<ien ; i++ ) {
8070
					row = rows[i];
8071
	
8072
					if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
8073
						out.push( _fnAddTr( settings, row )[0] );
8074
					}
8075
					else {
8076
						out.push( _fnAddData( settings, row ) );
8077
					}
8078
				}
8079
	
8080
				return out;
8081
			}, 1 );
8082
	
8083
		// Return an Api.rows() extended instance, so rows().nodes() etc can be used
8084
		var modRows = this.rows( -1 );
8085
		modRows.pop();
8086
		$.merge( modRows, newRows );
8087
	
8088
		return modRows;
8089
	} );
8090
	
8091
	
8092
	
8093
	
8094
	
8095
	/**
8096
	 *
8097
	 */
8098
	_api_register( 'row()', function ( selector, opts ) {
8099
		return _selector_first( this.rows( selector, opts ) );
8100
	} );
8101
	
8102
	
8103
	_api_register( 'row().data()', function ( data ) {
8104
		var ctx = this.context;
8105
	
8106
		if ( data === undefined ) {
8107
			// Get
8108
			return ctx.length && this.length ?
8109
				ctx[0].aoData[ this[0] ]._aData :
8110
				undefined;
8111
		}
8112
	
8113
		// Set
8114
		ctx[0].aoData[ this[0] ]._aData = data;
8115
	
8116
		// Automatically invalidate
8117
		_fnInvalidate( ctx[0], this[0], 'data' );
8118
	
8119
		return this;
8120
	} );
8121
	
8122
	
8123
	_api_register( 'row().node()', function () {
8124
		var ctx = this.context;
8125
	
8126
		return ctx.length && this.length ?
8127
			ctx[0].aoData[ this[0] ].nTr || null :
8128
			null;
8129
	} );
8130
	
8131
	
8132
	_api_register( 'row.add()', function ( row ) {
8133
		// Allow a jQuery object to be passed in - only a single row is added from
8134
		// it though - the first element in the set
8135
		if ( row instanceof $ && row.length ) {
8136
			row = row[0];
8137
		}
8138
	
8139
		var rows = this.iterator( 'table', function ( settings ) {
8140
			if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
8141
				return _fnAddTr( settings, row )[0];
8142
			}
8143
			return _fnAddData( settings, row );
8144
		} );
8145
	
8146
		// Return an Api.rows() extended instance, with the newly added row selected
8147
		return this.row( rows[0] );
8148
	} );
8149
	
8150
	
8151
	
8152
	var __details_add = function ( ctx, row, data, klass )
8153
	{
8154
		// Convert to array of TR elements
8155
		var rows = [];
8156
		var addRow = function ( r, k ) {
8157
			// Recursion to allow for arrays of jQuery objects
8158
			if ( $.isArray( r ) || r instanceof $ ) {
8159
				for ( var i=0, ien=r.length ; i<ien ; i++ ) {
8160
					addRow( r[i], k );
8161
				}
8162
				return;
8163
			}
8164
	
8165
			// If we get a TR element, then just add it directly - up to the dev
8166
			// to add the correct number of columns etc
8167
			if ( r.nodeName && r.nodeName.toLowerCase() === 'tr' ) {
8168
				rows.push( r );
8169
			}
8170
			else {
8171
				// Otherwise create a row with a wrapper
8172
				var created = $('<tr><td/></tr>').addClass( k );
8173
				$('td', created)
8174
					.addClass( k )
8175
					.html( r )
8176
					[0].colSpan = _fnVisbleColumns( ctx );
8177
	
8178
				rows.push( created[0] );
8179
			}
8180
		};
8181
	
8182
		addRow( data, klass );
8183
	
8184
		if ( row._details ) {
8185
			row._details.detach();
8186
		}
8187
	
8188
		row._details = $(rows);
8189
	
8190
		// If the children were already shown, that state should be retained
8191
		if ( row._detailsShow ) {
8192
			row._details.insertAfter( row.nTr );
8193
		}
8194
	};
8195
	
8196
	
8197
	var __details_remove = function ( api, idx )
8198
	{
8199
		var ctx = api.context;
8200
	
8201
		if ( ctx.length ) {
8202
			var row = ctx[0].aoData[ idx !== undefined ? idx : api[0] ];
8203
	
8204
			if ( row && row._details ) {
8205
				row._details.remove();
8206
	
8207
				row._detailsShow = undefined;
8208
				row._details = undefined;
8209
			}
8210
		}
8211
	};
8212
	
8213
	
8214
	var __details_display = function ( api, show ) {
8215
		var ctx = api.context;
8216
	
8217
		if ( ctx.length && api.length ) {
8218
			var row = ctx[0].aoData[ api[0] ];
8219
	
8220
			if ( row._details ) {
8221
				row._detailsShow = show;
8222
	
8223
				if ( show ) {
8224
					row._details.insertAfter( row.nTr );
8225
				}
8226
				else {
8227
					row._details.detach();
8228
				}
8229
	
8230
				__details_events( ctx[0] );
8231
			}
8232
		}
8233
	};
8234
	
8235
	
8236
	var __details_events = function ( settings )
8237
	{
8238
		var api = new _Api( settings );
8239
		var namespace = '.dt.DT_details';
8240
		var drawEvent = 'draw'+namespace;
8241
		var colvisEvent = 'column-visibility'+namespace;
8242
		var destroyEvent = 'destroy'+namespace;
8243
		var data = settings.aoData;
8244
	
8245
		api.off( drawEvent +' '+ colvisEvent +' '+ destroyEvent );
8246
	
8247
		if ( _pluck( data, '_details' ).length > 0 ) {
8248
			// On each draw, insert the required elements into the document
8249
			api.on( drawEvent, function ( e, ctx ) {
8250
				if ( settings !== ctx ) {
8251
					return;
8252
				}
8253
	
8254
				api.rows( {page:'current'} ).eq(0).each( function (idx) {
8255
					// Internal data grab
8256
					var row = data[ idx ];
8257
	
8258
					if ( row._detailsShow ) {
8259
						row._details.insertAfter( row.nTr );
8260
					}
8261
				} );
8262
			} );
8263
	
8264
			// Column visibility change - update the colspan
8265
			api.on( colvisEvent, function ( e, ctx, idx, vis ) {
0 ignored issues
show
Unused Code introduced by
The parameter idx is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter vis is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
8266
				if ( settings !== ctx ) {
8267
					return;
8268
				}
8269
	
8270
				// Update the colspan for the details rows (note, only if it already has
8271
				// a colspan)
8272
				var row, visible = _fnVisbleColumns( ctx );
8273
	
8274
				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
8275
					row = data[i];
8276
	
8277
					if ( row._details ) {
8278
						row._details.children('td[colspan]').attr('colspan', visible );
8279
					}
8280
				}
8281
			} );
8282
	
8283
			// Table destroyed - nuke any child rows
8284
			api.on( destroyEvent, function ( e, ctx ) {
8285
				if ( settings !== ctx ) {
8286
					return;
8287
				}
8288
	
8289
				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
8290
					if ( data[i]._details ) {
8291
						__details_remove( api, i );
8292
					}
8293
				}
8294
			} );
8295
		}
8296
	};
8297
	
8298
	// Strings for the method names to help minification
8299
	var _emp = '';
8300
	var _child_obj = _emp+'row().child';
8301
	var _child_mth = _child_obj+'()';
8302
	
8303
	// data can be:
8304
	//  tr
8305
	//  string
8306
	//  jQuery or array of any of the above
8307
	_api_register( _child_mth, function ( data, klass ) {
8308
		var ctx = this.context;
8309
	
8310
		if ( data === undefined ) {
8311
			// get
8312
			return ctx.length && this.length ?
8313
				ctx[0].aoData[ this[0] ]._details :
8314
				undefined;
8315
		}
8316
		else if ( data === true ) {
8317
			// show
8318
			this.child.show();
8319
		}
8320
		else if ( data === false ) {
8321
			// remove
8322
			__details_remove( this );
8323
		}
8324
		else if ( ctx.length && this.length ) {
8325
			// set
8326
			__details_add( ctx[0], ctx[0].aoData[ this[0] ], data, klass );
8327
		}
8328
	
8329
		return this;
8330
	} );
8331
	
8332
	
8333
	_api_register( [
8334
		_child_obj+'.show()',
8335
		_child_mth+'.show()' // only when `child()` was called with parameters (without
8336
	], function ( show ) {   // it returns an object and this method is not executed)
0 ignored issues
show
Unused Code introduced by
The parameter show is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
8337
		__details_display( this, true );
8338
		return this;
8339
	} );
8340
	
8341
	
8342
	_api_register( [
8343
		_child_obj+'.hide()',
8344
		_child_mth+'.hide()' // only when `child()` was called with parameters (without
8345
	], function () {         // it returns an object and this method is not executed)
8346
		__details_display( this, false );
8347
		return this;
8348
	} );
8349
	
8350
	
8351
	_api_register( [
8352
		_child_obj+'.remove()',
8353
		_child_mth+'.remove()' // only when `child()` was called with parameters (without
8354
	], function () {           // it returns an object and this method is not executed)
8355
		__details_remove( this );
8356
		return this;
8357
	} );
8358
	
8359
	
8360
	_api_register( _child_obj+'.isShown()', function () {
8361
		var ctx = this.context;
8362
	
8363
		if ( ctx.length && this.length ) {
8364
			// _detailsShown as false or undefined will fall through to return false
8365
			return ctx[0].aoData[ this[0] ]._detailsShow || false;
8366
		}
8367
		return false;
8368
	} );
8369
	
8370
	
8371
	
8372
	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
8373
	 * Columns
8374
	 *
8375
	 * {integer}           - column index (>=0 count from left, <0 count from right)
8376
	 * "{integer}:visIdx"  - visible column index (i.e. translate to column index)  (>=0 count from left, <0 count from right)
8377
	 * "{integer}:visible" - alias for {integer}:visIdx  (>=0 count from left, <0 count from right)
8378
	 * "{string}:name"     - column name
8379
	 * "{string}"          - jQuery selector on column header nodes
8380
	 *
8381
	 */
8382
	
8383
	// can be an array of these items, comma separated list, or an array of comma
8384
	// separated lists
8385
	
8386
	var __re_column_selector = /^([^:]+):(name|visIdx|visible)$/;
8387
	
8388
	
8389
	// r1 and r2 are redundant - but it means that the parameters match for the
8390
	// iterator callback in columns().data()
8391
	var __columnData = function ( settings, column, r1, r2, rows ) {
8392
		var a = [];
8393
		for ( var row=0, ien=rows.length ; row<ien ; row++ ) {
8394
			a.push( _fnGetCellData( settings, rows[row], column ) );
8395
		}
8396
		return a;
8397
	};
8398
	
8399
	
8400
	var __column_selector = function ( settings, selector, opts )
8401
	{
8402
		var
8403
			columns = settings.aoColumns,
8404
			names = _pluck( columns, 'sName' ),
8405
			nodes = _pluck( columns, 'nTh' );
8406
	
8407
		var run = function ( s ) {
8408
			var selInt = _intVal( s );
8409
	
8410
			// Selector - all
8411
			if ( s === '' ) {
8412
				return _range( columns.length );
8413
			}
8414
	
8415
			// Selector - index
8416
			if ( selInt !== null ) {
8417
				return [ selInt >= 0 ?
8418
					selInt : // Count from left
8419
					columns.length + selInt // Count from right (+ because its a negative value)
8420
				];
8421
			}
8422
	
8423
			// Selector = function
8424
			if ( typeof s === 'function' ) {
8425
				var rows = _selector_row_indexes( settings, opts );
8426
	
8427
				return $.map( columns, function (col, idx) {
8428
					return s(
8429
							idx,
8430
							__columnData( settings, idx, 0, 0, rows ),
8431
							nodes[ idx ]
8432
						) ? idx : null;
8433
				} );
8434
			}
8435
	
8436
			// jQuery or string selector
8437
			var match = typeof s === 'string' ?
8438
				s.match( __re_column_selector ) :
8439
				'';
8440
	
8441
			if ( match ) {
8442
				switch( match[2] ) {
8443
					case 'visIdx':
8444
					case 'visible':
8445
						var idx = parseInt( match[1], 10 );
8446
						// Visible index given, convert to column index
8447
						if ( idx < 0 ) {
8448
							// Counting from the right
8449
							var visColumns = $.map( columns, function (col,i) {
8450
								return col.bVisible ? i : null;
8451
							} );
8452
							return [ visColumns[ visColumns.length + idx ] ];
8453
						}
8454
						// Counting from the left
8455
						return [ _fnVisibleToColumnIndex( settings, idx ) ];
8456
	
8457
					case 'name':
8458
						// match by name. `names` is column index complete and in order
8459
						return $.map( names, function (name, i) {
8460
							return name === match[1] ? i : null;
8461
						} );
8462
	
8463
					default:
8464
						return [];
8465
				}
8466
			}
8467
	
8468
			// Cell in the table body
8469
			if ( s.nodeName && s._DT_CellIndex ) {
8470
				return [ s._DT_CellIndex.column ];
8471
			}
8472
	
8473
			// jQuery selector on the TH elements for the columns
8474
			var jqResult = $( nodes )
8475
				.filter( s )
8476
				.map( function () {
8477
					return $.inArray( this, nodes ); // `nodes` is column index complete and in order
8478
				} )
8479
				.toArray();
8480
	
8481
			if ( jqResult.length || ! s.nodeName ) {
8482
				return jqResult;
8483
			}
8484
	
8485
			// Otherwise a node which might have a `dt-column` data attribute, or be
8486
			// a child or such an element
8487
			var host = $(s).closest('*[data-dt-column]');
8488
			return host.length ?
8489
				[ host.data('dt-column') ] :
8490
				[];
8491
		};
8492
	
8493
		return _selector_run( 'column', selector, run, settings, opts );
8494
	};
8495
	
8496
	
8497
	var __setColumnVis = function ( settings, column, vis ) {
8498
		var
8499
			cols = settings.aoColumns,
8500
			col  = cols[ column ],
8501
			data = settings.aoData,
8502
			row, cells, i, ien, tr;
0 ignored issues
show
Unused Code introduced by
The variable row seems to be never used. Consider removing it.
Loading history...
8503
	
8504
		// Get
8505
		if ( vis === undefined ) {
8506
			return col.bVisible;
8507
		}
8508
	
8509
		// Set
8510
		// No change
8511
		if ( col.bVisible === vis ) {
8512
			return;
8513
		}
8514
	
8515
		if ( vis ) {
8516
			// Insert column
8517
			// Need to decide if we should use appendChild or insertBefore
8518
			var insertBefore = $.inArray( true, _pluck(cols, 'bVisible'), column+1 );
8519
	
8520
			for ( i=0, ien=data.length ; i<ien ; i++ ) {
8521
				tr = data[i].nTr;
8522
				cells = data[i].anCells;
8523
	
8524
				if ( tr ) {
8525
					// insertBefore can act like appendChild if 2nd arg is null
8526
					tr.insertBefore( cells[ column ], cells[ insertBefore ] || null );
8527
				}
8528
			}
8529
		}
8530
		else {
8531
			// Remove column
8532
			$( _pluck( settings.aoData, 'anCells', column ) ).detach();
8533
		}
8534
	
8535
		// Common actions
8536
		col.bVisible = vis;
8537
		_fnDrawHead( settings, settings.aoHeader );
8538
		_fnDrawHead( settings, settings.aoFooter );
8539
	
8540
		_fnSaveState( settings );
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
8541
	};
8542
	
8543
	
8544
	_api_register( 'columns()', function ( selector, opts ) {
8545
		// argument shifting
8546
		if ( selector === undefined ) {
8547
			selector = '';
8548
		}
8549
		else if ( $.isPlainObject( selector ) ) {
8550
			opts = selector;
8551
			selector = '';
8552
		}
8553
	
8554
		opts = _selector_opts( opts );
8555
	
8556
		var inst = this.iterator( 'table', function ( settings ) {
8557
			return __column_selector( settings, selector, opts );
8558
		}, 1 );
8559
	
8560
		// Want argument shifting here and in _row_selector?
8561
		inst.selector.cols = selector;
8562
		inst.selector.opts = opts;
8563
	
8564
		return inst;
8565
	} );
8566
	
8567
	_api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) {
0 ignored issues
show
Unused Code introduced by
The parameter selector is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter opts is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
8568
		return this.iterator( 'column', function ( settings, column ) {
8569
			return settings.aoColumns[column].nTh;
8570
		}, 1 );
8571
	} );
8572
	
8573
	_api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) {
0 ignored issues
show
Unused Code introduced by
The parameter selector is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter opts is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
8574
		return this.iterator( 'column', function ( settings, column ) {
8575
			return settings.aoColumns[column].nTf;
8576
		}, 1 );
8577
	} );
8578
	
8579
	_api_registerPlural( 'columns().data()', 'column().data()', function () {
8580
		return this.iterator( 'column-rows', __columnData, 1 );
8581
	} );
8582
	
8583
	_api_registerPlural( 'columns().dataSrc()', 'column().dataSrc()', function () {
8584
		return this.iterator( 'column', function ( settings, column ) {
8585
			return settings.aoColumns[column].mData;
8586
		}, 1 );
8587
	} );
8588
	
8589
	_api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) {
8590
		return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8591
			return _pluck_order( settings.aoData, rows,
8592
				type === 'search' ? '_aFilterData' : '_aSortData', column
8593
			);
8594
		}, 1 );
8595
	} );
8596
	
8597
	_api_registerPlural( 'columns().nodes()', 'column().nodes()', function () {
8598
		return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8599
			return _pluck_order( settings.aoData, rows, 'anCells', column ) ;
8600
		}, 1 );
8601
	} );
8602
	
8603
	_api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis, calc ) {
8604
		var ret = this.iterator( 'column', function ( settings, column ) {
8605
			if ( vis === undefined ) {
8606
				return settings.aoColumns[ column ].bVisible;
8607
			} // else
8608
			__setColumnVis( settings, column, vis );
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
8609
		} );
8610
	
8611
		// Group the column visibility changes
8612
		if ( vis !== undefined ) {
8613
			// Second loop once the first is done for events
8614
			this.iterator( 'column', function ( settings, column ) {
8615
				_fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis, calc] );
8616
			} );
8617
	
8618
			if ( calc === undefined || calc ) {
8619
				this.columns.adjust();
8620
			}
8621
		}
8622
	
8623
		return ret;
8624
	} );
8625
	
8626
	_api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) {
8627
		return this.iterator( 'column', function ( settings, column ) {
8628
			return type === 'visible' ?
8629
				_fnColumnIndexToVisible( settings, column ) :
8630
				column;
8631
		}, 1 );
8632
	} );
8633
	
8634
	_api_register( 'columns.adjust()', function () {
8635
		return this.iterator( 'table', function ( settings ) {
8636
			_fnAdjustColumnSizing( settings );
8637
		}, 1 );
8638
	} );
8639
	
8640
	_api_register( 'column.index()', function ( type, idx ) {
8641
		if ( this.context.length !== 0 ) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if this.context.length !== 0 is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
8642
			var ctx = this.context[0];
8643
	
8644
			if ( type === 'fromVisible' || type === 'toData' ) {
8645
				return _fnVisibleToColumnIndex( ctx, idx );
8646
			}
8647
			else if ( type === 'fromData' || type === 'toVisible' ) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if type === "fromData" || type === "toVisible" is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
8648
				return _fnColumnIndexToVisible( ctx, idx );
8649
			}
8650
		}
8651
	} );
8652
	
8653
	_api_register( 'column()', function ( selector, opts ) {
8654
		return _selector_first( this.columns( selector, opts ) );
8655
	} );
8656
	
8657
	
8658
	
8659
	var __cell_selector = function ( settings, selector, opts )
8660
	{
8661
		var data = settings.aoData;
8662
		var rows = _selector_row_indexes( settings, opts );
8663
		var cells = _removeEmpty( _pluck_order( data, rows, 'anCells' ) );
8664
		var allCells = $( [].concat.apply([], cells) );
8665
		var row;
8666
		var columns = settings.aoColumns.length;
8667
		var a, i, ien, j, o, host;
8668
	
8669
		var run = function ( s ) {
8670
			var fnSelector = typeof s === 'function';
8671
	
8672
			if ( s === null || s === undefined || fnSelector ) {
8673
				// All cells and function selectors
8674
				a = [];
8675
	
8676
				for ( i=0, ien=rows.length ; i<ien ; i++ ) {
0 ignored issues
show
Bug introduced by
The variable i is changed as part of the for loop for example by i++ on line 8676. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
8677
					row = rows[i];
8678
	
8679
					for ( j=0 ; j<columns ; j++ ) {
0 ignored issues
show
Bug introduced by
The variable j is changed as part of the for loop for example by j++ on line 8679. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
8680
						o = {
8681
							row: row,
8682
							column: j
8683
						};
8684
	
8685
						if ( fnSelector ) {
8686
							// Selector - function
8687
							host = data[ row ];
8688
	
8689
							if ( s( o, _fnGetCellData(settings, row, j), host.anCells ? host.anCells[j] : null ) ) {
0 ignored issues
show
Bug introduced by
The variable host is changed as part of the for loop for example by data.row on line 8687. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
Bug introduced by
The variable o is changed as part of the for loop for example by {IdentifierNode(row,fals...dentifierNode(j,false)} on line 8680. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
8690
								a.push( o );
8691
							}
8692
						}
8693
						else {
8694
							// Selector - all
8695
							a.push( o );
8696
						}
8697
					}
8698
				}
8699
	
8700
				return a;
8701
			}
8702
			
8703
			// Selector - index
8704
			if ( $.isPlainObject( s ) ) {
8705
				return [s];
8706
			}
8707
	
8708
			// Selector - jQuery filtered cells
8709
			var jqResult = allCells
8710
				.filter( s )
8711
				.map( function (i, el) {
8712
					return { // use a new object, in case someone changes the values
8713
						row:    el._DT_CellIndex.row,
8714
						column: el._DT_CellIndex.column
8715
	 				};
8716
				} )
8717
				.toArray();
8718
	
8719
			if ( jqResult.length || ! s.nodeName ) {
8720
				return jqResult;
8721
			}
8722
	
8723
			// Otherwise the selector is a node, and there is one last option - the
8724
			// element might be a child of an element which has dt-row and dt-column
8725
			// data attributes
8726
			host = $(s).closest('*[data-dt-row]');
8727
			return host.length ?
8728
				[ {
8729
					row: host.data('dt-row'),
8730
					column: host.data('dt-column')
8731
				} ] :
8732
				[];
8733
		};
8734
	
8735
		return _selector_run( 'cell', selector, run, settings, opts );
8736
	};
8737
	
8738
	
8739
	
8740
	
8741
	_api_register( 'cells()', function ( rowSelector, columnSelector, opts ) {
8742
		// Argument shifting
8743
		if ( $.isPlainObject( rowSelector ) ) {
8744
			// Indexes
8745
			if ( rowSelector.row === undefined ) {
8746
				// Selector options in first parameter
8747
				opts = rowSelector;
8748
				rowSelector = null;
8749
			}
8750
			else {
8751
				// Cell index objects in first parameter
8752
				opts = columnSelector;
8753
				columnSelector = null;
8754
			}
8755
		}
8756
		if ( $.isPlainObject( columnSelector ) ) {
8757
			opts = columnSelector;
8758
			columnSelector = null;
8759
		}
8760
	
8761
		// Cell selector
8762
		if ( columnSelector === null || columnSelector === undefined ) {
8763
			return this.iterator( 'table', function ( settings ) {
8764
				return __cell_selector( settings, rowSelector, _selector_opts( opts ) );
8765
			} );
8766
		}
8767
	
8768
		// Row + column selector
8769
		var columns = this.columns( columnSelector, opts );
8770
		var rows = this.rows( rowSelector, opts );
8771
		var a, i, ien, j, jen;
8772
	
8773
		var cells = this.iterator( 'table', function ( settings, idx ) {
8774
			a = [];
8775
	
8776
			for ( i=0, ien=rows[idx].length ; i<ien ; i++ ) {
0 ignored issues
show
Bug introduced by
The variable i is changed as part of the for loop for example by i++ on line 8776. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
8777
				for ( j=0, jen=columns[idx].length ; j<jen ; j++ ) {
0 ignored issues
show
Bug introduced by
The variable j is changed as part of the for loop for example by j++ on line 8777. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
8778
					a.push( {
8779
						row:    rows[idx][i],
8780
						column: columns[idx][j]
8781
					} );
8782
				}
8783
			}
8784
	
8785
			return a;
8786
		}, 1 );
8787
	
8788
		$.extend( cells.selector, {
8789
			cols: columnSelector,
8790
			rows: rowSelector,
8791
			opts: opts
8792
		} );
8793
	
8794
		return cells;
8795
	} );
8796
	
8797
	
8798
	_api_registerPlural( 'cells().nodes()', 'cell().node()', function () {
8799
		return this.iterator( 'cell', function ( settings, row, column ) {
8800
			var data = settings.aoData[ row ];
8801
	
8802
			return data && data.anCells ?
8803
				data.anCells[ column ] :
8804
				undefined;
8805
		}, 1 );
8806
	} );
8807
	
8808
	
8809
	_api_register( 'cells().data()', function () {
8810
		return this.iterator( 'cell', function ( settings, row, column ) {
8811
			return _fnGetCellData( settings, row, column );
8812
		}, 1 );
8813
	} );
8814
	
8815
	
8816
	_api_registerPlural( 'cells().cache()', 'cell().cache()', function ( type ) {
8817
		type = type === 'search' ? '_aFilterData' : '_aSortData';
8818
	
8819
		return this.iterator( 'cell', function ( settings, row, column ) {
8820
			return settings.aoData[ row ][ type ][ column ];
8821
		}, 1 );
8822
	} );
8823
	
8824
	
8825
	_api_registerPlural( 'cells().render()', 'cell().render()', function ( type ) {
8826
		return this.iterator( 'cell', function ( settings, row, column ) {
8827
			return _fnGetCellData( settings, row, column, type );
8828
		}, 1 );
8829
	} );
8830
	
8831
	
8832
	_api_registerPlural( 'cells().indexes()', 'cell().index()', function () {
8833
		return this.iterator( 'cell', function ( settings, row, column ) {
8834
			return {
8835
				row: row,
8836
				column: column,
8837
				columnVisible: _fnColumnIndexToVisible( settings, column )
8838
			};
8839
		}, 1 );
8840
	} );
8841
	
8842
	
8843
	_api_registerPlural( 'cells().invalidate()', 'cell().invalidate()', function ( src ) {
8844
		return this.iterator( 'cell', function ( settings, row, column ) {
8845
			_fnInvalidate( settings, row, src, column );
8846
		} );
8847
	} );
8848
	
8849
	
8850
	
8851
	_api_register( 'cell()', function ( rowSelector, columnSelector, opts ) {
8852
		return _selector_first( this.cells( rowSelector, columnSelector, opts ) );
8853
	} );
8854
	
8855
	
8856
	_api_register( 'cell().data()', function ( data ) {
8857
		var ctx = this.context;
8858
		var cell = this[0];
8859
	
8860
		if ( data === undefined ) {
8861
			// Get
8862
			return ctx.length && cell.length ?
8863
				_fnGetCellData( ctx[0], cell[0].row, cell[0].column ) :
8864
				undefined;
8865
		}
8866
	
8867
		// Set
8868
		_fnSetCellData( ctx[0], cell[0].row, cell[0].column, data );
8869
		_fnInvalidate( ctx[0], cell[0].row, 'data', cell[0].column );
8870
	
8871
		return this;
8872
	} );
8873
	
8874
	
8875
	
8876
	/**
8877
	 * Get current ordering (sorting) that has been applied to the table.
8878
	 *
8879
	 * @returns {array} 2D array containing the sorting information for the first
8880
	 *   table in the current context. Each element in the parent array represents
8881
	 *   a column being sorted upon (i.e. multi-sorting with two columns would have
8882
	 *   2 inner arrays). The inner arrays may have 2 or 3 elements. The first is
8883
	 *   the column index that the sorting condition applies to, the second is the
8884
	 *   direction of the sort (`desc` or `asc`) and, optionally, the third is the
8885
	 *   index of the sorting order from the `column.sorting` initialisation array.
8886
	 *//**
8887
	 * Set the ordering for the table.
8888
	 *
8889
	 * @param {integer} order Column index to sort upon.
8890
	 * @param {string} direction Direction of the sort to be applied (`asc` or `desc`)
8891
	 * @returns {DataTables.Api} this
8892
	 *//**
8893
	 * Set the ordering for the table.
8894
	 *
8895
	 * @param {array} order 1D array of sorting information to be applied.
8896
	 * @param {array} [...] Optional additional sorting conditions
8897
	 * @returns {DataTables.Api} this
8898
	 *//**
8899
	 * Set the ordering for the table.
8900
	 *
8901
	 * @param {array} order 2D array of sorting information to be applied.
8902
	 * @returns {DataTables.Api} this
8903
	 */
8904
	_api_register( 'order()', function ( order, dir ) {
8905
		var ctx = this.context;
8906
	
8907
		if ( order === undefined ) {
8908
			// get
8909
			return ctx.length !== 0 ?
8910
				ctx[0].aaSorting :
8911
				undefined;
8912
		}
8913
	
8914
		// set
8915
		if ( typeof order === 'number' ) {
8916
			// Simple column / direction passed in
8917
			order = [ [ order, dir ] ];
8918
		}
8919
		else if ( order.length && ! $.isArray( order[0] ) ) {
8920
			// Arguments passed in (list of 1D arrays)
8921
			order = Array.prototype.slice.call( arguments );
8922
		}
8923
		// otherwise a 2D array was passed in
8924
	
8925
		return this.iterator( 'table', function ( settings ) {
8926
			settings.aaSorting = order.slice();
8927
		} );
8928
	} );
8929
	
8930
	
8931
	/**
8932
	 * Attach a sort listener to an element for a given column
8933
	 *
8934
	 * @param {node|jQuery|string} node Identifier for the element(s) to attach the
8935
	 *   listener to. This can take the form of a single DOM node, a jQuery
8936
	 *   collection of nodes or a jQuery selector which will identify the node(s).
8937
	 * @param {integer} column the column that a click on this node will sort on
8938
	 * @param {function} [callback] callback function when sort is run
8939
	 * @returns {DataTables.Api} this
8940
	 */
8941
	_api_register( 'order.listener()', function ( node, column, callback ) {
8942
		return this.iterator( 'table', function ( settings ) {
8943
			_fnSortAttachListener( settings, node, column, callback );
8944
		} );
8945
	} );
8946
	
8947
	
8948
	_api_register( 'order.fixed()', function ( set ) {
8949
		if ( ! set ) {
8950
			var ctx = this.context;
8951
			var fixed = ctx.length ?
8952
				ctx[0].aaSortingFixed :
8953
				undefined;
8954
	
8955
			return $.isArray( fixed ) ?
8956
				{ pre: fixed } :
8957
				fixed;
8958
		}
8959
	
8960
		return this.iterator( 'table', function ( settings ) {
8961
			settings.aaSortingFixed = $.extend( true, {}, set );
8962
		} );
8963
	} );
8964
	
8965
	
8966
	// Order by the selected column(s)
8967
	_api_register( [
8968
		'columns().order()',
8969
		'column().order()'
8970
	], function ( dir ) {
8971
		var that = this;
8972
	
8973
		return this.iterator( 'table', function ( settings, i ) {
8974
			var sort = [];
8975
	
8976
			$.each( that[i], function (j, col) {
8977
				sort.push( [ col, dir ] );
8978
			} );
8979
	
8980
			settings.aaSorting = sort;
8981
		} );
8982
	} );
8983
	
8984
	
8985
	
8986
	_api_register( 'search()', function ( input, regex, smart, caseInsen ) {
8987
		var ctx = this.context;
8988
	
8989
		if ( input === undefined ) {
8990
			// get
8991
			return ctx.length !== 0 ?
8992
				ctx[0].oPreviousSearch.sSearch :
8993
				undefined;
8994
		}
8995
	
8996
		// set
8997
		return this.iterator( 'table', function ( settings ) {
8998
			if ( ! settings.oFeatures.bFilter ) {
8999
				return;
9000
			}
9001
	
9002
			_fnFilterComplete( settings, $.extend( {}, settings.oPreviousSearch, {
9003
				"sSearch": input+"",
9004
				"bRegex":  regex === null ? false : regex,
9005
				"bSmart":  smart === null ? true  : smart,
9006
				"bCaseInsensitive": caseInsen === null ? true : caseInsen
9007
			} ), 1 );
9008
		} );
9009
	} );
9010
	
9011
	
9012
	_api_registerPlural(
9013
		'columns().search()',
9014
		'column().search()',
9015
		function ( input, regex, smart, caseInsen ) {
9016
			return this.iterator( 'column', function ( settings, column ) {
9017
				var preSearch = settings.aoPreSearchCols;
9018
	
9019
				if ( input === undefined ) {
9020
					// get
9021
					return preSearch[ column ].sSearch;
9022
				}
9023
	
9024
				// set
9025
				if ( ! settings.oFeatures.bFilter ) {
9026
					return;
9027
				}
9028
	
9029
				$.extend( preSearch[ column ], {
9030
					"sSearch": input+"",
9031
					"bRegex":  regex === null ? false : regex,
9032
					"bSmart":  smart === null ? true  : smart,
9033
					"bCaseInsensitive": caseInsen === null ? true : caseInsen
9034
				} );
9035
	
9036
				_fnFilterComplete( settings, settings.oPreviousSearch, 1 );
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
9037
			} );
9038
		}
9039
	);
9040
	
9041
	/*
9042
	 * State API methods
9043
	 */
9044
	
9045
	_api_register( 'state()', function () {
9046
		return this.context.length ?
9047
			this.context[0].oSavedState :
9048
			null;
9049
	} );
9050
	
9051
	
9052
	_api_register( 'state.clear()', function () {
9053
		return this.iterator( 'table', function ( settings ) {
9054
			// Save an empty object
9055
			settings.fnStateSaveCallback.call( settings.oInstance, settings, {} );
9056
		} );
9057
	} );
9058
	
9059
	
9060
	_api_register( 'state.loaded()', function () {
9061
		return this.context.length ?
9062
			this.context[0].oLoadedState :
9063
			null;
9064
	} );
9065
	
9066
	
9067
	_api_register( 'state.save()', function () {
9068
		return this.iterator( 'table', function ( settings ) {
9069
			_fnSaveState( settings );
9070
		} );
9071
	} );
9072
	
9073
	
9074
	
9075
	/**
9076
	 * Provide a common method for plug-ins to check the version of DataTables being
9077
	 * used, in order to ensure compatibility.
9078
	 *
9079
	 *  @param {string} version Version string to check for, in the format "X.Y.Z".
9080
	 *    Note that the formats "X" and "X.Y" are also acceptable.
9081
	 *  @returns {boolean} true if this version of DataTables is greater or equal to
9082
	 *    the required version, or false if this version of DataTales is not
9083
	 *    suitable
9084
	 *  @static
9085
	 *  @dtopt API-Static
9086
	 *
9087
	 *  @example
9088
	 *    alert( $.fn.dataTable.versionCheck( '1.9.0' ) );
9089
	 */
9090
	DataTable.versionCheck = DataTable.fnVersionCheck = function( version )
9091
	{
9092
		var aThis = DataTable.version.split('.');
9093
		var aThat = version.split('.');
9094
		var iThis, iThat;
9095
	
9096
		for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) {
9097
			iThis = parseInt( aThis[i], 10 ) || 0;
9098
			iThat = parseInt( aThat[i], 10 ) || 0;
9099
	
9100
			// Parts are the same, keep comparing
9101
			if (iThis === iThat) {
9102
				continue;
9103
			}
9104
	
9105
			// Parts are different, return immediately
9106
			return iThis > iThat;
9107
		}
9108
	
9109
		return true;
9110
	};
9111
	
9112
	
9113
	/**
9114
	 * Check if a `<table>` node is a DataTable table already or not.
9115
	 *
9116
	 *  @param {node|jquery|string} table Table node, jQuery object or jQuery
9117
	 *      selector for the table to test. Note that if more than more than one
9118
	 *      table is passed on, only the first will be checked
9119
	 *  @returns {boolean} true the table given is a DataTable, or false otherwise
9120
	 *  @static
9121
	 *  @dtopt API-Static
9122
	 *
9123
	 *  @example
9124
	 *    if ( ! $.fn.DataTable.isDataTable( '#example' ) ) {
9125
	 *      $('#example').dataTable();
9126
	 *    }
9127
	 */
9128
	DataTable.isDataTable = DataTable.fnIsDataTable = function ( table )
9129
	{
9130
		var t = $(table).get(0);
9131
		var is = false;
9132
	
9133
		if ( table instanceof DataTable.Api ) {
9134
			return true;
9135
		}
9136
	
9137
		$.each( DataTable.settings, function (i, o) {
9138
			var head = o.nScrollHead ? $('table', o.nScrollHead)[0] : null;
9139
			var foot = o.nScrollFoot ? $('table', o.nScrollFoot)[0] : null;
9140
	
9141
			if ( o.nTable === t || head === t || foot === t ) {
9142
				is = true;
9143
			}
9144
		} );
9145
	
9146
		return is;
9147
	};
9148
	
9149
	
9150
	/**
9151
	 * Get all DataTable tables that have been initialised - optionally you can
9152
	 * select to get only currently visible tables.
9153
	 *
9154
	 *  @param {boolean} [visible=false] Flag to indicate if you want all (default)
9155
	 *    or visible tables only.
9156
	 *  @returns {array} Array of `table` nodes (not DataTable instances) which are
9157
	 *    DataTables
9158
	 *  @static
9159
	 *  @dtopt API-Static
9160
	 *
9161
	 *  @example
9162
	 *    $.each( $.fn.dataTable.tables(true), function () {
9163
	 *      $(table).DataTable().columns.adjust();
9164
	 *    } );
9165
	 */
9166
	DataTable.tables = DataTable.fnTables = function ( visible )
9167
	{
9168
		var api = false;
9169
	
9170
		if ( $.isPlainObject( visible ) ) {
9171
			api = visible.api;
9172
			visible = visible.visible;
9173
		}
9174
	
9175
		var a = $.map( DataTable.settings, function (o) {
9176
			if ( !visible || (visible && $(o.nTable).is(':visible')) ) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if !visible || visible && $(o.nTable).is(":visible") is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
9177
				return o.nTable;
9178
			}
9179
		} );
9180
	
9181
		return api ?
9182
			new _Api( a ) :
9183
			a;
9184
	};
9185
	
9186
	
9187
	/**
9188
	 * Convert from camel case parameters to Hungarian notation. This is made public
9189
	 * for the extensions to provide the same ability as DataTables core to accept
9190
	 * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase
9191
	 * parameters.
9192
	 *
9193
	 *  @param {object} src The model object which holds all parameters that can be
9194
	 *    mapped.
9195
	 *  @param {object} user The object to convert from camel case to Hungarian.
9196
	 *  @param {boolean} force When set to `true`, properties which already have a
9197
	 *    Hungarian value in the `user` object will be overwritten. Otherwise they
9198
	 *    won't be.
9199
	 */
9200
	DataTable.camelToHungarian = _fnCamelToHungarian;
9201
	
9202
	
9203
	
9204
	/**
9205
	 *
9206
	 */
9207
	_api_register( '$()', function ( selector, opts ) {
9208
		var
9209
			rows   = this.rows( opts ).nodes(), // Get all rows
9210
			jqRows = $(rows);
9211
	
9212
		return $( [].concat(
9213
			jqRows.filter( selector ).toArray(),
9214
			jqRows.find( selector ).toArray()
9215
		) );
9216
	} );
9217
	
9218
	
9219
	// jQuery functions to operate on the tables
9220
	$.each( [ 'on', 'one', 'off' ], function (i, key) {
9221
		_api_register( key+'()', function ( /* event, handler */ ) {
9222
			var args = Array.prototype.slice.call(arguments);
9223
	
9224
			// Add the `dt` namespace automatically if it isn't already present
9225
			args[0] = $.map( args[0].split( /\s/ ), function ( e ) {
9226
				return ! e.match(/\.dt\b/) ?
9227
					e+'.dt' :
9228
					e;
9229
				} ).join( ' ' );
9230
	
9231
			var inst = $( this.tables().nodes() );
9232
			inst[key].apply( inst, args );
9233
			return this;
9234
		} );
9235
	} );
9236
	
9237
	
9238
	_api_register( 'clear()', function () {
9239
		return this.iterator( 'table', function ( settings ) {
9240
			_fnClearTable( settings );
9241
		} );
9242
	} );
9243
	
9244
	
9245
	_api_register( 'settings()', function () {
9246
		return new _Api( this.context, this.context );
9247
	} );
9248
	
9249
	
9250
	_api_register( 'init()', function () {
9251
		var ctx = this.context;
9252
		return ctx.length ? ctx[0].oInit : null;
9253
	} );
9254
	
9255
	
9256
	_api_register( 'data()', function () {
9257
		return this.iterator( 'table', function ( settings ) {
9258
			return _pluck( settings.aoData, '_aData' );
9259
		} ).flatten();
9260
	} );
9261
	
9262
	
9263
	_api_register( 'destroy()', function ( remove ) {
9264
		remove = remove || false;
9265
	
9266
		return this.iterator( 'table', function ( settings ) {
9267
			var orig      = settings.nTableWrapper.parentNode;
9268
			var classes   = settings.oClasses;
9269
			var table     = settings.nTable;
9270
			var tbody     = settings.nTBody;
9271
			var thead     = settings.nTHead;
9272
			var tfoot     = settings.nTFoot;
9273
			var jqTable   = $(table);
9274
			var jqTbody   = $(tbody);
9275
			var jqWrapper = $(settings.nTableWrapper);
9276
			var rows      = $.map( settings.aoData, function (r) { return r.nTr; } );
9277
			var i, ien;
0 ignored issues
show
Unused Code introduced by
The variable i seems to be never used. Consider removing it.
Loading history...
9278
	
9279
			// Flag to note that the table is currently being destroyed - no action
9280
			// should be taken
9281
			settings.bDestroying = true;
9282
	
9283
			// Fire off the destroy callbacks for plug-ins etc
9284
			_fnCallbackFire( settings, "aoDestroyCallback", "destroy", [settings] );
9285
	
9286
			// If not being removed from the document, make all columns visible
9287
			if ( ! remove ) {
9288
				new _Api( settings ).columns().visible( true );
9289
			}
9290
	
9291
			// Blitz all `DT` namespaced events (these are internal events, the
9292
			// lowercase, `dt` events are user subscribed and they are responsible
9293
			// for removing them
9294
			jqWrapper.off('.DT').find(':not(tbody *)').off('.DT');
9295
			$(window).off('.DT-'+settings.sInstance);
9296
	
9297
			// When scrolling we had to break the table up - restore it
9298
			if ( table != thead.parentNode ) {
9299
				jqTable.children('thead').detach();
9300
				jqTable.append( thead );
9301
			}
9302
	
9303
			if ( tfoot && table != tfoot.parentNode ) {
9304
				jqTable.children('tfoot').detach();
9305
				jqTable.append( tfoot );
9306
			}
9307
	
9308
			settings.aaSorting = [];
9309
			settings.aaSortingFixed = [];
9310
			_fnSortingClasses( settings );
9311
	
9312
			$( rows ).removeClass( settings.asStripeClasses.join(' ') );
9313
	
9314
			$('th, td', thead).removeClass( classes.sSortable+' '+
9315
				classes.sSortableAsc+' '+classes.sSortableDesc+' '+classes.sSortableNone
9316
			);
9317
	
9318
			// Add the TR elements back into the table in their original order
9319
			jqTbody.children().detach();
9320
			jqTbody.append( rows );
9321
	
9322
			// Remove the DataTables generated nodes, events and classes
9323
			var removedMethod = remove ? 'remove' : 'detach';
9324
			jqTable[ removedMethod ]();
9325
			jqWrapper[ removedMethod ]();
9326
	
9327
			// If we need to reattach the table to the document
9328
			if ( ! remove && orig ) {
9329
				// insertBefore acts like appendChild if !arg[1]
9330
				orig.insertBefore( table, settings.nTableReinsertBefore );
9331
	
9332
				// Restore the width of the original table - was read from the style property,
9333
				// so we can restore directly to that
9334
				jqTable
9335
					.css( 'width', settings.sDestroyWidth )
9336
					.removeClass( classes.sTable );
9337
	
9338
				// If the were originally stripe classes - then we add them back here.
9339
				// Note this is not fool proof (for example if not all rows had stripe
9340
				// classes - but it's a good effort without getting carried away
9341
				ien = settings.asDestroyStripes.length;
9342
	
9343
				if ( ien ) {
9344
					jqTbody.children().each( function (i) {
9345
						$(this).addClass( settings.asDestroyStripes[i % ien] );
9346
					} );
9347
				}
9348
			}
9349
	
9350
			/* Remove the settings object from the settings array */
9351
			var idx = $.inArray( settings, DataTable.settings );
9352
			if ( idx !== -1 ) {
9353
				DataTable.settings.splice( idx, 1 );
9354
			}
9355
		} );
9356
	} );
9357
	
9358
	
9359
	// Add the `every()` method for rows, columns and cells in a compact form
9360
	$.each( [ 'column', 'row', 'cell' ], function ( i, type ) {
9361
		_api_register( type+'s().every()', function ( fn ) {
9362
			var opts = this.selector.opts;
9363
			var api = this;
9364
	
9365
			return this.iterator( type, function ( settings, arg1, arg2, arg3, arg4 ) {
9366
				// Rows and columns:
9367
				//  arg1 - index
9368
				//  arg2 - table counter
9369
				//  arg3 - loop counter
9370
				//  arg4 - undefined
9371
				// Cells:
9372
				//  arg1 - row index
9373
				//  arg2 - column index
9374
				//  arg3 - table counter
9375
				//  arg4 - loop counter
9376
				fn.call(
9377
					api[ type ](
9378
						arg1,
9379
						type==='cell' ? arg2 : opts,
9380
						type==='cell' ? opts : undefined
9381
					),
9382
					arg1, arg2, arg3, arg4
9383
				);
9384
			} );
9385
		} );
9386
	} );
9387
	
9388
	
9389
	// i18n method for extensions to be able to use the language object from the
9390
	// DataTable
9391
	_api_register( 'i18n()', function ( token, def, plural ) {
9392
		var ctx = this.context[0];
9393
		var resolved = _fnGetObjectDataFn( token )( ctx.oLanguage );
9394
	
9395
		if ( resolved === undefined ) {
9396
			resolved = def;
9397
		}
9398
	
9399
		if ( plural !== undefined && $.isPlainObject( resolved ) ) {
9400
			resolved = resolved[ plural ] !== undefined ?
9401
				resolved[ plural ] :
9402
				resolved._;
9403
		}
9404
	
9405
		return resolved.replace( '%d', plural ); // nb: plural might be undefined,
9406
	} );
9407
	/**
9408
	 * Version string for plug-ins to check compatibility. Allowed format is
9409
	 * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used
9410
	 * only for non-release builds. See http://semver.org/ for more information.
9411
	 *  @member
9412
	 *  @type string
9413
	 *  @default Version number
9414
	 */
9415
	DataTable.version = "1.10.16";
9416
9417
	/**
9418
	 * Private data store, containing all of the settings objects that are
9419
	 * created for the tables on a given page.
9420
	 *
9421
	 * Note that the `DataTable.settings` object is aliased to
9422
	 * `jQuery.fn.dataTableExt` through which it may be accessed and
9423
	 * manipulated, or `jQuery.fn.dataTable.settings`.
9424
	 *  @member
9425
	 *  @type array
9426
	 *  @default []
9427
	 *  @private
9428
	 */
9429
	DataTable.settings = [];
9430
9431
	/**
9432
	 * Object models container, for the various models that DataTables has
9433
	 * available to it. These models define the objects that are used to hold
9434
	 * the active state and configuration of the table.
9435
	 *  @namespace
9436
	 */
9437
	DataTable.models = {};
9438
	
9439
	
9440
	
9441
	/**
9442
	 * Template object for the way in which DataTables holds information about
9443
	 * search information for the global filter and individual column filters.
9444
	 *  @namespace
9445
	 */
9446
	DataTable.models.oSearch = {
9447
		/**
9448
		 * Flag to indicate if the filtering should be case insensitive or not
9449
		 *  @type boolean
9450
		 *  @default true
9451
		 */
9452
		"bCaseInsensitive": true,
9453
	
9454
		/**
9455
		 * Applied search term
9456
		 *  @type string
9457
		 *  @default <i>Empty string</i>
9458
		 */
9459
		"sSearch": "",
9460
	
9461
		/**
9462
		 * Flag to indicate if the search term should be interpreted as a
9463
		 * regular expression (true) or not (false) and therefore and special
9464
		 * regex characters escaped.
9465
		 *  @type boolean
9466
		 *  @default false
9467
		 */
9468
		"bRegex": false,
9469
	
9470
		/**
9471
		 * Flag to indicate if DataTables is to use its smart filtering or not.
9472
		 *  @type boolean
9473
		 *  @default true
9474
		 */
9475
		"bSmart": true
9476
	};
9477
	
9478
	
9479
	
9480
	
9481
	/**
9482
	 * Template object for the way in which DataTables holds information about
9483
	 * each individual row. This is the object format used for the settings
9484
	 * aoData array.
9485
	 *  @namespace
9486
	 */
9487
	DataTable.models.oRow = {
9488
		/**
9489
		 * TR element for the row
9490
		 *  @type node
9491
		 *  @default null
9492
		 */
9493
		"nTr": null,
9494
	
9495
		/**
9496
		 * Array of TD elements for each row. This is null until the row has been
9497
		 * created.
9498
		 *  @type array nodes
9499
		 *  @default []
9500
		 */
9501
		"anCells": null,
9502
	
9503
		/**
9504
		 * Data object from the original data source for the row. This is either
9505
		 * an array if using the traditional form of DataTables, or an object if
9506
		 * using mData options. The exact type will depend on the passed in
9507
		 * data from the data source, or will be an array if using DOM a data
9508
		 * source.
9509
		 *  @type array|object
9510
		 *  @default []
9511
		 */
9512
		"_aData": [],
9513
	
9514
		/**
9515
		 * Sorting data cache - this array is ostensibly the same length as the
9516
		 * number of columns (although each index is generated only as it is
9517
		 * needed), and holds the data that is used for sorting each column in the
9518
		 * row. We do this cache generation at the start of the sort in order that
9519
		 * the formatting of the sort data need be done only once for each cell
9520
		 * per sort. This array should not be read from or written to by anything
9521
		 * other than the master sorting methods.
9522
		 *  @type array
9523
		 *  @default null
9524
		 *  @private
9525
		 */
9526
		"_aSortData": null,
9527
	
9528
		/**
9529
		 * Per cell filtering data cache. As per the sort data cache, used to
9530
		 * increase the performance of the filtering in DataTables
9531
		 *  @type array
9532
		 *  @default null
9533
		 *  @private
9534
		 */
9535
		"_aFilterData": null,
9536
	
9537
		/**
9538
		 * Filtering data cache. This is the same as the cell filtering cache, but
9539
		 * in this case a string rather than an array. This is easily computed with
9540
		 * a join on `_aFilterData`, but is provided as a cache so the join isn't
9541
		 * needed on every search (memory traded for performance)
9542
		 *  @type array
9543
		 *  @default null
9544
		 *  @private
9545
		 */
9546
		"_sFilterRow": null,
9547
	
9548
		/**
9549
		 * Cache of the class name that DataTables has applied to the row, so we
9550
		 * can quickly look at this variable rather than needing to do a DOM check
9551
		 * on className for the nTr property.
9552
		 *  @type string
9553
		 *  @default <i>Empty string</i>
9554
		 *  @private
9555
		 */
9556
		"_sRowStripe": "",
9557
	
9558
		/**
9559
		 * Denote if the original data source was from the DOM, or the data source
9560
		 * object. This is used for invalidating data, so DataTables can
9561
		 * automatically read data from the original source, unless uninstructed
9562
		 * otherwise.
9563
		 *  @type string
9564
		 *  @default null
9565
		 *  @private
9566
		 */
9567
		"src": null,
9568
	
9569
		/**
9570
		 * Index in the aoData array. This saves an indexOf lookup when we have the
9571
		 * object, but want to know the index
9572
		 *  @type integer
9573
		 *  @default -1
9574
		 *  @private
9575
		 */
9576
		"idx": -1
9577
	};
9578
	
9579
	
9580
	/**
9581
	 * Template object for the column information object in DataTables. This object
9582
	 * is held in the settings aoColumns array and contains all the information that
9583
	 * DataTables needs about each individual column.
9584
	 *
9585
	 * Note that this object is related to {@link DataTable.defaults.column}
9586
	 * but this one is the internal data store for DataTables's cache of columns.
9587
	 * It should NOT be manipulated outside of DataTables. Any configuration should
9588
	 * be done through the initialisation options.
9589
	 *  @namespace
9590
	 */
9591
	DataTable.models.oColumn = {
9592
		/**
9593
		 * Column index. This could be worked out on-the-fly with $.inArray, but it
9594
		 * is faster to just hold it as a variable
9595
		 *  @type integer
9596
		 *  @default null
9597
		 */
9598
		"idx": null,
9599
	
9600
		/**
9601
		 * A list of the columns that sorting should occur on when this column
9602
		 * is sorted. That this property is an array allows multi-column sorting
9603
		 * to be defined for a column (for example first name / last name columns
9604
		 * would benefit from this). The values are integers pointing to the
9605
		 * columns to be sorted on (typically it will be a single integer pointing
9606
		 * at itself, but that doesn't need to be the case).
9607
		 *  @type array
9608
		 */
9609
		"aDataSort": null,
9610
	
9611
		/**
9612
		 * Define the sorting directions that are applied to the column, in sequence
9613
		 * as the column is repeatedly sorted upon - i.e. the first value is used
9614
		 * as the sorting direction when the column if first sorted (clicked on).
9615
		 * Sort it again (click again) and it will move on to the next index.
9616
		 * Repeat until loop.
9617
		 *  @type array
9618
		 */
9619
		"asSorting": null,
9620
	
9621
		/**
9622
		 * Flag to indicate if the column is searchable, and thus should be included
9623
		 * in the filtering or not.
9624
		 *  @type boolean
9625
		 */
9626
		"bSearchable": null,
9627
	
9628
		/**
9629
		 * Flag to indicate if the column is sortable or not.
9630
		 *  @type boolean
9631
		 */
9632
		"bSortable": null,
9633
	
9634
		/**
9635
		 * Flag to indicate if the column is currently visible in the table or not
9636
		 *  @type boolean
9637
		 */
9638
		"bVisible": null,
9639
	
9640
		/**
9641
		 * Store for manual type assignment using the `column.type` option. This
9642
		 * is held in store so we can manipulate the column's `sType` property.
9643
		 *  @type string
9644
		 *  @default null
9645
		 *  @private
9646
		 */
9647
		"_sManualType": null,
9648
	
9649
		/**
9650
		 * Flag to indicate if HTML5 data attributes should be used as the data
9651
		 * source for filtering or sorting. True is either are.
9652
		 *  @type boolean
9653
		 *  @default false
9654
		 *  @private
9655
		 */
9656
		"_bAttrSrc": false,
9657
	
9658
		/**
9659
		 * Developer definable function that is called whenever a cell is created (Ajax source,
9660
		 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
9661
		 * allowing you to modify the DOM element (add background colour for example) when the
9662
		 * element is available.
9663
		 *  @type function
9664
		 *  @param {element} nTd The TD node that has been created
9665
		 *  @param {*} sData The Data for the cell
9666
		 *  @param {array|object} oData The data for the whole row
9667
		 *  @param {int} iRow The row index for the aoData data store
9668
		 *  @default null
9669
		 */
9670
		"fnCreatedCell": null,
9671
	
9672
		/**
9673
		 * Function to get data from a cell in a column. You should <b>never</b>
9674
		 * access data directly through _aData internally in DataTables - always use
9675
		 * the method attached to this property. It allows mData to function as
9676
		 * required. This function is automatically assigned by the column
9677
		 * initialisation method
9678
		 *  @type function
9679
		 *  @param {array|object} oData The data array/object for the array
9680
		 *    (i.e. aoData[]._aData)
9681
		 *  @param {string} sSpecific The specific data type you want to get -
9682
		 *    'display', 'type' 'filter' 'sort'
9683
		 *  @returns {*} The data for the cell from the given row's data
9684
		 *  @default null
9685
		 */
9686
		"fnGetData": null,
9687
	
9688
		/**
9689
		 * Function to set data for a cell in the column. You should <b>never</b>
9690
		 * set the data directly to _aData internally in DataTables - always use
9691
		 * this method. It allows mData to function as required. This function
9692
		 * is automatically assigned by the column initialisation method
9693
		 *  @type function
9694
		 *  @param {array|object} oData The data array/object for the array
9695
		 *    (i.e. aoData[]._aData)
9696
		 *  @param {*} sValue Value to set
9697
		 *  @default null
9698
		 */
9699
		"fnSetData": null,
9700
	
9701
		/**
9702
		 * Property to read the value for the cells in the column from the data
9703
		 * source array / object. If null, then the default content is used, if a
9704
		 * function is given then the return from the function is used.
9705
		 *  @type function|int|string|null
9706
		 *  @default null
9707
		 */
9708
		"mData": null,
9709
	
9710
		/**
9711
		 * Partner property to mData which is used (only when defined) to get
9712
		 * the data - i.e. it is basically the same as mData, but without the
9713
		 * 'set' option, and also the data fed to it is the result from mData.
9714
		 * This is the rendering method to match the data method of mData.
9715
		 *  @type function|int|string|null
9716
		 *  @default null
9717
		 */
9718
		"mRender": null,
9719
	
9720
		/**
9721
		 * Unique header TH/TD element for this column - this is what the sorting
9722
		 * listener is attached to (if sorting is enabled.)
9723
		 *  @type node
9724
		 *  @default null
9725
		 */
9726
		"nTh": null,
9727
	
9728
		/**
9729
		 * Unique footer TH/TD element for this column (if there is one). Not used
9730
		 * in DataTables as such, but can be used for plug-ins to reference the
9731
		 * footer for each column.
9732
		 *  @type node
9733
		 *  @default null
9734
		 */
9735
		"nTf": null,
9736
	
9737
		/**
9738
		 * The class to apply to all TD elements in the table's TBODY for the column
9739
		 *  @type string
9740
		 *  @default null
9741
		 */
9742
		"sClass": null,
9743
	
9744
		/**
9745
		 * When DataTables calculates the column widths to assign to each column,
9746
		 * it finds the longest string in each column and then constructs a
9747
		 * temporary table and reads the widths from that. The problem with this
9748
		 * is that "mmm" is much wider then "iiii", but the latter is a longer
9749
		 * string - thus the calculation can go wrong (doing it properly and putting
9750
		 * it into an DOM object and measuring that is horribly(!) slow). Thus as
9751
		 * a "work around" we provide this option. It will append its value to the
9752
		 * text that is found to be the longest string for the column - i.e. padding.
9753
		 *  @type string
9754
		 */
9755
		"sContentPadding": null,
9756
	
9757
		/**
9758
		 * Allows a default value to be given for a column's data, and will be used
9759
		 * whenever a null data source is encountered (this can be because mData
9760
		 * is set to null, or because the data source itself is null).
9761
		 *  @type string
9762
		 *  @default null
9763
		 */
9764
		"sDefaultContent": null,
9765
	
9766
		/**
9767
		 * Name for the column, allowing reference to the column by name as well as
9768
		 * by index (needs a lookup to work by name).
9769
		 *  @type string
9770
		 */
9771
		"sName": null,
9772
	
9773
		/**
9774
		 * Custom sorting data type - defines which of the available plug-ins in
9775
		 * afnSortData the custom sorting will use - if any is defined.
9776
		 *  @type string
9777
		 *  @default std
9778
		 */
9779
		"sSortDataType": 'std',
9780
	
9781
		/**
9782
		 * Class to be applied to the header element when sorting on this column
9783
		 *  @type string
9784
		 *  @default null
9785
		 */
9786
		"sSortingClass": null,
9787
	
9788
		/**
9789
		 * Class to be applied to the header element when sorting on this column -
9790
		 * when jQuery UI theming is used.
9791
		 *  @type string
9792
		 *  @default null
9793
		 */
9794
		"sSortingClassJUI": null,
9795
	
9796
		/**
9797
		 * Title of the column - what is seen in the TH element (nTh).
9798
		 *  @type string
9799
		 */
9800
		"sTitle": null,
9801
	
9802
		/**
9803
		 * Column sorting and filtering type
9804
		 *  @type string
9805
		 *  @default null
9806
		 */
9807
		"sType": null,
9808
	
9809
		/**
9810
		 * Width of the column
9811
		 *  @type string
9812
		 *  @default null
9813
		 */
9814
		"sWidth": null,
9815
	
9816
		/**
9817
		 * Width of the column when it was first "encountered"
9818
		 *  @type string
9819
		 *  @default null
9820
		 */
9821
		"sWidthOrig": null
9822
	};
9823
	
9824
	
9825
	/*
9826
	 * Developer note: The properties of the object below are given in Hungarian
9827
	 * notation, that was used as the interface for DataTables prior to v1.10, however
9828
	 * from v1.10 onwards the primary interface is camel case. In order to avoid
9829
	 * breaking backwards compatibility utterly with this change, the Hungarian
9830
	 * version is still, internally the primary interface, but is is not documented
9831
	 * - hence the @name tags in each doc comment. This allows a Javascript function
9832
	 * to create a map from Hungarian notation to camel case (going the other direction
9833
	 * would require each property to be listed, which would at around 3K to the size
9834
	 * of DataTables, while this method is about a 0.5K hit.
9835
	 *
9836
	 * Ultimately this does pave the way for Hungarian notation to be dropped
9837
	 * completely, but that is a massive amount of work and will break current
9838
	 * installs (therefore is on-hold until v2).
9839
	 */
9840
	
9841
	/**
9842
	 * Initialisation options that can be given to DataTables at initialisation
9843
	 * time.
9844
	 *  @namespace
9845
	 */
9846
	DataTable.defaults = {
9847
		/**
9848
		 * An array of data to use for the table, passed in at initialisation which
9849
		 * will be used in preference to any data which is already in the DOM. This is
9850
		 * particularly useful for constructing tables purely in Javascript, for
9851
		 * example with a custom Ajax call.
9852
		 *  @type array
9853
		 *  @default null
9854
		 *
9855
		 *  @dtopt Option
9856
		 *  @name DataTable.defaults.data
9857
		 *
9858
		 *  @example
9859
		 *    // Using a 2D array data source
9860
		 *    $(document).ready( function () {
9861
		 *      $('#example').dataTable( {
9862
		 *        "data": [
9863
		 *          ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
9864
		 *          ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
9865
		 *        ],
9866
		 *        "columns": [
9867
		 *          { "title": "Engine" },
9868
		 *          { "title": "Browser" },
9869
		 *          { "title": "Platform" },
9870
		 *          { "title": "Version" },
9871
		 *          { "title": "Grade" }
9872
		 *        ]
9873
		 *      } );
9874
		 *    } );
9875
		 *
9876
		 *  @example
9877
		 *    // Using an array of objects as a data source (`data`)
9878
		 *    $(document).ready( function () {
9879
		 *      $('#example').dataTable( {
9880
		 *        "data": [
9881
		 *          {
9882
		 *            "engine":   "Trident",
9883
		 *            "browser":  "Internet Explorer 4.0",
9884
		 *            "platform": "Win 95+",
9885
		 *            "version":  4,
9886
		 *            "grade":    "X"
9887
		 *          },
9888
		 *          {
9889
		 *            "engine":   "Trident",
9890
		 *            "browser":  "Internet Explorer 5.0",
9891
		 *            "platform": "Win 95+",
9892
		 *            "version":  5,
9893
		 *            "grade":    "C"
9894
		 *          }
9895
		 *        ],
9896
		 *        "columns": [
9897
		 *          { "title": "Engine",   "data": "engine" },
9898
		 *          { "title": "Browser",  "data": "browser" },
9899
		 *          { "title": "Platform", "data": "platform" },
9900
		 *          { "title": "Version",  "data": "version" },
9901
		 *          { "title": "Grade",    "data": "grade" }
9902
		 *        ]
9903
		 *      } );
9904
		 *    } );
9905
		 */
9906
		"aaData": null,
9907
	
9908
	
9909
		/**
9910
		 * If ordering is enabled, then DataTables will perform a first pass sort on
9911
		 * initialisation. You can define which column(s) the sort is performed
9912
		 * upon, and the sorting direction, with this variable. The `sorting` array
9913
		 * should contain an array for each column to be sorted initially containing
9914
		 * the column's index and a direction string ('asc' or 'desc').
9915
		 *  @type array
9916
		 *  @default [[0,'asc']]
9917
		 *
9918
		 *  @dtopt Option
9919
		 *  @name DataTable.defaults.order
9920
		 *
9921
		 *  @example
9922
		 *    // Sort by 3rd column first, and then 4th column
9923
		 *    $(document).ready( function() {
9924
		 *      $('#example').dataTable( {
9925
		 *        "order": [[2,'asc'], [3,'desc']]
9926
		 *      } );
9927
		 *    } );
9928
		 *
9929
		 *    // No initial sorting
9930
		 *    $(document).ready( function() {
9931
		 *      $('#example').dataTable( {
9932
		 *        "order": []
9933
		 *      } );
9934
		 *    } );
9935
		 */
9936
		"aaSorting": [[0,'asc']],
9937
	
9938
	
9939
		/**
9940
		 * This parameter is basically identical to the `sorting` parameter, but
9941
		 * cannot be overridden by user interaction with the table. What this means
9942
		 * is that you could have a column (visible or hidden) which the sorting
9943
		 * will always be forced on first - any sorting after that (from the user)
9944
		 * will then be performed as required. This can be useful for grouping rows
9945
		 * together.
9946
		 *  @type array
9947
		 *  @default null
9948
		 *
9949
		 *  @dtopt Option
9950
		 *  @name DataTable.defaults.orderFixed
9951
		 *
9952
		 *  @example
9953
		 *    $(document).ready( function() {
9954
		 *      $('#example').dataTable( {
9955
		 *        "orderFixed": [[0,'asc']]
9956
		 *      } );
9957
		 *    } )
9958
		 */
9959
		"aaSortingFixed": [],
9960
	
9961
	
9962
		/**
9963
		 * DataTables can be instructed to load data to display in the table from a
9964
		 * Ajax source. This option defines how that Ajax call is made and where to.
9965
		 *
9966
		 * The `ajax` property has three different modes of operation, depending on
9967
		 * how it is defined. These are:
9968
		 *
9969
		 * * `string` - Set the URL from where the data should be loaded from.
9970
		 * * `object` - Define properties for `jQuery.ajax`.
9971
		 * * `function` - Custom data get function
9972
		 *
9973
		 * `string`
9974
		 * --------
9975
		 *
9976
		 * As a string, the `ajax` property simply defines the URL from which
9977
		 * DataTables will load data.
9978
		 *
9979
		 * `object`
9980
		 * --------
9981
		 *
9982
		 * As an object, the parameters in the object are passed to
9983
		 * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control
9984
		 * of the Ajax request. DataTables has a number of default parameters which
9985
		 * you can override using this option. Please refer to the jQuery
9986
		 * documentation for a full description of the options available, although
9987
		 * the following parameters provide additional options in DataTables or
9988
		 * require special consideration:
9989
		 *
9990
		 * * `data` - As with jQuery, `data` can be provided as an object, but it
9991
		 *   can also be used as a function to manipulate the data DataTables sends
9992
		 *   to the server. The function takes a single parameter, an object of
9993
		 *   parameters with the values that DataTables has readied for sending. An
9994
		 *   object may be returned which will be merged into the DataTables
9995
		 *   defaults, or you can add the items to the object that was passed in and
9996
		 *   not return anything from the function. This supersedes `fnServerParams`
9997
		 *   from DataTables 1.9-.
9998
		 *
9999
		 * * `dataSrc` - By default DataTables will look for the property `data` (or
10000
		 *   `aaData` for compatibility with DataTables 1.9-) when obtaining data
10001
		 *   from an Ajax source or for server-side processing - this parameter
10002
		 *   allows that property to be changed. You can use Javascript dotted
10003
		 *   object notation to get a data source for multiple levels of nesting, or
10004
		 *   it my be used as a function. As a function it takes a single parameter,
10005
		 *   the JSON returned from the server, which can be manipulated as
10006
		 *   required, with the returned value being that used by DataTables as the
10007
		 *   data source for the table. This supersedes `sAjaxDataProp` from
10008
		 *   DataTables 1.9-.
10009
		 *
10010
		 * * `success` - Should not be overridden it is used internally in
10011
		 *   DataTables. To manipulate / transform the data returned by the server
10012
		 *   use `ajax.dataSrc`, or use `ajax` as a function (see below).
10013
		 *
10014
		 * `function`
10015
		 * ----------
10016
		 *
10017
		 * As a function, making the Ajax call is left up to yourself allowing
10018
		 * complete control of the Ajax request. Indeed, if desired, a method other
10019
		 * than Ajax could be used to obtain the required data, such as Web storage
10020
		 * or an AIR database.
10021
		 *
10022
		 * The function is given four parameters and no return is required. The
10023
		 * parameters are:
10024
		 *
10025
		 * 1. _object_ - Data to send to the server
10026
		 * 2. _function_ - Callback function that must be executed when the required
10027
		 *    data has been obtained. That data should be passed into the callback
10028
		 *    as the only parameter
10029
		 * 3. _object_ - DataTables settings object for the table
10030
		 *
10031
		 * Note that this supersedes `fnServerData` from DataTables 1.9-.
10032
		 *
10033
		 *  @type string|object|function
10034
		 *  @default null
10035
		 *
10036
		 *  @dtopt Option
10037
		 *  @name DataTable.defaults.ajax
10038
		 *  @since 1.10.0
10039
		 *
10040
		 * @example
10041
		 *   // Get JSON data from a file via Ajax.
10042
		 *   // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default).
10043
		 *   $('#example').dataTable( {
10044
		 *     "ajax": "data.json"
10045
		 *   } );
10046
		 *
10047
		 * @example
10048
		 *   // Get JSON data from a file via Ajax, using `dataSrc` to change
10049
		 *   // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`)
10050
		 *   $('#example').dataTable( {
10051
		 *     "ajax": {
10052
		 *       "url": "data.json",
10053
		 *       "dataSrc": "tableData"
10054
		 *     }
10055
		 *   } );
10056
		 *
10057
		 * @example
10058
		 *   // Get JSON data from a file via Ajax, using `dataSrc` to read data
10059
		 *   // from a plain array rather than an array in an object
10060
		 *   $('#example').dataTable( {
10061
		 *     "ajax": {
10062
		 *       "url": "data.json",
10063
		 *       "dataSrc": ""
10064
		 *     }
10065
		 *   } );
10066
		 *
10067
		 * @example
10068
		 *   // Manipulate the data returned from the server - add a link to data
10069
		 *   // (note this can, should, be done using `render` for the column - this
10070
		 *   // is just a simple example of how the data can be manipulated).
10071
		 *   $('#example').dataTable( {
10072
		 *     "ajax": {
10073
		 *       "url": "data.json",
10074
		 *       "dataSrc": function ( json ) {
10075
		 *         for ( var i=0, ien=json.length ; i<ien ; i++ ) {
10076
		 *           json[i][0] = '<a href="/message/'+json[i][0]+'>View message</a>';
10077
		 *         }
10078
		 *         return json;
10079
		 *       }
10080
		 *     }
10081
		 *   } );
10082
		 *
10083
		 * @example
10084
		 *   // Add data to the request
10085
		 *   $('#example').dataTable( {
10086
		 *     "ajax": {
10087
		 *       "url": "data.json",
10088
		 *       "data": function ( d ) {
10089
		 *         return {
10090
		 *           "extra_search": $('#extra').val()
10091
		 *         };
10092
		 *       }
10093
		 *     }
10094
		 *   } );
10095
		 *
10096
		 * @example
10097
		 *   // Send request as POST
10098
		 *   $('#example').dataTable( {
10099
		 *     "ajax": {
10100
		 *       "url": "data.json",
10101
		 *       "type": "POST"
10102
		 *     }
10103
		 *   } );
10104
		 *
10105
		 * @example
10106
		 *   // Get the data from localStorage (could interface with a form for
10107
		 *   // adding, editing and removing rows).
10108
		 *   $('#example').dataTable( {
10109
		 *     "ajax": function (data, callback, settings) {
10110
		 *       callback(
10111
		 *         JSON.parse( localStorage.getItem('dataTablesData') )
10112
		 *       );
10113
		 *     }
10114
		 *   } );
10115
		 */
10116
		"ajax": null,
10117
	
10118
	
10119
		/**
10120
		 * This parameter allows you to readily specify the entries in the length drop
10121
		 * down menu that DataTables shows when pagination is enabled. It can be
10122
		 * either a 1D array of options which will be used for both the displayed
10123
		 * option and the value, or a 2D array which will use the array in the first
10124
		 * position as the value, and the array in the second position as the
10125
		 * displayed options (useful for language strings such as 'All').
10126
		 *
10127
		 * Note that the `pageLength` property will be automatically set to the
10128
		 * first value given in this array, unless `pageLength` is also provided.
10129
		 *  @type array
10130
		 *  @default [ 10, 25, 50, 100 ]
10131
		 *
10132
		 *  @dtopt Option
10133
		 *  @name DataTable.defaults.lengthMenu
10134
		 *
10135
		 *  @example
10136
		 *    $(document).ready( function() {
10137
		 *      $('#example').dataTable( {
10138
		 *        "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
10139
		 *      } );
10140
		 *    } );
10141
		 */
10142
		"aLengthMenu": [ 10, 25, 50, 100 ],
10143
	
10144
	
10145
		/**
10146
		 * The `columns` option in the initialisation parameter allows you to define
10147
		 * details about the way individual columns behave. For a full list of
10148
		 * column options that can be set, please see
10149
		 * {@link DataTable.defaults.column}. Note that if you use `columns` to
10150
		 * define your columns, you must have an entry in the array for every single
10151
		 * column that you have in your table (these can be null if you don't which
10152
		 * to specify any options).
10153
		 *  @member
10154
		 *
10155
		 *  @name DataTable.defaults.column
10156
		 */
10157
		"aoColumns": null,
10158
	
10159
		/**
10160
		 * Very similar to `columns`, `columnDefs` allows you to target a specific
10161
		 * column, multiple columns, or all columns, using the `targets` property of
10162
		 * each object in the array. This allows great flexibility when creating
10163
		 * tables, as the `columnDefs` arrays can be of any length, targeting the
10164
		 * columns you specifically want. `columnDefs` may use any of the column
10165
		 * options available: {@link DataTable.defaults.column}, but it _must_
10166
		 * have `targets` defined in each object in the array. Values in the `targets`
10167
		 * array may be:
10168
		 *   <ul>
10169
		 *     <li>a string - class name will be matched on the TH for the column</li>
10170
		 *     <li>0 or a positive integer - column index counting from the left</li>
10171
		 *     <li>a negative integer - column index counting from the right</li>
10172
		 *     <li>the string "_all" - all columns (i.e. assign a default)</li>
10173
		 *   </ul>
10174
		 *  @member
10175
		 *
10176
		 *  @name DataTable.defaults.columnDefs
10177
		 */
10178
		"aoColumnDefs": null,
10179
	
10180
	
10181
		/**
10182
		 * Basically the same as `search`, this parameter defines the individual column
10183
		 * filtering state at initialisation time. The array must be of the same size
10184
		 * as the number of columns, and each element be an object with the parameters
10185
		 * `search` and `escapeRegex` (the latter is optional). 'null' is also
10186
		 * accepted and the default will be used.
10187
		 *  @type array
10188
		 *  @default []
10189
		 *
10190
		 *  @dtopt Option
10191
		 *  @name DataTable.defaults.searchCols
10192
		 *
10193
		 *  @example
10194
		 *    $(document).ready( function() {
10195
		 *      $('#example').dataTable( {
10196
		 *        "searchCols": [
10197
		 *          null,
10198
		 *          { "search": "My filter" },
10199
		 *          null,
10200
		 *          { "search": "^[0-9]", "escapeRegex": false }
10201
		 *        ]
10202
		 *      } );
10203
		 *    } )
10204
		 */
10205
		"aoSearchCols": [],
10206
	
10207
	
10208
		/**
10209
		 * An array of CSS classes that should be applied to displayed rows. This
10210
		 * array may be of any length, and DataTables will apply each class
10211
		 * sequentially, looping when required.
10212
		 *  @type array
10213
		 *  @default null <i>Will take the values determined by the `oClasses.stripe*`
10214
		 *    options</i>
10215
		 *
10216
		 *  @dtopt Option
10217
		 *  @name DataTable.defaults.stripeClasses
10218
		 *
10219
		 *  @example
10220
		 *    $(document).ready( function() {
10221
		 *      $('#example').dataTable( {
10222
		 *        "stripeClasses": [ 'strip1', 'strip2', 'strip3' ]
10223
		 *      } );
10224
		 *    } )
10225
		 */
10226
		"asStripeClasses": null,
10227
	
10228
	
10229
		/**
10230
		 * Enable or disable automatic column width calculation. This can be disabled
10231
		 * as an optimisation (it takes some time to calculate the widths) if the
10232
		 * tables widths are passed in using `columns`.
10233
		 *  @type boolean
10234
		 *  @default true
10235
		 *
10236
		 *  @dtopt Features
10237
		 *  @name DataTable.defaults.autoWidth
10238
		 *
10239
		 *  @example
10240
		 *    $(document).ready( function () {
10241
		 *      $('#example').dataTable( {
10242
		 *        "autoWidth": false
10243
		 *      } );
10244
		 *    } );
10245
		 */
10246
		"bAutoWidth": true,
10247
	
10248
	
10249
		/**
10250
		 * Deferred rendering can provide DataTables with a huge speed boost when you
10251
		 * are using an Ajax or JS data source for the table. This option, when set to
10252
		 * true, will cause DataTables to defer the creation of the table elements for
10253
		 * each row until they are needed for a draw - saving a significant amount of
10254
		 * time.
10255
		 *  @type boolean
10256
		 *  @default false
10257
		 *
10258
		 *  @dtopt Features
10259
		 *  @name DataTable.defaults.deferRender
10260
		 *
10261
		 *  @example
10262
		 *    $(document).ready( function() {
10263
		 *      $('#example').dataTable( {
10264
		 *        "ajax": "sources/arrays.txt",
10265
		 *        "deferRender": true
10266
		 *      } );
10267
		 *    } );
10268
		 */
10269
		"bDeferRender": false,
10270
	
10271
	
10272
		/**
10273
		 * Replace a DataTable which matches the given selector and replace it with
10274
		 * one which has the properties of the new initialisation object passed. If no
10275
		 * table matches the selector, then the new DataTable will be constructed as
10276
		 * per normal.
10277
		 *  @type boolean
10278
		 *  @default false
10279
		 *
10280
		 *  @dtopt Options
10281
		 *  @name DataTable.defaults.destroy
10282
		 *
10283
		 *  @example
10284
		 *    $(document).ready( function() {
10285
		 *      $('#example').dataTable( {
10286
		 *        "srollY": "200px",
10287
		 *        "paginate": false
10288
		 *      } );
10289
		 *
10290
		 *      // Some time later....
10291
		 *      $('#example').dataTable( {
10292
		 *        "filter": false,
10293
		 *        "destroy": true
10294
		 *      } );
10295
		 *    } );
10296
		 */
10297
		"bDestroy": false,
10298
	
10299
	
10300
		/**
10301
		 * Enable or disable filtering of data. Filtering in DataTables is "smart" in
10302
		 * that it allows the end user to input multiple words (space separated) and
10303
		 * will match a row containing those words, even if not in the order that was
10304
		 * specified (this allow matching across multiple columns). Note that if you
10305
		 * wish to use filtering in DataTables this must remain 'true' - to remove the
10306
		 * default filtering input box and retain filtering abilities, please use
10307
		 * {@link DataTable.defaults.dom}.
10308
		 *  @type boolean
10309
		 *  @default true
10310
		 *
10311
		 *  @dtopt Features
10312
		 *  @name DataTable.defaults.searching
10313
		 *
10314
		 *  @example
10315
		 *    $(document).ready( function () {
10316
		 *      $('#example').dataTable( {
10317
		 *        "searching": false
10318
		 *      } );
10319
		 *    } );
10320
		 */
10321
		"bFilter": true,
10322
	
10323
	
10324
		/**
10325
		 * Enable or disable the table information display. This shows information
10326
		 * about the data that is currently visible on the page, including information
10327
		 * about filtered data if that action is being performed.
10328
		 *  @type boolean
10329
		 *  @default true
10330
		 *
10331
		 *  @dtopt Features
10332
		 *  @name DataTable.defaults.info
10333
		 *
10334
		 *  @example
10335
		 *    $(document).ready( function () {
10336
		 *      $('#example').dataTable( {
10337
		 *        "info": false
10338
		 *      } );
10339
		 *    } );
10340
		 */
10341
		"bInfo": true,
10342
	
10343
	
10344
		/**
10345
		 * Allows the end user to select the size of a formatted page from a select
10346
		 * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`).
10347
		 *  @type boolean
10348
		 *  @default true
10349
		 *
10350
		 *  @dtopt Features
10351
		 *  @name DataTable.defaults.lengthChange
10352
		 *
10353
		 *  @example
10354
		 *    $(document).ready( function () {
10355
		 *      $('#example').dataTable( {
10356
		 *        "lengthChange": false
10357
		 *      } );
10358
		 *    } );
10359
		 */
10360
		"bLengthChange": true,
10361
	
10362
	
10363
		/**
10364
		 * Enable or disable pagination.
10365
		 *  @type boolean
10366
		 *  @default true
10367
		 *
10368
		 *  @dtopt Features
10369
		 *  @name DataTable.defaults.paging
10370
		 *
10371
		 *  @example
10372
		 *    $(document).ready( function () {
10373
		 *      $('#example').dataTable( {
10374
		 *        "paging": false
10375
		 *      } );
10376
		 *    } );
10377
		 */
10378
		"bPaginate": true,
10379
	
10380
	
10381
		/**
10382
		 * Enable or disable the display of a 'processing' indicator when the table is
10383
		 * being processed (e.g. a sort). This is particularly useful for tables with
10384
		 * large amounts of data where it can take a noticeable amount of time to sort
10385
		 * the entries.
10386
		 *  @type boolean
10387
		 *  @default false
10388
		 *
10389
		 *  @dtopt Features
10390
		 *  @name DataTable.defaults.processing
10391
		 *
10392
		 *  @example
10393
		 *    $(document).ready( function () {
10394
		 *      $('#example').dataTable( {
10395
		 *        "processing": true
10396
		 *      } );
10397
		 *    } );
10398
		 */
10399
		"bProcessing": false,
10400
	
10401
	
10402
		/**
10403
		 * Retrieve the DataTables object for the given selector. Note that if the
10404
		 * table has already been initialised, this parameter will cause DataTables
10405
		 * to simply return the object that has already been set up - it will not take
10406
		 * account of any changes you might have made to the initialisation object
10407
		 * passed to DataTables (setting this parameter to true is an acknowledgement
10408
		 * that you understand this). `destroy` can be used to reinitialise a table if
10409
		 * you need.
10410
		 *  @type boolean
10411
		 *  @default false
10412
		 *
10413
		 *  @dtopt Options
10414
		 *  @name DataTable.defaults.retrieve
10415
		 *
10416
		 *  @example
10417
		 *    $(document).ready( function() {
10418
		 *      initTable();
10419
		 *      tableActions();
10420
		 *    } );
10421
		 *
10422
		 *    function initTable ()
10423
		 *    {
10424
		 *      return $('#example').dataTable( {
10425
		 *        "scrollY": "200px",
10426
		 *        "paginate": false,
10427
		 *        "retrieve": true
10428
		 *      } );
10429
		 *    }
10430
		 *
10431
		 *    function tableActions ()
10432
		 *    {
10433
		 *      var table = initTable();
10434
		 *      // perform API operations with oTable
10435
		 *    }
10436
		 */
10437
		"bRetrieve": false,
10438
	
10439
	
10440
		/**
10441
		 * When vertical (y) scrolling is enabled, DataTables will force the height of
10442
		 * the table's viewport to the given height at all times (useful for layout).
10443
		 * However, this can look odd when filtering data down to a small data set,
10444
		 * and the footer is left "floating" further down. This parameter (when
10445
		 * enabled) will cause DataTables to collapse the table's viewport down when
10446
		 * the result set will fit within the given Y height.
10447
		 *  @type boolean
10448
		 *  @default false
10449
		 *
10450
		 *  @dtopt Options
10451
		 *  @name DataTable.defaults.scrollCollapse
10452
		 *
10453
		 *  @example
10454
		 *    $(document).ready( function() {
10455
		 *      $('#example').dataTable( {
10456
		 *        "scrollY": "200",
10457
		 *        "scrollCollapse": true
10458
		 *      } );
10459
		 *    } );
10460
		 */
10461
		"bScrollCollapse": false,
10462
	
10463
	
10464
		/**
10465
		 * Configure DataTables to use server-side processing. Note that the
10466
		 * `ajax` parameter must also be given in order to give DataTables a
10467
		 * source to obtain the required data for each draw.
10468
		 *  @type boolean
10469
		 *  @default false
10470
		 *
10471
		 *  @dtopt Features
10472
		 *  @dtopt Server-side
10473
		 *  @name DataTable.defaults.serverSide
10474
		 *
10475
		 *  @example
10476
		 *    $(document).ready( function () {
10477
		 *      $('#example').dataTable( {
10478
		 *        "serverSide": true,
10479
		 *        "ajax": "xhr.php"
10480
		 *      } );
10481
		 *    } );
10482
		 */
10483
		"bServerSide": false,
10484
	
10485
	
10486
		/**
10487
		 * Enable or disable sorting of columns. Sorting of individual columns can be
10488
		 * disabled by the `sortable` option for each column.
10489
		 *  @type boolean
10490
		 *  @default true
10491
		 *
10492
		 *  @dtopt Features
10493
		 *  @name DataTable.defaults.ordering
10494
		 *
10495
		 *  @example
10496
		 *    $(document).ready( function () {
10497
		 *      $('#example').dataTable( {
10498
		 *        "ordering": false
10499
		 *      } );
10500
		 *    } );
10501
		 */
10502
		"bSort": true,
10503
	
10504
	
10505
		/**
10506
		 * Enable or display DataTables' ability to sort multiple columns at the
10507
		 * same time (activated by shift-click by the user).
10508
		 *  @type boolean
10509
		 *  @default true
10510
		 *
10511
		 *  @dtopt Options
10512
		 *  @name DataTable.defaults.orderMulti
10513
		 *
10514
		 *  @example
10515
		 *    // Disable multiple column sorting ability
10516
		 *    $(document).ready( function () {
10517
		 *      $('#example').dataTable( {
10518
		 *        "orderMulti": false
10519
		 *      } );
10520
		 *    } );
10521
		 */
10522
		"bSortMulti": true,
10523
	
10524
	
10525
		/**
10526
		 * Allows control over whether DataTables should use the top (true) unique
10527
		 * cell that is found for a single column, or the bottom (false - default).
10528
		 * This is useful when using complex headers.
10529
		 *  @type boolean
10530
		 *  @default false
10531
		 *
10532
		 *  @dtopt Options
10533
		 *  @name DataTable.defaults.orderCellsTop
10534
		 *
10535
		 *  @example
10536
		 *    $(document).ready( function() {
10537
		 *      $('#example').dataTable( {
10538
		 *        "orderCellsTop": true
10539
		 *      } );
10540
		 *    } );
10541
		 */
10542
		"bSortCellsTop": false,
10543
	
10544
	
10545
		/**
10546
		 * Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and
10547
		 * `sorting\_3` to the columns which are currently being sorted on. This is
10548
		 * presented as a feature switch as it can increase processing time (while
10549
		 * classes are removed and added) so for large data sets you might want to
10550
		 * turn this off.
10551
		 *  @type boolean
10552
		 *  @default true
10553
		 *
10554
		 *  @dtopt Features
10555
		 *  @name DataTable.defaults.orderClasses
10556
		 *
10557
		 *  @example
10558
		 *    $(document).ready( function () {
10559
		 *      $('#example').dataTable( {
10560
		 *        "orderClasses": false
10561
		 *      } );
10562
		 *    } );
10563
		 */
10564
		"bSortClasses": true,
10565
	
10566
	
10567
		/**
10568
		 * Enable or disable state saving. When enabled HTML5 `localStorage` will be
10569
		 * used to save table display information such as pagination information,
10570
		 * display length, filtering and sorting. As such when the end user reloads
10571
		 * the page the display display will match what thy had previously set up.
10572
		 *
10573
		 * Due to the use of `localStorage` the default state saving is not supported
10574
		 * in IE6 or 7. If state saving is required in those browsers, use
10575
		 * `stateSaveCallback` to provide a storage solution such as cookies.
10576
		 *  @type boolean
10577
		 *  @default false
10578
		 *
10579
		 *  @dtopt Features
10580
		 *  @name DataTable.defaults.stateSave
10581
		 *
10582
		 *  @example
10583
		 *    $(document).ready( function () {
10584
		 *      $('#example').dataTable( {
10585
		 *        "stateSave": true
10586
		 *      } );
10587
		 *    } );
10588
		 */
10589
		"bStateSave": false,
10590
	
10591
	
10592
		/**
10593
		 * This function is called when a TR element is created (and all TD child
10594
		 * elements have been inserted), or registered if using a DOM source, allowing
10595
		 * manipulation of the TR element (adding classes etc).
10596
		 *  @type function
10597
		 *  @param {node} row "TR" element for the current row
10598
		 *  @param {array} data Raw data array for this row
10599
		 *  @param {int} dataIndex The index of this row in the internal aoData array
10600
		 *
10601
		 *  @dtopt Callbacks
10602
		 *  @name DataTable.defaults.createdRow
10603
		 *
10604
		 *  @example
10605
		 *    $(document).ready( function() {
10606
		 *      $('#example').dataTable( {
10607
		 *        "createdRow": function( row, data, dataIndex ) {
10608
		 *          // Bold the grade for all 'A' grade browsers
10609
		 *          if ( data[4] == "A" )
10610
		 *          {
10611
		 *            $('td:eq(4)', row).html( '<b>A</b>' );
10612
		 *          }
10613
		 *        }
10614
		 *      } );
10615
		 *    } );
10616
		 */
10617
		"fnCreatedRow": null,
10618
	
10619
	
10620
		/**
10621
		 * This function is called on every 'draw' event, and allows you to
10622
		 * dynamically modify any aspect you want about the created DOM.
10623
		 *  @type function
10624
		 *  @param {object} settings DataTables settings object
10625
		 *
10626
		 *  @dtopt Callbacks
10627
		 *  @name DataTable.defaults.drawCallback
10628
		 *
10629
		 *  @example
10630
		 *    $(document).ready( function() {
10631
		 *      $('#example').dataTable( {
10632
		 *        "drawCallback": function( settings ) {
10633
		 *          alert( 'DataTables has redrawn the table' );
10634
		 *        }
10635
		 *      } );
10636
		 *    } );
10637
		 */
10638
		"fnDrawCallback": null,
10639
	
10640
	
10641
		/**
10642
		 * Identical to fnHeaderCallback() but for the table footer this function
10643
		 * allows you to modify the table footer on every 'draw' event.
10644
		 *  @type function
10645
		 *  @param {node} foot "TR" element for the footer
10646
		 *  @param {array} data Full table data (as derived from the original HTML)
10647
		 *  @param {int} start Index for the current display starting point in the
10648
		 *    display array
10649
		 *  @param {int} end Index for the current display ending point in the
10650
		 *    display array
10651
		 *  @param {array int} display Index array to translate the visual position
10652
		 *    to the full data array
10653
		 *
10654
		 *  @dtopt Callbacks
10655
		 *  @name DataTable.defaults.footerCallback
10656
		 *
10657
		 *  @example
10658
		 *    $(document).ready( function() {
10659
		 *      $('#example').dataTable( {
10660
		 *        "footerCallback": function( tfoot, data, start, end, display ) {
10661
		 *          tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start;
10662
		 *        }
10663
		 *      } );
10664
		 *    } )
10665
		 */
10666
		"fnFooterCallback": null,
10667
	
10668
	
10669
		/**
10670
		 * When rendering large numbers in the information element for the table
10671
		 * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
10672
		 * to have a comma separator for the 'thousands' units (e.g. 1 million is
10673
		 * rendered as "1,000,000") to help readability for the end user. This
10674
		 * function will override the default method DataTables uses.
10675
		 *  @type function
10676
		 *  @member
10677
		 *  @param {int} toFormat number to be formatted
10678
		 *  @returns {string} formatted string for DataTables to show the number
10679
		 *
10680
		 *  @dtopt Callbacks
10681
		 *  @name DataTable.defaults.formatNumber
10682
		 *
10683
		 *  @example
10684
		 *    // Format a number using a single quote for the separator (note that
10685
		 *    // this can also be done with the language.thousands option)
10686
		 *    $(document).ready( function() {
10687
		 *      $('#example').dataTable( {
10688
		 *        "formatNumber": function ( toFormat ) {
10689
		 *          return toFormat.toString().replace(
10690
		 *            /\B(?=(\d{3})+(?!\d))/g, "'"
10691
		 *          );
10692
		 *        };
10693
		 *      } );
10694
		 *    } );
10695
		 */
10696
		"fnFormatNumber": function ( toFormat ) {
10697
			return toFormat.toString().replace(
10698
				/\B(?=(\d{3})+(?!\d))/g,
10699
				this.oLanguage.sThousands
10700
			);
10701
		},
10702
	
10703
	
10704
		/**
10705
		 * This function is called on every 'draw' event, and allows you to
10706
		 * dynamically modify the header row. This can be used to calculate and
10707
		 * display useful information about the table.
10708
		 *  @type function
10709
		 *  @param {node} head "TR" element for the header
10710
		 *  @param {array} data Full table data (as derived from the original HTML)
10711
		 *  @param {int} start Index for the current display starting point in the
10712
		 *    display array
10713
		 *  @param {int} end Index for the current display ending point in the
10714
		 *    display array
10715
		 *  @param {array int} display Index array to translate the visual position
10716
		 *    to the full data array
10717
		 *
10718
		 *  @dtopt Callbacks
10719
		 *  @name DataTable.defaults.headerCallback
10720
		 *
10721
		 *  @example
10722
		 *    $(document).ready( function() {
10723
		 *      $('#example').dataTable( {
10724
		 *        "fheaderCallback": function( head, data, start, end, display ) {
10725
		 *          head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records";
10726
		 *        }
10727
		 *      } );
10728
		 *    } )
10729
		 */
10730
		"fnHeaderCallback": null,
10731
	
10732
	
10733
		/**
10734
		 * The information element can be used to convey information about the current
10735
		 * state of the table. Although the internationalisation options presented by
10736
		 * DataTables are quite capable of dealing with most customisations, there may
10737
		 * be times where you wish to customise the string further. This callback
10738
		 * allows you to do exactly that.
10739
		 *  @type function
10740
		 *  @param {object} oSettings DataTables settings object
10741
		 *  @param {int} start Starting position in data for the draw
10742
		 *  @param {int} end End position in data for the draw
10743
		 *  @param {int} max Total number of rows in the table (regardless of
10744
		 *    filtering)
10745
		 *  @param {int} total Total number of rows in the data set, after filtering
10746
		 *  @param {string} pre The string that DataTables has formatted using it's
10747
		 *    own rules
10748
		 *  @returns {string} The string to be displayed in the information element.
10749
		 *
10750
		 *  @dtopt Callbacks
10751
		 *  @name DataTable.defaults.infoCallback
10752
		 *
10753
		 *  @example
10754
		 *    $('#example').dataTable( {
10755
		 *      "infoCallback": function( settings, start, end, max, total, pre ) {
10756
		 *        return start +" to "+ end;
10757
		 *      }
10758
		 *    } );
10759
		 */
10760
		"fnInfoCallback": null,
10761
	
10762
	
10763
		/**
10764
		 * Called when the table has been initialised. Normally DataTables will
10765
		 * initialise sequentially and there will be no need for this function,
10766
		 * however, this does not hold true when using external language information
10767
		 * since that is obtained using an async XHR call.
10768
		 *  @type function
10769
		 *  @param {object} settings DataTables settings object
10770
		 *  @param {object} json The JSON object request from the server - only
10771
		 *    present if client-side Ajax sourced data is used
10772
		 *
10773
		 *  @dtopt Callbacks
10774
		 *  @name DataTable.defaults.initComplete
10775
		 *
10776
		 *  @example
10777
		 *    $(document).ready( function() {
10778
		 *      $('#example').dataTable( {
10779
		 *        "initComplete": function(settings, json) {
10780
		 *          alert( 'DataTables has finished its initialisation.' );
10781
		 *        }
10782
		 *      } );
10783
		 *    } )
10784
		 */
10785
		"fnInitComplete": null,
10786
	
10787
	
10788
		/**
10789
		 * Called at the very start of each table draw and can be used to cancel the
10790
		 * draw by returning false, any other return (including undefined) results in
10791
		 * the full draw occurring).
10792
		 *  @type function
10793
		 *  @param {object} settings DataTables settings object
10794
		 *  @returns {boolean} False will cancel the draw, anything else (including no
10795
		 *    return) will allow it to complete.
10796
		 *
10797
		 *  @dtopt Callbacks
10798
		 *  @name DataTable.defaults.preDrawCallback
10799
		 *
10800
		 *  @example
10801
		 *    $(document).ready( function() {
10802
		 *      $('#example').dataTable( {
10803
		 *        "preDrawCallback": function( settings ) {
10804
		 *          if ( $('#test').val() == 1 ) {
10805
		 *            return false;
10806
		 *          }
10807
		 *        }
10808
		 *      } );
10809
		 *    } );
10810
		 */
10811
		"fnPreDrawCallback": null,
10812
	
10813
	
10814
		/**
10815
		 * This function allows you to 'post process' each row after it have been
10816
		 * generated for each table draw, but before it is rendered on screen. This
10817
		 * function might be used for setting the row class name etc.
10818
		 *  @type function
10819
		 *  @param {node} row "TR" element for the current row
10820
		 *  @param {array} data Raw data array for this row
10821
		 *  @param {int} displayIndex The display index for the current table draw
10822
		 *  @param {int} displayIndexFull The index of the data in the full list of
10823
		 *    rows (after filtering)
10824
		 *
10825
		 *  @dtopt Callbacks
10826
		 *  @name DataTable.defaults.rowCallback
10827
		 *
10828
		 *  @example
10829
		 *    $(document).ready( function() {
10830
		 *      $('#example').dataTable( {
10831
		 *        "rowCallback": function( row, data, displayIndex, displayIndexFull ) {
10832
		 *          // Bold the grade for all 'A' grade browsers
10833
		 *          if ( data[4] == "A" ) {
10834
		 *            $('td:eq(4)', row).html( '<b>A</b>' );
10835
		 *          }
10836
		 *        }
10837
		 *      } );
10838
		 *    } );
10839
		 */
10840
		"fnRowCallback": null,
10841
	
10842
	
10843
		/**
10844
		 * __Deprecated__ The functionality provided by this parameter has now been
10845
		 * superseded by that provided through `ajax`, which should be used instead.
10846
		 *
10847
		 * This parameter allows you to override the default function which obtains
10848
		 * the data from the server so something more suitable for your application.
10849
		 * For example you could use POST data, or pull information from a Gears or
10850
		 * AIR database.
10851
		 *  @type function
10852
		 *  @member
10853
		 *  @param {string} source HTTP source to obtain the data from (`ajax`)
10854
		 *  @param {array} data A key/value pair object containing the data to send
10855
		 *    to the server
10856
		 *  @param {function} callback to be called on completion of the data get
10857
		 *    process that will draw the data on the page.
10858
		 *  @param {object} settings DataTables settings object
10859
		 *
10860
		 *  @dtopt Callbacks
10861
		 *  @dtopt Server-side
10862
		 *  @name DataTable.defaults.serverData
10863
		 *
10864
		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
10865
		 */
10866
		"fnServerData": null,
10867
	
10868
	
10869
		/**
10870
		 * __Deprecated__ The functionality provided by this parameter has now been
10871
		 * superseded by that provided through `ajax`, which should be used instead.
10872
		 *
10873
		 *  It is often useful to send extra data to the server when making an Ajax
10874
		 * request - for example custom filtering information, and this callback
10875
		 * function makes it trivial to send extra information to the server. The
10876
		 * passed in parameter is the data set that has been constructed by
10877
		 * DataTables, and you can add to this or modify it as you require.
10878
		 *  @type function
10879
		 *  @param {array} data Data array (array of objects which are name/value
10880
		 *    pairs) that has been constructed by DataTables and will be sent to the
10881
		 *    server. In the case of Ajax sourced data with server-side processing
10882
		 *    this will be an empty array, for server-side processing there will be a
10883
		 *    significant number of parameters!
10884
		 *  @returns {undefined} Ensure that you modify the data array passed in,
10885
		 *    as this is passed by reference.
10886
		 *
10887
		 *  @dtopt Callbacks
10888
		 *  @dtopt Server-side
10889
		 *  @name DataTable.defaults.serverParams
10890
		 *
10891
		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
10892
		 */
10893
		"fnServerParams": null,
10894
	
10895
	
10896
		/**
10897
		 * Load the table state. With this function you can define from where, and how, the
10898
		 * state of a table is loaded. By default DataTables will load from `localStorage`
10899
		 * but you might wish to use a server-side database or cookies.
10900
		 *  @type function
10901
		 *  @member
10902
		 *  @param {object} settings DataTables settings object
10903
		 *  @param {object} callback Callback that can be executed when done. It
10904
		 *    should be passed the loaded state object.
10905
		 *  @return {object} The DataTables state object to be loaded
10906
		 *
10907
		 *  @dtopt Callbacks
10908
		 *  @name DataTable.defaults.stateLoadCallback
10909
		 *
10910
		 *  @example
10911
		 *    $(document).ready( function() {
10912
		 *      $('#example').dataTable( {
10913
		 *        "stateSave": true,
10914
		 *        "stateLoadCallback": function (settings, callback) {
10915
		 *          $.ajax( {
10916
		 *            "url": "/state_load",
10917
		 *            "dataType": "json",
10918
		 *            "success": function (json) {
10919
		 *              callback( json );
10920
		 *            }
10921
		 *          } );
10922
		 *        }
10923
		 *      } );
10924
		 *    } );
10925
		 */
10926
		"fnStateLoadCallback": function ( settings ) {
10927
			try {
10928
				return JSON.parse(
10929
					(settings.iStateDuration === -1 ? sessionStorage : localStorage).getItem(
0 ignored issues
show
Bug introduced by
The variable localStorage seems to be never declared. If this is a global, consider adding a /** global: localStorage */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
Bug introduced by
The variable sessionStorage seems to be never declared. If this is a global, consider adding a /** global: sessionStorage */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
10930
						'DataTables_'+settings.sInstance+'_'+location.pathname
10931
					)
10932
				);
10933
			} catch (e) {}
0 ignored issues
show
Coding Style Comprehensibility Best Practice introduced by
Empty catch clauses should be used with caution; consider adding a comment why this is needed.
Loading history...
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
10934
		},
10935
	
10936
	
10937
		/**
10938
		 * Callback which allows modification of the saved state prior to loading that state.
10939
		 * This callback is called when the table is loading state from the stored data, but
10940
		 * prior to the settings object being modified by the saved state. Note that for
10941
		 * plug-in authors, you should use the `stateLoadParams` event to load parameters for
10942
		 * a plug-in.
10943
		 *  @type function
10944
		 *  @param {object} settings DataTables settings object
10945
		 *  @param {object} data The state object that is to be loaded
10946
		 *
10947
		 *  @dtopt Callbacks
10948
		 *  @name DataTable.defaults.stateLoadParams
10949
		 *
10950
		 *  @example
10951
		 *    // Remove a saved filter, so filtering is never loaded
10952
		 *    $(document).ready( function() {
10953
		 *      $('#example').dataTable( {
10954
		 *        "stateSave": true,
10955
		 *        "stateLoadParams": function (settings, data) {
10956
		 *          data.oSearch.sSearch = "";
10957
		 *        }
10958
		 *      } );
10959
		 *    } );
10960
		 *
10961
		 *  @example
10962
		 *    // Disallow state loading by returning false
10963
		 *    $(document).ready( function() {
10964
		 *      $('#example').dataTable( {
10965
		 *        "stateSave": true,
10966
		 *        "stateLoadParams": function (settings, data) {
10967
		 *          return false;
10968
		 *        }
10969
		 *      } );
10970
		 *    } );
10971
		 */
10972
		"fnStateLoadParams": null,
10973
	
10974
	
10975
		/**
10976
		 * Callback that is called when the state has been loaded from the state saving method
10977
		 * and the DataTables settings object has been modified as a result of the loaded state.
10978
		 *  @type function
10979
		 *  @param {object} settings DataTables settings object
10980
		 *  @param {object} data The state object that was loaded
10981
		 *
10982
		 *  @dtopt Callbacks
10983
		 *  @name DataTable.defaults.stateLoaded
10984
		 *
10985
		 *  @example
10986
		 *    // Show an alert with the filtering value that was saved
10987
		 *    $(document).ready( function() {
10988
		 *      $('#example').dataTable( {
10989
		 *        "stateSave": true,
10990
		 *        "stateLoaded": function (settings, data) {
10991
		 *          alert( 'Saved filter was: '+data.oSearch.sSearch );
10992
		 *        }
10993
		 *      } );
10994
		 *    } );
10995
		 */
10996
		"fnStateLoaded": null,
10997
	
10998
	
10999
		/**
11000
		 * Save the table state. This function allows you to define where and how the state
11001
		 * information for the table is stored By default DataTables will use `localStorage`
11002
		 * but you might wish to use a server-side database or cookies.
11003
		 *  @type function
11004
		 *  @member
11005
		 *  @param {object} settings DataTables settings object
11006
		 *  @param {object} data The state object to be saved
11007
		 *
11008
		 *  @dtopt Callbacks
11009
		 *  @name DataTable.defaults.stateSaveCallback
11010
		 *
11011
		 *  @example
11012
		 *    $(document).ready( function() {
11013
		 *      $('#example').dataTable( {
11014
		 *        "stateSave": true,
11015
		 *        "stateSaveCallback": function (settings, data) {
11016
		 *          // Send an Ajax request to the server with the state object
11017
		 *          $.ajax( {
11018
		 *            "url": "/state_save",
11019
		 *            "data": data,
11020
		 *            "dataType": "json",
11021
		 *            "method": "POST"
11022
		 *            "success": function () {}
11023
		 *          } );
11024
		 *        }
11025
		 *      } );
11026
		 *    } );
11027
		 */
11028
		"fnStateSaveCallback": function ( settings, data ) {
11029
			try {
11030
				(settings.iStateDuration === -1 ? sessionStorage : localStorage).setItem(
0 ignored issues
show
Bug introduced by
The variable localStorage seems to be never declared. If this is a global, consider adding a /** global: localStorage */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
Bug introduced by
The variable sessionStorage seems to be never declared. If this is a global, consider adding a /** global: sessionStorage */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
11031
					'DataTables_'+settings.sInstance+'_'+location.pathname,
11032
					JSON.stringify( data )
11033
				);
11034
			} catch (e) {}
0 ignored issues
show
Coding Style Comprehensibility Best Practice introduced by
Empty catch clauses should be used with caution; consider adding a comment why this is needed.
Loading history...
11035
		},
11036
	
11037
	
11038
		/**
11039
		 * Callback which allows modification of the state to be saved. Called when the table
11040
		 * has changed state a new state save is required. This method allows modification of
11041
		 * the state saving object prior to actually doing the save, including addition or
11042
		 * other state properties or modification. Note that for plug-in authors, you should
11043
		 * use the `stateSaveParams` event to save parameters for a plug-in.
11044
		 *  @type function
11045
		 *  @param {object} settings DataTables settings object
11046
		 *  @param {object} data The state object to be saved
11047
		 *
11048
		 *  @dtopt Callbacks
11049
		 *  @name DataTable.defaults.stateSaveParams
11050
		 *
11051
		 *  @example
11052
		 *    // Remove a saved filter, so filtering is never saved
11053
		 *    $(document).ready( function() {
11054
		 *      $('#example').dataTable( {
11055
		 *        "stateSave": true,
11056
		 *        "stateSaveParams": function (settings, data) {
11057
		 *          data.oSearch.sSearch = "";
11058
		 *        }
11059
		 *      } );
11060
		 *    } );
11061
		 */
11062
		"fnStateSaveParams": null,
11063
	
11064
	
11065
		/**
11066
		 * Duration for which the saved state information is considered valid. After this period
11067
		 * has elapsed the state will be returned to the default.
11068
		 * Value is given in seconds.
11069
		 *  @type int
11070
		 *  @default 7200 <i>(2 hours)</i>
11071
		 *
11072
		 *  @dtopt Options
11073
		 *  @name DataTable.defaults.stateDuration
11074
		 *
11075
		 *  @example
11076
		 *    $(document).ready( function() {
11077
		 *      $('#example').dataTable( {
11078
		 *        "stateDuration": 60*60*24; // 1 day
11079
		 *      } );
11080
		 *    } )
11081
		 */
11082
		"iStateDuration": 7200,
11083
	
11084
	
11085
		/**
11086
		 * When enabled DataTables will not make a request to the server for the first
11087
		 * page draw - rather it will use the data already on the page (no sorting etc
11088
		 * will be applied to it), thus saving on an XHR at load time. `deferLoading`
11089
		 * is used to indicate that deferred loading is required, but it is also used
11090
		 * to tell DataTables how many records there are in the full table (allowing
11091
		 * the information element and pagination to be displayed correctly). In the case
11092
		 * where a filtering is applied to the table on initial load, this can be
11093
		 * indicated by giving the parameter as an array, where the first element is
11094
		 * the number of records available after filtering and the second element is the
11095
		 * number of records without filtering (allowing the table information element
11096
		 * to be shown correctly).
11097
		 *  @type int | array
11098
		 *  @default null
11099
		 *
11100
		 *  @dtopt Options
11101
		 *  @name DataTable.defaults.deferLoading
11102
		 *
11103
		 *  @example
11104
		 *    // 57 records available in the table, no filtering applied
11105
		 *    $(document).ready( function() {
11106
		 *      $('#example').dataTable( {
11107
		 *        "serverSide": true,
11108
		 *        "ajax": "scripts/server_processing.php",
11109
		 *        "deferLoading": 57
11110
		 *      } );
11111
		 *    } );
11112
		 *
11113
		 *  @example
11114
		 *    // 57 records after filtering, 100 without filtering (an initial filter applied)
11115
		 *    $(document).ready( function() {
11116
		 *      $('#example').dataTable( {
11117
		 *        "serverSide": true,
11118
		 *        "ajax": "scripts/server_processing.php",
11119
		 *        "deferLoading": [ 57, 100 ],
11120
		 *        "search": {
11121
		 *          "search": "my_filter"
11122
		 *        }
11123
		 *      } );
11124
		 *    } );
11125
		 */
11126
		"iDeferLoading": null,
11127
	
11128
	
11129
		/**
11130
		 * Number of rows to display on a single page when using pagination. If
11131
		 * feature enabled (`lengthChange`) then the end user will be able to override
11132
		 * this to a custom setting using a pop-up menu.
11133
		 *  @type int
11134
		 *  @default 10
11135
		 *
11136
		 *  @dtopt Options
11137
		 *  @name DataTable.defaults.pageLength
11138
		 *
11139
		 *  @example
11140
		 *    $(document).ready( function() {
11141
		 *      $('#example').dataTable( {
11142
		 *        "pageLength": 50
11143
		 *      } );
11144
		 *    } )
11145
		 */
11146
		"iDisplayLength": 10,
11147
	
11148
	
11149
		/**
11150
		 * Define the starting point for data display when using DataTables with
11151
		 * pagination. Note that this parameter is the number of records, rather than
11152
		 * the page number, so if you have 10 records per page and want to start on
11153
		 * the third page, it should be "20".
11154
		 *  @type int
11155
		 *  @default 0
11156
		 *
11157
		 *  @dtopt Options
11158
		 *  @name DataTable.defaults.displayStart
11159
		 *
11160
		 *  @example
11161
		 *    $(document).ready( function() {
11162
		 *      $('#example').dataTable( {
11163
		 *        "displayStart": 20
11164
		 *      } );
11165
		 *    } )
11166
		 */
11167
		"iDisplayStart": 0,
11168
	
11169
	
11170
		/**
11171
		 * By default DataTables allows keyboard navigation of the table (sorting, paging,
11172
		 * and filtering) by adding a `tabindex` attribute to the required elements. This
11173
		 * allows you to tab through the controls and press the enter key to activate them.
11174
		 * The tabindex is default 0, meaning that the tab follows the flow of the document.
11175
		 * You can overrule this using this parameter if you wish. Use a value of -1 to
11176
		 * disable built-in keyboard navigation.
11177
		 *  @type int
11178
		 *  @default 0
11179
		 *
11180
		 *  @dtopt Options
11181
		 *  @name DataTable.defaults.tabIndex
11182
		 *
11183
		 *  @example
11184
		 *    $(document).ready( function() {
11185
		 *      $('#example').dataTable( {
11186
		 *        "tabIndex": 1
11187
		 *      } );
11188
		 *    } );
11189
		 */
11190
		"iTabIndex": 0,
11191
	
11192
	
11193
		/**
11194
		 * Classes that DataTables assigns to the various components and features
11195
		 * that it adds to the HTML table. This allows classes to be configured
11196
		 * during initialisation in addition to through the static
11197
		 * {@link DataTable.ext.oStdClasses} object).
11198
		 *  @namespace
11199
		 *  @name DataTable.defaults.classes
11200
		 */
11201
		"oClasses": {},
11202
	
11203
	
11204
		/**
11205
		 * All strings that DataTables uses in the user interface that it creates
11206
		 * are defined in this object, allowing you to modified them individually or
11207
		 * completely replace them all as required.
11208
		 *  @namespace
11209
		 *  @name DataTable.defaults.language
11210
		 */
11211
		"oLanguage": {
11212
			/**
11213
			 * Strings that are used for WAI-ARIA labels and controls only (these are not
11214
			 * actually visible on the page, but will be read by screenreaders, and thus
11215
			 * must be internationalised as well).
11216
			 *  @namespace
11217
			 *  @name DataTable.defaults.language.aria
11218
			 */
11219
			"oAria": {
11220
				/**
11221
				 * ARIA label that is added to the table headers when the column may be
11222
				 * sorted ascending by activing the column (click or return when focused).
11223
				 * Note that the column header is prefixed to this string.
11224
				 *  @type string
11225
				 *  @default : activate to sort column ascending
11226
				 *
11227
				 *  @dtopt Language
11228
				 *  @name DataTable.defaults.language.aria.sortAscending
11229
				 *
11230
				 *  @example
11231
				 *    $(document).ready( function() {
11232
				 *      $('#example').dataTable( {
11233
				 *        "language": {
11234
				 *          "aria": {
11235
				 *            "sortAscending": " - click/return to sort ascending"
11236
				 *          }
11237
				 *        }
11238
				 *      } );
11239
				 *    } );
11240
				 */
11241
				"sSortAscending": ": activate to sort column ascending",
11242
	
11243
				/**
11244
				 * ARIA label that is added to the table headers when the column may be
11245
				 * sorted descending by activing the column (click or return when focused).
11246
				 * Note that the column header is prefixed to this string.
11247
				 *  @type string
11248
				 *  @default : activate to sort column ascending
11249
				 *
11250
				 *  @dtopt Language
11251
				 *  @name DataTable.defaults.language.aria.sortDescending
11252
				 *
11253
				 *  @example
11254
				 *    $(document).ready( function() {
11255
				 *      $('#example').dataTable( {
11256
				 *        "language": {
11257
				 *          "aria": {
11258
				 *            "sortDescending": " - click/return to sort descending"
11259
				 *          }
11260
				 *        }
11261
				 *      } );
11262
				 *    } );
11263
				 */
11264
				"sSortDescending": ": activate to sort column descending"
11265
			},
11266
	
11267
			/**
11268
			 * Pagination string used by DataTables for the built-in pagination
11269
			 * control types.
11270
			 *  @namespace
11271
			 *  @name DataTable.defaults.language.paginate
11272
			 */
11273
			"oPaginate": {
11274
				/**
11275
				 * Text to use when using the 'full_numbers' type of pagination for the
11276
				 * button to take the user to the first page.
11277
				 *  @type string
11278
				 *  @default First
11279
				 *
11280
				 *  @dtopt Language
11281
				 *  @name DataTable.defaults.language.paginate.first
11282
				 *
11283
				 *  @example
11284
				 *    $(document).ready( function() {
11285
				 *      $('#example').dataTable( {
11286
				 *        "language": {
11287
				 *          "paginate": {
11288
				 *            "first": "First page"
11289
				 *          }
11290
				 *        }
11291
				 *      } );
11292
				 *    } );
11293
				 */
11294
				"sFirst": "First",
11295
	
11296
	
11297
				/**
11298
				 * Text to use when using the 'full_numbers' type of pagination for the
11299
				 * button to take the user to the last page.
11300
				 *  @type string
11301
				 *  @default Last
11302
				 *
11303
				 *  @dtopt Language
11304
				 *  @name DataTable.defaults.language.paginate.last
11305
				 *
11306
				 *  @example
11307
				 *    $(document).ready( function() {
11308
				 *      $('#example').dataTable( {
11309
				 *        "language": {
11310
				 *          "paginate": {
11311
				 *            "last": "Last page"
11312
				 *          }
11313
				 *        }
11314
				 *      } );
11315
				 *    } );
11316
				 */
11317
				"sLast": "Last",
11318
	
11319
	
11320
				/**
11321
				 * Text to use for the 'next' pagination button (to take the user to the
11322
				 * next page).
11323
				 *  @type string
11324
				 *  @default Next
11325
				 *
11326
				 *  @dtopt Language
11327
				 *  @name DataTable.defaults.language.paginate.next
11328
				 *
11329
				 *  @example
11330
				 *    $(document).ready( function() {
11331
				 *      $('#example').dataTable( {
11332
				 *        "language": {
11333
				 *          "paginate": {
11334
				 *            "next": "Next page"
11335
				 *          }
11336
				 *        }
11337
				 *      } );
11338
				 *    } );
11339
				 */
11340
				"sNext": "Next",
11341
	
11342
	
11343
				/**
11344
				 * Text to use for the 'previous' pagination button (to take the user to
11345
				 * the previous page).
11346
				 *  @type string
11347
				 *  @default Previous
11348
				 *
11349
				 *  @dtopt Language
11350
				 *  @name DataTable.defaults.language.paginate.previous
11351
				 *
11352
				 *  @example
11353
				 *    $(document).ready( function() {
11354
				 *      $('#example').dataTable( {
11355
				 *        "language": {
11356
				 *          "paginate": {
11357
				 *            "previous": "Previous page"
11358
				 *          }
11359
				 *        }
11360
				 *      } );
11361
				 *    } );
11362
				 */
11363
				"sPrevious": "Previous"
11364
			},
11365
	
11366
			/**
11367
			 * This string is shown in preference to `zeroRecords` when the table is
11368
			 * empty of data (regardless of filtering). Note that this is an optional
11369
			 * parameter - if it is not given, the value of `zeroRecords` will be used
11370
			 * instead (either the default or given value).
11371
			 *  @type string
11372
			 *  @default No data available in table
11373
			 *
11374
			 *  @dtopt Language
11375
			 *  @name DataTable.defaults.language.emptyTable
11376
			 *
11377
			 *  @example
11378
			 *    $(document).ready( function() {
11379
			 *      $('#example').dataTable( {
11380
			 *        "language": {
11381
			 *          "emptyTable": "No data available in table"
11382
			 *        }
11383
			 *      } );
11384
			 *    } );
11385
			 */
11386
			"sEmptyTable": "No data available in table",
11387
	
11388
	
11389
			/**
11390
			 * This string gives information to the end user about the information
11391
			 * that is current on display on the page. The following tokens can be
11392
			 * used in the string and will be dynamically replaced as the table
11393
			 * display updates. This tokens can be placed anywhere in the string, or
11394
			 * removed as needed by the language requires:
11395
			 *
11396
			 * * `\_START\_` - Display index of the first record on the current page
11397
			 * * `\_END\_` - Display index of the last record on the current page
11398
			 * * `\_TOTAL\_` - Number of records in the table after filtering
11399
			 * * `\_MAX\_` - Number of records in the table without filtering
11400
			 * * `\_PAGE\_` - Current page number
11401
			 * * `\_PAGES\_` - Total number of pages of data in the table
11402
			 *
11403
			 *  @type string
11404
			 *  @default Showing _START_ to _END_ of _TOTAL_ entries
11405
			 *
11406
			 *  @dtopt Language
11407
			 *  @name DataTable.defaults.language.info
11408
			 *
11409
			 *  @example
11410
			 *    $(document).ready( function() {
11411
			 *      $('#example').dataTable( {
11412
			 *        "language": {
11413
			 *          "info": "Showing page _PAGE_ of _PAGES_"
11414
			 *        }
11415
			 *      } );
11416
			 *    } );
11417
			 */
11418
			"sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
11419
	
11420
	
11421
			/**
11422
			 * Display information string for when the table is empty. Typically the
11423
			 * format of this string should match `info`.
11424
			 *  @type string
11425
			 *  @default Showing 0 to 0 of 0 entries
11426
			 *
11427
			 *  @dtopt Language
11428
			 *  @name DataTable.defaults.language.infoEmpty
11429
			 *
11430
			 *  @example
11431
			 *    $(document).ready( function() {
11432
			 *      $('#example').dataTable( {
11433
			 *        "language": {
11434
			 *          "infoEmpty": "No entries to show"
11435
			 *        }
11436
			 *      } );
11437
			 *    } );
11438
			 */
11439
			"sInfoEmpty": "Showing 0 to 0 of 0 entries",
11440
	
11441
	
11442
			/**
11443
			 * When a user filters the information in a table, this string is appended
11444
			 * to the information (`info`) to give an idea of how strong the filtering
11445
			 * is. The variable _MAX_ is dynamically updated.
11446
			 *  @type string
11447
			 *  @default (filtered from _MAX_ total entries)
11448
			 *
11449
			 *  @dtopt Language
11450
			 *  @name DataTable.defaults.language.infoFiltered
11451
			 *
11452
			 *  @example
11453
			 *    $(document).ready( function() {
11454
			 *      $('#example').dataTable( {
11455
			 *        "language": {
11456
			 *          "infoFiltered": " - filtering from _MAX_ records"
11457
			 *        }
11458
			 *      } );
11459
			 *    } );
11460
			 */
11461
			"sInfoFiltered": "(filtered from _MAX_ total entries)",
11462
	
11463
	
11464
			/**
11465
			 * If can be useful to append extra information to the info string at times,
11466
			 * and this variable does exactly that. This information will be appended to
11467
			 * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are
11468
			 * being used) at all times.
11469
			 *  @type string
11470
			 *  @default <i>Empty string</i>
11471
			 *
11472
			 *  @dtopt Language
11473
			 *  @name DataTable.defaults.language.infoPostFix
11474
			 *
11475
			 *  @example
11476
			 *    $(document).ready( function() {
11477
			 *      $('#example').dataTable( {
11478
			 *        "language": {
11479
			 *          "infoPostFix": "All records shown are derived from real information."
11480
			 *        }
11481
			 *      } );
11482
			 *    } );
11483
			 */
11484
			"sInfoPostFix": "",
11485
	
11486
	
11487
			/**
11488
			 * This decimal place operator is a little different from the other
11489
			 * language options since DataTables doesn't output floating point
11490
			 * numbers, so it won't ever use this for display of a number. Rather,
11491
			 * what this parameter does is modify the sort methods of the table so
11492
			 * that numbers which are in a format which has a character other than
11493
			 * a period (`.`) as a decimal place will be sorted numerically.
11494
			 *
11495
			 * Note that numbers with different decimal places cannot be shown in
11496
			 * the same table and still be sortable, the table must be consistent.
11497
			 * However, multiple different tables on the page can use different
11498
			 * decimal place characters.
11499
			 *  @type string
11500
			 *  @default 
11501
			 *
11502
			 *  @dtopt Language
11503
			 *  @name DataTable.defaults.language.decimal
11504
			 *
11505
			 *  @example
11506
			 *    $(document).ready( function() {
11507
			 *      $('#example').dataTable( {
11508
			 *        "language": {
11509
			 *          "decimal": ","
11510
			 *          "thousands": "."
11511
			 *        }
11512
			 *      } );
11513
			 *    } );
11514
			 */
11515
			"sDecimal": "",
11516
	
11517
	
11518
			/**
11519
			 * DataTables has a build in number formatter (`formatNumber`) which is
11520
			 * used to format large numbers that are used in the table information.
11521
			 * By default a comma is used, but this can be trivially changed to any
11522
			 * character you wish with this parameter.
11523
			 *  @type string
11524
			 *  @default ,
11525
			 *
11526
			 *  @dtopt Language
11527
			 *  @name DataTable.defaults.language.thousands
11528
			 *
11529
			 *  @example
11530
			 *    $(document).ready( function() {
11531
			 *      $('#example').dataTable( {
11532
			 *        "language": {
11533
			 *          "thousands": "'"
11534
			 *        }
11535
			 *      } );
11536
			 *    } );
11537
			 */
11538
			"sThousands": ",",
11539
	
11540
	
11541
			/**
11542
			 * Detail the action that will be taken when the drop down menu for the
11543
			 * pagination length option is changed. The '_MENU_' variable is replaced
11544
			 * with a default select list of 10, 25, 50 and 100, and can be replaced
11545
			 * with a custom select box if required.
11546
			 *  @type string
11547
			 *  @default Show _MENU_ entries
11548
			 *
11549
			 *  @dtopt Language
11550
			 *  @name DataTable.defaults.language.lengthMenu
11551
			 *
11552
			 *  @example
11553
			 *    // Language change only
11554
			 *    $(document).ready( function() {
11555
			 *      $('#example').dataTable( {
11556
			 *        "language": {
11557
			 *          "lengthMenu": "Display _MENU_ records"
11558
			 *        }
11559
			 *      } );
11560
			 *    } );
11561
			 *
11562
			 *  @example
11563
			 *    // Language and options change
11564
			 *    $(document).ready( function() {
11565
			 *      $('#example').dataTable( {
11566
			 *        "language": {
11567
			 *          "lengthMenu": 'Display <select>'+
11568
			 *            '<option value="10">10</option>'+
11569
			 *            '<option value="20">20</option>'+
11570
			 *            '<option value="30">30</option>'+
11571
			 *            '<option value="40">40</option>'+
11572
			 *            '<option value="50">50</option>'+
11573
			 *            '<option value="-1">All</option>'+
11574
			 *            '</select> records'
11575
			 *        }
11576
			 *      } );
11577
			 *    } );
11578
			 */
11579
			"sLengthMenu": "Show _MENU_ entries",
11580
	
11581
	
11582
			/**
11583
			 * When using Ajax sourced data and during the first draw when DataTables is
11584
			 * gathering the data, this message is shown in an empty row in the table to
11585
			 * indicate to the end user the the data is being loaded. Note that this
11586
			 * parameter is not used when loading data by server-side processing, just
11587
			 * Ajax sourced data with client-side processing.
11588
			 *  @type string
11589
			 *  @default Loading...
11590
			 *
11591
			 *  @dtopt Language
11592
			 *  @name DataTable.defaults.language.loadingRecords
11593
			 *
11594
			 *  @example
11595
			 *    $(document).ready( function() {
11596
			 *      $('#example').dataTable( {
11597
			 *        "language": {
11598
			 *          "loadingRecords": "Please wait - loading..."
11599
			 *        }
11600
			 *      } );
11601
			 *    } );
11602
			 */
11603
			"sLoadingRecords": "Loading...",
11604
	
11605
	
11606
			/**
11607
			 * Text which is displayed when the table is processing a user action
11608
			 * (usually a sort command or similar).
11609
			 *  @type string
11610
			 *  @default Processing...
11611
			 *
11612
			 *  @dtopt Language
11613
			 *  @name DataTable.defaults.language.processing
11614
			 *
11615
			 *  @example
11616
			 *    $(document).ready( function() {
11617
			 *      $('#example').dataTable( {
11618
			 *        "language": {
11619
			 *          "processing": "DataTables is currently busy"
11620
			 *        }
11621
			 *      } );
11622
			 *    } );
11623
			 */
11624
			"sProcessing": "Processing...",
11625
	
11626
	
11627
			/**
11628
			 * Details the actions that will be taken when the user types into the
11629
			 * filtering input text box. The variable "_INPUT_", if used in the string,
11630
			 * is replaced with the HTML text box for the filtering input allowing
11631
			 * control over where it appears in the string. If "_INPUT_" is not given
11632
			 * then the input box is appended to the string automatically.
11633
			 *  @type string
11634
			 *  @default Search:
11635
			 *
11636
			 *  @dtopt Language
11637
			 *  @name DataTable.defaults.language.search
11638
			 *
11639
			 *  @example
11640
			 *    // Input text box will be appended at the end automatically
11641
			 *    $(document).ready( function() {
11642
			 *      $('#example').dataTable( {
11643
			 *        "language": {
11644
			 *          "search": "Filter records:"
11645
			 *        }
11646
			 *      } );
11647
			 *    } );
11648
			 *
11649
			 *  @example
11650
			 *    // Specify where the filter should appear
11651
			 *    $(document).ready( function() {
11652
			 *      $('#example').dataTable( {
11653
			 *        "language": {
11654
			 *          "search": "Apply filter _INPUT_ to table"
11655
			 *        }
11656
			 *      } );
11657
			 *    } );
11658
			 */
11659
			"sSearch": "Search:",
11660
	
11661
	
11662
			/**
11663
			 * Assign a `placeholder` attribute to the search `input` element
11664
			 *  @type string
11665
			 *  @default 
11666
			 *
11667
			 *  @dtopt Language
11668
			 *  @name DataTable.defaults.language.searchPlaceholder
11669
			 */
11670
			"sSearchPlaceholder": "",
11671
	
11672
	
11673
			/**
11674
			 * All of the language information can be stored in a file on the
11675
			 * server-side, which DataTables will look up if this parameter is passed.
11676
			 * It must store the URL of the language file, which is in a JSON format,
11677
			 * and the object has the same properties as the oLanguage object in the
11678
			 * initialiser object (i.e. the above parameters). Please refer to one of
11679
			 * the example language files to see how this works in action.
11680
			 *  @type string
11681
			 *  @default <i>Empty string - i.e. disabled</i>
11682
			 *
11683
			 *  @dtopt Language
11684
			 *  @name DataTable.defaults.language.url
11685
			 *
11686
			 *  @example
11687
			 *    $(document).ready( function() {
11688
			 *      $('#example').dataTable( {
11689
			 *        "language": {
11690
			 *          "url": "http://www.sprymedia.co.uk/dataTables/lang.txt"
11691
			 *        }
11692
			 *      } );
11693
			 *    } );
11694
			 */
11695
			"sUrl": "",
11696
	
11697
	
11698
			/**
11699
			 * Text shown inside the table records when the is no information to be
11700
			 * displayed after filtering. `emptyTable` is shown when there is simply no
11701
			 * information in the table at all (regardless of filtering).
11702
			 *  @type string
11703
			 *  @default No matching records found
11704
			 *
11705
			 *  @dtopt Language
11706
			 *  @name DataTable.defaults.language.zeroRecords
11707
			 *
11708
			 *  @example
11709
			 *    $(document).ready( function() {
11710
			 *      $('#example').dataTable( {
11711
			 *        "language": {
11712
			 *          "zeroRecords": "No records to display"
11713
			 *        }
11714
			 *      } );
11715
			 *    } );
11716
			 */
11717
			"sZeroRecords": "No matching records found"
11718
		},
11719
	
11720
	
11721
		/**
11722
		 * This parameter allows you to have define the global filtering state at
11723
		 * initialisation time. As an object the `search` parameter must be
11724
		 * defined, but all other parameters are optional. When `regex` is true,
11725
		 * the search string will be treated as a regular expression, when false
11726
		 * (default) it will be treated as a straight string. When `smart`
11727
		 * DataTables will use it's smart filtering methods (to word match at
11728
		 * any point in the data), when false this will not be done.
11729
		 *  @namespace
11730
		 *  @extends DataTable.models.oSearch
11731
		 *
11732
		 *  @dtopt Options
11733
		 *  @name DataTable.defaults.search
11734
		 *
11735
		 *  @example
11736
		 *    $(document).ready( function() {
11737
		 *      $('#example').dataTable( {
11738
		 *        "search": {"search": "Initial search"}
11739
		 *      } );
11740
		 *    } )
11741
		 */
11742
		"oSearch": $.extend( {}, DataTable.models.oSearch ),
11743
	
11744
	
11745
		/**
11746
		 * __Deprecated__ The functionality provided by this parameter has now been
11747
		 * superseded by that provided through `ajax`, which should be used instead.
11748
		 *
11749
		 * By default DataTables will look for the property `data` (or `aaData` for
11750
		 * compatibility with DataTables 1.9-) when obtaining data from an Ajax
11751
		 * source or for server-side processing - this parameter allows that
11752
		 * property to be changed. You can use Javascript dotted object notation to
11753
		 * get a data source for multiple levels of nesting.
11754
		 *  @type string
11755
		 *  @default data
11756
		 *
11757
		 *  @dtopt Options
11758
		 *  @dtopt Server-side
11759
		 *  @name DataTable.defaults.ajaxDataProp
11760
		 *
11761
		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11762
		 */
11763
		"sAjaxDataProp": "data",
11764
	
11765
	
11766
		/**
11767
		 * __Deprecated__ The functionality provided by this parameter has now been
11768
		 * superseded by that provided through `ajax`, which should be used instead.
11769
		 *
11770
		 * You can instruct DataTables to load data from an external
11771
		 * source using this parameter (use aData if you want to pass data in you
11772
		 * already have). Simply provide a url a JSON object can be obtained from.
11773
		 *  @type string
11774
		 *  @default null
11775
		 *
11776
		 *  @dtopt Options
11777
		 *  @dtopt Server-side
11778
		 *  @name DataTable.defaults.ajaxSource
11779
		 *
11780
		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11781
		 */
11782
		"sAjaxSource": null,
11783
	
11784
	
11785
		/**
11786
		 * This initialisation variable allows you to specify exactly where in the
11787
		 * DOM you want DataTables to inject the various controls it adds to the page
11788
		 * (for example you might want the pagination controls at the top of the
11789
		 * table). DIV elements (with or without a custom class) can also be added to
11790
		 * aid styling. The follow syntax is used:
11791
		 *   <ul>
11792
		 *     <li>The following options are allowed:
11793
		 *       <ul>
11794
		 *         <li>'l' - Length changing</li>
11795
		 *         <li>'f' - Filtering input</li>
11796
		 *         <li>'t' - The table!</li>
11797
		 *         <li>'i' - Information</li>
11798
		 *         <li>'p' - Pagination</li>
11799
		 *         <li>'r' - pRocessing</li>
11800
		 *       </ul>
11801
		 *     </li>
11802
		 *     <li>The following constants are allowed:
11803
		 *       <ul>
11804
		 *         <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>
11805
		 *         <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>
11806
		 *       </ul>
11807
		 *     </li>
11808
		 *     <li>The following syntax is expected:
11809
		 *       <ul>
11810
		 *         <li>'&lt;' and '&gt;' - div elements</li>
11811
		 *         <li>'&lt;"class" and '&gt;' - div with a class</li>
11812
		 *         <li>'&lt;"#id" and '&gt;' - div with an ID</li>
11813
		 *       </ul>
11814
		 *     </li>
11815
		 *     <li>Examples:
11816
		 *       <ul>
11817
		 *         <li>'&lt;"wrapper"flipt&gt;'</li>
11818
		 *         <li>'&lt;lf&lt;t&gt;ip&gt;'</li>
11819
		 *       </ul>
11820
		 *     </li>
11821
		 *   </ul>
11822
		 *  @type string
11823
		 *  @default lfrtip <i>(when `jQueryUI` is false)</i> <b>or</b>
11824
		 *    <"H"lfr>t<"F"ip> <i>(when `jQueryUI` is true)</i>
11825
		 *
11826
		 *  @dtopt Options
11827
		 *  @name DataTable.defaults.dom
11828
		 *
11829
		 *  @example
11830
		 *    $(document).ready( function() {
11831
		 *      $('#example').dataTable( {
11832
		 *        "dom": '&lt;"top"i&gt;rt&lt;"bottom"flp&gt;&lt;"clear"&gt;'
11833
		 *      } );
11834
		 *    } );
11835
		 */
11836
		"sDom": "lfrtip",
11837
	
11838
	
11839
		/**
11840
		 * Search delay option. This will throttle full table searches that use the
11841
		 * DataTables provided search input element (it does not effect calls to
11842
		 * `dt-api search()`, providing a delay before the search is made.
11843
		 *  @type integer
11844
		 *  @default 0
11845
		 *
11846
		 *  @dtopt Options
11847
		 *  @name DataTable.defaults.searchDelay
11848
		 *
11849
		 *  @example
11850
		 *    $(document).ready( function() {
11851
		 *      $('#example').dataTable( {
11852
		 *        "searchDelay": 200
11853
		 *      } );
11854
		 *    } )
11855
		 */
11856
		"searchDelay": null,
11857
	
11858
	
11859
		/**
11860
		 * DataTables features six different built-in options for the buttons to
11861
		 * display for pagination control:
11862
		 *
11863
		 * * `numbers` - Page number buttons only
11864
		 * * `simple` - 'Previous' and 'Next' buttons only
11865
		 * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers
11866
		 * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons
11867
		 * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus page numbers
11868
		 * * `first_last_numbers` - 'First' and 'Last' buttons, plus page numbers
11869
		 *  
11870
		 * Further methods can be added using {@link DataTable.ext.oPagination}.
11871
		 *  @type string
11872
		 *  @default simple_numbers
11873
		 *
11874
		 *  @dtopt Options
11875
		 *  @name DataTable.defaults.pagingType
11876
		 *
11877
		 *  @example
11878
		 *    $(document).ready( function() {
11879
		 *      $('#example').dataTable( {
11880
		 *        "pagingType": "full_numbers"
11881
		 *      } );
11882
		 *    } )
11883
		 */
11884
		"sPaginationType": "simple_numbers",
11885
	
11886
	
11887
		/**
11888
		 * Enable horizontal scrolling. When a table is too wide to fit into a
11889
		 * certain layout, or you have a large number of columns in the table, you
11890
		 * can enable x-scrolling to show the table in a viewport, which can be
11891
		 * scrolled. This property can be `true` which will allow the table to
11892
		 * scroll horizontally when needed, or any CSS unit, or a number (in which
11893
		 * case it will be treated as a pixel measurement). Setting as simply `true`
11894
		 * is recommended.
11895
		 *  @type boolean|string
11896
		 *  @default <i>blank string - i.e. disabled</i>
11897
		 *
11898
		 *  @dtopt Features
11899
		 *  @name DataTable.defaults.scrollX
11900
		 *
11901
		 *  @example
11902
		 *    $(document).ready( function() {
11903
		 *      $('#example').dataTable( {
11904
		 *        "scrollX": true,
11905
		 *        "scrollCollapse": true
11906
		 *      } );
11907
		 *    } );
11908
		 */
11909
		"sScrollX": "",
11910
	
11911
	
11912
		/**
11913
		 * This property can be used to force a DataTable to use more width than it
11914
		 * might otherwise do when x-scrolling is enabled. For example if you have a
11915
		 * table which requires to be well spaced, this parameter is useful for
11916
		 * "over-sizing" the table, and thus forcing scrolling. This property can by
11917
		 * any CSS unit, or a number (in which case it will be treated as a pixel
11918
		 * measurement).
11919
		 *  @type string
11920
		 *  @default <i>blank string - i.e. disabled</i>
11921
		 *
11922
		 *  @dtopt Options
11923
		 *  @name DataTable.defaults.scrollXInner
11924
		 *
11925
		 *  @example
11926
		 *    $(document).ready( function() {
11927
		 *      $('#example').dataTable( {
11928
		 *        "scrollX": "100%",
11929
		 *        "scrollXInner": "110%"
11930
		 *      } );
11931
		 *    } );
11932
		 */
11933
		"sScrollXInner": "",
11934
	
11935
	
11936
		/**
11937
		 * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
11938
		 * to the given height, and enable scrolling for any data which overflows the
11939
		 * current viewport. This can be used as an alternative to paging to display
11940
		 * a lot of data in a small area (although paging and scrolling can both be
11941
		 * enabled at the same time). This property can be any CSS unit, or a number
11942
		 * (in which case it will be treated as a pixel measurement).
11943
		 *  @type string
11944
		 *  @default <i>blank string - i.e. disabled</i>
11945
		 *
11946
		 *  @dtopt Features
11947
		 *  @name DataTable.defaults.scrollY
11948
		 *
11949
		 *  @example
11950
		 *    $(document).ready( function() {
11951
		 *      $('#example').dataTable( {
11952
		 *        "scrollY": "200px",
11953
		 *        "paginate": false
11954
		 *      } );
11955
		 *    } );
11956
		 */
11957
		"sScrollY": "",
11958
	
11959
	
11960
		/**
11961
		 * __Deprecated__ The functionality provided by this parameter has now been
11962
		 * superseded by that provided through `ajax`, which should be used instead.
11963
		 *
11964
		 * Set the HTTP method that is used to make the Ajax call for server-side
11965
		 * processing or Ajax sourced data.
11966
		 *  @type string
11967
		 *  @default GET
11968
		 *
11969
		 *  @dtopt Options
11970
		 *  @dtopt Server-side
11971
		 *  @name DataTable.defaults.serverMethod
11972
		 *
11973
		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11974
		 */
11975
		"sServerMethod": "GET",
11976
	
11977
	
11978
		/**
11979
		 * DataTables makes use of renderers when displaying HTML elements for
11980
		 * a table. These renderers can be added or modified by plug-ins to
11981
		 * generate suitable mark-up for a site. For example the Bootstrap
11982
		 * integration plug-in for DataTables uses a paging button renderer to
11983
		 * display pagination buttons in the mark-up required by Bootstrap.
11984
		 *
11985
		 * For further information about the renderers available see
11986
		 * DataTable.ext.renderer
11987
		 *  @type string|object
11988
		 *  @default null
11989
		 *
11990
		 *  @name DataTable.defaults.renderer
11991
		 *
11992
		 */
11993
		"renderer": null,
11994
	
11995
	
11996
		/**
11997
		 * Set the data property name that DataTables should use to get a row's id
11998
		 * to set as the `id` property in the node.
11999
		 *  @type string
12000
		 *  @default DT_RowId
12001
		 *
12002
		 *  @name DataTable.defaults.rowId
12003
		 */
12004
		"rowId": "DT_RowId"
12005
	};
12006
	
12007
	_fnHungarianMap( DataTable.defaults );
12008
	
12009
	
12010
	
12011
	/*
12012
	 * Developer note - See note in model.defaults.js about the use of Hungarian
12013
	 * notation and camel case.
12014
	 */
12015
	
12016
	/**
12017
	 * Column options that can be given to DataTables at initialisation time.
12018
	 *  @namespace
12019
	 */
12020
	DataTable.defaults.column = {
12021
		/**
12022
		 * Define which column(s) an order will occur on for this column. This
12023
		 * allows a column's ordering to take multiple columns into account when
12024
		 * doing a sort or use the data from a different column. For example first
12025
		 * name / last name columns make sense to do a multi-column sort over the
12026
		 * two columns.
12027
		 *  @type array|int
12028
		 *  @default null <i>Takes the value of the column index automatically</i>
12029
		 *
12030
		 *  @name DataTable.defaults.column.orderData
12031
		 *  @dtopt Columns
12032
		 *
12033
		 *  @example
12034
		 *    // Using `columnDefs`
12035
		 *    $(document).ready( function() {
12036
		 *      $('#example').dataTable( {
12037
		 *        "columnDefs": [
12038
		 *          { "orderData": [ 0, 1 ], "targets": [ 0 ] },
12039
		 *          { "orderData": [ 1, 0 ], "targets": [ 1 ] },
12040
		 *          { "orderData": 2, "targets": [ 2 ] }
12041
		 *        ]
12042
		 *      } );
12043
		 *    } );
12044
		 *
12045
		 *  @example
12046
		 *    // Using `columns`
12047
		 *    $(document).ready( function() {
12048
		 *      $('#example').dataTable( {
12049
		 *        "columns": [
12050
		 *          { "orderData": [ 0, 1 ] },
12051
		 *          { "orderData": [ 1, 0 ] },
12052
		 *          { "orderData": 2 },
12053
		 *          null,
12054
		 *          null
12055
		 *        ]
12056
		 *      } );
12057
		 *    } );
12058
		 */
12059
		"aDataSort": null,
12060
		"iDataSort": -1,
12061
	
12062
	
12063
		/**
12064
		 * You can control the default ordering direction, and even alter the
12065
		 * behaviour of the sort handler (i.e. only allow ascending ordering etc)
12066
		 * using this parameter.
12067
		 *  @type array
12068
		 *  @default [ 'asc', 'desc' ]
12069
		 *
12070
		 *  @name DataTable.defaults.column.orderSequence
12071
		 *  @dtopt Columns
12072
		 *
12073
		 *  @example
12074
		 *    // Using `columnDefs`
12075
		 *    $(document).ready( function() {
12076
		 *      $('#example').dataTable( {
12077
		 *        "columnDefs": [
12078
		 *          { "orderSequence": [ "asc" ], "targets": [ 1 ] },
12079
		 *          { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] },
12080
		 *          { "orderSequence": [ "desc" ], "targets": [ 3 ] }
12081
		 *        ]
12082
		 *      } );
12083
		 *    } );
12084
		 *
12085
		 *  @example
12086
		 *    // Using `columns`
12087
		 *    $(document).ready( function() {
12088
		 *      $('#example').dataTable( {
12089
		 *        "columns": [
12090
		 *          null,
12091
		 *          { "orderSequence": [ "asc" ] },
12092
		 *          { "orderSequence": [ "desc", "asc", "asc" ] },
12093
		 *          { "orderSequence": [ "desc" ] },
12094
		 *          null
12095
		 *        ]
12096
		 *      } );
12097
		 *    } );
12098
		 */
12099
		"asSorting": [ 'asc', 'desc' ],
12100
	
12101
	
12102
		/**
12103
		 * Enable or disable filtering on the data in this column.
12104
		 *  @type boolean
12105
		 *  @default true
12106
		 *
12107
		 *  @name DataTable.defaults.column.searchable
12108
		 *  @dtopt Columns
12109
		 *
12110
		 *  @example
12111
		 *    // Using `columnDefs`
12112
		 *    $(document).ready( function() {
12113
		 *      $('#example').dataTable( {
12114
		 *        "columnDefs": [
12115
		 *          { "searchable": false, "targets": [ 0 ] }
12116
		 *        ] } );
12117
		 *    } );
12118
		 *
12119
		 *  @example
12120
		 *    // Using `columns`
12121
		 *    $(document).ready( function() {
12122
		 *      $('#example').dataTable( {
12123
		 *        "columns": [
12124
		 *          { "searchable": false },
12125
		 *          null,
12126
		 *          null,
12127
		 *          null,
12128
		 *          null
12129
		 *        ] } );
12130
		 *    } );
12131
		 */
12132
		"bSearchable": true,
12133
	
12134
	
12135
		/**
12136
		 * Enable or disable ordering on this column.
12137
		 *  @type boolean
12138
		 *  @default true
12139
		 *
12140
		 *  @name DataTable.defaults.column.orderable
12141
		 *  @dtopt Columns
12142
		 *
12143
		 *  @example
12144
		 *    // Using `columnDefs`
12145
		 *    $(document).ready( function() {
12146
		 *      $('#example').dataTable( {
12147
		 *        "columnDefs": [
12148
		 *          { "orderable": false, "targets": [ 0 ] }
12149
		 *        ] } );
12150
		 *    } );
12151
		 *
12152
		 *  @example
12153
		 *    // Using `columns`
12154
		 *    $(document).ready( function() {
12155
		 *      $('#example').dataTable( {
12156
		 *        "columns": [
12157
		 *          { "orderable": false },
12158
		 *          null,
12159
		 *          null,
12160
		 *          null,
12161
		 *          null
12162
		 *        ] } );
12163
		 *    } );
12164
		 */
12165
		"bSortable": true,
12166
	
12167
	
12168
		/**
12169
		 * Enable or disable the display of this column.
12170
		 *  @type boolean
12171
		 *  @default true
12172
		 *
12173
		 *  @name DataTable.defaults.column.visible
12174
		 *  @dtopt Columns
12175
		 *
12176
		 *  @example
12177
		 *    // Using `columnDefs`
12178
		 *    $(document).ready( function() {
12179
		 *      $('#example').dataTable( {
12180
		 *        "columnDefs": [
12181
		 *          { "visible": false, "targets": [ 0 ] }
12182
		 *        ] } );
12183
		 *    } );
12184
		 *
12185
		 *  @example
12186
		 *    // Using `columns`
12187
		 *    $(document).ready( function() {
12188
		 *      $('#example').dataTable( {
12189
		 *        "columns": [
12190
		 *          { "visible": false },
12191
		 *          null,
12192
		 *          null,
12193
		 *          null,
12194
		 *          null
12195
		 *        ] } );
12196
		 *    } );
12197
		 */
12198
		"bVisible": true,
12199
	
12200
	
12201
		/**
12202
		 * Developer definable function that is called whenever a cell is created (Ajax source,
12203
		 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
12204
		 * allowing you to modify the DOM element (add background colour for example) when the
12205
		 * element is available.
12206
		 *  @type function
12207
		 *  @param {element} td The TD node that has been created
12208
		 *  @param {*} cellData The Data for the cell
12209
		 *  @param {array|object} rowData The data for the whole row
12210
		 *  @param {int} row The row index for the aoData data store
12211
		 *  @param {int} col The column index for aoColumns
12212
		 *
12213
		 *  @name DataTable.defaults.column.createdCell
12214
		 *  @dtopt Columns
12215
		 *
12216
		 *  @example
12217
		 *    $(document).ready( function() {
12218
		 *      $('#example').dataTable( {
12219
		 *        "columnDefs": [ {
12220
		 *          "targets": [3],
12221
		 *          "createdCell": function (td, cellData, rowData, row, col) {
12222
		 *            if ( cellData == "1.7" ) {
12223
		 *              $(td).css('color', 'blue')
12224
		 *            }
12225
		 *          }
12226
		 *        } ]
12227
		 *      });
12228
		 *    } );
12229
		 */
12230
		"fnCreatedCell": null,
12231
	
12232
	
12233
		/**
12234
		 * This parameter has been replaced by `data` in DataTables to ensure naming
12235
		 * consistency. `dataProp` can still be used, as there is backwards
12236
		 * compatibility in DataTables for this option, but it is strongly
12237
		 * recommended that you use `data` in preference to `dataProp`.
12238
		 *  @name DataTable.defaults.column.dataProp
12239
		 */
12240
	
12241
	
12242
		/**
12243
		 * This property can be used to read data from any data source property,
12244
		 * including deeply nested objects / properties. `data` can be given in a
12245
		 * number of different ways which effect its behaviour:
12246
		 *
12247
		 * * `integer` - treated as an array index for the data source. This is the
12248
		 *   default that DataTables uses (incrementally increased for each column).
12249
		 * * `string` - read an object property from the data source. There are
12250
		 *   three 'special' options that can be used in the string to alter how
12251
		 *   DataTables reads the data from the source object:
12252
		 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
12253
		 *      Javascript to read from nested objects, so to can the options
12254
		 *      specified in `data`. For example: `browser.version` or
12255
		 *      `browser.name`. If your object parameter name contains a period, use
12256
		 *      `\\` to escape it - i.e. `first\\.name`.
12257
		 *    * `[]` - Array notation. DataTables can automatically combine data
12258
		 *      from and array source, joining the data with the characters provided
12259
		 *      between the two brackets. For example: `name[, ]` would provide a
12260
		 *      comma-space separated list from the source array. If no characters
12261
		 *      are provided between the brackets, the original array source is
12262
		 *      returned.
12263
		 *    * `()` - Function notation. Adding `()` to the end of a parameter will
12264
		 *      execute a function of the name given. For example: `browser()` for a
12265
		 *      simple function on the data source, `browser.version()` for a
12266
		 *      function in a nested property or even `browser().version` to get an
12267
		 *      object property if the function called returns an object. Note that
12268
		 *      function notation is recommended for use in `render` rather than
12269
		 *      `data` as it is much simpler to use as a renderer.
12270
		 * * `null` - use the original data source for the row rather than plucking
12271
		 *   data directly from it. This action has effects on two other
12272
		 *   initialisation options:
12273
		 *    * `defaultContent` - When null is given as the `data` option and
12274
		 *      `defaultContent` is specified for the column, the value defined by
12275
		 *      `defaultContent` will be used for the cell.
12276
		 *    * `render` - When null is used for the `data` option and the `render`
12277
		 *      option is specified for the column, the whole data source for the
12278
		 *      row is used for the renderer.
12279
		 * * `function` - the function given will be executed whenever DataTables
12280
		 *   needs to set or get the data for a cell in the column. The function
12281
		 *   takes three parameters:
12282
		 *    * Parameters:
12283
		 *      * `{array|object}` The data source for the row
12284
		 *      * `{string}` The type call data requested - this will be 'set' when
12285
		 *        setting data or 'filter', 'display', 'type', 'sort' or undefined
12286
		 *        when gathering data. Note that when `undefined` is given for the
12287
		 *        type DataTables expects to get the raw data for the object back<
12288
		 *      * `{*}` Data to set when the second parameter is 'set'.
12289
		 *    * Return:
12290
		 *      * The return value from the function is not required when 'set' is
12291
		 *        the type of call, but otherwise the return is what will be used
12292
		 *        for the data requested.
12293
		 *
12294
		 * Note that `data` is a getter and setter option. If you just require
12295
		 * formatting of data for output, you will likely want to use `render` which
12296
		 * is simply a getter and thus simpler to use.
12297
		 *
12298
		 * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The
12299
		 * name change reflects the flexibility of this property and is consistent
12300
		 * with the naming of mRender. If 'mDataProp' is given, then it will still
12301
		 * be used by DataTables, as it automatically maps the old name to the new
12302
		 * if required.
12303
		 *
12304
		 *  @type string|int|function|null
12305
		 *  @default null <i>Use automatically calculated column index</i>
12306
		 *
12307
		 *  @name DataTable.defaults.column.data
12308
		 *  @dtopt Columns
12309
		 *
12310
		 *  @example
12311
		 *    // Read table data from objects
12312
		 *    // JSON structure for each row:
12313
		 *    //   {
12314
		 *    //      "engine": {value},
12315
		 *    //      "browser": {value},
12316
		 *    //      "platform": {value},
12317
		 *    //      "version": {value},
12318
		 *    //      "grade": {value}
12319
		 *    //   }
12320
		 *    $(document).ready( function() {
12321
		 *      $('#example').dataTable( {
12322
		 *        "ajaxSource": "sources/objects.txt",
12323
		 *        "columns": [
12324
		 *          { "data": "engine" },
12325
		 *          { "data": "browser" },
12326
		 *          { "data": "platform" },
12327
		 *          { "data": "version" },
12328
		 *          { "data": "grade" }
12329
		 *        ]
12330
		 *      } );
12331
		 *    } );
12332
		 *
12333
		 *  @example
12334
		 *    // Read information from deeply nested objects
12335
		 *    // JSON structure for each row:
12336
		 *    //   {
12337
		 *    //      "engine": {value},
12338
		 *    //      "browser": {value},
12339
		 *    //      "platform": {
12340
		 *    //         "inner": {value}
12341
		 *    //      },
12342
		 *    //      "details": [
12343
		 *    //         {value}, {value}
12344
		 *    //      ]
12345
		 *    //   }
12346
		 *    $(document).ready( function() {
12347
		 *      $('#example').dataTable( {
12348
		 *        "ajaxSource": "sources/deep.txt",
12349
		 *        "columns": [
12350
		 *          { "data": "engine" },
12351
		 *          { "data": "browser" },
12352
		 *          { "data": "platform.inner" },
12353
		 *          { "data": "platform.details.0" },
12354
		 *          { "data": "platform.details.1" }
12355
		 *        ]
12356
		 *      } );
12357
		 *    } );
12358
		 *
12359
		 *  @example
12360
		 *    // Using `data` as a function to provide different information for
12361
		 *    // sorting, filtering and display. In this case, currency (price)
12362
		 *    $(document).ready( function() {
12363
		 *      $('#example').dataTable( {
12364
		 *        "columnDefs": [ {
12365
		 *          "targets": [ 0 ],
12366
		 *          "data": function ( source, type, val ) {
12367
		 *            if (type === 'set') {
12368
		 *              source.price = val;
12369
		 *              // Store the computed dislay and filter values for efficiency
12370
		 *              source.price_display = val=="" ? "" : "$"+numberFormat(val);
12371
		 *              source.price_filter  = val=="" ? "" : "$"+numberFormat(val)+" "+val;
12372
		 *              return;
12373
		 *            }
12374
		 *            else if (type === 'display') {
12375
		 *              return source.price_display;
12376
		 *            }
12377
		 *            else if (type === 'filter') {
12378
		 *              return source.price_filter;
12379
		 *            }
12380
		 *            // 'sort', 'type' and undefined all just use the integer
12381
		 *            return source.price;
12382
		 *          }
12383
		 *        } ]
12384
		 *      } );
12385
		 *    } );
12386
		 *
12387
		 *  @example
12388
		 *    // Using default content
12389
		 *    $(document).ready( function() {
12390
		 *      $('#example').dataTable( {
12391
		 *        "columnDefs": [ {
12392
		 *          "targets": [ 0 ],
12393
		 *          "data": null,
12394
		 *          "defaultContent": "Click to edit"
12395
		 *        } ]
12396
		 *      } );
12397
		 *    } );
12398
		 *
12399
		 *  @example
12400
		 *    // Using array notation - outputting a list from an array
12401
		 *    $(document).ready( function() {
12402
		 *      $('#example').dataTable( {
12403
		 *        "columnDefs": [ {
12404
		 *          "targets": [ 0 ],
12405
		 *          "data": "name[, ]"
12406
		 *        } ]
12407
		 *      } );
12408
		 *    } );
12409
		 *
12410
		 */
12411
		"mData": null,
12412
	
12413
	
12414
		/**
12415
		 * This property is the rendering partner to `data` and it is suggested that
12416
		 * when you want to manipulate data for display (including filtering,
12417
		 * sorting etc) without altering the underlying data for the table, use this
12418
		 * property. `render` can be considered to be the the read only companion to
12419
		 * `data` which is read / write (then as such more complex). Like `data`
12420
		 * this option can be given in a number of different ways to effect its
12421
		 * behaviour:
12422
		 *
12423
		 * * `integer` - treated as an array index for the data source. This is the
12424
		 *   default that DataTables uses (incrementally increased for each column).
12425
		 * * `string` - read an object property from the data source. There are
12426
		 *   three 'special' options that can be used in the string to alter how
12427
		 *   DataTables reads the data from the source object:
12428
		 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
12429
		 *      Javascript to read from nested objects, so to can the options
12430
		 *      specified in `data`. For example: `browser.version` or
12431
		 *      `browser.name`. If your object parameter name contains a period, use
12432
		 *      `\\` to escape it - i.e. `first\\.name`.
12433
		 *    * `[]` - Array notation. DataTables can automatically combine data
12434
		 *      from and array source, joining the data with the characters provided
12435
		 *      between the two brackets. For example: `name[, ]` would provide a
12436
		 *      comma-space separated list from the source array. If no characters
12437
		 *      are provided between the brackets, the original array source is
12438
		 *      returned.
12439
		 *    * `()` - Function notation. Adding `()` to the end of a parameter will
12440
		 *      execute a function of the name given. For example: `browser()` for a
12441
		 *      simple function on the data source, `browser.version()` for a
12442
		 *      function in a nested property or even `browser().version` to get an
12443
		 *      object property if the function called returns an object.
12444
		 * * `object` - use different data for the different data types requested by
12445
		 *   DataTables ('filter', 'display', 'type' or 'sort'). The property names
12446
		 *   of the object is the data type the property refers to and the value can
12447
		 *   defined using an integer, string or function using the same rules as
12448
		 *   `render` normally does. Note that an `_` option _must_ be specified.
12449
		 *   This is the default value to use if you haven't specified a value for
12450
		 *   the data type requested by DataTables.
12451
		 * * `function` - the function given will be executed whenever DataTables
12452
		 *   needs to set or get the data for a cell in the column. The function
12453
		 *   takes three parameters:
12454
		 *    * Parameters:
12455
		 *      * {array|object} The data source for the row (based on `data`)
12456
		 *      * {string} The type call data requested - this will be 'filter',
12457
		 *        'display', 'type' or 'sort'.
12458
		 *      * {array|object} The full data source for the row (not based on
12459
		 *        `data`)
12460
		 *    * Return:
12461
		 *      * The return value from the function is what will be used for the
12462
		 *        data requested.
12463
		 *
12464
		 *  @type string|int|function|object|null
12465
		 *  @default null Use the data source value.
12466
		 *
12467
		 *  @name DataTable.defaults.column.render
12468
		 *  @dtopt Columns
12469
		 *
12470
		 *  @example
12471
		 *    // Create a comma separated list from an array of objects
12472
		 *    $(document).ready( function() {
12473
		 *      $('#example').dataTable( {
12474
		 *        "ajaxSource": "sources/deep.txt",
12475
		 *        "columns": [
12476
		 *          { "data": "engine" },
12477
		 *          { "data": "browser" },
12478
		 *          {
12479
		 *            "data": "platform",
12480
		 *            "render": "[, ].name"
12481
		 *          }
12482
		 *        ]
12483
		 *      } );
12484
		 *    } );
12485
		 *
12486
		 *  @example
12487
		 *    // Execute a function to obtain data
12488
		 *    $(document).ready( function() {
12489
		 *      $('#example').dataTable( {
12490
		 *        "columnDefs": [ {
12491
		 *          "targets": [ 0 ],
12492
		 *          "data": null, // Use the full data source object for the renderer's source
12493
		 *          "render": "browserName()"
12494
		 *        } ]
12495
		 *      } );
12496
		 *    } );
12497
		 *
12498
		 *  @example
12499
		 *    // As an object, extracting different data for the different types
12500
		 *    // This would be used with a data source such as:
12501
		 *    //   { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" }
12502
		 *    // Here the `phone` integer is used for sorting and type detection, while `phone_filter`
12503
		 *    // (which has both forms) is used for filtering for if a user inputs either format, while
12504
		 *    // the formatted phone number is the one that is shown in the table.
12505
		 *    $(document).ready( function() {
12506
		 *      $('#example').dataTable( {
12507
		 *        "columnDefs": [ {
12508
		 *          "targets": [ 0 ],
12509
		 *          "data": null, // Use the full data source object for the renderer's source
12510
		 *          "render": {
12511
		 *            "_": "phone",
12512
		 *            "filter": "phone_filter",
12513
		 *            "display": "phone_display"
12514
		 *          }
12515
		 *        } ]
12516
		 *      } );
12517
		 *    } );
12518
		 *
12519
		 *  @example
12520
		 *    // Use as a function to create a link from the data source
12521
		 *    $(document).ready( function() {
12522
		 *      $('#example').dataTable( {
12523
		 *        "columnDefs": [ {
12524
		 *          "targets": [ 0 ],
12525
		 *          "data": "download_link",
12526
		 *          "render": function ( data, type, full ) {
12527
		 *            return '<a href="'+data+'">Download</a>';
12528
		 *          }
12529
		 *        } ]
12530
		 *      } );
12531
		 *    } );
12532
		 */
12533
		"mRender": null,
12534
	
12535
	
12536
		/**
12537
		 * Change the cell type created for the column - either TD cells or TH cells. This
12538
		 * can be useful as TH cells have semantic meaning in the table body, allowing them
12539
		 * to act as a header for a row (you may wish to add scope='row' to the TH elements).
12540
		 *  @type string
12541
		 *  @default td
12542
		 *
12543
		 *  @name DataTable.defaults.column.cellType
12544
		 *  @dtopt Columns
12545
		 *
12546
		 *  @example
12547
		 *    // Make the first column use TH cells
12548
		 *    $(document).ready( function() {
12549
		 *      $('#example').dataTable( {
12550
		 *        "columnDefs": [ {
12551
		 *          "targets": [ 0 ],
12552
		 *          "cellType": "th"
12553
		 *        } ]
12554
		 *      } );
12555
		 *    } );
12556
		 */
12557
		"sCellType": "td",
12558
	
12559
	
12560
		/**
12561
		 * Class to give to each cell in this column.
12562
		 *  @type string
12563
		 *  @default <i>Empty string</i>
12564
		 *
12565
		 *  @name DataTable.defaults.column.class
12566
		 *  @dtopt Columns
12567
		 *
12568
		 *  @example
12569
		 *    // Using `columnDefs`
12570
		 *    $(document).ready( function() {
12571
		 *      $('#example').dataTable( {
12572
		 *        "columnDefs": [
12573
		 *          { "class": "my_class", "targets": [ 0 ] }
12574
		 *        ]
12575
		 *      } );
12576
		 *    } );
12577
		 *
12578
		 *  @example
12579
		 *    // Using `columns`
12580
		 *    $(document).ready( function() {
12581
		 *      $('#example').dataTable( {
12582
		 *        "columns": [
12583
		 *          { "class": "my_class" },
12584
		 *          null,
12585
		 *          null,
12586
		 *          null,
12587
		 *          null
12588
		 *        ]
12589
		 *      } );
12590
		 *    } );
12591
		 */
12592
		"sClass": "",
12593
	
12594
		/**
12595
		 * When DataTables calculates the column widths to assign to each column,
12596
		 * it finds the longest string in each column and then constructs a
12597
		 * temporary table and reads the widths from that. The problem with this
12598
		 * is that "mmm" is much wider then "iiii", but the latter is a longer
12599
		 * string - thus the calculation can go wrong (doing it properly and putting
12600
		 * it into an DOM object and measuring that is horribly(!) slow). Thus as
12601
		 * a "work around" we provide this option. It will append its value to the
12602
		 * text that is found to be the longest string for the column - i.e. padding.
12603
		 * Generally you shouldn't need this!
12604
		 *  @type string
12605
		 *  @default <i>Empty string<i>
12606
		 *
12607
		 *  @name DataTable.defaults.column.contentPadding
12608
		 *  @dtopt Columns
12609
		 *
12610
		 *  @example
12611
		 *    // Using `columns`
12612
		 *    $(document).ready( function() {
12613
		 *      $('#example').dataTable( {
12614
		 *        "columns": [
12615
		 *          null,
12616
		 *          null,
12617
		 *          null,
12618
		 *          {
12619
		 *            "contentPadding": "mmm"
12620
		 *          }
12621
		 *        ]
12622
		 *      } );
12623
		 *    } );
12624
		 */
12625
		"sContentPadding": "",
12626
	
12627
	
12628
		/**
12629
		 * Allows a default value to be given for a column's data, and will be used
12630
		 * whenever a null data source is encountered (this can be because `data`
12631
		 * is set to null, or because the data source itself is null).
12632
		 *  @type string
12633
		 *  @default null
12634
		 *
12635
		 *  @name DataTable.defaults.column.defaultContent
12636
		 *  @dtopt Columns
12637
		 *
12638
		 *  @example
12639
		 *    // Using `columnDefs`
12640
		 *    $(document).ready( function() {
12641
		 *      $('#example').dataTable( {
12642
		 *        "columnDefs": [
12643
		 *          {
12644
		 *            "data": null,
12645
		 *            "defaultContent": "Edit",
12646
		 *            "targets": [ -1 ]
12647
		 *          }
12648
		 *        ]
12649
		 *      } );
12650
		 *    } );
12651
		 *
12652
		 *  @example
12653
		 *    // Using `columns`
12654
		 *    $(document).ready( function() {
12655
		 *      $('#example').dataTable( {
12656
		 *        "columns": [
12657
		 *          null,
12658
		 *          null,
12659
		 *          null,
12660
		 *          {
12661
		 *            "data": null,
12662
		 *            "defaultContent": "Edit"
12663
		 *          }
12664
		 *        ]
12665
		 *      } );
12666
		 *    } );
12667
		 */
12668
		"sDefaultContent": null,
12669
	
12670
	
12671
		/**
12672
		 * This parameter is only used in DataTables' server-side processing. It can
12673
		 * be exceptionally useful to know what columns are being displayed on the
12674
		 * client side, and to map these to database fields. When defined, the names
12675
		 * also allow DataTables to reorder information from the server if it comes
12676
		 * back in an unexpected order (i.e. if you switch your columns around on the
12677
		 * client-side, your server-side code does not also need updating).
12678
		 *  @type string
12679
		 *  @default <i>Empty string</i>
12680
		 *
12681
		 *  @name DataTable.defaults.column.name
12682
		 *  @dtopt Columns
12683
		 *
12684
		 *  @example
12685
		 *    // Using `columnDefs`
12686
		 *    $(document).ready( function() {
12687
		 *      $('#example').dataTable( {
12688
		 *        "columnDefs": [
12689
		 *          { "name": "engine", "targets": [ 0 ] },
12690
		 *          { "name": "browser", "targets": [ 1 ] },
12691
		 *          { "name": "platform", "targets": [ 2 ] },
12692
		 *          { "name": "version", "targets": [ 3 ] },
12693
		 *          { "name": "grade", "targets": [ 4 ] }
12694
		 *        ]
12695
		 *      } );
12696
		 *    } );
12697
		 *
12698
		 *  @example
12699
		 *    // Using `columns`
12700
		 *    $(document).ready( function() {
12701
		 *      $('#example').dataTable( {
12702
		 *        "columns": [
12703
		 *          { "name": "engine" },
12704
		 *          { "name": "browser" },
12705
		 *          { "name": "platform" },
12706
		 *          { "name": "version" },
12707
		 *          { "name": "grade" }
12708
		 *        ]
12709
		 *      } );
12710
		 *    } );
12711
		 */
12712
		"sName": "",
12713
	
12714
	
12715
		/**
12716
		 * Defines a data source type for the ordering which can be used to read
12717
		 * real-time information from the table (updating the internally cached
12718
		 * version) prior to ordering. This allows ordering to occur on user
12719
		 * editable elements such as form inputs.
12720
		 *  @type string
12721
		 *  @default std
12722
		 *
12723
		 *  @name DataTable.defaults.column.orderDataType
12724
		 *  @dtopt Columns
12725
		 *
12726
		 *  @example
12727
		 *    // Using `columnDefs`
12728
		 *    $(document).ready( function() {
12729
		 *      $('#example').dataTable( {
12730
		 *        "columnDefs": [
12731
		 *          { "orderDataType": "dom-text", "targets": [ 2, 3 ] },
12732
		 *          { "type": "numeric", "targets": [ 3 ] },
12733
		 *          { "orderDataType": "dom-select", "targets": [ 4 ] },
12734
		 *          { "orderDataType": "dom-checkbox", "targets": [ 5 ] }
12735
		 *        ]
12736
		 *      } );
12737
		 *    } );
12738
		 *
12739
		 *  @example
12740
		 *    // Using `columns`
12741
		 *    $(document).ready( function() {
12742
		 *      $('#example').dataTable( {
12743
		 *        "columns": [
12744
		 *          null,
12745
		 *          null,
12746
		 *          { "orderDataType": "dom-text" },
12747
		 *          { "orderDataType": "dom-text", "type": "numeric" },
12748
		 *          { "orderDataType": "dom-select" },
12749
		 *          { "orderDataType": "dom-checkbox" }
12750
		 *        ]
12751
		 *      } );
12752
		 *    } );
12753
		 */
12754
		"sSortDataType": "std",
12755
	
12756
	
12757
		/**
12758
		 * The title of this column.
12759
		 *  @type string
12760
		 *  @default null <i>Derived from the 'TH' value for this column in the
12761
		 *    original HTML table.</i>
12762
		 *
12763
		 *  @name DataTable.defaults.column.title
12764
		 *  @dtopt Columns
12765
		 *
12766
		 *  @example
12767
		 *    // Using `columnDefs`
12768
		 *    $(document).ready( function() {
12769
		 *      $('#example').dataTable( {
12770
		 *        "columnDefs": [
12771
		 *          { "title": "My column title", "targets": [ 0 ] }
12772
		 *        ]
12773
		 *      } );
12774
		 *    } );
12775
		 *
12776
		 *  @example
12777
		 *    // Using `columns`
12778
		 *    $(document).ready( function() {
12779
		 *      $('#example').dataTable( {
12780
		 *        "columns": [
12781
		 *          { "title": "My column title" },
12782
		 *          null,
12783
		 *          null,
12784
		 *          null,
12785
		 *          null
12786
		 *        ]
12787
		 *      } );
12788
		 *    } );
12789
		 */
12790
		"sTitle": null,
12791
	
12792
	
12793
		/**
12794
		 * The type allows you to specify how the data for this column will be
12795
		 * ordered. Four types (string, numeric, date and html (which will strip
12796
		 * HTML tags before ordering)) are currently available. Note that only date
12797
		 * formats understood by Javascript's Date() object will be accepted as type
12798
		 * date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string',
12799
		 * 'numeric', 'date' or 'html' (by default). Further types can be adding
12800
		 * through plug-ins.
12801
		 *  @type string
12802
		 *  @default null <i>Auto-detected from raw data</i>
12803
		 *
12804
		 *  @name DataTable.defaults.column.type
12805
		 *  @dtopt Columns
12806
		 *
12807
		 *  @example
12808
		 *    // Using `columnDefs`
12809
		 *    $(document).ready( function() {
12810
		 *      $('#example').dataTable( {
12811
		 *        "columnDefs": [
12812
		 *          { "type": "html", "targets": [ 0 ] }
12813
		 *        ]
12814
		 *      } );
12815
		 *    } );
12816
		 *
12817
		 *  @example
12818
		 *    // Using `columns`
12819
		 *    $(document).ready( function() {
12820
		 *      $('#example').dataTable( {
12821
		 *        "columns": [
12822
		 *          { "type": "html" },
12823
		 *          null,
12824
		 *          null,
12825
		 *          null,
12826
		 *          null
12827
		 *        ]
12828
		 *      } );
12829
		 *    } );
12830
		 */
12831
		"sType": null,
12832
	
12833
	
12834
		/**
12835
		 * Defining the width of the column, this parameter may take any CSS value
12836
		 * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not
12837
		 * been given a specific width through this interface ensuring that the table
12838
		 * remains readable.
12839
		 *  @type string
12840
		 *  @default null <i>Automatic</i>
12841
		 *
12842
		 *  @name DataTable.defaults.column.width
12843
		 *  @dtopt Columns
12844
		 *
12845
		 *  @example
12846
		 *    // Using `columnDefs`
12847
		 *    $(document).ready( function() {
12848
		 *      $('#example').dataTable( {
12849
		 *        "columnDefs": [
12850
		 *          { "width": "20%", "targets": [ 0 ] }
12851
		 *        ]
12852
		 *      } );
12853
		 *    } );
12854
		 *
12855
		 *  @example
12856
		 *    // Using `columns`
12857
		 *    $(document).ready( function() {
12858
		 *      $('#example').dataTable( {
12859
		 *        "columns": [
12860
		 *          { "width": "20%" },
12861
		 *          null,
12862
		 *          null,
12863
		 *          null,
12864
		 *          null
12865
		 *        ]
12866
		 *      } );
12867
		 *    } );
12868
		 */
12869
		"sWidth": null
12870
	};
12871
	
12872
	_fnHungarianMap( DataTable.defaults.column );
12873
	
12874
	
12875
	
12876
	/**
12877
	 * DataTables settings object - this holds all the information needed for a
12878
	 * given table, including configuration, data and current application of the
12879
	 * table options. DataTables does not have a single instance for each DataTable
12880
	 * with the settings attached to that instance, but rather instances of the
12881
	 * DataTable "class" are created on-the-fly as needed (typically by a
12882
	 * $().dataTable() call) and the settings object is then applied to that
12883
	 * instance.
12884
	 *
12885
	 * Note that this object is related to {@link DataTable.defaults} but this
12886
	 * one is the internal data store for DataTables's cache of columns. It should
12887
	 * NOT be manipulated outside of DataTables. Any configuration should be done
12888
	 * through the initialisation options.
12889
	 *  @namespace
12890
	 *  @todo Really should attach the settings object to individual instances so we
12891
	 *    don't need to create new instances on each $().dataTable() call (if the
12892
	 *    table already exists). It would also save passing oSettings around and
12893
	 *    into every single function. However, this is a very significant
12894
	 *    architecture change for DataTables and will almost certainly break
12895
	 *    backwards compatibility with older installations. This is something that
12896
	 *    will be done in 2.0.
12897
	 */
12898
	DataTable.models.oSettings = {
12899
		/**
12900
		 * Primary features of DataTables and their enablement state.
12901
		 *  @namespace
12902
		 */
12903
		"oFeatures": {
12904
	
12905
			/**
12906
			 * Flag to say if DataTables should automatically try to calculate the
12907
			 * optimum table and columns widths (true) or not (false).
12908
			 * Note that this parameter will be set by the initialisation routine. To
12909
			 * set a default use {@link DataTable.defaults}.
12910
			 *  @type boolean
12911
			 */
12912
			"bAutoWidth": null,
12913
	
12914
			/**
12915
			 * Delay the creation of TR and TD elements until they are actually
12916
			 * needed by a driven page draw. This can give a significant speed
12917
			 * increase for Ajax source and Javascript source data, but makes no
12918
			 * difference at all fro DOM and server-side processing tables.
12919
			 * Note that this parameter will be set by the initialisation routine. To
12920
			 * set a default use {@link DataTable.defaults}.
12921
			 *  @type boolean
12922
			 */
12923
			"bDeferRender": null,
12924
	
12925
			/**
12926
			 * Enable filtering on the table or not. Note that if this is disabled
12927
			 * then there is no filtering at all on the table, including fnFilter.
12928
			 * To just remove the filtering input use sDom and remove the 'f' option.
12929
			 * Note that this parameter will be set by the initialisation routine. To
12930
			 * set a default use {@link DataTable.defaults}.
12931
			 *  @type boolean
12932
			 */
12933
			"bFilter": null,
12934
	
12935
			/**
12936
			 * Table information element (the 'Showing x of y records' div) enable
12937
			 * flag.
12938
			 * Note that this parameter will be set by the initialisation routine. To
12939
			 * set a default use {@link DataTable.defaults}.
12940
			 *  @type boolean
12941
			 */
12942
			"bInfo": null,
12943
	
12944
			/**
12945
			 * Present a user control allowing the end user to change the page size
12946
			 * when pagination is enabled.
12947
			 * Note that this parameter will be set by the initialisation routine. To
12948
			 * set a default use {@link DataTable.defaults}.
12949
			 *  @type boolean
12950
			 */
12951
			"bLengthChange": null,
12952
	
12953
			/**
12954
			 * Pagination enabled or not. Note that if this is disabled then length
12955
			 * changing must also be disabled.
12956
			 * Note that this parameter will be set by the initialisation routine. To
12957
			 * set a default use {@link DataTable.defaults}.
12958
			 *  @type boolean
12959
			 */
12960
			"bPaginate": null,
12961
	
12962
			/**
12963
			 * Processing indicator enable flag whenever DataTables is enacting a
12964
			 * user request - typically an Ajax request for server-side processing.
12965
			 * Note that this parameter will be set by the initialisation routine. To
12966
			 * set a default use {@link DataTable.defaults}.
12967
			 *  @type boolean
12968
			 */
12969
			"bProcessing": null,
12970
	
12971
			/**
12972
			 * Server-side processing enabled flag - when enabled DataTables will
12973
			 * get all data from the server for every draw - there is no filtering,
12974
			 * sorting or paging done on the client-side.
12975
			 * Note that this parameter will be set by the initialisation routine. To
12976
			 * set a default use {@link DataTable.defaults}.
12977
			 *  @type boolean
12978
			 */
12979
			"bServerSide": null,
12980
	
12981
			/**
12982
			 * Sorting enablement flag.
12983
			 * Note that this parameter will be set by the initialisation routine. To
12984
			 * set a default use {@link DataTable.defaults}.
12985
			 *  @type boolean
12986
			 */
12987
			"bSort": null,
12988
	
12989
			/**
12990
			 * Multi-column sorting
12991
			 * Note that this parameter will be set by the initialisation routine. To
12992
			 * set a default use {@link DataTable.defaults}.
12993
			 *  @type boolean
12994
			 */
12995
			"bSortMulti": null,
12996
	
12997
			/**
12998
			 * Apply a class to the columns which are being sorted to provide a
12999
			 * visual highlight or not. This can slow things down when enabled since
13000
			 * there is a lot of DOM interaction.
13001
			 * Note that this parameter will be set by the initialisation routine. To
13002
			 * set a default use {@link DataTable.defaults}.
13003
			 *  @type boolean
13004
			 */
13005
			"bSortClasses": null,
13006
	
13007
			/**
13008
			 * State saving enablement flag.
13009
			 * Note that this parameter will be set by the initialisation routine. To
13010
			 * set a default use {@link DataTable.defaults}.
13011
			 *  @type boolean
13012
			 */
13013
			"bStateSave": null
13014
		},
13015
	
13016
	
13017
		/**
13018
		 * Scrolling settings for a table.
13019
		 *  @namespace
13020
		 */
13021
		"oScroll": {
13022
			/**
13023
			 * When the table is shorter in height than sScrollY, collapse the
13024
			 * table container down to the height of the table (when true).
13025
			 * Note that this parameter will be set by the initialisation routine. To
13026
			 * set a default use {@link DataTable.defaults}.
13027
			 *  @type boolean
13028
			 */
13029
			"bCollapse": null,
13030
	
13031
			/**
13032
			 * Width of the scrollbar for the web-browser's platform. Calculated
13033
			 * during table initialisation.
13034
			 *  @type int
13035
			 *  @default 0
13036
			 */
13037
			"iBarWidth": 0,
13038
	
13039
			/**
13040
			 * Viewport width for horizontal scrolling. Horizontal scrolling is
13041
			 * disabled if an empty string.
13042
			 * Note that this parameter will be set by the initialisation routine. To
13043
			 * set a default use {@link DataTable.defaults}.
13044
			 *  @type string
13045
			 */
13046
			"sX": null,
13047
	
13048
			/**
13049
			 * Width to expand the table to when using x-scrolling. Typically you
13050
			 * should not need to use this.
13051
			 * Note that this parameter will be set by the initialisation routine. To
13052
			 * set a default use {@link DataTable.defaults}.
13053
			 *  @type string
13054
			 *  @deprecated
13055
			 */
13056
			"sXInner": null,
13057
	
13058
			/**
13059
			 * Viewport height for vertical scrolling. Vertical scrolling is disabled
13060
			 * if an empty string.
13061
			 * Note that this parameter will be set by the initialisation routine. To
13062
			 * set a default use {@link DataTable.defaults}.
13063
			 *  @type string
13064
			 */
13065
			"sY": null
13066
		},
13067
	
13068
		/**
13069
		 * Language information for the table.
13070
		 *  @namespace
13071
		 *  @extends DataTable.defaults.oLanguage
13072
		 */
13073
		"oLanguage": {
13074
			/**
13075
			 * Information callback function. See
13076
			 * {@link DataTable.defaults.fnInfoCallback}
13077
			 *  @type function
13078
			 *  @default null
13079
			 */
13080
			"fnInfoCallback": null
13081
		},
13082
	
13083
		/**
13084
		 * Browser support parameters
13085
		 *  @namespace
13086
		 */
13087
		"oBrowser": {
13088
			/**
13089
			 * Indicate if the browser incorrectly calculates width:100% inside a
13090
			 * scrolling element (IE6/7)
13091
			 *  @type boolean
13092
			 *  @default false
13093
			 */
13094
			"bScrollOversize": false,
13095
	
13096
			/**
13097
			 * Determine if the vertical scrollbar is on the right or left of the
13098
			 * scrolling container - needed for rtl language layout, although not
13099
			 * all browsers move the scrollbar (Safari).
13100
			 *  @type boolean
13101
			 *  @default false
13102
			 */
13103
			"bScrollbarLeft": false,
13104
	
13105
			/**
13106
			 * Flag for if `getBoundingClientRect` is fully supported or not
13107
			 *  @type boolean
13108
			 *  @default false
13109
			 */
13110
			"bBounding": false,
13111
	
13112
			/**
13113
			 * Browser scrollbar width
13114
			 *  @type integer
13115
			 *  @default 0
13116
			 */
13117
			"barWidth": 0
13118
		},
13119
	
13120
	
13121
		"ajax": null,
13122
	
13123
	
13124
		/**
13125
		 * Array referencing the nodes which are used for the features. The
13126
		 * parameters of this object match what is allowed by sDom - i.e.
13127
		 *   <ul>
13128
		 *     <li>'l' - Length changing</li>
13129
		 *     <li>'f' - Filtering input</li>
13130
		 *     <li>'t' - The table!</li>
13131
		 *     <li>'i' - Information</li>
13132
		 *     <li>'p' - Pagination</li>
13133
		 *     <li>'r' - pRocessing</li>
13134
		 *   </ul>
13135
		 *  @type array
13136
		 *  @default []
13137
		 */
13138
		"aanFeatures": [],
13139
	
13140
		/**
13141
		 * Store data information - see {@link DataTable.models.oRow} for detailed
13142
		 * information.
13143
		 *  @type array
13144
		 *  @default []
13145
		 */
13146
		"aoData": [],
13147
	
13148
		/**
13149
		 * Array of indexes which are in the current display (after filtering etc)
13150
		 *  @type array
13151
		 *  @default []
13152
		 */
13153
		"aiDisplay": [],
13154
	
13155
		/**
13156
		 * Array of indexes for display - no filtering
13157
		 *  @type array
13158
		 *  @default []
13159
		 */
13160
		"aiDisplayMaster": [],
13161
	
13162
		/**
13163
		 * Map of row ids to data indexes
13164
		 *  @type object
13165
		 *  @default {}
13166
		 */
13167
		"aIds": {},
13168
	
13169
		/**
13170
		 * Store information about each column that is in use
13171
		 *  @type array
13172
		 *  @default []
13173
		 */
13174
		"aoColumns": [],
13175
	
13176
		/**
13177
		 * Store information about the table's header
13178
		 *  @type array
13179
		 *  @default []
13180
		 */
13181
		"aoHeader": [],
13182
	
13183
		/**
13184
		 * Store information about the table's footer
13185
		 *  @type array
13186
		 *  @default []
13187
		 */
13188
		"aoFooter": [],
13189
	
13190
		/**
13191
		 * Store the applied global search information in case we want to force a
13192
		 * research or compare the old search to a new one.
13193
		 * Note that this parameter will be set by the initialisation routine. To
13194
		 * set a default use {@link DataTable.defaults}.
13195
		 *  @namespace
13196
		 *  @extends DataTable.models.oSearch
13197
		 */
13198
		"oPreviousSearch": {},
13199
	
13200
		/**
13201
		 * Store the applied search for each column - see
13202
		 * {@link DataTable.models.oSearch} for the format that is used for the
13203
		 * filtering information for each column.
13204
		 *  @type array
13205
		 *  @default []
13206
		 */
13207
		"aoPreSearchCols": [],
13208
	
13209
		/**
13210
		 * Sorting that is applied to the table. Note that the inner arrays are
13211
		 * used in the following manner:
13212
		 * <ul>
13213
		 *   <li>Index 0 - column number</li>
13214
		 *   <li>Index 1 - current sorting direction</li>
13215
		 * </ul>
13216
		 * Note that this parameter will be set by the initialisation routine. To
13217
		 * set a default use {@link DataTable.defaults}.
13218
		 *  @type array
13219
		 *  @todo These inner arrays should really be objects
13220
		 */
13221
		"aaSorting": null,
13222
	
13223
		/**
13224
		 * Sorting that is always applied to the table (i.e. prefixed in front of
13225
		 * aaSorting).
13226
		 * Note that this parameter will be set by the initialisation routine. To
13227
		 * set a default use {@link DataTable.defaults}.
13228
		 *  @type array
13229
		 *  @default []
13230
		 */
13231
		"aaSortingFixed": [],
13232
	
13233
		/**
13234
		 * Classes to use for the striping of a table.
13235
		 * Note that this parameter will be set by the initialisation routine. To
13236
		 * set a default use {@link DataTable.defaults}.
13237
		 *  @type array
13238
		 *  @default []
13239
		 */
13240
		"asStripeClasses": null,
13241
	
13242
		/**
13243
		 * If restoring a table - we should restore its striping classes as well
13244
		 *  @type array
13245
		 *  @default []
13246
		 */
13247
		"asDestroyStripes": [],
13248
	
13249
		/**
13250
		 * If restoring a table - we should restore its width
13251
		 *  @type int
13252
		 *  @default 0
13253
		 */
13254
		"sDestroyWidth": 0,
13255
	
13256
		/**
13257
		 * Callback functions array for every time a row is inserted (i.e. on a draw).
13258
		 *  @type array
13259
		 *  @default []
13260
		 */
13261
		"aoRowCallback": [],
13262
	
13263
		/**
13264
		 * Callback functions for the header on each draw.
13265
		 *  @type array
13266
		 *  @default []
13267
		 */
13268
		"aoHeaderCallback": [],
13269
	
13270
		/**
13271
		 * Callback function for the footer on each draw.
13272
		 *  @type array
13273
		 *  @default []
13274
		 */
13275
		"aoFooterCallback": [],
13276
	
13277
		/**
13278
		 * Array of callback functions for draw callback functions
13279
		 *  @type array
13280
		 *  @default []
13281
		 */
13282
		"aoDrawCallback": [],
13283
	
13284
		/**
13285
		 * Array of callback functions for row created function
13286
		 *  @type array
13287
		 *  @default []
13288
		 */
13289
		"aoRowCreatedCallback": [],
13290
	
13291
		/**
13292
		 * Callback functions for just before the table is redrawn. A return of
13293
		 * false will be used to cancel the draw.
13294
		 *  @type array
13295
		 *  @default []
13296
		 */
13297
		"aoPreDrawCallback": [],
13298
	
13299
		/**
13300
		 * Callback functions for when the table has been initialised.
13301
		 *  @type array
13302
		 *  @default []
13303
		 */
13304
		"aoInitComplete": [],
13305
	
13306
	
13307
		/**
13308
		 * Callbacks for modifying the settings to be stored for state saving, prior to
13309
		 * saving state.
13310
		 *  @type array
13311
		 *  @default []
13312
		 */
13313
		"aoStateSaveParams": [],
13314
	
13315
		/**
13316
		 * Callbacks for modifying the settings that have been stored for state saving
13317
		 * prior to using the stored values to restore the state.
13318
		 *  @type array
13319
		 *  @default []
13320
		 */
13321
		"aoStateLoadParams": [],
13322
	
13323
		/**
13324
		 * Callbacks for operating on the settings object once the saved state has been
13325
		 * loaded
13326
		 *  @type array
13327
		 *  @default []
13328
		 */
13329
		"aoStateLoaded": [],
13330
	
13331
		/**
13332
		 * Cache the table ID for quick access
13333
		 *  @type string
13334
		 *  @default <i>Empty string</i>
13335
		 */
13336
		"sTableId": "",
13337
	
13338
		/**
13339
		 * The TABLE node for the main table
13340
		 *  @type node
13341
		 *  @default null
13342
		 */
13343
		"nTable": null,
13344
	
13345
		/**
13346
		 * Permanent ref to the thead element
13347
		 *  @type node
13348
		 *  @default null
13349
		 */
13350
		"nTHead": null,
13351
	
13352
		/**
13353
		 * Permanent ref to the tfoot element - if it exists
13354
		 *  @type node
13355
		 *  @default null
13356
		 */
13357
		"nTFoot": null,
13358
	
13359
		/**
13360
		 * Permanent ref to the tbody element
13361
		 *  @type node
13362
		 *  @default null
13363
		 */
13364
		"nTBody": null,
13365
	
13366
		/**
13367
		 * Cache the wrapper node (contains all DataTables controlled elements)
13368
		 *  @type node
13369
		 *  @default null
13370
		 */
13371
		"nTableWrapper": null,
13372
	
13373
		/**
13374
		 * Indicate if when using server-side processing the loading of data
13375
		 * should be deferred until the second draw.
13376
		 * Note that this parameter will be set by the initialisation routine. To
13377
		 * set a default use {@link DataTable.defaults}.
13378
		 *  @type boolean
13379
		 *  @default false
13380
		 */
13381
		"bDeferLoading": false,
13382
	
13383
		/**
13384
		 * Indicate if all required information has been read in
13385
		 *  @type boolean
13386
		 *  @default false
13387
		 */
13388
		"bInitialised": false,
13389
	
13390
		/**
13391
		 * Information about open rows. Each object in the array has the parameters
13392
		 * 'nTr' and 'nParent'
13393
		 *  @type array
13394
		 *  @default []
13395
		 */
13396
		"aoOpenRows": [],
13397
	
13398
		/**
13399
		 * Dictate the positioning of DataTables' control elements - see
13400
		 * {@link DataTable.model.oInit.sDom}.
13401
		 * Note that this parameter will be set by the initialisation routine. To
13402
		 * set a default use {@link DataTable.defaults}.
13403
		 *  @type string
13404
		 *  @default null
13405
		 */
13406
		"sDom": null,
13407
	
13408
		/**
13409
		 * Search delay (in mS)
13410
		 *  @type integer
13411
		 *  @default null
13412
		 */
13413
		"searchDelay": null,
13414
	
13415
		/**
13416
		 * Which type of pagination should be used.
13417
		 * Note that this parameter will be set by the initialisation routine. To
13418
		 * set a default use {@link DataTable.defaults}.
13419
		 *  @type string
13420
		 *  @default two_button
13421
		 */
13422
		"sPaginationType": "two_button",
13423
	
13424
		/**
13425
		 * The state duration (for `stateSave`) in seconds.
13426
		 * Note that this parameter will be set by the initialisation routine. To
13427
		 * set a default use {@link DataTable.defaults}.
13428
		 *  @type int
13429
		 *  @default 0
13430
		 */
13431
		"iStateDuration": 0,
13432
	
13433
		/**
13434
		 * Array of callback functions for state saving. Each array element is an
13435
		 * object with the following parameters:
13436
		 *   <ul>
13437
		 *     <li>function:fn - function to call. Takes two parameters, oSettings
13438
		 *       and the JSON string to save that has been thus far created. Returns
13439
		 *       a JSON string to be inserted into a json object
13440
		 *       (i.e. '"param": [ 0, 1, 2]')</li>
13441
		 *     <li>string:sName - name of callback</li>
13442
		 *   </ul>
13443
		 *  @type array
13444
		 *  @default []
13445
		 */
13446
		"aoStateSave": [],
13447
	
13448
		/**
13449
		 * Array of callback functions for state loading. Each array element is an
13450
		 * object with the following parameters:
13451
		 *   <ul>
13452
		 *     <li>function:fn - function to call. Takes two parameters, oSettings
13453
		 *       and the object stored. May return false to cancel state loading</li>
13454
		 *     <li>string:sName - name of callback</li>
13455
		 *   </ul>
13456
		 *  @type array
13457
		 *  @default []
13458
		 */
13459
		"aoStateLoad": [],
13460
	
13461
		/**
13462
		 * State that was saved. Useful for back reference
13463
		 *  @type object
13464
		 *  @default null
13465
		 */
13466
		"oSavedState": null,
13467
	
13468
		/**
13469
		 * State that was loaded. Useful for back reference
13470
		 *  @type object
13471
		 *  @default null
13472
		 */
13473
		"oLoadedState": null,
13474
	
13475
		/**
13476
		 * Source url for AJAX data for the table.
13477
		 * Note that this parameter will be set by the initialisation routine. To
13478
		 * set a default use {@link DataTable.defaults}.
13479
		 *  @type string
13480
		 *  @default null
13481
		 */
13482
		"sAjaxSource": null,
13483
	
13484
		/**
13485
		 * Property from a given object from which to read the table data from. This
13486
		 * can be an empty string (when not server-side processing), in which case
13487
		 * it is  assumed an an array is given directly.
13488
		 * Note that this parameter will be set by the initialisation routine. To
13489
		 * set a default use {@link DataTable.defaults}.
13490
		 *  @type string
13491
		 */
13492
		"sAjaxDataProp": null,
13493
	
13494
		/**
13495
		 * Note if draw should be blocked while getting data
13496
		 *  @type boolean
13497
		 *  @default true
13498
		 */
13499
		"bAjaxDataGet": true,
13500
	
13501
		/**
13502
		 * The last jQuery XHR object that was used for server-side data gathering.
13503
		 * This can be used for working with the XHR information in one of the
13504
		 * callbacks
13505
		 *  @type object
13506
		 *  @default null
13507
		 */
13508
		"jqXHR": null,
13509
	
13510
		/**
13511
		 * JSON returned from the server in the last Ajax request
13512
		 *  @type object
13513
		 *  @default undefined
13514
		 */
13515
		"json": undefined,
13516
	
13517
		/**
13518
		 * Data submitted as part of the last Ajax request
13519
		 *  @type object
13520
		 *  @default undefined
13521
		 */
13522
		"oAjaxData": undefined,
13523
	
13524
		/**
13525
		 * Function to get the server-side data.
13526
		 * Note that this parameter will be set by the initialisation routine. To
13527
		 * set a default use {@link DataTable.defaults}.
13528
		 *  @type function
13529
		 */
13530
		"fnServerData": null,
13531
	
13532
		/**
13533
		 * Functions which are called prior to sending an Ajax request so extra
13534
		 * parameters can easily be sent to the server
13535
		 *  @type array
13536
		 *  @default []
13537
		 */
13538
		"aoServerParams": [],
13539
	
13540
		/**
13541
		 * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
13542
		 * required).
13543
		 * Note that this parameter will be set by the initialisation routine. To
13544
		 * set a default use {@link DataTable.defaults}.
13545
		 *  @type string
13546
		 */
13547
		"sServerMethod": null,
13548
	
13549
		/**
13550
		 * Format numbers for display.
13551
		 * Note that this parameter will be set by the initialisation routine. To
13552
		 * set a default use {@link DataTable.defaults}.
13553
		 *  @type function
13554
		 */
13555
		"fnFormatNumber": null,
13556
	
13557
		/**
13558
		 * List of options that can be used for the user selectable length menu.
13559
		 * Note that this parameter will be set by the initialisation routine. To
13560
		 * set a default use {@link DataTable.defaults}.
13561
		 *  @type array
13562
		 *  @default []
13563
		 */
13564
		"aLengthMenu": null,
13565
	
13566
		/**
13567
		 * Counter for the draws that the table does. Also used as a tracker for
13568
		 * server-side processing
13569
		 *  @type int
13570
		 *  @default 0
13571
		 */
13572
		"iDraw": 0,
13573
	
13574
		/**
13575
		 * Indicate if a redraw is being done - useful for Ajax
13576
		 *  @type boolean
13577
		 *  @default false
13578
		 */
13579
		"bDrawing": false,
13580
	
13581
		/**
13582
		 * Draw index (iDraw) of the last error when parsing the returned data
13583
		 *  @type int
13584
		 *  @default -1
13585
		 */
13586
		"iDrawError": -1,
13587
	
13588
		/**
13589
		 * Paging display length
13590
		 *  @type int
13591
		 *  @default 10
13592
		 */
13593
		"_iDisplayLength": 10,
13594
	
13595
		/**
13596
		 * Paging start point - aiDisplay index
13597
		 *  @type int
13598
		 *  @default 0
13599
		 */
13600
		"_iDisplayStart": 0,
13601
	
13602
		/**
13603
		 * Server-side processing - number of records in the result set
13604
		 * (i.e. before filtering), Use fnRecordsTotal rather than
13605
		 * this property to get the value of the number of records, regardless of
13606
		 * the server-side processing setting.
13607
		 *  @type int
13608
		 *  @default 0
13609
		 *  @private
13610
		 */
13611
		"_iRecordsTotal": 0,
13612
	
13613
		/**
13614
		 * Server-side processing - number of records in the current display set
13615
		 * (i.e. after filtering). Use fnRecordsDisplay rather than
13616
		 * this property to get the value of the number of records, regardless of
13617
		 * the server-side processing setting.
13618
		 *  @type boolean
13619
		 *  @default 0
13620
		 *  @private
13621
		 */
13622
		"_iRecordsDisplay": 0,
13623
	
13624
		/**
13625
		 * The classes to use for the table
13626
		 *  @type object
13627
		 *  @default {}
13628
		 */
13629
		"oClasses": {},
13630
	
13631
		/**
13632
		 * Flag attached to the settings object so you can check in the draw
13633
		 * callback if filtering has been done in the draw. Deprecated in favour of
13634
		 * events.
13635
		 *  @type boolean
13636
		 *  @default false
13637
		 *  @deprecated
13638
		 */
13639
		"bFiltered": false,
13640
	
13641
		/**
13642
		 * Flag attached to the settings object so you can check in the draw
13643
		 * callback if sorting has been done in the draw. Deprecated in favour of
13644
		 * events.
13645
		 *  @type boolean
13646
		 *  @default false
13647
		 *  @deprecated
13648
		 */
13649
		"bSorted": false,
13650
	
13651
		/**
13652
		 * Indicate that if multiple rows are in the header and there is more than
13653
		 * one unique cell per column, if the top one (true) or bottom one (false)
13654
		 * should be used for sorting / title by DataTables.
13655
		 * Note that this parameter will be set by the initialisation routine. To
13656
		 * set a default use {@link DataTable.defaults}.
13657
		 *  @type boolean
13658
		 */
13659
		"bSortCellsTop": null,
13660
	
13661
		/**
13662
		 * Initialisation object that is used for the table
13663
		 *  @type object
13664
		 *  @default null
13665
		 */
13666
		"oInit": null,
13667
	
13668
		/**
13669
		 * Destroy callback functions - for plug-ins to attach themselves to the
13670
		 * destroy so they can clean up markup and events.
13671
		 *  @type array
13672
		 *  @default []
13673
		 */
13674
		"aoDestroyCallback": [],
13675
	
13676
	
13677
		/**
13678
		 * Get the number of records in the current record set, before filtering
13679
		 *  @type function
13680
		 */
13681
		"fnRecordsTotal": function ()
13682
		{
13683
			return _fnDataSource( this ) == 'ssp' ?
13684
				this._iRecordsTotal * 1 :
13685
				this.aiDisplayMaster.length;
13686
		},
13687
	
13688
		/**
13689
		 * Get the number of records in the current record set, after filtering
13690
		 *  @type function
13691
		 */
13692
		"fnRecordsDisplay": function ()
13693
		{
13694
			return _fnDataSource( this ) == 'ssp' ?
13695
				this._iRecordsDisplay * 1 :
13696
				this.aiDisplay.length;
13697
		},
13698
	
13699
		/**
13700
		 * Get the display end point - aiDisplay index
13701
		 *  @type function
13702
		 */
13703
		"fnDisplayEnd": function ()
13704
		{
13705
			var
13706
				len      = this._iDisplayLength,
13707
				start    = this._iDisplayStart,
13708
				calc     = start + len,
13709
				records  = this.aiDisplay.length,
13710
				features = this.oFeatures,
13711
				paginate = features.bPaginate;
13712
	
13713
			if ( features.bServerSide ) {
13714
				return paginate === false || len === -1 ?
13715
					start + records :
13716
					Math.min( start+len, this._iRecordsDisplay );
13717
			}
13718
			else {
13719
				return ! paginate || calc>records || len===-1 ?
13720
					records :
13721
					calc;
13722
			}
13723
		},
13724
	
13725
		/**
13726
		 * The DataTables object for this table
13727
		 *  @type object
13728
		 *  @default null
13729
		 */
13730
		"oInstance": null,
13731
	
13732
		/**
13733
		 * Unique identifier for each instance of the DataTables object. If there
13734
		 * is an ID on the table node, then it takes that value, otherwise an
13735
		 * incrementing internal counter is used.
13736
		 *  @type string
13737
		 *  @default null
13738
		 */
13739
		"sInstance": null,
13740
	
13741
		/**
13742
		 * tabindex attribute value that is added to DataTables control elements, allowing
13743
		 * keyboard navigation of the table and its controls.
13744
		 */
13745
		"iTabIndex": 0,
13746
	
13747
		/**
13748
		 * DIV container for the footer scrolling table if scrolling
13749
		 */
13750
		"nScrollHead": null,
13751
	
13752
		/**
13753
		 * DIV container for the footer scrolling table if scrolling
13754
		 */
13755
		"nScrollFoot": null,
13756
	
13757
		/**
13758
		 * Last applied sort
13759
		 *  @type array
13760
		 *  @default []
13761
		 */
13762
		"aLastSort": [],
13763
	
13764
		/**
13765
		 * Stored plug-in instances
13766
		 *  @type object
13767
		 *  @default {}
13768
		 */
13769
		"oPlugins": {},
13770
	
13771
		/**
13772
		 * Function used to get a row's id from the row's data
13773
		 *  @type function
13774
		 *  @default null
13775
		 */
13776
		"rowIdFn": null,
13777
	
13778
		/**
13779
		 * Data location where to store a row's id
13780
		 *  @type string
13781
		 *  @default null
13782
		 */
13783
		"rowId": null
13784
	};
13785
13786
	/**
13787
	 * Extension object for DataTables that is used to provide all extension
13788
	 * options.
13789
	 *
13790
	 * Note that the `DataTable.ext` object is available through
13791
	 * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is
13792
	 * also aliased to `jQuery.fn.dataTableExt` for historic reasons.
13793
	 *  @namespace
13794
	 *  @extends DataTable.models.ext
13795
	 */
13796
	
13797
	
13798
	/**
13799
	 * DataTables extensions
13800
	 * 
13801
	 * This namespace acts as a collection area for plug-ins that can be used to
13802
	 * extend DataTables capabilities. Indeed many of the build in methods
13803
	 * use this method to provide their own capabilities (sorting methods for
13804
	 * example).
13805
	 *
13806
	 * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy
13807
	 * reasons
13808
	 *
13809
	 *  @namespace
13810
	 */
13811
	DataTable.ext = _ext = {
13812
		/**
13813
		 * Buttons. For use with the Buttons extension for DataTables. This is
13814
		 * defined here so other extensions can define buttons regardless of load
13815
		 * order. It is _not_ used by DataTables core.
13816
		 *
13817
		 *  @type object
13818
		 *  @default {}
13819
		 */
13820
		buttons: {},
13821
	
13822
	
13823
		/**
13824
		 * Element class names
13825
		 *
13826
		 *  @type object
13827
		 *  @default {}
13828
		 */
13829
		classes: {},
13830
	
13831
	
13832
		/**
13833
		 * DataTables build type (expanded by the download builder)
13834
		 *
13835
		 *  @type string
13836
		 */
13837
		builder: "-source-",
13838
	
13839
	
13840
		/**
13841
		 * Error reporting.
13842
		 * 
13843
		 * How should DataTables report an error. Can take the value 'alert',
13844
		 * 'throw', 'none' or a function.
13845
		 *
13846
		 *  @type string|function
13847
		 *  @default alert
13848
		 */
13849
		errMode: "alert",
13850
	
13851
	
13852
		/**
13853
		 * Feature plug-ins.
13854
		 * 
13855
		 * This is an array of objects which describe the feature plug-ins that are
13856
		 * available to DataTables. These feature plug-ins are then available for
13857
		 * use through the `dom` initialisation option.
13858
		 * 
13859
		 * Each feature plug-in is described by an object which must have the
13860
		 * following properties:
13861
		 * 
13862
		 * * `fnInit` - function that is used to initialise the plug-in,
13863
		 * * `cFeature` - a character so the feature can be enabled by the `dom`
13864
		 *   instillation option. This is case sensitive.
13865
		 *
13866
		 * The `fnInit` function has the following input parameters:
13867
		 *
13868
		 * 1. `{object}` DataTables settings object: see
13869
		 *    {@link DataTable.models.oSettings}
13870
		 *
13871
		 * And the following return is expected:
13872
		 * 
13873
		 * * {node|null} The element which contains your feature. Note that the
13874
		 *   return may also be void if your plug-in does not require to inject any
13875
		 *   DOM elements into DataTables control (`dom`) - for example this might
13876
		 *   be useful when developing a plug-in which allows table control via
13877
		 *   keyboard entry
13878
		 *
13879
		 *  @type array
13880
		 *
13881
		 *  @example
13882
		 *    $.fn.dataTable.ext.features.push( {
13883
		 *      "fnInit": function( oSettings ) {
13884
		 *        return new TableTools( { "oDTSettings": oSettings } );
13885
		 *      },
13886
		 *      "cFeature": "T"
13887
		 *    } );
13888
		 */
13889
		feature: [],
13890
	
13891
	
13892
		/**
13893
		 * Row searching.
13894
		 * 
13895
		 * This method of searching is complimentary to the default type based
13896
		 * searching, and a lot more comprehensive as it allows you complete control
13897
		 * over the searching logic. Each element in this array is a function
13898
		 * (parameters described below) that is called for every row in the table,
13899
		 * and your logic decides if it should be included in the searching data set
13900
		 * or not.
13901
		 *
13902
		 * Searching functions have the following input parameters:
13903
		 *
13904
		 * 1. `{object}` DataTables settings object: see
13905
		 *    {@link DataTable.models.oSettings}
13906
		 * 2. `{array|object}` Data for the row to be processed (same as the
13907
		 *    original format that was passed in as the data source, or an array
13908
		 *    from a DOM data source
13909
		 * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which
13910
		 *    can be useful to retrieve the `TR` element if you need DOM interaction.
13911
		 *
13912
		 * And the following return is expected:
13913
		 *
13914
		 * * {boolean} Include the row in the searched result set (true) or not
13915
		 *   (false)
13916
		 *
13917
		 * Note that as with the main search ability in DataTables, technically this
13918
		 * is "filtering", since it is subtractive. However, for consistency in
13919
		 * naming we call it searching here.
13920
		 *
13921
		 *  @type array
13922
		 *  @default []
13923
		 *
13924
		 *  @example
13925
		 *    // The following example shows custom search being applied to the
13926
		 *    // fourth column (i.e. the data[3] index) based on two input values
13927
		 *    // from the end-user, matching the data in a certain range.
13928
		 *    $.fn.dataTable.ext.search.push(
13929
		 *      function( settings, data, dataIndex ) {
13930
		 *        var min = document.getElementById('min').value * 1;
13931
		 *        var max = document.getElementById('max').value * 1;
13932
		 *        var version = data[3] == "-" ? 0 : data[3]*1;
13933
		 *
13934
		 *        if ( min == "" && max == "" ) {
13935
		 *          return true;
13936
		 *        }
13937
		 *        else if ( min == "" && version < max ) {
13938
		 *          return true;
13939
		 *        }
13940
		 *        else if ( min < version && "" == max ) {
13941
		 *          return true;
13942
		 *        }
13943
		 *        else if ( min < version && version < max ) {
13944
		 *          return true;
13945
		 *        }
13946
		 *        return false;
13947
		 *      }
13948
		 *    );
13949
		 */
13950
		search: [],
13951
	
13952
	
13953
		/**
13954
		 * Selector extensions
13955
		 *
13956
		 * The `selector` option can be used to extend the options available for the
13957
		 * selector modifier options (`selector-modifier` object data type) that
13958
		 * each of the three built in selector types offer (row, column and cell +
13959
		 * their plural counterparts). For example the Select extension uses this
13960
		 * mechanism to provide an option to select only rows, columns and cells
13961
		 * that have been marked as selected by the end user (`{selected: true}`),
13962
		 * which can be used in conjunction with the existing built in selector
13963
		 * options.
13964
		 *
13965
		 * Each property is an array to which functions can be pushed. The functions
13966
		 * take three attributes:
13967
		 *
13968
		 * * Settings object for the host table
13969
		 * * Options object (`selector-modifier` object type)
13970
		 * * Array of selected item indexes
13971
		 *
13972
		 * The return is an array of the resulting item indexes after the custom
13973
		 * selector has been applied.
13974
		 *
13975
		 *  @type object
13976
		 */
13977
		selector: {
13978
			cell: [],
13979
			column: [],
13980
			row: []
13981
		},
13982
	
13983
	
13984
		/**
13985
		 * Internal functions, exposed for used in plug-ins.
13986
		 * 
13987
		 * Please note that you should not need to use the internal methods for
13988
		 * anything other than a plug-in (and even then, try to avoid if possible).
13989
		 * The internal function may change between releases.
13990
		 *
13991
		 *  @type object
13992
		 *  @default {}
13993
		 */
13994
		internal: {},
13995
	
13996
	
13997
		/**
13998
		 * Legacy configuration options. Enable and disable legacy options that
13999
		 * are available in DataTables.
14000
		 *
14001
		 *  @type object
14002
		 */
14003
		legacy: {
14004
			/**
14005
			 * Enable / disable DataTables 1.9 compatible server-side processing
14006
			 * requests
14007
			 *
14008
			 *  @type boolean
14009
			 *  @default null
14010
			 */
14011
			ajax: null
14012
		},
14013
	
14014
	
14015
		/**
14016
		 * Pagination plug-in methods.
14017
		 * 
14018
		 * Each entry in this object is a function and defines which buttons should
14019
		 * be shown by the pagination rendering method that is used for the table:
14020
		 * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the
14021
		 * buttons are displayed in the document, while the functions here tell it
14022
		 * what buttons to display. This is done by returning an array of button
14023
		 * descriptions (what each button will do).
14024
		 *
14025
		 * Pagination types (the four built in options and any additional plug-in
14026
		 * options defined here) can be used through the `paginationType`
14027
		 * initialisation parameter.
14028
		 *
14029
		 * The functions defined take two parameters:
14030
		 *
14031
		 * 1. `{int} page` The current page index
14032
		 * 2. `{int} pages` The number of pages in the table
14033
		 *
14034
		 * Each function is expected to return an array where each element of the
14035
		 * array can be one of:
14036
		 *
14037
		 * * `first` - Jump to first page when activated
14038
		 * * `last` - Jump to last page when activated
14039
		 * * `previous` - Show previous page when activated
14040
		 * * `next` - Show next page when activated
14041
		 * * `{int}` - Show page of the index given
14042
		 * * `{array}` - A nested array containing the above elements to add a
14043
		 *   containing 'DIV' element (might be useful for styling).
14044
		 *
14045
		 * Note that DataTables v1.9- used this object slightly differently whereby
14046
		 * an object with two functions would be defined for each plug-in. That
14047
		 * ability is still supported by DataTables 1.10+ to provide backwards
14048
		 * compatibility, but this option of use is now decremented and no longer
14049
		 * documented in DataTables 1.10+.
14050
		 *
14051
		 *  @type object
14052
		 *  @default {}
14053
		 *
14054
		 *  @example
14055
		 *    // Show previous, next and current page buttons only
14056
		 *    $.fn.dataTableExt.oPagination.current = function ( page, pages ) {
14057
		 *      return [ 'previous', page, 'next' ];
14058
		 *    };
14059
		 */
14060
		pager: {},
14061
	
14062
	
14063
		renderer: {
14064
			pageButton: {},
14065
			header: {}
14066
		},
14067
	
14068
	
14069
		/**
14070
		 * Ordering plug-ins - custom data source
14071
		 * 
14072
		 * The extension options for ordering of data available here is complimentary
14073
		 * to the default type based ordering that DataTables typically uses. It
14074
		 * allows much greater control over the the data that is being used to
14075
		 * order a column, but is necessarily therefore more complex.
14076
		 * 
14077
		 * This type of ordering is useful if you want to do ordering based on data
14078
		 * live from the DOM (for example the contents of an 'input' element) rather
14079
		 * than just the static string that DataTables knows of.
14080
		 * 
14081
		 * The way these plug-ins work is that you create an array of the values you
14082
		 * wish to be ordering for the column in question and then return that
14083
		 * array. The data in the array much be in the index order of the rows in
14084
		 * the table (not the currently ordering order!). Which order data gathering
14085
		 * function is run here depends on the `dt-init columns.orderDataType`
14086
		 * parameter that is used for the column (if any).
14087
		 *
14088
		 * The functions defined take two parameters:
14089
		 *
14090
		 * 1. `{object}` DataTables settings object: see
14091
		 *    {@link DataTable.models.oSettings}
14092
		 * 2. `{int}` Target column index
14093
		 *
14094
		 * Each function is expected to return an array:
14095
		 *
14096
		 * * `{array}` Data for the column to be ordering upon
14097
		 *
14098
		 *  @type array
14099
		 *
14100
		 *  @example
14101
		 *    // Ordering using `input` node values
14102
		 *    $.fn.dataTable.ext.order['dom-text'] = function  ( settings, col )
14103
		 *    {
14104
		 *      return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
14105
		 *        return $('input', td).val();
14106
		 *      } );
14107
		 *    }
14108
		 */
14109
		order: {},
14110
	
14111
	
14112
		/**
14113
		 * Type based plug-ins.
14114
		 *
14115
		 * Each column in DataTables has a type assigned to it, either by automatic
14116
		 * detection or by direct assignment using the `type` option for the column.
14117
		 * The type of a column will effect how it is ordering and search (plug-ins
14118
		 * can also make use of the column type if required).
14119
		 *
14120
		 * @namespace
14121
		 */
14122
		type: {
14123
			/**
14124
			 * Type detection functions.
14125
			 *
14126
			 * The functions defined in this object are used to automatically detect
14127
			 * a column's type, making initialisation of DataTables super easy, even
14128
			 * when complex data is in the table.
14129
			 *
14130
			 * The functions defined take two parameters:
14131
			 *
14132
		     *  1. `{*}` Data from the column cell to be analysed
14133
		     *  2. `{settings}` DataTables settings object. This can be used to
14134
		     *     perform context specific type detection - for example detection
14135
		     *     based on language settings such as using a comma for a decimal
14136
		     *     place. Generally speaking the options from the settings will not
14137
		     *     be required
14138
			 *
14139
			 * Each function is expected to return:
14140
			 *
14141
			 * * `{string|null}` Data type detected, or null if unknown (and thus
14142
			 *   pass it on to the other type detection functions.
14143
			 *
14144
			 *  @type array
14145
			 *
14146
			 *  @example
14147
			 *    // Currency type detection plug-in:
14148
			 *    $.fn.dataTable.ext.type.detect.push(
14149
			 *      function ( data, settings ) {
14150
			 *        // Check the numeric part
14151
			 *        if ( ! $.isNumeric( data.substring(1) ) ) {
14152
			 *          return null;
14153
			 *        }
14154
			 *
14155
			 *        // Check prefixed by currency
14156
			 *        if ( data.charAt(0) == '$' || data.charAt(0) == '&pound;' ) {
14157
			 *          return 'currency';
14158
			 *        }
14159
			 *        return null;
14160
			 *      }
14161
			 *    );
14162
			 */
14163
			detect: [],
14164
	
14165
	
14166
			/**
14167
			 * Type based search formatting.
14168
			 *
14169
			 * The type based searching functions can be used to pre-format the
14170
			 * data to be search on. For example, it can be used to strip HTML
14171
			 * tags or to de-format telephone numbers for numeric only searching.
14172
			 *
14173
			 * Note that is a search is not defined for a column of a given type,
14174
			 * no search formatting will be performed.
14175
			 * 
14176
			 * Pre-processing of searching data plug-ins - When you assign the sType
14177
			 * for a column (or have it automatically detected for you by DataTables
14178
			 * or a type detection plug-in), you will typically be using this for
14179
			 * custom sorting, but it can also be used to provide custom searching
14180
			 * by allowing you to pre-processing the data and returning the data in
14181
			 * the format that should be searched upon. This is done by adding
14182
			 * functions this object with a parameter name which matches the sType
14183
			 * for that target column. This is the corollary of <i>afnSortData</i>
14184
			 * for searching data.
14185
			 *
14186
			 * The functions defined take a single parameter:
14187
			 *
14188
		     *  1. `{*}` Data from the column cell to be prepared for searching
14189
			 *
14190
			 * Each function is expected to return:
14191
			 *
14192
			 * * `{string|null}` Formatted string that will be used for the searching.
14193
			 *
14194
			 *  @type object
14195
			 *  @default {}
14196
			 *
14197
			 *  @example
14198
			 *    $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) {
14199
			 *      return d.replace(/\n/g," ").replace( /<.*?>/g, "" );
14200
			 *    }
14201
			 */
14202
			search: {},
14203
	
14204
	
14205
			/**
14206
			 * Type based ordering.
14207
			 *
14208
			 * The column type tells DataTables what ordering to apply to the table
14209
			 * when a column is sorted upon. The order for each type that is defined,
14210
			 * is defined by the functions available in this object.
14211
			 *
14212
			 * Each ordering option can be described by three properties added to
14213
			 * this object:
14214
			 *
14215
			 * * `{type}-pre` - Pre-formatting function
14216
			 * * `{type}-asc` - Ascending order function
14217
			 * * `{type}-desc` - Descending order function
14218
			 *
14219
			 * All three can be used together, only `{type}-pre` or only
14220
			 * `{type}-asc` and `{type}-desc` together. It is generally recommended
14221
			 * that only `{type}-pre` is used, as this provides the optimal
14222
			 * implementation in terms of speed, although the others are provided
14223
			 * for compatibility with existing Javascript sort functions.
14224
			 *
14225
			 * `{type}-pre`: Functions defined take a single parameter:
14226
			 *
14227
		     *  1. `{*}` Data from the column cell to be prepared for ordering
14228
			 *
14229
			 * And return:
14230
			 *
14231
			 * * `{*}` Data to be sorted upon
14232
			 *
14233
			 * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort
14234
			 * functions, taking two parameters:
14235
			 *
14236
		     *  1. `{*}` Data to compare to the second parameter
14237
		     *  2. `{*}` Data to compare to the first parameter
14238
			 *
14239
			 * And returning:
14240
			 *
14241
			 * * `{*}` Ordering match: <0 if first parameter should be sorted lower
14242
			 *   than the second parameter, ===0 if the two parameters are equal and
14243
			 *   >0 if the first parameter should be sorted height than the second
14244
			 *   parameter.
14245
			 * 
14246
			 *  @type object
14247
			 *  @default {}
14248
			 *
14249
			 *  @example
14250
			 *    // Numeric ordering of formatted numbers with a pre-formatter
14251
			 *    $.extend( $.fn.dataTable.ext.type.order, {
14252
			 *      "string-pre": function(x) {
14253
			 *        a = (a === "-" || a === "") ? 0 : a.replace( /[^\d\-\.]/g, "" );
14254
			 *        return parseFloat( a );
14255
			 *      }
14256
			 *    } );
14257
			 *
14258
			 *  @example
14259
			 *    // Case-sensitive string ordering, with no pre-formatting method
14260
			 *    $.extend( $.fn.dataTable.ext.order, {
14261
			 *      "string-case-asc": function(x,y) {
14262
			 *        return ((x < y) ? -1 : ((x > y) ? 1 : 0));
14263
			 *      },
14264
			 *      "string-case-desc": function(x,y) {
14265
			 *        return ((x < y) ? 1 : ((x > y) ? -1 : 0));
14266
			 *      }
14267
			 *    } );
14268
			 */
14269
			order: {}
14270
		},
14271
	
14272
		/**
14273
		 * Unique DataTables instance counter
14274
		 *
14275
		 * @type int
14276
		 * @private
14277
		 */
14278
		_unique: 0,
14279
	
14280
	
14281
		//
14282
		// Depreciated
14283
		// The following properties are retained for backwards compatiblity only.
14284
		// The should not be used in new projects and will be removed in a future
14285
		// version
14286
		//
14287
	
14288
		/**
14289
		 * Version check function.
14290
		 *  @type function
14291
		 *  @depreciated Since 1.10
14292
		 */
14293
		fnVersionCheck: DataTable.fnVersionCheck,
14294
	
14295
	
14296
		/**
14297
		 * Index for what 'this' index API functions should use
14298
		 *  @type int
14299
		 *  @deprecated Since v1.10
14300
		 */
14301
		iApiIndex: 0,
14302
	
14303
	
14304
		/**
14305
		 * jQuery UI class container
14306
		 *  @type object
14307
		 *  @deprecated Since v1.10
14308
		 */
14309
		oJUIClasses: {},
14310
	
14311
	
14312
		/**
14313
		 * Software version
14314
		 *  @type string
14315
		 *  @deprecated Since v1.10
14316
		 */
14317
		sVersion: DataTable.version
14318
	};
14319
	
14320
	
14321
	//
14322
	// Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts
14323
	//
14324
	$.extend( _ext, {
14325
		afnFiltering: _ext.search,
14326
		aTypes:       _ext.type.detect,
14327
		ofnSearch:    _ext.type.search,
14328
		oSort:        _ext.type.order,
14329
		afnSortData:  _ext.order,
14330
		aoFeatures:   _ext.feature,
14331
		oApi:         _ext.internal,
14332
		oStdClasses:  _ext.classes,
14333
		oPagination:  _ext.pager
14334
	} );
14335
	
14336
	
14337
	$.extend( DataTable.ext.classes, {
14338
		"sTable": "dataTable",
14339
		"sNoFooter": "no-footer",
14340
	
14341
		/* Paging buttons */
14342
		"sPageButton": "paginate_button",
14343
		"sPageButtonActive": "current",
14344
		"sPageButtonDisabled": "disabled",
14345
	
14346
		/* Striping classes */
14347
		"sStripeOdd": "odd",
14348
		"sStripeEven": "even",
14349
	
14350
		/* Empty row */
14351
		"sRowEmpty": "dataTables_empty",
14352
	
14353
		/* Features */
14354
		"sWrapper": "dataTables_wrapper",
14355
		"sFilter": "dataTables_filter",
14356
		"sInfo": "dataTables_info",
14357
		"sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
14358
		"sLength": "dataTables_length",
14359
		"sProcessing": "dataTables_processing",
14360
	
14361
		/* Sorting */
14362
		"sSortAsc": "sorting_asc",
14363
		"sSortDesc": "sorting_desc",
14364
		"sSortable": "sorting", /* Sortable in both directions */
14365
		"sSortableAsc": "sorting_asc_disabled",
14366
		"sSortableDesc": "sorting_desc_disabled",
14367
		"sSortableNone": "sorting_disabled",
14368
		"sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
14369
	
14370
		/* Filtering */
14371
		"sFilterInput": "",
14372
	
14373
		/* Page length */
14374
		"sLengthSelect": "",
14375
	
14376
		/* Scrolling */
14377
		"sScrollWrapper": "dataTables_scroll",
14378
		"sScrollHead": "dataTables_scrollHead",
14379
		"sScrollHeadInner": "dataTables_scrollHeadInner",
14380
		"sScrollBody": "dataTables_scrollBody",
14381
		"sScrollFoot": "dataTables_scrollFoot",
14382
		"sScrollFootInner": "dataTables_scrollFootInner",
14383
	
14384
		/* Misc */
14385
		"sHeaderTH": "",
14386
		"sFooterTH": "",
14387
	
14388
		// Deprecated
14389
		"sSortJUIAsc": "",
14390
		"sSortJUIDesc": "",
14391
		"sSortJUI": "",
14392
		"sSortJUIAscAllowed": "",
14393
		"sSortJUIDescAllowed": "",
14394
		"sSortJUIWrapper": "",
14395
		"sSortIcon": "",
14396
		"sJUIHeader": "",
14397
		"sJUIFooter": ""
14398
	} );
14399
	
14400
	
14401
	var extPagination = DataTable.ext.pager;
14402
	
14403
	function _numbers ( page, pages ) {
14404
		var
14405
			numbers = [],
0 ignored issues
show
Unused Code introduced by
The assignment to variable numbers seems to be never used. Consider removing it.
Loading history...
14406
			buttons = extPagination.numbers_length,
14407
			half = Math.floor( buttons / 2 ),
14408
			i = 1;
0 ignored issues
show
Unused Code introduced by
The variable i seems to be never used. Consider removing it.
Loading history...
14409
	
14410
		if ( pages <= buttons ) {
14411
			numbers = _range( 0, pages );
14412
		}
14413
		else if ( page <= half ) {
14414
			numbers = _range( 0, buttons-2 );
14415
			numbers.push( 'ellipsis' );
14416
			numbers.push( pages-1 );
14417
		}
14418
		else if ( page >= pages - 1 - half ) {
14419
			numbers = _range( pages-(buttons-2), pages );
14420
			numbers.splice( 0, 0, 'ellipsis' ); // no unshift in ie6
14421
			numbers.splice( 0, 0, 0 );
14422
		}
14423
		else {
14424
			numbers = _range( page-half+2, page+half-1 );
14425
			numbers.push( 'ellipsis' );
14426
			numbers.push( pages-1 );
14427
			numbers.splice( 0, 0, 'ellipsis' );
14428
			numbers.splice( 0, 0, 0 );
14429
		}
14430
	
14431
		numbers.DT_el = 'span';
14432
		return numbers;
14433
	}
14434
	
14435
	
14436
	$.extend( extPagination, {
14437
		simple: function ( page, pages ) {
0 ignored issues
show
Unused Code introduced by
The parameter page is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter pages is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
14438
			return [ 'previous', 'next' ];
14439
		},
14440
	
14441
		full: function ( page, pages ) {
0 ignored issues
show
Unused Code introduced by
The parameter pages is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter page is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
14442
			return [  'first', 'previous', 'next', 'last' ];
14443
		},
14444
	
14445
		numbers: function ( page, pages ) {
14446
			return [ _numbers(page, pages) ];
14447
		},
14448
	
14449
		simple_numbers: function ( page, pages ) {
14450
			return [ 'previous', _numbers(page, pages), 'next' ];
14451
		},
14452
	
14453
		full_numbers: function ( page, pages ) {
14454
			return [ 'first', 'previous', _numbers(page, pages), 'next', 'last' ];
14455
		},
14456
		
14457
		first_last_numbers: function (page, pages) {
14458
	 		return ['first', _numbers(page, pages), 'last'];
14459
	 	},
14460
	
14461
		// For testing and plug-ins to use
14462
		_numbers: _numbers,
14463
	
14464
		// Number of number buttons (including ellipsis) to show. _Must be odd!_
14465
		numbers_length: 7
14466
	} );
14467
	
14468
	
14469
	$.extend( true, DataTable.ext.renderer, {
14470
		pageButton: {
14471 View Code Duplication
			_: function ( settings, host, idx, buttons, page, pages ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
14472
				var classes = settings.oClasses;
14473
				var lang = settings.oLanguage.oPaginate;
14474
				var aria = settings.oLanguage.oAria.paginate || {};
14475
				var btnDisplay, btnClass, counter=0;
14476
	
14477
				var attach = function( container, buttons ) {
14478
					var i, ien, node, button;
14479
					var clickHandler = function ( e ) {
14480
						_fnPageChange( settings, e.data.action, true );
14481
					};
14482
	
14483
					for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
14484
						button = buttons[i];
14485
	
14486
						if ( $.isArray( button ) ) {
14487
							var inner = $( '<'+(button.DT_el || 'div')+'/>' )
14488
								.appendTo( container );
14489
							attach( inner, button );
14490
						}
14491
						else {
14492
							btnDisplay = null;
14493
							btnClass = '';
14494
	
14495
							switch ( button ) {
14496
								case 'ellipsis':
14497
									container.append('<span class="ellipsis">&#x2026;</span>');
14498
									break;
14499
	
14500
								case 'first':
14501
									btnDisplay = lang.sFirst;
14502
									btnClass = button + (page > 0 ?
14503
										'' : ' '+classes.sPageButtonDisabled);
14504
									break;
14505
	
14506
								case 'previous':
14507
									btnDisplay = lang.sPrevious;
14508
									btnClass = button + (page > 0 ?
14509
										'' : ' '+classes.sPageButtonDisabled);
14510
									break;
14511
	
14512
								case 'next':
14513
									btnDisplay = lang.sNext;
14514
									btnClass = button + (page < pages-1 ?
14515
										'' : ' '+classes.sPageButtonDisabled);
14516
									break;
14517
	
14518
								case 'last':
14519
									btnDisplay = lang.sLast;
14520
									btnClass = button + (page < pages-1 ?
14521
										'' : ' '+classes.sPageButtonDisabled);
14522
									break;
14523
	
14524
								default:
14525
									btnDisplay = button + 1;
14526
									btnClass = page === button ?
14527
										classes.sPageButtonActive : '';
14528
									break;
14529
							}
14530
	
14531
							if ( btnDisplay !== null ) {
0 ignored issues
show
Bug introduced by
The variable btnDisplay is changed as part of the for loop for example by lang.sLast on line 14519. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
14532
								node = $('<a>', {
14533
										'class': classes.sPageButton+' '+btnClass,
0 ignored issues
show
Bug introduced by
The variable btnClass is changed as part of the for loop for example by "" on line 14493. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
14534
										'aria-controls': settings.sTableId,
14535
										'aria-label': aria[ button ],
14536
										'data-dt-idx': counter,
0 ignored issues
show
Bug introduced by
The variable counter is changed as part of the for loop for example by counter++ on line 14549. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
14537
										'tabindex': settings.iTabIndex,
14538
										'id': idx === 0 && typeof button === 'string' ?
14539
											settings.sTableId +'_'+ button :
14540
											null
14541
									} )
14542
									.html( btnDisplay )
14543
									.appendTo( container );
14544
	
14545
								_fnBindAction(
14546
									node, {action: button}, clickHandler
14547
								);
14548
	
14549
								counter++;
14550
							}
14551
						}
14552
					}
14553
				};
14554
	
14555
				// IE9 throws an 'unknown error' if document.activeElement is used
14556
				// inside an iframe or frame. Try / catch the error. Not good for
14557
				// accessibility, but neither are frames.
14558
				var activeEl;
14559
	
14560
				try {
14561
					// Because this approach is destroying and recreating the paging
14562
					// elements, focus is lost on the select button which is bad for
14563
					// accessibility. So we want to restore focus once the draw has
14564
					// completed
14565
					activeEl = $(host).find(document.activeElement).data('dt-idx');
14566
				}
14567
				catch (e) {}
0 ignored issues
show
Coding Style Comprehensibility Best Practice introduced by
Empty catch clauses should be used with caution; consider adding a comment why this is needed.
Loading history...
14568
	
14569
				attach( $(host).empty(), buttons );
14570
	
14571
				if ( activeEl !== undefined ) {
14572
					$(host).find( '[data-dt-idx='+activeEl+']' ).focus();
14573
				}
14574
			}
14575
		}
14576
	} );
14577
	
14578
	
14579
	
14580
	// Built in type detection. See model.ext.aTypes for information about
14581
	// what is required from this methods.
14582
	$.extend( DataTable.ext.type.detect, [
14583
		// Plain numbers - first since V8 detects some plain numbers as dates
14584
		// e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...).
14585
		function ( d, settings )
14586
		{
14587
			var decimal = settings.oLanguage.sDecimal;
14588
			return _isNumber( d, decimal ) ? 'num'+decimal : null;
14589
		},
14590
	
14591
		// Dates (only those recognised by the browser's Date.parse)
14592
		function ( d, settings )
0 ignored issues
show
Unused Code introduced by
The parameter settings is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
14593
		{
14594
			// V8 tries _very_ hard to make a string passed into `Date.parse()`
14595
			// valid, so we need to use a regex to restrict date formats. Use a
14596
			// plug-in for anything other than ISO8601 style strings
14597
			if ( d && !(d instanceof Date) && ! _re_date.test(d) ) {
14598
				return null;
14599
			}
14600
			var parsed = Date.parse(d);
14601
			return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null;
14602
		},
14603
	
14604
		// Formatted numbers
14605
		function ( d, settings )
14606
		{
14607
			var decimal = settings.oLanguage.sDecimal;
14608
			return _isNumber( d, decimal, true ) ? 'num-fmt'+decimal : null;
14609
		},
14610
	
14611
		// HTML numeric
14612
		function ( d, settings )
14613
		{
14614
			var decimal = settings.oLanguage.sDecimal;
14615
			return _htmlNumeric( d, decimal ) ? 'html-num'+decimal : null;
14616
		},
14617
	
14618
		// HTML numeric, formatted
14619
		function ( d, settings )
14620
		{
14621
			var decimal = settings.oLanguage.sDecimal;
14622
			return _htmlNumeric( d, decimal, true ) ? 'html-num-fmt'+decimal : null;
14623
		},
14624
	
14625
		// HTML (this is strict checking - there must be html)
14626
		function ( d, settings )
0 ignored issues
show
Unused Code introduced by
The parameter settings is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
14627
		{
14628
			return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ?
14629
				'html' : null;
14630
		}
14631
	] );
14632
	
14633
	
14634
	
14635
	// Filter formatting functions. See model.ext.ofnSearch for information about
14636
	// what is required from these methods.
14637
	// 
14638
	// Note that additional search methods are added for the html numbers and
14639
	// html formatted numbers by `_addNumericSort()` when we know what the decimal
14640
	// place is
14641
	
14642
	
14643
	$.extend( DataTable.ext.type.search, {
14644
		html: function ( data ) {
14645
			return _empty(data) ?
14646
				data :
14647
				typeof data === 'string' ?
14648
					data
14649
						.replace( _re_new_lines, " " )
14650
						.replace( _re_html, "" ) :
14651
					'';
14652
		},
14653
	
14654
		string: function ( data ) {
14655
			return _empty(data) ?
14656
				data :
14657
				typeof data === 'string' ?
14658
					data.replace( _re_new_lines, " " ) :
14659
					data;
14660
		}
14661
	} );
14662
	
14663
	
14664
	
14665
	var __numericReplace = function ( d, decimalPlace, re1, re2 ) {
14666
		if ( d !== 0 && (!d || d === '-') ) {
14667
			return -Infinity;
14668
		}
14669
	
14670
		// If a decimal place other than `.` is used, it needs to be given to the
14671
		// function so we can detect it and replace with a `.` which is the only
14672
		// decimal place Javascript recognises - it is not locale aware.
14673
		if ( decimalPlace ) {
14674
			d = _numToDecimal( d, decimalPlace );
14675
		}
14676
	
14677
		if ( d.replace ) {
14678
			if ( re1 ) {
14679
				d = d.replace( re1, '' );
14680
			}
14681
	
14682
			if ( re2 ) {
14683
				d = d.replace( re2, '' );
14684
			}
14685
		}
14686
	
14687
		return d * 1;
14688
	};
14689
	
14690
	
14691
	// Add the numeric 'deformatting' functions for sorting and search. This is done
14692
	// in a function to provide an easy ability for the language options to add
14693
	// additional methods if a non-period decimal place is used.
14694
	function _addNumericSort ( decimalPlace ) {
14695
		$.each(
14696
			{
14697
				// Plain numbers
14698
				"num": function ( d ) {
14699
					return __numericReplace( d, decimalPlace );
14700
				},
14701
	
14702
				// Formatted numbers
14703
				"num-fmt": function ( d ) {
14704
					return __numericReplace( d, decimalPlace, _re_formatted_numeric );
14705
				},
14706
	
14707
				// HTML numeric
14708
				"html-num": function ( d ) {
14709
					return __numericReplace( d, decimalPlace, _re_html );
14710
				},
14711
	
14712
				// HTML numeric, formatted
14713
				"html-num-fmt": function ( d ) {
14714
					return __numericReplace( d, decimalPlace, _re_html, _re_formatted_numeric );
14715
				}
14716
			},
14717
			function ( key, fn ) {
14718
				// Add the ordering method
14719
				_ext.type.order[ key+decimalPlace+'-pre' ] = fn;
14720
	
14721
				// For HTML types add a search formatter that will strip the HTML
14722
				if ( key.match(/^html\-/) ) {
14723
					_ext.type.search[ key+decimalPlace ] = _ext.type.search.html;
14724
				}
14725
			}
14726
		);
14727
	}
14728
	
14729
	
14730
	// Default sort methods
14731
	$.extend( _ext.type.order, {
14732
		// Dates
14733
		"date-pre": function ( d ) {
14734
			return Date.parse( d ) || -Infinity;
14735
		},
14736
	
14737
		// html
14738
		"html-pre": function ( a ) {
14739
			return _empty(a) ?
14740
				'' :
14741
				a.replace ?
14742
					a.replace( /<.*?>/g, "" ).toLowerCase() :
14743
					a+'';
14744
		},
14745
	
14746
		// string
14747
		"string-pre": function ( a ) {
14748
			// This is a little complex, but faster than always calling toString,
14749
			// http://jsperf.com/tostring-v-check
14750
			return _empty(a) ?
14751
				'' :
14752
				typeof a === 'string' ?
14753
					a.toLowerCase() :
14754
					! a.toString ?
14755
						'' :
14756
						a.toString();
14757
		},
14758
	
14759
		// string-asc and -desc are retained only for compatibility with the old
14760
		// sort methods
14761
		"string-asc": function ( x, y ) {
14762
			return ((x < y) ? -1 : ((x > y) ? 1 : 0));
14763
		},
14764
	
14765
		"string-desc": function ( x, y ) {
14766
			return ((x < y) ? 1 : ((x > y) ? -1 : 0));
14767
		}
14768
	} );
14769
	
14770
	
14771
	// Numeric sorting types - order doesn't matter here
14772
	_addNumericSort( '' );
14773
	
14774
	
14775
	$.extend( true, DataTable.ext.renderer, {
14776
		header: {
14777
			_: function ( settings, cell, column, classes ) {
14778
				// No additional mark-up required
14779
				// Attach a sort listener to update on sort - note that using the
14780
				// `DT` namespace will allow the event to be removed automatically
14781
				// on destroy, while the `dt` namespaced event is the one we are
14782
				// listening for
14783
				$(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
14784
					if ( settings !== ctx ) { // need to check this this is the host
14785
						return;               // table, not a nested one
14786
					}
14787
	
14788
					var colIdx = column.idx;
14789
	
14790
					cell
14791
						.removeClass(
14792
							column.sSortingClass +' '+
14793
							classes.sSortAsc +' '+
14794
							classes.sSortDesc
14795
						)
14796
						.addClass( columns[ colIdx ] == 'asc' ?
14797
							classes.sSortAsc : columns[ colIdx ] == 'desc' ?
14798
								classes.sSortDesc :
14799
								column.sSortingClass
14800
						);
14801
				} );
14802
			},
14803
	
14804
			jqueryui: function ( settings, cell, column, classes ) {
14805
				$('<div/>')
14806
					.addClass( classes.sSortJUIWrapper )
14807
					.append( cell.contents() )
14808
					.append( $('<span/>')
14809
						.addClass( classes.sSortIcon+' '+column.sSortingClassJUI )
14810
					)
14811
					.appendTo( cell );
14812
	
14813
				// Attach a sort listener to update on sort
14814
				$(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
14815
					if ( settings !== ctx ) {
14816
						return;
14817
					}
14818
	
14819
					var colIdx = column.idx;
14820
	
14821
					cell
14822
						.removeClass( classes.sSortAsc +" "+classes.sSortDesc )
14823
						.addClass( columns[ colIdx ] == 'asc' ?
14824
							classes.sSortAsc : columns[ colIdx ] == 'desc' ?
14825
								classes.sSortDesc :
14826
								column.sSortingClass
14827
						);
14828
	
14829
					cell
14830
						.find( 'span.'+classes.sSortIcon )
14831
						.removeClass(
14832
							classes.sSortJUIAsc +" "+
14833
							classes.sSortJUIDesc +" "+
14834
							classes.sSortJUI +" "+
14835
							classes.sSortJUIAscAllowed +" "+
14836
							classes.sSortJUIDescAllowed
14837
						)
14838
						.addClass( columns[ colIdx ] == 'asc' ?
14839
							classes.sSortJUIAsc : columns[ colIdx ] == 'desc' ?
14840
								classes.sSortJUIDesc :
14841
								column.sSortingClassJUI
14842
						);
14843
				} );
14844
			}
14845
		}
14846
	} );
14847
	
14848
	/*
14849
	 * Public helper functions. These aren't used internally by DataTables, or
14850
	 * called by any of the options passed into DataTables, but they can be used
14851
	 * externally by developers working with DataTables. They are helper functions
14852
	 * to make working with DataTables a little bit easier.
14853
	 */
14854
	
14855
	var __htmlEscapeEntities = function ( d ) {
14856
		return typeof d === 'string' ?
14857
			d.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;') :
14858
			d;
14859
	};
14860
	
14861
	/**
14862
	 * Helpers for `columns.render`.
14863
	 *
14864
	 * The options defined here can be used with the `columns.render` initialisation
14865
	 * option to provide a display renderer. The following functions are defined:
14866
	 *
14867
	 * * `number` - Will format numeric data (defined by `columns.data`) for
14868
	 *   display, retaining the original unformatted data for sorting and filtering.
14869
	 *   It takes 5 parameters:
14870
	 *   * `string` - Thousands grouping separator
14871
	 *   * `string` - Decimal point indicator
14872
	 *   * `integer` - Number of decimal points to show
14873
	 *   * `string` (optional) - Prefix.
14874
	 *   * `string` (optional) - Postfix (/suffix).
14875
	 * * `text` - Escape HTML to help prevent XSS attacks. It has no optional
14876
	 *   parameters.
14877
	 *
14878
	 * @example
14879
	 *   // Column definition using the number renderer
14880
	 *   {
14881
	 *     data: "salary",
14882
	 *     render: $.fn.dataTable.render.number( '\'', '.', 0, '$' )
14883
	 *   }
14884
	 *
14885
	 * @namespace
14886
	 */
14887
	DataTable.render = {
14888
		number: function ( thousands, decimal, precision, prefix, postfix ) {
14889
			return {
14890
				display: function ( d ) {
14891
					if ( typeof d !== 'number' && typeof d !== 'string' ) {
14892
						return d;
14893
					}
14894
	
14895
					var negative = d < 0 ? '-' : '';
14896
					var flo = parseFloat( d );
14897
	
14898
					// If NaN then there isn't much formatting that we can do - just
14899
					// return immediately, escaping any HTML (this was supposed to
14900
					// be a number after all)
14901
					if ( isNaN( flo ) ) {
14902
						return __htmlEscapeEntities( d );
14903
					}
14904
	
14905
					flo = flo.toFixed( precision );
14906
					d = Math.abs( flo );
14907
	
14908
					var intPart = parseInt( d, 10 );
14909
					var floatPart = precision ?
14910
						decimal+(d - intPart).toFixed( precision ).substring( 2 ):
14911
						'';
14912
	
14913
					return negative + (prefix||'') +
14914
						intPart.toString().replace(
14915
							/\B(?=(\d{3})+(?!\d))/g, thousands
14916
						) +
14917
						floatPart +
14918
						(postfix||'');
14919
				}
14920
			};
14921
		},
14922
	
14923
		text: function () {
14924
			return {
14925
				display: __htmlEscapeEntities
14926
			};
14927
		}
14928
	};
14929
	
14930
	
14931
	/*
14932
	 * This is really a good bit rubbish this method of exposing the internal methods
14933
	 * publicly... - To be fixed in 2.0 using methods on the prototype
14934
	 */
14935
	
14936
	
14937
	/**
14938
	 * Create a wrapper function for exporting an internal functions to an external API.
14939
	 *  @param {string} fn API function name
14940
	 *  @returns {function} wrapped function
14941
	 *  @memberof DataTable#internal
14942
	 */
14943
	function _fnExternApiFunc (fn)
14944
	{
14945
		return function() {
14946
			var args = [_fnSettingsFromNode( this[DataTable.ext.iApiIndex] )].concat(
14947
				Array.prototype.slice.call(arguments)
14948
			);
14949
			return DataTable.ext.internal[fn].apply( this, args );
14950
		};
14951
	}
14952
	
14953
	
14954
	/**
14955
	 * Reference to internal functions for use by plug-in developers. Note that
14956
	 * these methods are references to internal functions and are considered to be
14957
	 * private. If you use these methods, be aware that they are liable to change
14958
	 * between versions.
14959
	 *  @namespace
14960
	 */
14961
	$.extend( DataTable.ext.internal, {
14962
		_fnExternApiFunc: _fnExternApiFunc,
14963
		_fnBuildAjax: _fnBuildAjax,
14964
		_fnAjaxUpdate: _fnAjaxUpdate,
14965
		_fnAjaxParameters: _fnAjaxParameters,
14966
		_fnAjaxUpdateDraw: _fnAjaxUpdateDraw,
14967
		_fnAjaxDataSrc: _fnAjaxDataSrc,
14968
		_fnAddColumn: _fnAddColumn,
14969
		_fnColumnOptions: _fnColumnOptions,
14970
		_fnAdjustColumnSizing: _fnAdjustColumnSizing,
14971
		_fnVisibleToColumnIndex: _fnVisibleToColumnIndex,
14972
		_fnColumnIndexToVisible: _fnColumnIndexToVisible,
14973
		_fnVisbleColumns: _fnVisbleColumns,
14974
		_fnGetColumns: _fnGetColumns,
14975
		_fnColumnTypes: _fnColumnTypes,
14976
		_fnApplyColumnDefs: _fnApplyColumnDefs,
14977
		_fnHungarianMap: _fnHungarianMap,
14978
		_fnCamelToHungarian: _fnCamelToHungarian,
14979
		_fnLanguageCompat: _fnLanguageCompat,
14980
		_fnBrowserDetect: _fnBrowserDetect,
14981
		_fnAddData: _fnAddData,
14982
		_fnAddTr: _fnAddTr,
14983
		_fnNodeToDataIndex: _fnNodeToDataIndex,
14984
		_fnNodeToColumnIndex: _fnNodeToColumnIndex,
14985
		_fnGetCellData: _fnGetCellData,
14986
		_fnSetCellData: _fnSetCellData,
14987
		_fnSplitObjNotation: _fnSplitObjNotation,
14988
		_fnGetObjectDataFn: _fnGetObjectDataFn,
14989
		_fnSetObjectDataFn: _fnSetObjectDataFn,
14990
		_fnGetDataMaster: _fnGetDataMaster,
14991
		_fnClearTable: _fnClearTable,
14992
		_fnDeleteIndex: _fnDeleteIndex,
14993
		_fnInvalidate: _fnInvalidate,
14994
		_fnGetRowElements: _fnGetRowElements,
14995
		_fnCreateTr: _fnCreateTr,
14996
		_fnBuildHead: _fnBuildHead,
14997
		_fnDrawHead: _fnDrawHead,
14998
		_fnDraw: _fnDraw,
14999
		_fnReDraw: _fnReDraw,
15000
		_fnAddOptionsHtml: _fnAddOptionsHtml,
15001
		_fnDetectHeader: _fnDetectHeader,
15002
		_fnGetUniqueThs: _fnGetUniqueThs,
15003
		_fnFeatureHtmlFilter: _fnFeatureHtmlFilter,
15004
		_fnFilterComplete: _fnFilterComplete,
15005
		_fnFilterCustom: _fnFilterCustom,
15006
		_fnFilterColumn: _fnFilterColumn,
15007
		_fnFilter: _fnFilter,
15008
		_fnFilterCreateSearch: _fnFilterCreateSearch,
15009
		_fnEscapeRegex: _fnEscapeRegex,
15010
		_fnFilterData: _fnFilterData,
15011
		_fnFeatureHtmlInfo: _fnFeatureHtmlInfo,
15012
		_fnUpdateInfo: _fnUpdateInfo,
15013
		_fnInfoMacros: _fnInfoMacros,
15014
		_fnInitialise: _fnInitialise,
15015
		_fnInitComplete: _fnInitComplete,
15016
		_fnLengthChange: _fnLengthChange,
15017
		_fnFeatureHtmlLength: _fnFeatureHtmlLength,
15018
		_fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate,
15019
		_fnPageChange: _fnPageChange,
15020
		_fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing,
15021
		_fnProcessingDisplay: _fnProcessingDisplay,
15022
		_fnFeatureHtmlTable: _fnFeatureHtmlTable,
15023
		_fnScrollDraw: _fnScrollDraw,
15024
		_fnApplyToChildren: _fnApplyToChildren,
15025
		_fnCalculateColumnWidths: _fnCalculateColumnWidths,
15026
		_fnThrottle: _fnThrottle,
15027
		_fnConvertToWidth: _fnConvertToWidth,
15028
		_fnGetWidestNode: _fnGetWidestNode,
15029
		_fnGetMaxLenString: _fnGetMaxLenString,
15030
		_fnStringToCss: _fnStringToCss,
15031
		_fnSortFlatten: _fnSortFlatten,
15032
		_fnSort: _fnSort,
15033
		_fnSortAria: _fnSortAria,
15034
		_fnSortListener: _fnSortListener,
15035
		_fnSortAttachListener: _fnSortAttachListener,
15036
		_fnSortingClasses: _fnSortingClasses,
15037
		_fnSortData: _fnSortData,
15038
		_fnSaveState: _fnSaveState,
15039
		_fnLoadState: _fnLoadState,
15040
		_fnSettingsFromNode: _fnSettingsFromNode,
15041
		_fnLog: _fnLog,
15042
		_fnMap: _fnMap,
15043
		_fnBindAction: _fnBindAction,
15044
		_fnCallbackReg: _fnCallbackReg,
15045
		_fnCallbackFire: _fnCallbackFire,
15046
		_fnLengthOverflow: _fnLengthOverflow,
15047
		_fnRenderer: _fnRenderer,
15048
		_fnDataSource: _fnDataSource,
15049
		_fnRowAttributes: _fnRowAttributes,
15050
		_fnCalculateEnd: function () {} // Used by a lot of plug-ins, but redundant
15051
		                                // in 1.10, so this dead-end function is
15052
		                                // added to prevent errors
15053
	} );
15054
	
15055
15056
	// jQuery access
15057
	$.fn.dataTable = DataTable;
15058
15059
	// Provide access to the host jQuery object (circular reference)
15060
	DataTable.$ = $;
15061
15062
	// Legacy aliases
15063
	$.fn.dataTableSettings = DataTable.settings;
15064
	$.fn.dataTableExt = DataTable.ext;
15065
15066
	// With a capital `D` we return a DataTables API instance rather than a
15067
	// jQuery object
15068
	$.fn.DataTable = function ( opts ) {
15069
		return $(this).dataTable( opts ).api();
15070
	};
15071
15072
	// All properties that are available to $.fn.dataTable should also be
15073
	// available on $.fn.DataTable
15074
	$.each( DataTable, function ( prop, val ) {
15075
		$.fn.DataTable[ prop ] = val;
15076
	} );
15077
15078
15079
	// Information about events fired by DataTables - for documentation.
15080
	/**
15081
	 * Draw event, fired whenever the table is redrawn on the page, at the same
15082
	 * point as fnDrawCallback. This may be useful for binding events or
15083
	 * performing calculations when the table is altered at all.
15084
	 *  @name DataTable#draw.dt
15085
	 *  @event
15086
	 *  @param {event} e jQuery event object
15087
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15088
	 */
15089
15090
	/**
15091
	 * Search event, fired when the searching applied to the table (using the
15092
	 * built-in global search, or column filters) is altered.
15093
	 *  @name DataTable#search.dt
15094
	 *  @event
15095
	 *  @param {event} e jQuery event object
15096
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15097
	 */
15098
15099
	/**
15100
	 * Page change event, fired when the paging of the table is altered.
15101
	 *  @name DataTable#page.dt
15102
	 *  @event
15103
	 *  @param {event} e jQuery event object
15104
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15105
	 */
15106
15107
	/**
15108
	 * Order event, fired when the ordering applied to the table is altered.
15109
	 *  @name DataTable#order.dt
15110
	 *  @event
15111
	 *  @param {event} e jQuery event object
15112
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15113
	 */
15114
15115
	/**
15116
	 * DataTables initialisation complete event, fired when the table is fully
15117
	 * drawn, including Ajax data loaded, if Ajax data is required.
15118
	 *  @name DataTable#init.dt
15119
	 *  @event
15120
	 *  @param {event} e jQuery event object
15121
	 *  @param {object} oSettings DataTables settings object
15122
	 *  @param {object} json The JSON object request from the server - only
15123
	 *    present if client-side Ajax sourced data is used</li></ol>
15124
	 */
15125
15126
	/**
15127
	 * State save event, fired when the table has changed state a new state save
15128
	 * is required. This event allows modification of the state saving object
15129
	 * prior to actually doing the save, including addition or other state
15130
	 * properties (for plug-ins) or modification of a DataTables core property.
15131
	 *  @name DataTable#stateSaveParams.dt
15132
	 *  @event
15133
	 *  @param {event} e jQuery event object
15134
	 *  @param {object} oSettings DataTables settings object
15135
	 *  @param {object} json The state information to be saved
15136
	 */
15137
15138
	/**
15139
	 * State load event, fired when the table is loading state from the stored
15140
	 * data, but prior to the settings object being modified by the saved state
15141
	 * - allowing modification of the saved state is required or loading of
15142
	 * state for a plug-in.
15143
	 *  @name DataTable#stateLoadParams.dt
15144
	 *  @event
15145
	 *  @param {event} e jQuery event object
15146
	 *  @param {object} oSettings DataTables settings object
15147
	 *  @param {object} json The saved state information
15148
	 */
15149
15150
	/**
15151
	 * State loaded event, fired when state has been loaded from stored data and
15152
	 * the settings object has been modified by the loaded data.
15153
	 *  @name DataTable#stateLoaded.dt
15154
	 *  @event
15155
	 *  @param {event} e jQuery event object
15156
	 *  @param {object} oSettings DataTables settings object
15157
	 *  @param {object} json The saved state information
15158
	 */
15159
15160
	/**
15161
	 * Processing event, fired when DataTables is doing some kind of processing
15162
	 * (be it, order, searcg or anything else). It can be used to indicate to
15163
	 * the end user that there is something happening, or that something has
15164
	 * finished.
15165
	 *  @name DataTable#processing.dt
15166
	 *  @event
15167
	 *  @param {event} e jQuery event object
15168
	 *  @param {object} oSettings DataTables settings object
15169
	 *  @param {boolean} bShow Flag for if DataTables is doing processing or not
15170
	 */
15171
15172
	/**
15173
	 * Ajax (XHR) event, fired whenever an Ajax request is completed from a
15174
	 * request to made to the server for new data. This event is called before
15175
	 * DataTables processed the returned data, so it can also be used to pre-
15176
	 * process the data returned from the server, if needed.
15177
	 *
15178
	 * Note that this trigger is called in `fnServerData`, if you override
15179
	 * `fnServerData` and which to use this event, you need to trigger it in you
15180
	 * success function.
15181
	 *  @name DataTable#xhr.dt
15182
	 *  @event
15183
	 *  @param {event} e jQuery event object
15184
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15185
	 *  @param {object} json JSON returned from the server
15186
	 *
15187
	 *  @example
15188
	 *     // Use a custom property returned from the server in another DOM element
15189
	 *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
15190
	 *       $('#status').html( json.status );
15191
	 *     } );
15192
	 *
15193
	 *  @example
15194
	 *     // Pre-process the data returned from the server
15195
	 *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
15196
	 *       for ( var i=0, ien=json.aaData.length ; i<ien ; i++ ) {
15197
	 *         json.aaData[i].sum = json.aaData[i].one + json.aaData[i].two;
15198
	 *       }
15199
	 *       // Note no return - manipulate the data directly in the JSON object.
15200
	 *     } );
15201
	 */
15202
15203
	/**
15204
	 * Destroy event, fired when the DataTable is destroyed by calling fnDestroy
15205
	 * or passing the bDestroy:true parameter in the initialisation object. This
15206
	 * can be used to remove bound events, added DOM nodes, etc.
15207
	 *  @name DataTable#destroy.dt
15208
	 *  @event
15209
	 *  @param {event} e jQuery event object
15210
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15211
	 */
15212
15213
	/**
15214
	 * Page length change event, fired when number of records to show on each
15215
	 * page (the length) is changed.
15216
	 *  @name DataTable#length.dt
15217
	 *  @event
15218
	 *  @param {event} e jQuery event object
15219
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15220
	 *  @param {integer} len New length
15221
	 */
15222
15223
	/**
15224
	 * Column sizing has changed.
15225
	 *  @name DataTable#column-sizing.dt
15226
	 *  @event
15227
	 *  @param {event} e jQuery event object
15228
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15229
	 */
15230
15231
	/**
15232
	 * Column visibility has changed.
15233
	 *  @name DataTable#column-visibility.dt
15234
	 *  @event
15235
	 *  @param {event} e jQuery event object
15236
	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15237
	 *  @param {int} column Column index
15238
	 *  @param {bool} vis `false` if column now hidden, or `true` if visible
15239
	 */
15240
15241
	return $.fn.dataTable;
15242
}));
15243